示例#1
0
文件: __init__.py 项目: aroba12/jedi
    def usages(self, additional_module_paths=()):
        """
        Return :class:`classes.Definition` objects, which contain all
        names that point to the definition of the name under the cursor. This
        is very useful for refactoring (renaming), or to show all usages of a
        variable.

        .. todo:: Implement additional_module_paths

        :rtype: list of :class:`classes.Definition`
        """
        temp, settings.dynamic_flow_information = \
            settings.dynamic_flow_information, False
        try:
            user_stmt = self._parser.user_stmt()
            definitions = self._goto(add_import_name=True)
            if not definitions:
                # Without a definition for a name we cannot find references.
                return []

            if not isinstance(user_stmt, pr.Import):
                # import case is looked at with add_import_name option
                definitions = usages.usages_add_import_modules(
                    self._evaluator, definitions)

            module = set([d.get_parent_until() for d in definitions])
            module.add(self._parser.module())
            names = usages.usages(self._evaluator, definitions, module)

            for d in set(definitions):
                names.append(classes.Definition(self._evaluator, d))
        finally:
            settings.dynamic_flow_information = temp

        return helpers.sorted_definitions(set(names))
示例#2
0
def names(source=None, path=None, encoding='utf-8', all_scopes=False,
          definitions=True, references=False):
    """
    Returns a list of `Definition` objects, containing name parts.
    This means you can call ``Definition.goto_assignments()`` and get the
    reference of a name.
    The parameters are the same as in :py:class:`Script`, except or the
    following ones:

    :param all_scopes: If True lists the names of all scopes instead of only
        the module namespace.
    :param definitions: If True lists the names that have been defined by a
        class, function or a statement (``a = b`` returns ``a``).
    :param references: If True lists all the names that are not listed by
        ``definitions=True``. E.g. ``a = b`` returns ``b``.
    """
    def def_ref_filter(_def):
        is_def = _def.is_definition()
        return definitions and is_def or references and not is_def

    # Set line/column to a random position, because they don't matter.
    script = Script(source, line=1, column=0, path=path, encoding=encoding)
    defs = [classes.Definition(script._evaluator, name_part)
            for name_part in get_module_names(script._get_module(), all_scopes)]
    return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column))
