diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 97e6274f..32bb5fe3 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -21,9 +21,7 @@ from jedi.common import unite from jedi import settings from jedi.evaluate import representation as er from jedi.evaluate.instance import AbstractInstanceContext -from jedi.evaluate import dynamic from jedi.evaluate import compiled -from jedi.evaluate import docstrings from jedi.evaluate import pep0484 from jedi.evaluate import iterable from jedi.evaluate import imports @@ -31,64 +29,7 @@ from jedi.evaluate import analysis from jedi.evaluate import flow_analysis from jedi.evaluate import param from jedi.evaluate import helpers -from jedi.evaluate.filters import get_global_filters, TreeNameDefinition - - -def filter_after_position(names, position, origin=None): - """ - Removes all names after a certain position. If position is None, just - returns the names list. - """ - if position is None: - return names - - names_new = [] - for n in names: - # Filter positions and also allow list comprehensions and lambdas. - if n.start_pos[0] is not None and n.start_pos < position: - names_new.append(n) - elif isinstance(n.get_definition(), (tree.CompFor, tree.Lambda)): - if origin is not None and origin.get_definition() != n.get_definition(): - # This is extremely hacky. A transition that we have to use - # until we get rid of names_dicts. - continue - names_new.append(n) - return names_new - - -def is_comprehension_name(name, origin): - definition = name.get_definition() - # TODO This is really hacky. It just compares the two definitions. This - # fails tests and is in general just a temporary way. - return definition.type == 'comp_for' and origin.get_definition().type != definition.type - - -def filter_definition_names(names, origin, position=None): - """ - Filter names that are actual definitions in a scope. Names that are just - used will be ignored. - """ - if not names: - return [] - - # Just calculate the scope from the first - stmt = names[0].get_definition() - scope = stmt.get_parent_scope() - - if not (isinstance(scope, er.FunctionExecution) and - isinstance(scope.base, LambdaWrapper)): - names = filter_after_position(names, position, origin) - names = [name for name in names - if name.is_definition() and not is_comprehension_name(name, origin)] - - # Private name mangling (compile.c) disallows access on names - # preceeded by two underscores `__` if used outside of the class. Names - # that also end with two underscores (e.g. __id__) are not affected. - for name in list(names): - if name.value.startswith('__') and not name.value.endswith('__'): - if filter_private_variable(scope, origin): - names.remove(name) - return names +from jedi.evaluate.filters import get_global_filters class NameFinder(object): @@ -111,8 +52,6 @@ class NameFinder(object): :params bool attribute_lookup: Tell to logic if we're accessing the attribute or the contents of e.g. a function. """ - # TODO rename scopes to names_dicts - names = self.filter_name(filters) if self._found_predefined_types is not None and names: check = flow_analysis.reachability_check( @@ -149,100 +88,6 @@ class NameFinder(object): else: return self._context.get_filters(search_global, self._position, origin_scope=origin_scope) - 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 - - try: - names = names_dict[self._string_name] - if not names: # We want names, otherwise stop. - return [] - except KeyError: - return [] - - names = filter_definition_names(names, self._name, 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._context, 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.ModuleContext): - # 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, tree.Name): - origin_scope = self._name.get_parent_until(tree.Scope, reverse=True) - scope = self._name - check = None - while True: - scope = scope.parent - if scope.type in ("if_stmt", "for_stmt"): - # TODO try removing for_stmt. - try: - name_dict = self.context.predefined_names[scope] - types = set(name_dict[self._string_name]) - except KeyError: - continue - else: - if self._name.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_types = types - else: - check = flow_analysis.reachability_check( - self._context, self._context, origin_scope) - if check is flow_analysis.UNREACHABLE: - self._found_predefined_types = set() - else: - self._found_predefined_types = 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.reachability_check(self._context, 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, filters): """ Searches names that are defined in a scope (the different @@ -270,27 +115,7 @@ class NameFinder(object): break debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self._string_name, self._context, names, self._position) - return list(self._clean_names(names)) - - def _clean_names(self, names): - """ - ``NameFinder.filter_name`` should only output names with correct - wrapper parents. We don't want to see AST classes out in the - evaluation, so remove them already here! - """ - - return names - #for n in names: - # definition = n.parent - # if isinstance(definition, (compiled.CompiledObject, - # iterable.BuiltinMethod)): - # # TODO this if should really be removed by changing the type of - # # those classes. - # yield n - # elif definition.type in ('funcdef', 'classdef', 'file_input'): - # yield self._evaluator.wrap(definition).name - # else: - # yield n + return list(names) def _check_getattr(self, inst): """Checks for both __getattr__ and __getattribute__ methods""" @@ -354,9 +179,6 @@ def _name_to_types(evaluator, context, name): container_types = context.eval_node(node.children[3]) for_types = iterable.py__iter__types(evaluator, container_types, node.children[3]) types = check_tuple_assignments(evaluator, for_types, name) - elif isinstance(node, tree.Param): - return set() # TODO remove - types = _eval_param(evaluator, context, node) elif node.isinstance(tree.ExprStmt): types = _remove_statements(evaluator, context, node, name) elif node.isinstance(tree.WithStmt): @@ -383,8 +205,7 @@ def _name_to_types(evaluator, context, name): for t in exceptions ) else: - raise DeprecationWarning - types = set([node]) + raise ValueError("Should not happen.") return types @@ -438,11 +259,6 @@ def _remove_statements(evaluator, context, stmt, name): evaluated. """ types = set() - # Remove the statement docstr stuff for now, that has to be - # implemented with the evaluator class. - #if stmt.docstr: - #res_new.append(stmt) - check_instance = None pep0484types = \ @@ -459,53 +275,6 @@ def _remove_statements(evaluator, context, stmt, name): return types -def _eval_param(evaluator, context, param, scope): - res_new = set() - func = param.get_parent_scope() - - cls = func.parent.get_parent_until((tree.Class, tree.Function)) - - from jedi.evaluate.param import ExecutedParam, Arguments - if isinstance(cls, tree.Class) and param.position_nr == 0 \ - and not isinstance(param, ExecutedParam): - # This is where we add self - if it has never been - # instantiated. - if isinstance(scope, er.InstanceElement): - res_new.add(scope.instance) - else: - inst = er.Instance(evaluator, context.parent_context.parent_context, context.parent_context, - Arguments(evaluator, context), - is_generated=True) - res_new.add(inst) - return res_new - - # Instances are typically faked, if the instance is not called from - # outside. Here we check it for __init__ functions and return. - if isinstance(func, er.InstanceElement) \ - and func.instance.is_generated and str(func.name) == '__init__': - param = func.var.params[param.position_nr] - - # Add pep0484 and docstring knowledge. - pep0484_hints = pep0484.follow_param(evaluator, param) - doc_params = docstrings.follow_param(evaluator, param) - if pep0484_hints or doc_params: - return list(set(pep0484_hints) | set(doc_params)) - - if isinstance(param, ExecutedParam): - return res_new | param.eval(evaluator) - else: - # Param owns no information itself. - res_new |= dynamic.search_params(evaluator, param) - if not res_new: - if param.stars: - t = 'tuple' if param.stars == 1 else 'dict' - typ = list(evaluator.BUILTINS.py__getattribute__(t))[0] - res_new = evaluator.execute(typ) - if param.default: - res_new |= evaluator.eval_element(context, param.default) - return res_new - - def _check_flow_information(context, flow, search_name, pos): """ Try to find out the type of a variable just with the information that is given by the flows: e.g. It is also responsible for assert checks.:: @@ -584,31 +353,6 @@ def _check_isinstance_type(context, element, search_name): return result -def global_names_dict_generator(evaluator, scope, position): - in_func = False - while scope is not None: - if not (scope.type == 'classdef' and in_func): - # Names in methods cannot be resolved within the class. - - for names_dict in scope.names_dicts(True): - yield names_dict, position - if hasattr(scope, 'resets_positions'): - # TODO This is so ugly, seriously. However there's - # currently no good way of influencing - # global_names_dict_generator when it comes to certain - # objects. - position = None - if scope.type == 'funcdef': - # The position should be reset if the current scope is a function. - in_func = True - position = None - scope = evaluator.wrap(scope.get_parent_scope()) - - # Add builtins to the global scope. - for names_dict in evaluator.BUILTINS.names_dicts(True): - yield names_dict, None - - def check_tuple_assignments(evaluator, types, name): """ Checks if tuples are assigned. @@ -627,19 +371,3 @@ def check_tuple_assignments(evaluator, types, name): return set() types = lazy_context.infer() return types - - -def filter_private_variable(scope, origin_node): - """Check if a variable is defined inside the same class or outside.""" - instance = scope.get_parent_scope() - coming_from = origin_node - while coming_from is not None \ - and not isinstance(coming_from, (tree.Class, compiled.CompiledObject)): - coming_from = coming_from.get_parent_scope() - - # CompiledObjects don't have double underscore attributes, but Jedi abuses - # those for fakes (builtins.pym -> list). - if isinstance(instance, compiled.CompiledObject): - return instance != coming_from - else: - return isinstance(instance, er.Instance) and instance.base.base != coming_from diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index 7ec43628..ce94a29c 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -42,19 +42,6 @@ def deep_ast_copy(obj, parent=None, new_elements=None): new_children.append(new_child) new_obj.children = new_children - # Copy the names_dict (if there is one). - try: - names_dict = obj.names_dict - except AttributeError: - pass - else: - try: - new_obj.names_dict = new_names_dict = {} - except AttributeError: # Impossible to set CompFor.names_dict - pass - else: - for string, names in names_dict.items(): - new_names_dict[string] = [new_elements[n] for n in names] return new_obj if isinstance(obj, tree.BaseNode):