From 643797d922aa3a22833a5afe497b2eddf3b29e86 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 30 Aug 2022 14:41:17 -0400 Subject: [PATCH] Support builtins (#50) --- resources/test/src/F821.py | 2 + src/builtins.rs | 163 +++++++++++++++++++++++++++++++++++++ src/check_ast.rs | 22 +++++ src/lib.rs | 1 + 4 files changed, 188 insertions(+) create mode 100644 src/builtins.rs diff --git a/resources/test/src/F821.py b/resources/test/src/F821.py index aaef818990..98af736d7f 100644 --- a/resources/test/src/F821.py +++ b/resources/test/src/F821.py @@ -12,3 +12,5 @@ def get_name(): def get_name(self): return self.name + +x = list() diff --git a/src/builtins.rs b/src/builtins.rs new file mode 100644 index 0000000000..d398bab137 --- /dev/null +++ b/src/builtins.rs @@ -0,0 +1,163 @@ +pub const BUILTINS: &[&str] = &[ + "ArithmeticError", + "AssertionError", + "AttributeError", + "BaseException", + "BlockingIOError", + "BrokenPipeError", + "BufferError", + "BytesWarning", + "ChildProcessError", + "ConnectionAbortedError", + "ConnectionError", + "ConnectionRefusedError", + "ConnectionResetError", + "DeprecationWarning", + "EOFError", + "Ellipsis", + "EnvironmentError", + "Exception", + "False", + "FileExistsError", + "FileNotFoundError", + "FloatingPointError", + "FutureWarning", + "GeneratorExit", + "IOError", + "ImportError", + "ImportWarning", + "IndentationError", + "IndexError", + "InterruptedError", + "IsADirectoryError", + "KeyError", + "KeyboardInterrupt", + "LookupError", + "MemoryError", + "ModuleNotFoundError", + "NameError", + "None", + "NotADirectoryError", + "NotImplemented", + "NotImplementedError", + "OSError", + "OverflowError", + "PendingDeprecationWarning", + "PermissionError", + "ProcessLookupError", + "RecursionError", + "ReferenceError", + "ResourceWarning", + "RuntimeError", + "RuntimeWarning", + "StopAsyncIteration", + "StopIteration", + "SyntaxError", + "SyntaxWarning", + "SystemError", + "SystemExit", + "TabError", + "TimeoutError", + "True", + "TypeError", + "UnboundLocalError", + "UnicodeDecodeError", + "UnicodeEncodeError", + "UnicodeError", + "UnicodeTranslateError", + "UnicodeWarning", + "UserWarning", + "ValueError", + "Warning", + "ZeroDivisionError", + "__build_class__", + "__debug__", + "__doc__", + "__import__", + "__loader__", + "__name__", + "__package__", + "__spec__", + "abs", + "all", + "any", + "ascii", + "bin", + "bool", + "breakpoint", + "bytearray", + "bytes", + "callable", + "chr", + "classmethod", + "compile", + "complex", + "copyright", + "credits", + "delattr", + "dict", + "dir", + "divmod", + "enumerate", + "eval", + "exec", + "exit", + "filter", + "float", + "format", + "frozenset", + "getattr", + "globals", + "hasattr", + "hash", + "help", + "hex", + "id", + "input", + "int", + "isinstance", + "issubclass", + "iter", + "len", + "license", + "list", + "locals", + "map", + "max", + "memoryview", + "min", + "next", + "object", + "oct", + "open", + "ord", + "pow", + "print", + "property", + "quit", + "range", + "repr", + "reversed", + "round", + "set", + "setattr", + "slice", + "sorted", + "staticmethod", + "str", + "sum", + "super", + "tuple", + "type", + "vars", + "zip", +]; + +// Globally defined names which are not attributes of the builtins module, or are only present on +// some platforms. +pub const MAGIC_GLOBALS: &[&str] = &[ + "__file__", + "__builtins__", + "__annotations__", + "WindowsError", +]; diff --git a/src/check_ast.rs b/src/check_ast.rs index bd7770aff7..91d55431ce 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::sync::atomic::{AtomicUsize, Ordering}; +use crate::builtins::{BUILTINS, MAGIC_GLOBALS}; use rustpython_parser::ast::{ Arg, Arguments, Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind, Suite, }; @@ -45,6 +46,7 @@ enum BindingKind { Assignment, ClassDefinition, Definition, + Builtin, FutureImportation, Importation(String), StarImportation, @@ -408,6 +410,25 @@ impl Checker<'_> { .push(self.scopes.pop().expect("Attempted to pop without scope.")); } + fn bind_builtins(&mut self) { + for builtin in BUILTINS { + self.add_binding(Binding { + kind: BindingKind::Builtin, + name: builtin.to_string(), + location: Default::default(), + used: None, + }) + } + for builtin in MAGIC_GLOBALS { + self.add_binding(Binding { + kind: BindingKind::Builtin, + name: builtin.to_string(), + location: Default::default(), + used: None, + }) + } + } + fn add_binding(&mut self, binding: Binding) { let scope = self.scopes.last_mut().expect("No current scope found."); @@ -532,6 +553,7 @@ impl Checker<'_> { pub fn check_ast(python_ast: &Suite, settings: &Settings, path: &str) -> Vec { let mut checker = Checker::new(settings); checker.push_scope(Scope::new(Module)); + checker.bind_builtins(); for stmt in python_ast { checker.visit_stmt(stmt); diff --git a/src/lib.rs b/src/lib.rs index 21eb15a345..7d8873ec92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod builtins; mod cache; pub mod check_ast; mod check_lines;