示例#3
0
文件: __init__.py 项目: orn688/jedi
    def goto_assignments(self, follow_imports=False):
        """
        Return the first definition found, while optionally following imports.
        Multiple objects may be returned, because Python itself is a
        dynamic language, which means depending on an option you can have two
        different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def filter_follow_imports(names, check):
            for name in names:
                if check(name):
                    for result in filter_follow_imports(name.goto(), check):
                        yield result
                else:
                    yield name

        tree_name = self._module_node.get_name_of_position(self._pos)
        if tree_name is None:
            return []
        context = self._evaluator.create_context(self._get_module(), tree_name)
        names = list(self._evaluator.goto(context, tree_name))

        if follow_imports:
            def check(name):
                return name.is_import()
        else:
            def check(name):
                return isinstance(name, imports.SubModuleName)

        names = filter_follow_imports(names, check)

        defs = [classes.Definition(self._evaluator, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
示例#4
0
文件: __init__.py 项目: wimmerX/jedi
    def get_context(self, line=None, column=None):
        pos = (line, column)
        leaf = self._module_node.get_leaf_for_position(pos,
                                                       include_prefixes=True)
        if leaf.start_pos > pos or leaf.type == 'endmarker':
            previous_leaf = leaf.get_previous_leaf()
            if previous_leaf is not None:
                leaf = previous_leaf

        module_context = self._get_module_context()

        n = tree.search_ancestor(leaf, 'funcdef', 'classdef')
        if n is not None and n.start_pos < pos <= n.children[-1].start_pos:
            # This is a bit of a special case. The context of a function/class
            # name/param/keyword is always it's parent context, not the
            # function itself. Catch all the cases here where we are before the
            # suite object, but still in the function.
            context = module_context.create_value(n).as_context()
        else:
            context = module_context.create_context(leaf)

        while context.name is None:
            context = context.parent_context  # comprehensions

        definition = classes.Definition(self._inference_state, context.name)
        while definition.type != 'module':
            name = definition._name  # TODO private access
            tree_name = name.tree_name
            if tree_name is not None:  # Happens with lambdas.
                scope = tree_name.get_definition()
                if scope.start_pos[1] < column:
                    break
            definition = definition.parent()
        return definition
示例#5
0
    def goto_definitions(self):
        """
        Return the definitions of a the path under the cursor.  goto function!
        This follows complicated paths and returns the end, not the first
        definition. The big difference between :meth:`goto_assignments` and
        :meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
        follow imports and statements. Multiple objects may be returned,
        because Python itself is a dynamic language, which means depending on
        an option you can have two different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        leaf = self._get_module().name_for_position(self._pos)
        if leaf is None:
            leaf = self._get_module().get_leaf_for_position(self._pos)
            if leaf is None:
                return []
        definitions = helpers.evaluate_goto_definition(self._evaluator, leaf)

        names = [s.name for s in definitions]
        defs = [classes.Definition(self._evaluator, name) for name in names]
        # The additional set here allows the definitions to become unique in an
        # API sense. In the internals we want to separate more things than in
        # the API.
        return helpers.sorted_definitions(set(defs))
    def goto_assignments(self, follow_imports=False):
        """
        Return the first definition found, while optionally following imports.
        Multiple objects may be returned, because Python itself is a
        dynamic language, which means depending on an option you can have two
        different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def filter_follow_imports(names, check):
            for name in names:
                if check(name):
                    for result in filter_follow_imports(name.goto(), check):
                        yield result
                else:
                    yield name

        names = self._goto()
        if follow_imports:

            def check(name):
                if isinstance(name, er.ModuleName):
                    return False
                return name.api_type == 'module'
        else:

            def check(name):
                return isinstance(name, imports.SubModuleName)

        names = filter_follow_imports(names, check)

        defs = [classes.Definition(self._evaluator, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
示例#7
0
def test_keyword_full_name_should_be_none():
    """issue #94"""
    # Using `from jedi.keywords import Keyword` here does NOT work
    # in Python 3.  This is due to the import hack jedi using.
    Keyword = classes.keywords.Keyword
    d = classes.Definition(Evaluator(), Keyword('(', (0, 0)))
    assert d.full_name is None
