def get_return_types(self, check_yields=False): func = self.base if func.isinstance(LambdaWrapper): return self._evaluator.eval_element(self.children[-1]) if func.listeners: # Feed the listeners, with the params. for listener in func.listeners: listener.execute(self._get_params()) # If we do have listeners, that means that there's not a regular # execution ongoing. In this case Jedi is interested in the # inserted params, not in the actual execution of the function. return [] if check_yields: types = [] returns = self.yields else: returns = self.returns types = list(docstrings.find_return_types(self._evaluator, func)) for r in returns: check = flow_analysis.break_check(self._evaluator, self, r) if check is flow_analysis.UNREACHABLE: debug.dbg('Return unreachable: %s', r) else: types += self._evaluator.eval_element(r.children[1]) if check is flow_analysis.REACHABLE: debug.dbg('Return reachable: %s', r) break return types
def get_return_types(self, check_yields=False): func = self.base if func.isinstance(LambdaWrapper): return self._evaluator.eval_element(self.children[-1]) if func.listeners: # Feed the listeners, with the params. for listener in func.listeners: listener.execute(self._get_params()) # If we do have listeners, that means that there's not a regular # execution ongoing. In this case Jedi is interested in the # inserted params, not in the actual execution of the function. return [] if check_yields: types = [] returns = self.yields else: returns = self.returns types = list(docstrings.find_return_types(self._evaluator, func)) for r in returns: check = flow_analysis.break_check(self._evaluator, self, r) if check is flow_analysis.UNREACHABLE: debug.dbg('Return unreachable: %s', r) else: types += self._evaluator.eval_element(r.children[1]) if check is flow_analysis.REACHABLE: debug.dbg('Return reachable: %s', r) break return types
def names_dict_lookup(self, names_dict, position): def get_param(scope, el): if isinstance(el.get_parent_until(pr.Param), pr.Param): return scope.param_by_name(str(el)) return el search_str = str(self.name_str) try: names = names_dict[search_str] if not names: # We want names, otherwise stop. return [] except KeyError: return [] names = filter_definition_names(names, self.name_str, position) name_scope = None # Only the names defined in the last position are valid definitions. last_names = [] for name in reversed(sorted(names, key=lambda name: name.start_pos)): stmt = name.get_definition() name_scope = er.wrap(self._evaluator, stmt.get_parent_scope()) if isinstance(self.scope, er.Instance) and not isinstance( name_scope, er.Instance): # Instances should not be checked for positioning, because we # don't know in which order the functions are called. last_names.append(name) continue if isinstance(name_scope, compiled.CompiledObject): # Let's test this. TODO need comment. shouldn't this be # filtered before? last_names.append(name) continue if isinstance(name, compiled.CompiledName) \ or isinstance(name, er.InstanceName) and isinstance(name._origin_name, compiled.CompiledName): last_names.append(name) continue if isinstance(self.name_str, pr.Name): origin_scope = self.name_str.get_parent_until(pr.Scope, reverse=True) else: origin_scope = None if isinstance(stmt.parent, compiled.CompiledObject): # TODO seriously? this is stupid. continue check = flow_analysis.break_check(self._evaluator, name_scope, stmt, origin_scope) if check is not flow_analysis.UNREACHABLE: last_names.append(name) if check is flow_analysis.REACHABLE: break if isinstance(name_scope, er.FunctionExecution): # Replace params return [get_param(name_scope, n) for n in last_names] return last_names
def get_return_types(self): func = self.base if func.listeners: # Feed the listeners, with the params. for listener in func.listeners: listener.execute(self._get_params()) # If we do have listeners, that means that there's not a regular # execution ongoing. In this case Jedi is interested in the # inserted params, not in the actual execution of the function. return [] types = list(docstrings.find_return_types(self._evaluator, func)) for r in self.returns: if isinstance(r, pr.KeywordStatement): stmt = r.stmt else: stmt = r # Lambdas if stmt is None: continue check = flow_analysis.break_check(self._evaluator, self, r.parent) if check is flow_analysis.UNREACHABLE: debug.dbg('Return unreachable: %s', r) else: types += self._evaluator.eval_statement(stmt) if check is flow_analysis.REACHABLE: debug.dbg('Return reachable: %s', r) break return types
def names_dict_lookup(self, names_dict, position): def get_param(scope, el): if isinstance(el.get_parent_until(pr.Param), pr.Param): return scope.param_by_name(str(el)) return el search_str = str(self.name_str) try: names = names_dict[search_str] if not names: # We want names, otherwise stop. return [] except KeyError: return [] names = filter_definition_names(names, self.name_str, position) name_scope = None # Only the names defined in the last position are valid definitions. last_names = [] for name in reversed(sorted(names, key=lambda name: name.start_pos)): stmt = name.get_definition() name_scope = er.wrap(self._evaluator, stmt.get_parent_scope()) if isinstance(self.scope, er.Instance) and not isinstance(name_scope, er.Instance): # Instances should not be checked for positioning, because we # don't know in which order the functions are called. last_names.append(name) continue if isinstance(name_scope, compiled.CompiledObject): # Let's test this. TODO need comment. shouldn't this be # filtered before? last_names.append(name) continue if isinstance(name, compiled.CompiledName) \ or isinstance(name, er.InstanceName) and isinstance(name._origin_name, compiled.CompiledName): last_names.append(name) continue if isinstance(self.name_str, pr.Name): origin_scope = self.name_str.get_parent_until(pr.Scope, reverse=True) else: origin_scope = None if isinstance(stmt.parent, compiled.CompiledObject): # TODO seriously? this is stupid. continue check = flow_analysis.break_check(self._evaluator, name_scope, stmt, origin_scope) if check is not flow_analysis.UNREACHABLE: last_names.append(name) if check is flow_analysis.REACHABLE: break if isinstance(name_scope, er.FunctionExecution): # Replace params return [get_param(name_scope, n) for n in last_names] return last_names
def filter_name(self, scope_names_generator): """ Filters all variables of a scope (which are defined in the `scope_names_generator`), until the name fits. """ # TODO Now this import is really ugly. Try to remove it. # It's possibly the only api dependency. from jedi.api.interpreter import InterpreterNamespace names = [] self.maybe_descriptor = isinstance(self.scope, er.Class) for name_list_scope, name_list in scope_names_generator: break_scopes = [] if not isinstance(name_list_scope, compiled.CompiledObject): # Here is the position stuff happening (sorting of variables). # Compiled objects don't need that, because there's only one # reference. name_list = sorted(name_list, key=lambda n: n.start_pos, reverse=True) for name in name_list: if unicode(self.name_str) != name.get_code(): continue stmt = name.get_definition() scope = stmt.parent if scope in break_scopes: continue # Exclude `arr[1] =` from the result set. if not self._name_is_array_assignment(name, stmt): # TODO we ignore a lot of elements here that should not be # ignored. But then again flow_analysis also stops when the # input scope is reached. This is not correct: variables # might still have conditions if defined outside of the # current scope. if isinstance(stmt, (pr.Param, pr.Import)) \ or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \ or isinstance(scope, compiled.CompiledObject) \ or isinstance(stmt, pr.ExprStmt) and stmt.is_global(): # Always reachable. names.append(name) else: check = flow_analysis.break_check(self._evaluator, name_list_scope, er.wrap(self._evaluator, scope), self.scope) if check is not flow_analysis.UNREACHABLE: names.append(name) if check is flow_analysis.REACHABLE: break if names and self._is_name_break_scope(stmt): if self._does_scope_break_immediately(scope, name_list_scope): break else: break_scopes.append(scope) if names: break if isinstance(self.scope, er.Instance): # After checking the dictionary of an instance (self # attributes), an attribute maybe a descriptor. self.maybe_descriptor = True scope_txt = (self.scope if self.scope == name_list_scope else '%s-%s' % (self.scope, name_list_scope)) debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self.name_str, scope_txt, u(names), self.position) return list(self._clean_names(names))
def names_dict_lookup(self, names_dict, position): def get_param(scope, el): if isinstance(el.get_parent_until(tree.Param), tree.Param): return scope.param_by_name(str(el)) return el search_str = str(self.name_str) try: names = names_dict[search_str] if not names: # We want names, otherwise stop. return [] except KeyError: return [] names = filter_definition_names(names, self.name_str, position) name_scope = None # Only the names defined in the last position are valid definitions. last_names = [] for name in reversed(sorted(names, key=lambda name: name.start_pos)): stmt = name.get_definition() name_scope = self._evaluator.wrap(stmt.get_parent_scope()) if isinstance(self.scope, er.Instance) and not isinstance( name_scope, er.Instance): # Instances should not be checked for positioning, because we # don't know in which order the functions are called. last_names.append(name) continue if isinstance(name_scope, compiled.CompiledObject): # Let's test this. TODO need comment. shouldn't this be # filtered before? last_names.append(name) continue if isinstance(stmt, er.ModuleWrapper): # In case of REPL completion, we can infer modules names that # don't really have a definition (because they are really just # namespaces). In this case we can just add it. last_names.append(name) continue if isinstance(name, compiled.CompiledName) \ or isinstance(name, er.InstanceName) and isinstance(name._origin_name, compiled.CompiledName): last_names.append(name) continue if isinstance(self.name_str, tree.Name): origin_scope = self.name_str.get_parent_until(tree.Scope, reverse=True) scope = self.name_str check = None while True: scope = scope.parent if scope.type in ("if_stmt", "for_stmt", "comp_for"): try: name_dict = self._evaluator.predefined_if_name_dict_dict[ scope] types = set(name_dict[str(self.name_str)]) except KeyError: continue else: if self.name_str.start_pos < scope.children[ 1].end_pos: # It doesn't make any sense to check if # statements in the if statement itself, just # deliver types. self._found_predefined_if_name = types else: check = flow_analysis.break_check( self._evaluator, self.scope, origin_scope) if check is flow_analysis.UNREACHABLE: self._found_predefined_if_name = set() else: self._found_predefined_if_name = types break if isinstance(scope, tree.IsScope) or scope is None: break else: origin_scope = None if isinstance(stmt.parent, compiled.CompiledObject): # TODO seriously? this is stupid. continue check = flow_analysis.break_check(self._evaluator, name_scope, stmt, origin_scope) if check is not flow_analysis.UNREACHABLE: last_names.append(name) if check is flow_analysis.REACHABLE: break if isinstance(name_scope, er.FunctionExecution): # Replace params return [get_param(name_scope, n) for n in last_names] return last_names
def names_dict_lookup(self, names_dict, position): def get_param(scope, el): if isinstance(el.get_parent_until(tree.Param), tree.Param): return scope.param_by_name(str(el)) return el search_str = str(self.name_str) try: names = names_dict[search_str] if not names: # We want names, otherwise stop. return [] except KeyError: return [] names = filter_definition_names(names, self.name_str, position) name_scope = None # Only the names defined in the last position are valid definitions. last_names = [] for name in reversed(sorted(names, key=lambda name: name.start_pos)): stmt = name.get_definition() name_scope = self._evaluator.wrap(stmt.get_parent_scope()) if isinstance(self.scope, er.Instance) and not isinstance(name_scope, er.Instance): # Instances should not be checked for positioning, because we # don't know in which order the functions are called. last_names.append(name) continue if isinstance(name_scope, compiled.CompiledObject): # Let's test this. TODO need comment. shouldn't this be # filtered before? last_names.append(name) continue if isinstance(stmt, er.ModuleWrapper): # In case of REPL completion, we can infer modules names that # don't really have a definition (because they are really just # namespaces). In this case we can just add it. last_names.append(name) continue if ( isinstance(name, compiled.CompiledName) or isinstance(name, er.InstanceName) and isinstance(name._origin_name, compiled.CompiledName) ): last_names.append(name) continue if isinstance(self.name_str, tree.Name): origin_scope = self.name_str.get_parent_until(tree.Scope, reverse=True) scope = self.name_str check = None while True: scope = scope.parent if scope.type in ("if_stmt", "for_stmt", "comp_for"): try: name_dict = self._evaluator.predefined_if_name_dict_dict[scope] types = set(name_dict[str(self.name_str)]) except KeyError: continue else: if self.name_str.start_pos < scope.children[1].end_pos: # It doesn't make any sense to check if # statements in the if statement itself, just # deliver types. self._found_predefined_if_name = types else: check = flow_analysis.break_check(self._evaluator, self.scope, origin_scope) if check is flow_analysis.UNREACHABLE: self._found_predefined_if_name = set() else: self._found_predefined_if_name = types break if isinstance(scope, tree.IsScope) or scope is None: break else: origin_scope = None if isinstance(stmt.parent, compiled.CompiledObject): # TODO seriously? this is stupid. continue check = flow_analysis.break_check(self._evaluator, name_scope, stmt, origin_scope) if check is not flow_analysis.UNREACHABLE: last_names.append(name) if check is flow_analysis.REACHABLE: break if isinstance(name_scope, er.FunctionExecution): # Replace params return [get_param(name_scope, n) for n in last_names] return last_names