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')
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')
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')
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)