示例#8
0
    def goto_assignments(self, follow_imports=False):
        """
        Return the first definition found, while optionally following imports.
        Multiple objects may be returned, because Python itself is a
        dynamic language, which means depending on an option you can have two
        different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def filter_follow_imports(names):
            for name in names:
                definition = name.get_definition()
                if definition.type in ('import_name', 'import_from'):
                    imp = imports.ImportWrapper(self._evaluator, name)
                    for name in filter_follow_imports(imp.follow(is_goto=True)):
                        yield name
                else:
                    yield name

        names = self._goto()
        if follow_imports:
            names = filter_follow_imports(names)

        defs = [classes.Definition(self._evaluator, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
    def _goto(self, line, column, follow_imports=False, follow_builtin_imports=False,
              only_stubs=False, prefer_stubs=False):
        tree_name = self._module_node.get_name_of_position((line, column))
        if tree_name is None:
            # Without a name we really just want to jump to the result e.g.
            # executed by `foo()`, if we the cursor is after `)`.
            return self.infer(line, column, only_stubs=only_stubs, prefer_stubs=prefer_stubs)
        name = self._get_module_context().create_name(tree_name)

        # Make it possible to goto the super class function/attribute
        # definitions, when they are overwritten.
        names = []
        if name.tree_name.is_definition() and name.parent_context.is_class():
            class_node = name.parent_context.tree_node
            class_value = self._get_module_context().create_value(class_node)
            mro = class_value.py__mro__()
            next(mro)  # Ignore the first entry, because it's the class itself.
            for cls in mro:
                names = cls.goto(tree_name.value)
                if names:
                    break

        if not names:
            names = list(name.goto())

        if follow_imports:
            names = helpers.filter_follow_imports(names)
        names = convert_names(
            names,
            only_stubs=only_stubs,
            prefer_stubs=prefer_stubs,
        )

        defs = [classes.Definition(self._inference_state, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
示例#10
0
文件: usages.py 项目: alx901/dotfiles
def usages(evaluator, definition_names, mods):
    """
    :param definitions: list of Name
    """
    def compare_array(definitions):
        """ `definitions` are being compared by module/start_pos, because
        sometimes the id's of the objects change (e.g. executions).
        """
        result = []
        for d in definitions:
            module = d.get_parent_until()
            result.append((module, d.start_pos))
        return result

    search_name = unicode(list(definition_names)[0])
    compare_definitions = compare_array(definition_names)
    mods |= set([d.get_parent_until() for d in definition_names])
    definitions = []
    for m in imports.get_modules_containing_name(evaluator, mods, search_name):
        try:
            check_names = m.used_names[search_name]
        except KeyError:
            continue
        for name in check_names:

            result = evaluator.goto(name)
            if [c for c in compare_array(result) if c in compare_definitions]:
                definitions.append(classes.Definition(evaluator, name))
                # Previous definitions might be imports, so include them
                # (because goto might return that import name).
                compare_definitions += compare_array([name])
    return definitions
示例#11
0
 def _usages_in_module(include_builtins=True):
     tree_name = self._module_node.get_name_of_position(self._pos)
     if tree_name is None:
         # Must be syntax
         return []
     names = usages.usages_in_module(self._get_module(), tree_name)
     definitions = [classes.Definition(self._evaluator, n) for n in names]
     if not include_builtins:
         definitions = [d for d in definitions if not d.in_builtin_module()]
     return helpers.sorted_definitions(definitions)
示例#12
0
    def usages(self, additional_module_paths=()):
        """
        Return :class:`classes.Definition` objects, which contain all
        names that point to the definition of the name under the cursor. This
        is very useful for refactoring (renaming), or to show all usages of a
        variable.

        .. todo:: Implement additional_module_paths

        :rtype: list of :class:`classes.Definition`
        """
        temp, settings.dynamic_flow_information = \
            settings.dynamic_flow_information, False
        user_stmt = self._parser.user_stmt()
        definitions, search_name = self._goto(add_import_name=True)
        if isinstance(user_stmt, pr.Statement):
            c = user_stmt.expression_list()[0]
            if not isinstance(c, unicode) and self._pos < c.start_pos:
                # the search_name might be before `=`
                definitions = [
                    v for v in user_stmt.get_defined_names()
                    if unicode(v.names[-1]) == search_name
                ]
        if not isinstance(user_stmt, pr.Import):
            # import case is looked at with add_import_name option
            definitions = usages.usages_add_import_modules(
                self._evaluator, definitions, search_name)

        module = set([d.get_parent_until() for d in definitions])
        module.add(self._parser.module())
        names = usages.usages(self._evaluator, definitions, search_name,
                              module)

        for d in set(definitions):
            try:
                name_part = d.names[-1]
            except AttributeError:
                names.append(classes.Definition(self._evaluator, d))
            else:
                names.append(classes.Definition(self._evaluator, name_part))

        settings.dynamic_flow_information = temp
        return helpers.sorted_definitions(set(names))
示例#13
0
    def goto_assignments(self):
        """
        Return the first definition found. Imports and statements aren't
        followed. Multiple objects may be returned, because Python itself is a
        dynamic language, which means depending on an option you can have two
        different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        results = self._goto()
        d = [classes.Definition(self._evaluator, d) for d in set(results)]
        return helpers.sorted_definitions(d)
