goto function added

This commit is contained in:
David Halter
2012-05-13 12:41:56 +02:00
parent d6c5363132
commit cb201c3b7b
4 changed files with 96 additions and 27 deletions

View File

@@ -39,6 +39,7 @@ nice in Python 2. To keep things simple, some things have been held back:
- Classes: Always Python 3, therefore all classes inherit from `object`.
- Generators: No `next` method. The `__next__` method is there instead.
- Exceptions are only looked at in the form of `Exception as e`, no comma!
Syntax Errors and other strange stuff, that is defined differently in the
Python language, may lead to undefined behaviour of the completion. If you

View File

@@ -286,11 +286,24 @@ class Instance(Executable):
return names
@property
def parent(self):
return self.base.parent
@property
def line_nr(self):
return self.base.line_nr
@property
def indent(self):
return self.base.indent
@property
def name(self):
return self.base.name
def __repr__(self):
return "<p%s of %s (var_args: %s)>" % \
return "<e%s of %s (var_args: %s)>" % \
(self.__class__.__name__, self.base, len(self.var_args or []))
@@ -345,11 +358,15 @@ class Class(object):
names.append(i)
return names
@property
def name(self):
return self.base.name
def __getattr__(self, name):
return getattr(self.base, name)
def __repr__(self):
return "<p%s of %s>" % (self.__class__.__name__, self.base)
return "<e%s of %s>" % (self.__class__.__name__, self.base)
class Execution(Executable):
@@ -537,7 +554,7 @@ class Array(object):
return self._array
def __repr__(self):
return "<p%s of %s>" % (self.__class__.__name__, self._array)
return "<e%s of %s>" % (self.__class__.__name__, self._array)
class ArrayElement(object):

View File

@@ -15,7 +15,7 @@ path = os.path.join(os.getcwd(), f_name)
f = open(path)
code = f.read()
for i in range(1):
completions = functions.complete(code, 180, 200, path)
completions = functions.get_definitions(code, 180, 200, path)
#completions = functions.complete(code, 42, 200, path)
print '\n', ', '.join(sorted(str(c) for c in completions))

View File

@@ -1,4 +1,5 @@
import re
import sys
import parsing
import evaluate
@@ -10,7 +11,10 @@ __all__ = ['complete', 'goto', 'get_completion_parts', 'set_debug_function']
class NotFoundError(Exception):
""" A custom error to avoid catching the wrong errors """
pass
def __init__(self, scope, path_tuple, message=None):
super(NotFoundError, self).__init__(message)
self.scope = scope
self.path_tuple = path_tuple
class Completion(object):
@@ -32,7 +36,7 @@ class Completion(object):
def help(self):
try:
return str(self.name.parent.docstr)
except:
except AttributeError:
return ''
def get_type(self):
@@ -63,6 +67,42 @@ class Completion(object):
return self.name.names[-1]
class Definition(object):
def __init__(self, scope):
""" The definition of a function """
self.scope = scope
def get_name(self):
return self.scope.name
def get_module(self):
par = self.scope
while True:
if par.parent is not None:
par = par.parent
else:
break
return par.path
def get_line(self):
return self.scope.line_nr
def get_indent(self):
return self.scope.indent
def __str__(self):
module = self.get_module()
if module[0] == '/':
position = '@%s' % (self.get_line())
else:
# no path - is a builtin
position = ''
return "%s.%s%s" % (module, self.get_name(), position)
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self)
def get_completion_parts(path):
"""
Returns the parts for the completion
@@ -88,18 +128,14 @@ def complete(source, row, column, source_path):
:return: list of completion objects
:rtype: list
"""
f = modules.ModuleWithCursor(source_path, source=source, row=row)
scope = f.parser.user_scope
path = f.get_path_until_cursor(column)
debug.dbg('completion_start: %s in %s' % (path, scope))
# just parse one statement, take it and evaluate it
path, dot, like = get_completion_parts(path)
r = parsing.PyFuzzyParser(path, source_path)
try:
stmt = r.top.statements[0]
except IndexError:
scope_generator = evaluate.get_names_for_scope(scope)
scopes, path, dot, like = prepare_goto(source, row, column, source_path, True)
except NotFoundError:
# normally this would be used like this: `NotFoundError as exc`, but
# this guarantues backwards compatibility with Python2.5.
exc = sys.exc_info()[1]
path, dot, like = exc.path_tuple
scope_generator = evaluate.get_names_for_scope(exc.scope)
completions = []
for dummy, name_list in scope_generator:
completions += name_list
@@ -107,11 +143,6 @@ def complete(source, row, column, source_path):
# if isinstance(, parsing.Function):
# print c.parent
else:
stmt.line_nr = row
stmt.indent = column
stmt.parent = scope
scopes = evaluate.follow_statement(stmt, scope=scope)
completions = []
debug.dbg('possible scopes', scopes)
for s in scopes:
@@ -146,20 +177,40 @@ def prepare_goto(source, row, column, source_path, is_like_search):
try:
stmt = r.top.statements[0]
except IndexError:
raise NotFoundError()
path_tuple = path, dot, like
raise NotFoundError(scope, path_tuple)
else:
stmt.line_nr = row
stmt.indent = column
stmt.parent = scope
scopes = evaluate.follow_statement(stmt, scope=scope)
return scope, scopes
if is_like_search:
return scopes, path, dot, like
else:
return scopes
def goto(source, row, column, source_path):
dummy, scopes = prepare_goto(source, row, column, source_path, False)
def get_definitions(source, row, column, source_path):
"""
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.
:param source: The source code of the current file
:type source: string
:param row: The row to complete in.
:type row: int
:param col: The column to complete in.
:type col: int
:param source_path: The path in the os, the current module is in.
:type source_path: int
:return: list of Definition objects, which are basically scopes.
:rtype: list
"""
scopes = prepare_goto(source, row, column, source_path, False)
_clear_caches()
return scopes
return [Definition(s) for s in set(scopes)]
def set_debug_function(func_cb):