예제 #1
0
파일: api.py 프로젝트: rayleyva/jedi
    def usages(self, additional_module_paths=()):
        """
        Return :class:`api_classes.Usage` 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:`api_classes.Usage`
        """
        temp, settings.dynamic_flow_information = \
            settings.dynamic_flow_information, False
        user_stmt = self._user_stmt()
        definitions, search_name = self._goto(add_import_name=True)
        if isinstance(user_stmt, pr.Statement):
            c = user_stmt.get_commands()[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_set_vars()
                    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 = dynamic.usages_add_import_modules(
                definitions, search_name)

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

        for d in set(definitions):
            if isinstance(d, pr.Module):
                names.append(api_classes.Usage(d, d))
            elif isinstance(d, er.Instance):
                # Instances can be ignored, because they are being created by
                # ``__getattr__``.
                pass
            else:
                names.append(api_classes.Usage(d.names[-1], d))

        settings.dynamic_flow_information = temp
        return self._sorted_defs(set(names))
예제 #2
0
    def usages(self, additional_module_paths=()):
        """
        Return :class:`api_classes.Usage` 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:`api_classes.Usage`
        """
        user_stmt = self._parser.user_stmt
        definitions, search_name = self._goto(add_import_name=True)
        if isinstance(user_stmt, pr.Statement) \
                    and self.pos < user_stmt.get_commands()[0].start_pos:
            # the search_name might be before `=`
            definitions = [
                v for v in user_stmt.set_vars
                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 = dynamic.usages_add_import_modules(
                definitions, search_name)

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

        for d in set(definitions):
            if isinstance(d, pr.Module):
                names.append(api_classes.Usage(d, d))
            else:
                names.append(api_classes.Usage(d.names[-1], d))

        return self._sorted_defs(set(names))
예제 #3
0
    def check_call(call):
        result = []
        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 name == search_name:
                follow.append(call_path[:i + 1])

        for f in follow:
            follow_res, search = evaluate.goto(call.parent, f)
            follow_res = usages_add_import_modules(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):
                scope = call.parent
                result.append(api_classes.Usage(search, scope))

        return result
예제 #4
0
def usages(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(call):
        result = []
        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 name == search_name:
                follow.append(call_path[:i + 1])

        for f in follow:
            follow_res, search = evaluate.goto(call.parent, f)
            follow_res = usages_add_import_modules(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):
                scope = call.parent
                result.append(api_classes.Usage(search, scope))

        return result

    if not definitions:
        return set()

    compare_definitions = compare_array(definitions)
    mods |= set([d.get_parent_until() for d in definitions])
    names = []
    for m in get_directory_modules_for_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 name_part == search_name:
                            imps.append((count, name_part))

                for used_count, name_part in imps:
                    i = imports.ImportPath(stmt,
                                           kill_count=count - used_count,
                                           direct_resolve=True)
                    f = i.follow(is_goto=True)
                    if set(f) & set(definitions):
                        names.append(api_classes.Usage(name_part, stmt))
            else:
                for call in _scan_statement(stmt,
                                            search_name,
                                            assignment_details=True):
                    names += check_call(call)
    return names