示例#14
0
        def _references(include_builtins=True):
            tree_name = self._module_node.get_name_of_position((line, column))
            if tree_name is None:
                # Must be syntax
                return []

            names = find_references(self._get_module_context(), tree_name)

            definitions = [classes.Definition(self._inference_state, n) for n in names]
            if not include_builtins:
                definitions = [d for d in definitions if not d.in_builtin_module()]
            return helpers.sorted_definitions(definitions)
示例#15
0
    def goto_definitions(self):
        """
        Return the definitions of a the path under the cursor.  goto function!
        This follows complicated paths and returns the end, not the first
        definition. The big difference between :meth:`goto_assignments` and
        :meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
        follow imports and statements. Multiple objects may be returned,
        because Python itself is a dynamic language, which means depending on
        an option you can have two different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def resolve_import_paths(scopes):
            for s in scopes.copy():
                if isinstance(s, imports.ImportPath):
                    scopes.remove(s)
                    scopes.update(resolve_import_paths(set(s.follow())))
            return scopes

        user_stmt = self._parser.user_stmt_with_whitespace()
        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        definitions = set()
        if next(context) in ('class', 'def'):
            definitions = set([self._parser.user_scope()])
        else:
            # Fetch definition of callee, if there's no path otherwise.
            if not goto_path:
                (call,
                 _) = helpers.func_call_and_param_index(user_stmt, self._pos)
                if call is not None:
                    while call.next is not None:
                        call = call.next
                    # reset cursor position:
                    (row, col) = call.name.end_pos
                    pos = (row, max(col - 1, 0))
                    self._user_context = UserContext(self.source, pos)
                    # then try to find the path again
                    goto_path = self._user_context.get_path_under_cursor()

        if not definitions:
            if goto_path:
                definitions = set(self._prepare_goto(goto_path))

        definitions = resolve_import_paths(definitions)
        d = set([
            classes.Definition(self._evaluator, s) for s in definitions
            if s is not imports.ImportPath.GlobalNamespace
        ])
        return helpers.sorted_definitions(d)
示例#16
0
文件: __init__.py 项目: wimmerX/jedi
    def _names(self, all_scopes=False, definitions=True, references=False):
        def def_ref_filter(_def):
            is_def = _def._name.tree_name.is_definition()
            return definitions and is_def or references and not is_def

        # Set line/column to a random position, because they don't matter.
        module_context = self._get_module_context()
        defs = [
            classes.Definition(self._inference_state,
                               module_context.create_name(name))
            for name in get_module_names(self._module_node, all_scopes)
        ]
        return sorted(filter(def_ref_filter, defs),
                      key=lambda x: (x.line, x.column))
示例#17
0
def usages(evaluator, definition_names, mods):
    """
    :param definitions: list of Name
    """
    def resolve_names(definition_names):
        for name in definition_names:
            if name.api_type == 'module':
                found = False
                for context in name.infer():
                    found = True
                    yield context.name
                if not found:
                    yield name
            else:
                yield name

    def compare_array(definition_names):
        """ `definitions` are being compared by module/start_pos, because
        sometimes the id's of the objects change (e.g. executions).
        """
        return [(name.get_root_context(), name.start_pos)
                for name in resolve_names(definition_names)]

    search_name = list(definition_names)[0].string_name
    compare_definitions = compare_array(definition_names)
    mods = mods | set([d.get_root_context() for d in definition_names])
    definition_names = set(resolve_names(definition_names))
    for m in imports.get_modules_containing_name(evaluator, mods, search_name):
        if isinstance(m, ModuleContext):
            for name_node in m.tree_node.used_names.get(search_name, []):
                context = evaluator.create_context(m, name_node)
                try:
                    result = evaluator.goto(context, name_node)
                except (NotImplementedError, RecursionError) as err:
                    logger.error(err)
                    continue
                if any(
                        compare_contexts(c1, c2)
                        for c1 in compare_array(result)
                        for c2 in compare_definitions):
                    name = TreeNameDefinition(context, name_node)
                    definition_names.add(name)
                    # Previous definitions might be imports, so include them
                    # (because goto might return that import name).
                    compare_definitions += compare_array([name])
        else:
            # compiled objects
            definition_names.add(m.name)

    return [classes.Definition(evaluator, n) for n in definition_names]
示例#18
0
    def goto_definitions(self):
        """
        Return the definitions of a the path under the cursor.  goto function!
        This follows complicated paths and returns the end, not the first
        definition. The big difference between :meth:`goto_assignments` and
        :meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
        follow imports and statements. Multiple objects may be returned,
        because Python itself is a dynamic language, which means depending on
        an option you can have two different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def resolve_import_paths(scopes):
            for s in scopes.copy():
                if isinstance(s, imports.ImportWrapper):
                    scopes.remove(s)
                    scopes.update(resolve_import_paths(set(s.follow())))
            return scopes

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        definitions = set()
        if next(context) in ('class', 'def'):
            definitions = set(
                [self._evaluator.wrap(self._parser.user_scope())])
        else:
            # Fetch definition of callee, if there's no path otherwise.
            if not goto_path:
                definitions = set(signature._definition
                                  for signature in self.call_signatures())

        if re.match('\w[\w\d_]*$', goto_path) and not definitions:
            user_stmt = self._parser.user_stmt()
            if user_stmt is not None and user_stmt.type == 'expr_stmt':
                for name in user_stmt.get_defined_names():
                    if name.start_pos <= self._pos <= name.end_pos:
                        # TODO scaning for a name and then using it should be
                        # the default.
                        definitions = set(
                            self._evaluator.goto_definition(name))

        if not definitions and goto_path:
            definitions = set(self._prepare_goto(goto_path))

        definitions = resolve_import_paths(definitions)
        names = [s.name for s in definitions]
        defs = [classes.Definition(self._evaluator, name) for name in names]
        return helpers.sorted_definitions(set(defs))
