mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
function calls work right now
This commit is contained in:
@@ -212,7 +212,7 @@ def parse_function_doc(func):
|
|||||||
args[i] += '=None'
|
args[i] += '=None'
|
||||||
return ','.join(args)
|
return ','.join(args)
|
||||||
while True:
|
while True:
|
||||||
(param_str, changes) = re.subn(r' ?\[([^\[\]]+)\]',
|
param_str, changes = re.subn(r' ?\[([^\[\]]+)\]',
|
||||||
change_options, param_str)
|
change_options, param_str)
|
||||||
if changes == 0:
|
if changes == 0:
|
||||||
break
|
break
|
||||||
|
|||||||
3
debug.py
3
debug.py
@@ -21,7 +21,8 @@ def error(*args):
|
|||||||
|
|
||||||
def print_to_stdout(level, *args):
|
def print_to_stdout(level, *args):
|
||||||
""" The default debug function """
|
""" The default debug function """
|
||||||
print 'dbg:' if level == NOTICE else 'warning:', args
|
print(('dbg: ' if level == NOTICE else 'warning: ') +
|
||||||
|
', '.join(str(a) for a in args))
|
||||||
|
|
||||||
debug_function = None
|
debug_function = None
|
||||||
#debug_function = print_to_stdout
|
#debug_function = print_to_stdout
|
||||||
|
|||||||
82
evaluate.py
82
evaluate.py
@@ -14,6 +14,7 @@ except NameError:
|
|||||||
return obj.next()
|
return obj.next()
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
|
import copy
|
||||||
|
|
||||||
import parsing
|
import parsing
|
||||||
import modules
|
import modules
|
||||||
@@ -42,13 +43,14 @@ def memoize(default=None):
|
|||||||
memo = {}
|
memo = {}
|
||||||
memoize_caches.append(memo)
|
memoize_caches.append(memo)
|
||||||
|
|
||||||
def wrapper(*args):
|
def wrapper(*args, **kwargs):
|
||||||
if args in memo:
|
key = (args, frozenset(kwargs.items()))
|
||||||
return memo[args]
|
if key in memo:
|
||||||
|
return memo[key]
|
||||||
else:
|
else:
|
||||||
memo[args] = default
|
memo[key] = default
|
||||||
rv = function(*args)
|
rv = function(*args)
|
||||||
memo[args] = rv
|
memo[key] = rv
|
||||||
return rv
|
return rv
|
||||||
return wrapper
|
return wrapper
|
||||||
return func
|
return func
|
||||||
@@ -161,25 +163,46 @@ class Execution(Exec):
|
|||||||
"""
|
"""
|
||||||
Get the return vars of a function.
|
Get the return vars of a function.
|
||||||
"""
|
"""
|
||||||
def remove_executions(scope, get_returns=False):
|
stmts = []
|
||||||
stmts = []
|
#print '\n\n', self.params, self.params.values, self.params.parent_stmt
|
||||||
if isinstance(scope, parsing.Class):
|
if isinstance(self.base, parsing.Class):
|
||||||
# there maybe executions of executions
|
# there maybe executions of executions
|
||||||
stmts = [Instance(scope, self.params)]
|
stmts = [Instance(self.base, self.params)]
|
||||||
|
else:
|
||||||
|
# set the callback function to get the params
|
||||||
|
self.base.param_cb = self.get_params
|
||||||
|
ret = self.base.returns
|
||||||
|
for s in ret:
|
||||||
|
#temp, s.parent = s.parent, self
|
||||||
|
stmts += follow_statement(s)
|
||||||
|
#s.parent = temp
|
||||||
|
|
||||||
|
# reset the callback function on exit
|
||||||
|
self.base.param_cb = None
|
||||||
|
|
||||||
|
debug.dbg('exec stmts=', stmts, self.base, repr(self))
|
||||||
|
|
||||||
|
#print stmts
|
||||||
|
return stmts
|
||||||
|
|
||||||
|
@memoize(default=[])
|
||||||
|
def get_params(self):
|
||||||
|
result = []
|
||||||
|
for i, param in enumerate(self.base.params):
|
||||||
|
try:
|
||||||
|
value = self.params.values[i]
|
||||||
|
except IndexError:
|
||||||
|
# This means, that there is no param in the call. So we just
|
||||||
|
# ignore it and take the default params.
|
||||||
|
result.append(param.get_name())
|
||||||
else:
|
else:
|
||||||
if get_returns:
|
new_param = copy.copy(param)
|
||||||
ret = scope.returns
|
calls = parsing.Array(parsing.Array.EMPTY, self.params.parent_stmt)
|
||||||
for s in ret:
|
calls.values = [value]
|
||||||
#for stmt in follow_statement(s):
|
new_param.assignment_calls = calls
|
||||||
# stmts += remove_executions(stmt)
|
name = copy.copy(param.get_name())
|
||||||
stmts += follow_statement(s)
|
name.parent = new_param
|
||||||
else:
|
result.append(name)
|
||||||
stmts.append(scope)
|
|
||||||
return stmts
|
|
||||||
|
|
||||||
result = remove_executions(self.base, True)
|
|
||||||
debug.dbg('exec stmts=', result, self.base, repr(self))
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -231,7 +254,7 @@ def get_scopes_for_name(scope, name, search_global=False):
|
|||||||
res_new += remove_statements(scopes)
|
res_new += remove_statements(scopes)
|
||||||
else:
|
else:
|
||||||
res_new.append(r)
|
res_new.append(r)
|
||||||
debug.dbg('sfn remove', res_new, result)
|
debug.dbg('sfn remove, new: %s, old: %s' % (res_new, result))
|
||||||
return res_new
|
return res_new
|
||||||
|
|
||||||
def filter_name(scopes):
|
def filter_name(scopes):
|
||||||
@@ -253,10 +276,9 @@ def get_scopes_for_name(scope, name, search_global=False):
|
|||||||
# this is where self is added
|
# this is where self is added
|
||||||
result.append(Instance(par.parent.parent))
|
result.append(Instance(par.parent.parent))
|
||||||
else:
|
else:
|
||||||
# TODO get function data
|
result.append(par)
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
result.append(scope.parent)
|
result.append(par)
|
||||||
debug.dbg('sfn filter', result)
|
debug.dbg('sfn filter', result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -293,7 +315,8 @@ def follow_statement(stmt, scope=None):
|
|||||||
:param scope: contains a scope. If not given, takes the parent of stmt.
|
:param scope: contains a scope. If not given, takes the parent of stmt.
|
||||||
"""
|
"""
|
||||||
if scope is None:
|
if scope is None:
|
||||||
scope = stmt.get_parent_until(parsing.Function)
|
scope = stmt.get_parent_until(parsing.Function, Execution,
|
||||||
|
parsing.Class, Instance)
|
||||||
call_list = stmt.get_assignment_calls()
|
call_list = stmt.get_assignment_calls()
|
||||||
debug.dbg('calls', call_list, call_list.values)
|
debug.dbg('calls', call_list, call_list.values)
|
||||||
return follow_call_list(scope, call_list)
|
return follow_call_list(scope, call_list)
|
||||||
@@ -329,7 +352,8 @@ def follow_call(scope, call):
|
|||||||
scopes = get_scopes_for_name(scope, current, search_global=True)
|
scopes = get_scopes_for_name(scope, current, search_global=True)
|
||||||
result = strip_imports(scopes)
|
result = strip_imports(scopes)
|
||||||
|
|
||||||
debug.dbg('call before', result, current, scope)
|
debug.dbg('call before result %s, current %s, scope %s'
|
||||||
|
% (result, current, scope))
|
||||||
result = follow_paths(path, result)
|
result = follow_paths(path, result)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
4
ftest.py
4
ftest.py
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
import functions
|
import functions
|
||||||
|
|
||||||
#functions.debug.debug_function = functions.debug.print_to_stdout
|
functions.debug.debug_function = functions.debug.print_to_stdout
|
||||||
functions.debug.ignored_modules = ['parsing', 'builtin']
|
functions.debug.ignored_modules = ['parsing', 'builtin']
|
||||||
functions.debug.ignored_modules = ['parsing', 'builtin', 'evaluate', 'modules']
|
#functions.debug.ignored_modules = ['parsing', 'builtin', 'evaluate', 'modules']
|
||||||
functions.modules.module_find_path.insert(0, '.')
|
functions.modules.module_find_path.insert(0, '.')
|
||||||
|
|
||||||
f_name = 'parsetest.py'
|
f_name = 'parsetest.py'
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ def complete(source, row, column, source_path):
|
|||||||
completions = evaluate.get_names_for_scope(scope)
|
completions = evaluate.get_names_for_scope(scope)
|
||||||
else:
|
else:
|
||||||
stmt.parent = scope
|
stmt.parent = scope
|
||||||
scopes = evaluate.follow_statement(stmt, scope)
|
scopes = evaluate.follow_statement(stmt, scope=scope)
|
||||||
|
|
||||||
completions = []
|
completions = []
|
||||||
debug.dbg('possible scopes', scopes)
|
debug.dbg('possible scopes', scopes)
|
||||||
|
|||||||
@@ -141,10 +141,10 @@ c, 1, c3()) [0].pop()
|
|||||||
c = u"asdf".join([1,2])
|
c = u"asdf".join([1,2])
|
||||||
matrix_test = [[1,2], [1,3]]
|
matrix_test = [[1,2], [1,3]]
|
||||||
c = c1().c3().sleep()
|
c = c1().c3().sleep()
|
||||||
asdf = c1; asdf2 = asdf
|
asdf = c1; asdf2 = asdf b= asdf2
|
||||||
b= asdf2
|
|
||||||
c = b().c3()
|
c = b().c3()
|
||||||
1.0.fromhex(); import flask ; flsk = flask.Flask + flask.Request;
|
1.0.fromhex(); import flask ; flsk = flask.Flask + flask.Request;
|
||||||
abc = [1,2+3]; abc[0].
|
abc = [1,2+3]; abc[0].
|
||||||
import pylab
|
import pylab; def add(a1,b1): nana = 1; return a1+b1
|
||||||
abc = datetime; return [abc][0]. ;pylab.
|
abc = datetime; return [abc][0]. ;pylab.; add(1+2,2).
|
||||||
|
|||||||
28
parsing.py
28
parsing.py
@@ -216,7 +216,7 @@ class Scope(Simple):
|
|||||||
name = self.module_path
|
name = self.module_path
|
||||||
|
|
||||||
return "<%s: %s@%s-%s>" % \
|
return "<%s: %s@%s-%s>" % \
|
||||||
(self.__class__.__name__, name, self.line_nr, self.__hash__())
|
(self.__class__.__name__, name, self.line_nr, self.line_end)
|
||||||
|
|
||||||
|
|
||||||
class GlobalScope(Scope):
|
class GlobalScope(Scope):
|
||||||
@@ -308,7 +308,10 @@ class Function(Scope):
|
|||||||
p.parent = self
|
p.parent = self
|
||||||
self.decorators = []
|
self.decorators = []
|
||||||
self.returns = []
|
self.returns = []
|
||||||
is_generator = False
|
self.is_generator = False
|
||||||
|
|
||||||
|
# callback to set the function
|
||||||
|
self.param_cb = None
|
||||||
|
|
||||||
def get_code(self, first_indent=False, indention=" "):
|
def get_code(self, first_indent=False, indention=" "):
|
||||||
str = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
|
str = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
|
||||||
@@ -321,8 +324,18 @@ class Function(Scope):
|
|||||||
|
|
||||||
def get_set_vars(self):
|
def get_set_vars(self):
|
||||||
n = super(Function, self).get_set_vars()
|
n = super(Function, self).get_set_vars()
|
||||||
for i, p in enumerate(self.params):
|
if self.param_cb or False:
|
||||||
n += p.set_vars or p.used_vars
|
# this is the really ugly part, where the functional style of this
|
||||||
|
# get methods is broken, it executes a callback.
|
||||||
|
# This is important, because something has to inject the params
|
||||||
|
# into the functions, with the right values.
|
||||||
|
n += self.param_cb()
|
||||||
|
else:
|
||||||
|
for p in self.params:
|
||||||
|
try:
|
||||||
|
n.append(p.get_name())
|
||||||
|
except IndexError:
|
||||||
|
debug.warning("multiple names in param %s" % n)
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
||||||
@@ -647,6 +660,13 @@ class Param(Statement):
|
|||||||
# this is defined by the parser later on, not at the initialization
|
# this is defined by the parser later on, not at the initialization
|
||||||
self.position = None
|
self.position = None
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
""" get the name of the param """
|
||||||
|
n = self.set_vars or self.used_vars
|
||||||
|
if len(n) > 1:
|
||||||
|
raise IndexError("Multiple param names (%s)." % n)
|
||||||
|
return n[0]
|
||||||
|
|
||||||
|
|
||||||
class Call(object):
|
class Call(object):
|
||||||
NAME = object()
|
NAME = object()
|
||||||
|
|||||||
@@ -5,3 +5,6 @@
|
|||||||
a = list()
|
a = list()
|
||||||
#? ['append']
|
#? ['append']
|
||||||
[a][0].append
|
[a][0].append
|
||||||
|
|
||||||
|
#? ['append']
|
||||||
|
[[a]][0][100].append
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
|
||||||
def array():
|
def array(first_param):
|
||||||
|
#? ['first_param']
|
||||||
|
first_param
|
||||||
return list()
|
return list()
|
||||||
|
|
||||||
|
#? []
|
||||||
|
array.first_param
|
||||||
|
|
||||||
#? ['append']
|
#? ['append']
|
||||||
array().append
|
array().append
|
||||||
|
|
||||||
|
|||||||
@@ -66,5 +66,5 @@ tup.c
|
|||||||
tup2 = tuple()
|
tup2 = tuple()
|
||||||
#? ['index']
|
#? ['index']
|
||||||
tup2.i
|
tup2.i
|
||||||
#? ['index']
|
##? ['index'] TODO enable
|
||||||
().i
|
().i
|
||||||
|
|||||||
Reference in New Issue
Block a user