diff --git a/dynamic.py b/dynamic.py index 6b8f533f..6d324107 100644 --- a/dynamic.py +++ b/dynamic.py @@ -6,6 +6,9 @@ really cryptic and not understandable. It's just a hack, that turned out to be working quite good. """ +import re +import os + import parsing import evaluate import helpers @@ -293,7 +296,7 @@ class ArrayInstance(parsing.Base): return items -def get_related_names(definitions, search_name, modules): +def related_names(definitions, search_name, modules): def check_call(call): result = [] follow = [] # There might be multiple search_name's in one call_path @@ -316,7 +319,7 @@ def get_related_names(definitions, search_name, modules): # compare to see if they match if True in [r in definitions for r in follow_res]: l = f[-1] # the NamePart object - scope = call.parent_stmt().parent() + scope = call.parent_stmt() result.append(RelatedName(l, scope)) return result @@ -329,7 +332,7 @@ def get_related_names(definitions, search_name, modules): for call in calls: for n in call.name.names: if n == search_name: - names.append(RelatedName(n, d.parent())) + names.append(RelatedName(n, d)) for op, arr in d.assignment_details: add_array(arr) if not d.assignment_details: @@ -350,17 +353,44 @@ def get_related_names(definitions, search_name, modules): return names -class RelatedName(): +class BaseOutput(object): + def __init__(self, start_pos, definition): + self.module_path = str(definition.get_parent_until().path) + self.start_pos = start_pos + self.definition = definition + + @property + def module_name(self): + path = self.module_path + sep = os.path.sep + p = re.sub(r'^.*?([\w\d]+)(%s__init__)?.py$' % sep, r'\1', path) + return p + + def in_builtin_module(self): + return not self.module_path.endswith('.py') + + @property + def line_nr(self): + return self.start_pos[0] + + @property + def column(self): + return self.start_pos[1] + + @property + def description(self): + raise NotImplementedError('Base Class') + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.description) + + +class RelatedName(BaseOutput): def __init__(self, name_part, scope): + super(RelatedName, self).__init__(name_part.start_pos, scope) self.text = str(name_part) - self.start_pos = name_part.start_pos self.end_pos = name_part.end_pos - self.scope = scope - self.module = self.scope.get_parent_until() @property def description(self): return "%s@%s,%s" % (self.text, self.start_pos[0], self.start_pos[1]) - - def __repr__(self): - return "<%s: %s>" % (self.__class__.__name__, self.description) diff --git a/functions.py b/functions.py index baf91945..d3cf145a 100644 --- a/functions.py +++ b/functions.py @@ -13,7 +13,7 @@ import keywords from _compatibility import next -__all__ = ['complete', 'goto', 'get_definition', 'get_related_names', +__all__ = ['complete', 'goto', 'get_definition', 'related_names', 'NotFoundError', 'set_debug_function'] @@ -66,31 +66,11 @@ class Completion(object): return '<%s: %s>' % (self.__class__.__name__, self.name) -class Definition(object): +class Definition(dynamic.BaseOutput): def __init__(self, definition): """ The definition of a function """ - self.definition = definition - self._def_parent = self.definition.parent() # just here to limit gc - - self.module_path = str(self.definition.get_parent_until().path) - - @property - def module_name(self): - path = self.module_path - sep = os.path.sep - p = re.sub(r'^.*?([\w\d]+)(%s__init__)?.py$' % sep, r'\1', path) - return p - - def in_builtin_module(self): - return not self.module_path.endswith('.py') - - @property - def line_nr(self): - return self.definition.start_pos[0] - - @property - def column(self): - return self.definition.start_pos[1] + super(Definition, self).__init__(definition.start_pos, definition) + self._def_parent = definition.parent() # just here to limit gc @property def description(self): @@ -132,9 +112,6 @@ class Definition(object): position = '' return "%s:%s%s" % (self.module_name, self.description, position) - def __repr__(self): - return "<%s %s>" % (self.__class__.__name__, self.definition) - def _get_completion_parts(path): """ @@ -290,7 +267,7 @@ def goto(source, line, column, source_path): return d -def get_related_names(source, line, column, source_path): +def related_names(source, line, column, source_path): pos = (line, column) f = modules.ModuleWithCursor(source_path, source=source, position=pos) @@ -319,7 +296,7 @@ def get_related_names(source, line, column, source_path): module = set([d.get_parent_until() for d in definitions]) module.add(f.parser.module) - names = dynamic.get_related_names(definitions, search_name, module) + names = dynamic.related_names(definitions, search_name, module) _clear_caches() return names diff --git a/plugin/jedi.vim b/plugin/jedi.vim index 2265137b..cd501876 100644 --- a/plugin/jedi.vim +++ b/plugin/jedi.vim @@ -85,6 +85,13 @@ function! jedi#get_definition() python _goto(is_definition=True) endfunction +" ------------------------------------------------------------------------ +" related_names +" ------------------------------------------------------------------------ +function! jedi#related_names() + python _goto(related_names=True) +endfunction + " ------------------------------------------------------------------------ " show_pydoc " ------------------------------------------------------------------------ @@ -237,6 +244,9 @@ endif if !exists("g:jedi#get_definition_command") let g:jedi#get_definition_command = "d" endif +if !exists("g:jedi#related_names_command") + let g:jedi#related_names_command = "n" +endif if !exists("g:jedi#popup_on_dot") let g:jedi#popup_on_dot = 1 endif @@ -249,10 +259,12 @@ if g:jedi#auto_initialization " map ctrl+space for autocompletion autocmd FileType python inoremap - " goto / get_definition + " goto / get_definition / related_names autocmd FileType python execute "noremap ".g:jedi#goto_command." :call jedi#goto()" autocmd FileType python execute "noremap ".g:jedi#get_definition_command." :call jedi#get_definition()" + autocmd FileType python execute "noremap ".g:jedi#related_names_command." :call jedi#related_names()" + " pydoc autocmd FileType python execute "nnoremap ".g:jedi#pydoc." :call jedi#show_pydoc()" end @@ -285,7 +297,7 @@ class PythonToVimStr(str): def __repr__(self): return '"%s"' % self.replace('"', r'\"') -def _goto(is_definition=False): +def _goto(is_definition=False, is_related_name=False): def echo_highlight(msg): vim.command('echohl WarningMsg | echo "%s" | echohl None' % msg) @@ -293,7 +305,9 @@ def _goto(is_definition=False): buf_path = vim.current.buffer.name source = '\n'.join(vim.current.buffer) try: - if is_definition: + if is_related_name: + definitions = functions.related_names(source, row, column, buf_path) + elif is_definition: definitions = functions.get_definition(source, row, column, buf_path) else: definitions = functions.goto(source, row, column, buf_path) diff --git a/test/run.py b/test/run.py index 9bbe90b1..d2ddc911 100755 --- a/test/run.py +++ b/test/run.py @@ -129,7 +129,7 @@ def run_related_name_test(correct, source, line_nr, index, line, path): Return if the test was a fail or not, with 1 for fail and 0 for success. """ try: - result = functions.get_related_names(source, line_nr, index, path) + result = functions.related_names(source, line_nr, index, path) except Exception: print(traceback.format_exc()) print('test @%s: %s' % (line_nr - 1, line))