def append_class(self, node: ast.ClassDef): self.class_list.append(len(self.classes)) preprocessed_class = PreprocessedClass( node.name, FilePosition(self.path, create_range_from_ast_node(node))) self.classes.append(preprocessed_class) self.handle_nested_class(node, preprocessed_class) for member in node.body: if isinstance(member, (ast.FunctionDef, ast.AsyncFunctionDef)): self.append_method( member, FilePosition(self.path, create_range_from_ast_node(member))) elif isinstance(member, ast.Assign): self.append_attribute( member, FilePosition(self.path, create_range_from_ast_node(member))) elif isinstance(member, ast.ClassDef): self.append_nested_class(preprocessed_class, member) elif isinstance(member, ast.Pass): pass elif isinstance(member, ast.Expr) and hasattr(member, 'value') and isinstance(member.value, ast.Constant) \ and hasattr(member.value, "value") and isinstance(member.value.value, str): pass # documentation comment else: pass
def visit_common_function_def( self, node: Union[ast.FunctionDef, ast.AsyncFunctionDef]) -> Any: r = create_range_from_ast_node(node) self.function = FunctionDeclaration( node.name, self.scope_manager.get_qualified_name_from_current_scope( node.name, r.start_position.line), FilePosition(self.current_file, r), [], "") for call in reversed(self.current_function_calls): if call.name == self.function.name and call.file_position == self.function.file_position: return # self.scope_manager.append_function_to_current_scope(self.function) self.current_function_declaration.append(self.function) def action(): self.collect_parameters(node) self.generic_visit(node) self.scope_manager.with_scope( FunctionScope( node.name, self.scope_manager.get_qualified_scope_name_from_current_scope( ), FilePosition.get_empty_file_position()), action) del self.current_function_declaration[-1]
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> Any: if self.depth == 0: self.preprocessed_functions.add( PreprocessedFunction( node.name, FilePosition(self.path, create_range_from_ast_node(node)), node)) self.depth += 1 self.generic_visit(node) self.depth -= 1
def visit_Assign(self, node: ast.Assign) -> Any: if self.depth == 0: for target in node.targets: if isinstance(target, ast.Name): self.preprocessed_variables.add( PreprocessedVariable( target.id, FilePosition(self.path, create_range_from_ast_node(node)))) else: pass # print("...")
def convert_ast_import_to_import(node: ast.Import, is_local: bool = False) -> List[Import]: imports = [] for module in node.names: module_parts = module.name.split('.') module_name = module_parts[-1] module_parts.remove(module_name) r = create_range_from_ast_node(node) imports.append( ImportTable.create_import(module_parts, module_name, module.asname, [], r, is_local)) return imports
def _(self, node: ast.Call): if hasattr(node.func, 'id'): # TODO: check if builtin class ctor-s are not hidden by other (custom) functions/classes # TODO: no args check (builtin is not hidden + correct code -> should not be a problem) built_in_function = get_built_in_function(node.func.id) if built_in_function is not None: return built_in_function elif node.func.id == 'TypeVar': return Type() return self.get_member_access_type(MemberAccessCollector(node), FilePosition(self.scope_manager.current_file, create_range_from_ast_node(node)))
def collect_parameters( self, node: Union[ast.FunctionDef, ast.AsyncFunctionDef]) -> None: args_with_default = [] for i in range(0, len(node.args.args)): if i < len(node.args.defaults): default = node.args.defaults[-(i + 1)] else: default = None args_with_default.append((node.args.args[-(i + 1)], default)) arg_idx = 0 for param in reversed(args_with_default): r = create_range_from_ast_node(node) qualified_name = self.scope_manager.\ get_qualified_name_from_current_scope(param[0].arg, r.start_position.line) new_variable = VariableDeclaration( param[0].arg, qualified_name, FilePosition(self.current_file, r)) if param[0].arg == 'self' and self.scope_manager.is_current_scope_method() and \ node.args.args[0] is param[0]: new_variable.type.add( self.scope_manager.get_current_class_declaration()) else: # has kw -> has arg -> default keyword = [k for k in self.arguments if k[1] == param[0].arg] if len(keyword) == 0: if arg_idx < len(self.arguments): new_variable.type.update( self.type_deduction.get_current_type( {self.arguments[arg_idx][0]})) arg_idx += 1 elif param[1] is not None: new_variable.type.update( self.type_deduction.get_current_type( self.type_deduction.deduct_type(param[1]))) elif len(keyword) == 1: new_variable.type.update( self.type_deduction.get_current_type({keyword[0][0]})) else: assert False self.scope_manager.append_variable_to_current_scope(new_variable)
def convert_ast_import_from_to_import(node: ast.ImportFrom, is_local: bool = False ) -> List[Import]: assert len(node.names) > 0 is_module = True try: if node.level > 0 and node.module is None: a = util.find_spec(node.names[0].name) if a is None: pass # print() elif (node.level == 0 or node.module is not None) and \ util.find_spec(node.module + '.' + node.names[0].name) is None: is_module = False except (AttributeError, ModuleNotFoundError, ImportError, ValueError): # v3.7: before: AttributeError, after: ModuleNotFoundError is_module = False imports = [] r = create_range_from_ast_node(node) if is_module: # modules if node.module is None: # relative module_path = [] else: module_path = node.module.split('.') for module in node.names: imports.append( ImportTable.create_import(module_path, module.name, module.asname, [], r, is_local)) else: # variables, functions imported = [] for module in node.names: imported.append(SymbolImport(module.name, module.asname)) module_parts = node.module.split('.') module_name = module_parts[-1] module_parts.remove(module_name) imports.append( ImportTable.create_import(module_parts, module_name, None, imported, r, is_local)) return imports
def visit_Assign(self, node: ast.Assign): self.append_attribute( node, FilePosition(self.path, create_range_from_ast_node(node))) self.generic_visit(node)
def _(self, node: ast.Attribute): return self.get_member_access_type(MemberAccessCollector(node), FilePosition(self.scope_manager.current_file, create_range_from_ast_node(node)))