def goto(self): """ Return the first definition found by goto. 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:`api_classes.Definition` """ d = [api_classes.Definition(d) for d in set(self._goto()[0])] return sorted(d, key=lambda x: (x.module_path, x.start_pos))
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:`api_classes.Definition` """ d = [api_classes.Definition(d) for d in set(self._goto()[0])] return self._sorted_defs(d)
def goto(self): """ Returns the first definition found by goto. This means: It 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. :return: list of Definition objects, which are basically scopes. """ d = [api_classes.Definition(d) for d in set(self._goto()[0])] return sorted(d, key=lambda x: (x.module_path, x.start_pos))
def get_definition(self): """ Returns the definitions of a the path under the cursor. This is not a goto function! This follows complicated paths and returns the end, not the first definition. The big difference of goto and get_definition is that goto 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. :return: list of Definition objects, which are basically scopes. :rtype: list """ 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() if next(context) in ('class', 'def'): scopes = set([self.module.parser.user_scope]) elif not goto_path: op = self.module.get_operator_under_cursor() scopes = set([keywords.get_operator(op, self.pos)] if op else []) else: scopes = set(self._prepare_goto(goto_path)) scopes = resolve_import_paths(scopes) # add keywords scopes |= keywords.get_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 sorted(d, key=lambda x: (x.module_path, x.start_pos))
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)