Beispiel #1
0
    def __init__(self,
                 source,
                 line=None,
                 column=None,
                 path=None,
                 source_encoding='utf-8',
                 source_path=None):
        if source_path is not None:
            warnings.warn("Use path instead of source_path.",
                          DeprecationWarning)
            path = source_path

        lines = source.splitlines() or ['']
        if source and source[-1] == '\n':
            lines.append('')

        self._line = max(len(lines), 1) if line is None else line
        self._column = len(lines[-1]) if column is None else column

        api_classes._clear_caches()
        debug.reset_time()
        self.source = modules.source_to_unicode(source, source_encoding)
        self._pos = self._line, self._column
        self._module = modules.ModuleWithCursor(path,
                                                source=self.source,
                                                position=self._pos)
        self._source_path = path
        self.path = None if path is None else os.path.abspath(path)
        debug.speed('init')
Beispiel #2
0
 def __init__(self,
              source,
              line,
              column,
              source_path,
              source_encoding='utf-8'):
     api_classes._clear_caches()
     debug.reset_time()
     self.source = modules.source_to_unicode(source, source_encoding)
     self.pos = line, column
     self._module = modules.ModuleWithCursor(source_path,
                                             source=self.source,
                                             position=self.pos)
     self._source_path = source_path
     self.source_path = None if source_path is None \
                                 else os.path.abspath(source_path)
     debug.speed('init')
Beispiel #3
0
    def __init__(self,
                 source=None,
                 line=None,
                 column=None,
                 path=None,
                 source_encoding='utf-8',
                 source_path=None):
        if source_path is not None:
            warnings.warn("Use path instead of source_path.",
                          DeprecationWarning)
            path = source_path

        if source is None:
            with open(path) as f:
                source = f.read()

        lines = source.splitlines() or ['']
        if source and source[-1] == '\n':
            lines.append('')

        self._line = max(len(lines), 1) if line is None else line
        if not (0 < self._line <= len(lines)):
            raise ValueError('`line` parameter is not in a valid range.')

        line_len = len(lines[self._line - 1])
        self._column = line_len if column is None else column
        if not (0 <= self._column <= line_len):
            raise ValueError('`column` parameter is not in a valid range.')

        api_classes._clear_caches()
        debug.reset_time()
        self.source = modules.source_to_unicode(source, source_encoding)
        self._pos = self._line, self._column
        self._module = modules.ModuleWithCursor(path,
                                                source=self.source,
                                                position=self._pos)
        self._source_path = path
        self.path = None if path is None else os.path.abspath(path)
        debug.speed('init')
Beispiel #4
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:`api_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

        goto_path = self._module.get_path_under_cursor()

        context = self._module.get_context()
        scopes = set()
        lower_priority_operators = ('()', '(', ',')
        """Operators that could hide callee."""
        if next(context) in ('class', 'def'):
            scopes = set([self._module.parser.user_scope])
        elif not goto_path:
            op = self._module.get_operator_under_cursor()
            if op and op not in lower_priority_operators:
                scopes = set([keywords.get_operator(op, self._pos)])

        # Fetch definition of callee, if there's no path otherwise.
        if not goto_path:
            (call, _) = self._func_call_and_param_index()
            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._module = modules.ModuleWithCursor(self._source_path,
                                                        source=self.source,
                                                        position=_pos)
                # then try to find the path again
                goto_path = self._module.get_path_under_cursor()

        if not scopes:
            if goto_path:
                scopes = set(self._prepare_goto(goto_path))
            elif op in lower_priority_operators:
                scopes = set([keywords.get_operator(op, self._pos)])

        scopes = resolve_import_paths(scopes)

        # add keywords
        scopes |= keywords.keywords(string=goto_path, pos=self._pos)

        d = set([
            api_classes.Definition(s) for s in scopes
            if not isinstance(s, imports.ImportPath._GlobalNamespace)
        ])
        return self._sorted_defs(d)