Beispiel #1
0
    def _prepare_goto(self, goto_path, is_completion=False):
        """
        Base for completions/goto. Basically it returns the resolved scopes
        under cursor.
        """
        debug.dbg('start: %s in %s', goto_path, self._parser.user_scope())

        user_stmt = self._parser.user_stmt_with_whitespace()
        if not user_stmt and len(goto_path.split('\n')) > 1:
            # If the user_stmt is not defined and the goto_path is multi line,
            # something's strange. Most probably the backwards tokenizer
            # matched to much.
            return []

        if isinstance(user_stmt, pr.Import):
            i, _ = helpers.get_on_import_stmt(self._evaluator, self._user_context,
                                              user_stmt, is_completion)
            if i is None:
                return []
            scopes = [i]
        else:
            # just parse one statement, take it and evaluate it
            eval_stmt = self._get_under_cursor_stmt(goto_path)
            if eval_stmt is None:
                return []

            module = self._parser.module()
            names, level, _, _ = helpers.check_error_statements(module, self._pos)
            if names:
                i = imports.get_importer(self._evaluator, names, module, level)
                return i.follow(self._evaluator)

            scopes = self._evaluator.eval_element(eval_stmt)

        return scopes
Beispiel #2
0
    def _prepare_goto(self, goto_path, is_completion=False):
        """
        Base for completions/goto. Basically it returns the resolved scopes
        under cursor.
        """
        debug.dbg('start: %s in %s', goto_path, self._parser.user_scope())

        user_stmt = self._parser.user_stmt_with_whitespace()
        if not user_stmt and len(goto_path.split('\n')) > 1:
            # If the user_stmt is not defined and the goto_path is multi line,
            # something's strange. Most probably the backwards tokenizer
            # matched to much.
            return []

        if isinstance(user_stmt, pr.Import):
            scopes = [helpers.get_on_import_stmt(self._evaluator, self._user_context,
                                                 user_stmt, is_completion)[0]]
        else:
            # just parse one statement, take it and evaluate it
            eval_stmt = self._get_under_cursor_stmt(goto_path)

            if not is_completion:
                # goto_definition returns definitions of its statements if the
                # cursor is on the assignee. By changing the start_pos of our
                # "pseud" statement, the Jedi evaluator can find the assignees.
                if user_stmt is not None:
                    eval_stmt.start_pos = user_stmt.end_pos
            scopes = self._evaluator.eval_statement(eval_stmt)
        return scopes
Beispiel #3
0
    def _goto(self, add_import_name=False):
        """
        Used for goto_assignments and usages.

        :param add_import_name: Add the the name (if import) to the result.
        """
        def follow_inexistent_imports(defs):
            """ Imports can be generated, e.g. following
            `multiprocessing.dummy` generates an import dummy in the
            multiprocessing module. The Import doesn't exist -> follow.
            """
            definitions = set(defs)
            for d in defs:
                if isinstance(d.parent, pr.Import) \
                        and d.start_pos == (0, 0):
                    i = imports.ImportPath(self._evaluator, d.parent).follow(is_goto=True)
                    definitions.remove(d)
                    definitions |= follow_inexistent_imports(i)
            return definitions

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        user_stmt = self._parser.user_stmt()
        if next(context) in ('class', 'def'):
            user_scope = self._parser.user_scope()
            definitions = set([user_scope.name])
            search_name = unicode(user_scope.name)
        elif isinstance(user_stmt, pr.Import):
            s, name_part = helpers.get_on_import_stmt(self._evaluator,
                                                   self._user_context, user_stmt)
            try:
                definitions = [s.follow(is_goto=True)[0]]
            except IndexError:
                definitions = []
            search_name = unicode(name_part)

            if add_import_name:
                import_name = user_stmt.get_defined_names()
                # imports have only one name
                if not user_stmt.star \
                        and name_part == import_name[0].names[-1]:
                    definitions.append(import_name[0])
        else:
            stmt = self._get_under_cursor_stmt(goto_path)
            defs, search_name = self._evaluator.goto(stmt)
            definitions = follow_inexistent_imports(defs)
            if isinstance(user_stmt, pr.Statement):
                c = user_stmt.expression_list()
                if c and not isinstance(c[0], (str, unicode)) \
                        and c[0].start_pos > self._pos \
                        and not re.search(r'\.\w+$', goto_path):
                    # The cursor must be after the start, otherwise the
                    # statement is just an assignee.
                    definitions = [user_stmt]
        return definitions, search_name
