def eval_statement(self, stmt, seek_name=None): """ The starting point of the completion. A statement always owns a call list, which are the calls, that a statement does. In case multiple names are defined in the statement, `seek_name` returns the result for this name. :param stmt: A `pr.ExprStmt`. """ debug.dbg('eval_statement %s (%s)', stmt, seek_name) types = self.eval_element(stmt.get_rhs()) if seek_name: types = finder.check_tuple_assignments(types, seek_name) first_operation = stmt.first_operation() if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement): # TODO don't check for this. # `=` is always the last character in aug assignments -> -1 operator = copy.copy(first_operation) operator.value = operator.value[:-1] name = str(stmt.get_defined_names()[0]) parent = er.wrap(self, stmt.get_parent_scope()) left = self.find_types(parent, name, stmt.start_pos, search_global=True) if isinstance(stmt.get_parent_until(pr.ForStmt), pr.ForStmt): # Iterate through result and add the values, that's possible # only in for loops without clutter, because they are # predictable. for r in types: left = precedence.calculate(self, left, operator, [r]) types = left else: types = precedence.calculate(self, left, operator, types) debug.dbg('eval_statement result %s', types) return types
def eval_statement(self, stmt, seek_name=None): """ The starting point of the completion. A statement always owns a call list, which are the calls, that a statement does. In case multiple names are defined in the statement, `seek_name` returns the result for this name. :param stmt: A `tree.ExprStmt`. """ debug.dbg('eval_statement %s (%s)', stmt, seek_name) rhs = stmt.get_rhs() types = self.eval_element(rhs) if seek_name: types = finder.check_tuple_assignments(self, types, seek_name) first_operation = stmt.first_operation() if first_operation not in ('=', None) and not isinstance( stmt, er.InstanceElement ) and first_operation.type == 'operator': # TODO don't check for this. id:458 gh:459 # `=` is always the last character in aug assignments -> -1 operator = copy.copy(first_operation) operator.value = operator.value[:-1] name = str(stmt.get_defined_names()[0]) parent = self.wrap(stmt.get_parent_scope()) left = self.find_types(parent, name, stmt.start_pos, search_global=True) for_stmt = stmt.get_parent_until(tree.ForStmt) if isinstance(for_stmt, tree.ForStmt) and types \ and for_stmt.defines_one_name(): # Iterate through result and add the values, that's possible # only in for loops without clutter, because they are # predictable. Also only do it, if the variable is not a tuple. node = for_stmt.get_input_node() for_iterables = self.eval_element(node) ordered = list(iterable.py__iter__(self, for_iterables, node)) for index_types in ordered: dct = {str(for_stmt.children[1]): index_types} self.predefined_if_name_dict_dict[for_stmt] = dct t = self.eval_element(rhs) left = precedence.calculate(self, left, operator, t) types = left if ordered: # If there are no for entries, we cannot iterate and the # types are defined by += entries. Therefore the for loop # is never called. del self.predefined_if_name_dict_dict[for_stmt] else: types = precedence.calculate(self, left, operator, types) debug.dbg('eval_statement result %s', types) return types
def eval_statement(self, stmt, seek_name=None): """ The starting point of the completion. A statement always owns a call list, which are the calls, that a statement does. In case multiple names are defined in the statement, `seek_name` returns the result for this name. :param stmt: A `tree.ExprStmt`. """ debug.dbg("eval_statement %s (%s)", stmt, seek_name) rhs = stmt.get_rhs() types = self.eval_element(rhs) if seek_name: types = finder.check_tuple_assignments(self, types, seek_name) first_operation = stmt.first_operation() if first_operation not in ("=", None) and not isinstance( stmt, er.InstanceElement ): # TODO don't check for this. # `=` is always the last character in aug assignments -> -1 operator = copy.copy(first_operation) operator.value = operator.value[:-1] name = str(stmt.get_defined_names()[0]) parent = self.wrap(stmt.get_parent_scope()) left = self.find_types(parent, name, stmt.start_pos, search_global=True) for_stmt = stmt.get_parent_until(tree.ForStmt) if isinstance(for_stmt, tree.ForStmt) and types and for_stmt.defines_one_name(): # Iterate through result and add the values, that's possible # only in for loops without clutter, because they are # predictable. Also only do it, if the variable is not a tuple. node = for_stmt.get_input_node() for_iterables = self.eval_element(node) ordered = list(iterable.py__iter__(self, for_iterables, node)) for index_types in ordered: dct = {str(for_stmt.children[1]): index_types} self.predefined_if_name_dict_dict[for_stmt] = dct t = self.eval_element(rhs) left = precedence.calculate(self, left, operator, t) types = left if ordered: # If there are no for entries, we cannot iterate and the # types are defined by += entries. Therefore the for loop # is never called. del self.predefined_if_name_dict_dict[for_stmt] else: types = precedence.calculate(self, left, operator, types) debug.dbg("eval_statement result %s", types) return types
def _eval_stmt(self, context, stmt, seek_name=None): """ The starting point of the completion. A statement always owns a call list, which are the calls, that a statement does. In case multiple names are defined in the statement, `seek_name` returns the result for this name. :param stmt: A `tree.ExprStmt`. """ debug.dbg('eval_statement %s (%s)', stmt, seek_name) rhs = stmt.get_rhs() types = self.eval_element(context, rhs) if seek_name: c_node = ContextualizedName(context, seek_name) types = finder.check_tuple_assignments(self, c_node, types) first_operation = stmt.first_operation() if first_operation not in ( '=', None) and first_operation.type == 'operator': # `=` is always the last character in aug assignments -> -1 operator = copy.copy(first_operation) operator.value = operator.value[:-1] name = str(stmt.get_defined_names()[0]) left = context.py__getattribute__(name, position=stmt.start_pos, search_global=True) for_stmt = tree.search_ancestor(stmt, 'for_stmt') if for_stmt is not None and for_stmt.type == 'for_stmt' and types \ and for_stmt.defines_one_name(): # Iterate through result and add the values, that's possible # only in for loops without clutter, because they are # predictable. Also only do it, if the variable is not a tuple. node = for_stmt.get_input_node() cn = ContextualizedNode(context, node) ordered = list(iterable.py__iter__(self, cn.infer(), cn)) for lazy_context in ordered: dct = {str(for_stmt.children[1]): lazy_context.infer()} with helpers.predefine_names(context, for_stmt, dct): t = self.eval_element(context, rhs) left = precedence.calculate(self, context, left, operator, t) types = left else: types = precedence.calculate(self, context, left, operator, types) debug.dbg('eval_statement result %s', types) return types
def goto_definitions(self, name): def_ = name.get_definition() is_simple_name = name.parent.type not in ("power", "trailer") if is_simple_name: if name.parent.type in ("file_input", "classdef", "funcdef"): return [self.wrap(name.parent)] if def_.type == "expr_stmt" and name in def_.get_defined_names(): return self.eval_statement(def_, name) elif def_.type == "for_stmt": container_types = self.eval_element(def_.children[3]) for_types = iterable.py__iter__types(self, container_types, def_.children[3]) return finder.check_tuple_assignments(self, for_types, name) elif def_.type in ("import_from", "import_name"): return imports.ImportWrapper(self, name).follow() call = helpers.call_of_leaf(name) return self.eval_element(call)
def _eval_stmt(self, context, stmt, seek_name=None): """ The starting point of the completion. A statement always owns a call list, which are the calls, that a statement does. In case multiple names are defined in the statement, `seek_name` returns the result for this name. :param stmt: A `tree.ExprStmt`. """ debug.dbg('eval_statement %s (%s)', stmt, seek_name) rhs = stmt.get_rhs() types = self.eval_element(context, rhs) if seek_name: c_node = ContextualizedName(context, seek_name) types = finder.check_tuple_assignments(self, c_node, types) first_operation = stmt.first_operation() if first_operation not in ('=', None) and first_operation.type == 'operator': # `=` is always the last character in aug assignments -> -1 operator = copy.copy(first_operation) operator.value = operator.value[:-1] name = str(stmt.get_defined_names()[0]) left = context.py__getattribute__( name, position=stmt.start_pos, search_global=True) for_stmt = tree.search_ancestor(stmt, 'for_stmt') if for_stmt is not None and for_stmt.type == 'for_stmt' and types \ and for_stmt.defines_one_name(): # Iterate through result and add the values, that's possible # only in for loops without clutter, because they are # predictable. Also only do it, if the variable is not a tuple. node = for_stmt.get_input_node() cn = ContextualizedNode(context, node) ordered = list(iterable.py__iter__(self, cn.infer(), cn)) for lazy_context in ordered: dct = {str(for_stmt.children[1]): lazy_context.infer()} with helpers.predefine_names(context, for_stmt, dct): t = self.eval_element(context, rhs) left = precedence.calculate(self, context, left, operator, t) types = left else: types = precedence.calculate(self, context, left, operator, types) debug.dbg('eval_statement result %s', types) return types
def goto_definitions(self, name): def_ = name.get_definition() is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: if name.parent.type in ('file_input', 'classdef', 'funcdef'): return [self.wrap(name.parent)] if def_.type == 'expr_stmt' and name in def_.get_defined_names(): return self.eval_statement(def_, name) elif def_.type == 'for_stmt': container_types = self.eval_element(def_.children[3]) for_types = iterable.py__iter__types(self, container_types, def_.children[3]) return finder.check_tuple_assignments(self, for_types, name) elif def_.type in ('import_from', 'import_name'): return imports.ImportWrapper(self, name).follow() call = helpers.call_of_leaf(name) return self.eval_element(call)
def goto_definitions(self, name): def_ = name.get_definition() is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: if name.parent.type == 'classdef' and name.parent.name == name: return [self.wrap(name.parent)] if name.parent.type in ('file_input', 'funcdef'): return [self.wrap(name.parent)] if def_.type == 'expr_stmt' and name in def_.get_defined_names(): return self.eval_statement(def_, name) elif def_.type == 'for_stmt': container_types = self.eval_element(def_.children[3]) for_types = iterable.py__iter__types(self, container_types, def_.children[3]) return finder.check_tuple_assignments(self, for_types, name) elif def_.type in ('import_from', 'import_name'): return imports.ImportWrapper(self, name).follow() call = helpers.call_of_leaf(name) return self.eval_element(call)
def goto_definitions(self, context, name): def_ = name.get_definition() is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: if name.parent.type == 'classdef' and name.parent.name == name: return [er.ClassContext(self, name.parent, context)] elif name.parent.type == 'funcdef': return [er.FunctionContext(self, context, name.parent)] elif name.parent.type == 'file_input': raise NotImplementedError if def_.type == 'expr_stmt' and name in def_.get_defined_names(): return self.eval_statement(context, def_, name) elif def_.type == 'for_stmt': container_types = self.eval_element(context, def_.children[3]) for_types = iterable.py__iter__types(self, container_types, def_.children[3]) return finder.check_tuple_assignments(self, for_types, name) elif def_.type in ('import_from', 'import_name'): return imports.infer_import(context, name) return helpers.evaluate_call_of_leaf(context, name)
def goto_definitions(self, context, name): def_ = name.get_definition() is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: if name.parent.type == 'classdef' and name.parent.name == name: return [er.ClassContext(self, name.parent, context)] elif name.parent.type == 'funcdef': return [er.FunctionContext(self, context, name.parent)] elif name.parent.type == 'file_input': raise NotImplementedError if def_.type == 'expr_stmt' and name in def_.get_defined_names(): return self.eval_statement(context, def_, name) elif def_.type == 'for_stmt': container_types = self.eval_element(context, def_.children[3]) cn = ContextualizedNode(context, def_.children[3]) for_types = iterable.py__iter__types(self, container_types, cn) c_node = ContextualizedName(context, name) return finder.check_tuple_assignments(self, c_node, for_types) elif def_.type in ('import_from', 'import_name'): return imports.infer_import(context, name) return helpers.evaluate_call_of_leaf(context, name)
def goto_definitions(self, context, name): def_ = name.get_definition(import_name_always=True) if def_ is not None: type_ = def_.type if type_ == 'classdef': return [er.ClassContext(self, name.parent, context)] elif type_ == 'funcdef': return [er.FunctionContext(self, context, name.parent)] if type_ == 'expr_stmt': is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return self.eval_statement(context, def_, name) if type_ == 'for_stmt': container_types = self.eval_element(context, def_.children[3]) cn = ContextualizedNode(context, def_.children[3]) for_types = iterable.py__iter__types(self, container_types, cn) c_node = ContextualizedName(context, name) return finder.check_tuple_assignments(self, c_node, for_types) if type_ in ('import_from', 'import_name'): return imports.infer_import(context, name) return helpers.evaluate_call_of_leaf(context, name)