示例#19
0
    def _goto(self,
              line,
              column,
              follow_imports=False,
              follow_builtin_imports=False,
              only_stubs=False,
              prefer_stubs=False):
        def filter_follow_imports(names):
            for name in names:
                if name.is_import():
                    new_names = list(filter_follow_imports(name.goto()))
                    found_builtin = False
                    if follow_builtin_imports:
                        for new_name in new_names:
                            if new_name.start_pos is None:
                                found_builtin = True

                    if found_builtin:
                        yield name
                    else:
                        for new_name in new_names:
                            yield new_name
                else:
                    yield name

        tree_name = self._module_node.get_name_of_position((line, column))
        if tree_name is None:
            # Without a name we really just want to jump to the result e.g.
            # executed by `foo()`, if we the cursor is after `)`.
            return self.infer(line,
                              column,
                              only_stubs=only_stubs,
                              prefer_stubs=prefer_stubs)
        name = self._get_module_context().create_name(tree_name)
        names = list(name.goto())

        if follow_imports:
            names = filter_follow_imports(names)
        names = convert_names(
            names,
            only_stubs=only_stubs,
            prefer_stubs=prefer_stubs,
        )

        defs = [
            classes.Definition(self._inference_state, d) for d in set(names)
        ]
        return helpers.sorted_definitions(defs)