Beispiel #4
0
    def _prepare_goto(self, goto_path, is_completion=False):
        """
        Base for completions/goto. Basically it returns the resolved scopes
        under cursor.
        """
        debug.dbg('start: %s in %s', goto_path, self._parser.user_scope())

        user_stmt = self._parser.user_stmt_with_whitespace()
        if not user_stmt and len(goto_path.split('\n')) > 1:
            # If the user_stmt is not defined and the goto_path is multi line,
            # something's strange. Most probably the backwards tokenizer
            # matched to much.
            return []

        if isinstance(user_stmt, pr.Import):
            scopes = [helpers.get_on_import_stmt(self._evaluator, self._user_context,
                                                 user_stmt, is_completion)[0]]
        else:
            # just parse one statement, take it and evaluate it
            stmt = self._get_under_cursor_stmt(goto_path)
            scopes = self._evaluator.eval_statement(stmt)
        return scopes
Beispiel #5
0
    def _goto(self, add_import_name=False):
        """
        Used for goto_assignments and usages.

        :param add_import_name: Add the the name (if import) to the result.
        """
        def follow_inexistent_imports(defs):
            """ Imports can be generated, e.g. following
            `multiprocessing.dummy` generates an import dummy in the
            multiprocessing module. The Import doesn't exist -> follow.
            """
            definitions = set(defs)
            for d in defs:
                if isinstance(d.parent, tree.Import) \
                        and d.start_pos == (0, 0):
                    i = imports.ImportWrapper(self._evaluator, d.parent).follow(is_goto=True)
                    definitions.remove(d)
                    definitions |= follow_inexistent_imports(i)
            return definitions

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        user_stmt = self._parser.user_stmt()
        user_scope = self._parser.user_scope()

        stmt = self._get_under_cursor_stmt(goto_path)
        if stmt is None:
            return []

        if user_scope is None:
            last_name = None
        else:
            # Try to use the parser if possible.
            last_name = user_scope.name_for_position(self._pos)

        if last_name is None:
            last_name = stmt
            while not isinstance(last_name, tree.Name):
                try:
                    last_name = last_name.children[-1]
                except AttributeError:
                    # Doesn't have a name in it.
                    return []

        if next(context) in ('class', 'def'):
            # The cursor is on a class/function name.
            user_scope = self._parser.user_scope()
            definitions = set([user_scope.name])
        elif isinstance(user_stmt, tree.Import):
            s, name = helpers.get_on_import_stmt(self._evaluator,
                                                 self._user_context, user_stmt)

            definitions = self._evaluator.goto(name)
        else:
            # The Evaluator.goto function checks for definitions, but since we
            # use a reverse tokenizer, we have new name_part objects, so we
            # have to check the user_stmt here for positions.
            if isinstance(user_stmt, tree.ExprStmt) \
                    and isinstance(last_name.parent, tree.ExprStmt):
                for name in user_stmt.get_defined_names():
                    if name.start_pos <= self._pos <= name.end_pos:
                        return [name]

            defs = self._evaluator.goto(last_name)
            definitions = follow_inexistent_imports(defs)
        return definitions
Beispiel #6
0
    def _goto(self, add_import_name=False):
        """
        Used for goto_assignments and usages.

        :param add_import_name: Add the the name (if import) to the result.
        """
        def follow_inexistent_imports(defs):
            """ Imports can be generated, e.g. following
            `multiprocessing.dummy` generates an import dummy in the
            multiprocessing module. The Import doesn't exist -> follow.
            """
            definitions = set(defs)
            for d in defs:
                if isinstance(d.parent, pr.Import) \
                        and d.start_pos == (0, 0):
                    i = imports.ImportWrapper(self._evaluator, d.parent).follow(is_goto=True)
                    definitions.remove(d)
                    definitions |= follow_inexistent_imports(i)
            return definitions

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        user_stmt = self._parser.user_stmt()
        if next(context) in ('class', 'def'):
            user_scope = self._parser.user_scope()
            definitions = set([user_scope.name])
            search_name = unicode(user_scope.name)
        elif isinstance(user_stmt, pr.Import):
            s, name_part = helpers.get_on_import_stmt(self._evaluator,
                                                      self._user_context, user_stmt)
            try:
                definitions = [s.follow(is_goto=True)[0]]
            except IndexError:
                definitions = []
            search_name = unicode(name_part)

            if add_import_name:
                import_name = user_stmt.get_defined_names()
                # imports have only one name
                if not user_stmt.star \
                        and unicode(name_part) == unicode(import_name[0].names[-1]):
                    definitions.append(import_name[0])
        else:
            stmt = self._get_under_cursor_stmt(goto_path)

            def test_lhs():
                """
                Special rule for goto, left hand side of the statement returns
                itself, if the name is ``foo``, but not ``foo.bar``.
                """
                if isinstance(user_stmt, pr.Statement):
                    for name in user_stmt.get_defined_names():
                        if name.start_pos <= self._pos <= name.end_pos \
                                and len(name.names) == 1:
                            return name, unicode(name.names[-1])
                return None, None

            lhs, search_name = test_lhs()
            if lhs is None:
                expression_list = stmt.expression_list()
                if len(expression_list) == 0:
                    return [], ''
                # Only the first command is important, the rest should basically not
                # happen except in broken code (e.g. docstrings that aren't code).
                call = expression_list[0]
                if isinstance(call, pr.Call):
                    call_path = list(call.generate_call_path())
                else:
                    call_path = [call]

                defs, search_name_part = self._evaluator.goto(stmt, call_path)
                search_name = unicode(search_name_part)
                definitions = follow_inexistent_imports(defs)
            else:
                definitions = [lhs]
            if isinstance(user_stmt, pr.Statement):
                c = user_stmt.expression_list()
                if c and not isinstance(c[0], (str, unicode)) \
                        and c[0].start_pos > self._pos \
                        and not re.search(r'\.\w+$', goto_path):
                    # The cursor must be after the start, otherwise the
                    # statement is just an assignee.
                    definitions = [user_stmt]
        return definitions, search_name
Beispiel #7
0
    def _goto(self, add_import_name=False):
        """
        Used for goto_assignments and usages.

        :param add_import_name: Add the the name (if import) to the result.
        """
        def follow_inexistent_imports(defs):
            """ Imports can be generated, e.g. following
            `multiprocessing.dummy` generates an import dummy in the
            multiprocessing module. The Import doesn't exist -> follow.
            """
            definitions = set(defs)
            for d in defs:
                if isinstance(d.parent, pr.Import) \
                        and d.start_pos == (0, 0):
                    i = imports.ImportWrapper(self._evaluator, d.parent).follow(is_goto=True)
                    definitions.remove(d)
                    definitions |= follow_inexistent_imports(i)
            return definitions

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        user_stmt = self._parser.user_stmt()

        stmt = self._get_under_cursor_stmt(goto_path)
        expression_list = stmt.expression_list()
        if len(expression_list) == 0:
            return []
        # The reverse tokenizer only generates parses call.
        assert len(expression_list) == 1
        call = expression_list[0]
        if isinstance(call, pr.Call):
            call_path = list(call.generate_call_path())
        else:
            # goto_assignments on Operator returns nothing.
            return []

        if next(context) in ('class', 'def'):
            # The cursor is on a class/function name.
            user_scope = self._parser.user_scope()
            definitions = set([user_scope.name])
        elif isinstance(user_stmt, pr.Import):
            s, name_part = helpers.get_on_import_stmt(self._evaluator,
                                                      self._user_context, user_stmt)
            try:
                definitions = [s.follow(is_goto=True)[0]]
            except IndexError:
                definitions = []

            if add_import_name:
                import_name = user_stmt.get_defined_names()
                # imports have only one name
                np = import_name[0]
                if not user_stmt.star and unicode(name_part) == unicode(np):
                    definitions.append(np)
        else:
            # The Evaluator.goto function checks for definitions, but since we
            # use a reverse tokenizer, we have new name_part objects, so we
            # have to check the user_stmt here for positions.
            if isinstance(user_stmt, pr.ExprStmt):
                for name in user_stmt.get_defined_names():
                    if name.start_pos <= self._pos <= name.end_pos \
                            and (not isinstance(name.parent, pr.Call)
                                 or name.parent.next is None):
                        return [name]

            defs = self._evaluator.goto(stmt, call_path)
            definitions = follow_inexistent_imports(defs)
        return definitions