示例#20
0
文件: __init__.py 项目: kavinvin/jedi
    def goto_assignments(self,
                         follow_imports=False,
                         follow_builtin_imports=False):
        """
        Return the first definition found, while optionally following imports.
        Multiple objects may be returned, because Python itself is a
        dynamic language, which means depending on an option you can have two
        different versions of a function.

        :param follow_imports: The goto call will follow imports.
        :param follow_builtin_imports: If follow_imports is True will decide if
            it follow builtin imports.
        :rtype: list of :class:`classes.Definition`
        """
        def filter_follow_imports(names, check):
            for name in names:
                if check(name):
                    new_names = list(filter_follow_imports(name.goto(), check))
                    found_builtin = False
                    if follow_builtin_imports:
                        for new_name in new_names:
                            if new_name.start_pos is None:
                                found_builtin = True

                    if found_builtin:
                        yield name
                    else:
                        for new_name in new_names:
                            yield new_name
                else:
                    yield name

        tree_name = self._module_node.get_name_of_position(self._pos)
        if tree_name is None:
            # Without a name we really just want to jump to the result e.g.
            # executed by `foo()`, if we the cursor is after `)`.
            return self.goto_definitions()
        context = self._evaluator.create_context(self._get_module(), tree_name)
        names = list(self._evaluator.goto(context, tree_name))

        if follow_imports:
            names = filter_follow_imports(names, lambda name: name.is_import())
        names = try_stub_to_actual_names(names, prefer_stub_to_compiled=True)

        defs = [classes.Definition(self._evaluator, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
示例#21
0
    def usages(self, additional_module_paths=()):
        """
        Return :class:`classes.Definition` objects, which contain all
        names that point to the definition of the name under the cursor. This
        is very useful for refactoring (renaming), or to show all usages of a
        variable.

        .. todo:: Implement additional_module_paths

        :rtype: list of :class:`classes.Definition`
        """
        temp, settings.dynamic_flow_information = \
            settings.dynamic_flow_information, False
        try:
            user_stmt = self._get_module().get_statement_for_position(
                self._pos)
            definitions = self._goto()
            if not definitions and isinstance(user_stmt, tree.Import):
                # For not defined imports (goto doesn't find something, we take
                # the name as a definition. This is enough, because every name
                # points to it.
                name = user_stmt.name_for_position(self._pos)
                if name is None:
                    # Must be syntax
                    return []
                definitions = [name]

            if not definitions:
                # Without a definition for a name we cannot find references.
                return []

            if not isinstance(user_stmt, tree.Import):
                # import case is looked at with add_import_name option
                definitions = usages.usages_add_import_modules(
                    self._evaluator, definitions)

            module = set([d.get_parent_until() for d in definitions])
            module.add(self._get_module())
            names = usages.usages(self._evaluator, definitions, module)

            for d in set(definitions):
                names.append(classes.Definition(self._evaluator, d))
        finally:
            settings.dynamic_flow_information = temp

        return helpers.sorted_definitions(set(names))
示例#22
0
    def _goto_assignments(self,
                          follow_imports,
                          follow_builtin_imports,
                          only_stubs=False,
                          prefer_stubs=False):
        def filter_follow_imports(names, check):
            for name in names:
                if check(name):
                    new_names = list(filter_follow_imports(name.goto(), check))
                    found_builtin = False
                    if follow_builtin_imports:
                        for new_name in new_names:
                            if new_name.start_pos is None:
                                found_builtin = True

                    if found_builtin:
                        yield name
                    else:
                        for new_name in new_names:
                            yield new_name
                else:
                    yield name

        tree_name = self._module_node.get_name_of_position(self._pos)
        if tree_name is None:
            # Without a name we really just want to jump to the result e.g.
            # executed by `foo()`, if we the cursor is after `)`.
            return self.goto_definitions(only_stubs=only_stubs,
                                         prefer_stubs=prefer_stubs)
        context = self._evaluator.create_context(self._get_module(), tree_name)
        names = list(self._evaluator.goto(context, tree_name))

        if follow_imports:
            names = filter_follow_imports(names, lambda name: name.is_import())
        names = convert_names(
            names,
            only_stubs=only_stubs,
            prefer_stubs=prefer_stubs,
        )

        defs = [classes.Definition(self._evaluator, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
示例#23
0
    def usages(self, additional_module_paths=()):
        """
        Return :class:`classes.Definition` objects, which contain all
        names that point to the definition of the name under the cursor. This
        is very useful for refactoring (renaming), or to show all usages of a
        variable.

        .. todo:: Implement additional_module_paths

        :rtype: list of :class:`classes.Definition`
        """
        tree_name = self._module_node.get_name_of_position(self._pos)
        if tree_name is None:
            # Must be syntax
            return []

        names = usages.usages(self._get_module(), tree_name)

        definitions = [classes.Definition(self._evaluator, n) for n in names]
        return helpers.sorted_definitions(definitions)
示例#24
0
    def help(self, line=None, column=None):
        """
        Works like goto and returns a list of Definition objects. Returns
        additional definitions for keywords and operators.

        The additional definitions are of ``Definition(...).type == 'keyword'``.
        These definitions do not have a lot of value apart from their docstring
        attribute, which contains the output of Python's ``help()`` function.

        :rtype: list of :class:`classes.Definition`
        """
        definitions = self.goto(line, column, follow_imports=True)
        if definitions:
            return definitions
        leaf = self._module_node.get_leaf_for_position((line, column))
        if leaf.type in ('keyword', 'operator', 'error_leaf'):
            reserved = self._grammar._pgen_grammar.reserved_syntax_strings.keys()
            if leaf.value in reserved:
                name = KeywordName(self._inference_state, leaf.value)
                return [classes.Definition(self._inference_state, name)]
        return []
示例#25
0
    def _goto_definitions(self, only_stubs=False, prefer_stubs=False):
        leaf = self._module_node.get_name_of_position(self._pos)
        if leaf is None:
            leaf = self._module_node.get_leaf_for_position(self._pos)
            if leaf is None:
                return []

        context = self._evaluator.create_context(self._get_module(), leaf)

        contexts = helpers.evaluate_goto_definition(self._evaluator, context, leaf)
        contexts = convert_contexts(
            contexts,
            only_stubs=only_stubs,
            prefer_stubs=prefer_stubs,
        )

        defs = [classes.Definition(self._evaluator, c.name) for c in contexts]
        # The additional set here allows the definitions to become unique in an
        # API sense. In the internals we want to separate more things than in
        # the API.
        return helpers.sorted_definitions(set(defs))
示例#26
0
    def _infer(self, line, column, only_stubs=False, prefer_stubs=False):
        pos = line, column
        leaf = self._module_node.get_name_of_position(pos)
        if leaf is None:
            leaf = self._module_node.get_leaf_for_position(pos)
            if leaf is None or leaf.type == 'string':
                return []

        context = self._get_module_context().create_context(leaf)

        values = helpers.infer(self._inference_state, context, leaf)
        values = convert_values(
            values,
            only_stubs=only_stubs,
            prefer_stubs=prefer_stubs,
        )

        defs = [classes.Definition(self._inference_state, c.name) for c in values]
        # The additional set here allows the definitions to become unique in an
        # API sense. In the internals we want to separate more things than in
        # the API.
        return helpers.sorted_definitions(set(defs))
示例#27
0
    def goto_assignments(self, follow_imports=False):
        """
        Return the first definition found, while optionally following imports.
        Multiple objects may be returned, because Python itself is a
        dynamic language, which means depending on an option you can have two
        different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def filter_follow_imports(names):
            for name in names:
                if isinstance(name, (imports.ImportName, TreeNameDefinition)):
                    for context in name.infer():
                        yield context.name
                else:
                    yield name

        names = self._goto()
        if follow_imports:
            names = filter_follow_imports(names)

        defs = [classes.Definition(self._evaluator, d) for d in set(names)]
        return helpers.sorted_definitions(defs)
示例#28
0
    def check_call_for_usage(call):
        stmt = call.parent
        while not isinstance(stmt.parent, pr.IsScope):
            stmt = stmt.parent
        # New definition, call cannot be a part of stmt
        if len(call.name) == 1 and call.execution is None \
                and call.name in stmt.get_defined_names():
            # Class params are not definitions (like function params). They
            # are super classes, that need to be resolved.
            if not (isinstance(stmt, pr.Param)
                    and isinstance(stmt.parent, pr.Class)):
                return

        follow = []  # There might be multiple search_name's in one call_path
        call_path = list(call.generate_call_path())
        for i, name in enumerate(call_path):
            # name is `pr.NamePart`.
            if u(name) == search_name:
                follow.append(call_path[:i + 1])

        for call_path in follow:
            follow_res, search = evaluator.goto(call.parent, call_path)
            # names can change (getattr stuff), therefore filter names that
            # don't match `search`.

            # TODO add something like that in the future - for now usages are
            # completely broken anyway.
            #follow_res = [r for r in follow_res if str(r) == search]
            #print search.start_pos,search_name.start_pos
            #print follow_res, search, search_name, [(r, r.start_pos) for r in follow_res]
            follow_res = usages_add_import_modules(evaluator, follow_res,
                                                   search)

            compare_follow_res = compare_array(follow_res)
            # compare to see if they match
            if any(r in compare_definitions for r in compare_follow_res):
                yield classes.Definition(evaluator, search)
示例#29
0
def usages(evaluator, definitions, search_name, mods):
    def compare_array(definitions):
        """ `definitions` are being compared by module/start_pos, because
        sometimes the id's of the objects change (e.g. executions).
        """
        result = []
        for d in definitions:
            module = d.get_parent_until()
            result.append((module, d.start_pos))
        return result

    def check_call_for_usage(call):
        stmt = call.parent
        while not isinstance(stmt.parent, pr.IsScope):
            stmt = stmt.parent
        # New definition, call cannot be a part of stmt
        if len(call.name) == 1 and call.execution is None \
                and call.name in stmt.get_defined_names():
            # Class params are not definitions (like function params). They
            # are super classes, that need to be resolved.
            if not (isinstance(stmt, pr.Param)
                    and isinstance(stmt.parent, pr.Class)):
                return

        follow = []  # There might be multiple search_name's in one call_path
        call_path = list(call.generate_call_path())
        for i, name in enumerate(call_path):
            # name is `pr.NamePart`.
            if u(name) == search_name:
                follow.append(call_path[:i + 1])

        for call_path in follow:
            follow_res, search = evaluator.goto(call.parent, call_path)
            # names can change (getattr stuff), therefore filter names that
            # don't match `search`.

            # TODO add something like that in the future - for now usages are
            # completely broken anyway.
            #follow_res = [r for r in follow_res if str(r) == search]
            #print search.start_pos,search_name.start_pos
            #print follow_res, search, search_name, [(r, r.start_pos) for r in follow_res]
            follow_res = usages_add_import_modules(evaluator, follow_res,
                                                   search)

            compare_follow_res = compare_array(follow_res)
            # compare to see if they match
            if any(r in compare_definitions for r in compare_follow_res):
                yield classes.Definition(evaluator, search)

    if not definitions:
        return set()

    compare_definitions = compare_array(definitions)
    mods |= set([d.get_parent_until() for d in definitions])
    names = []
    for m in imports.get_modules_containing_name(mods, search_name):
        try:
            stmts = m.used_names[search_name]
        except KeyError:
            continue
        for stmt in stmts:
            if isinstance(stmt, pr.Import):
                count = 0
                imps = []
                for i in stmt.get_all_import_names():
                    for name_part in i.names:
                        count += 1
                        if unicode(name_part) == search_name:
                            imps.append((count, name_part))

                for used_count, name_part in imps:
                    i = imports.ImportWrapper(evaluator,
                                              stmt,
                                              kill_count=count - used_count,
                                              nested_resolve=True)
                    f = i.follow(is_goto=True)
                    if set(f) & set(definitions):
                        names.append(classes.Definition(evaluator, name_part))
            else:
                for call in helpers.scan_statement_for_calls(
                        stmt, search_name, assignment_details=True):
                    names += check_call_for_usage(call)
    return names