introduced a dynamic completion for params

This commit is contained in:
David Halter
2012-08-05 17:24:26 +02:00
parent c2a5876d7b
commit ee798b03f2
6 changed files with 105 additions and 11 deletions

68
dynamic.py Normal file
View File

@@ -0,0 +1,68 @@
"""
For dynamic completion.
"""
import parsing
import evaluate
# This is something like the sys.path, but only for searching params. It means
# that this is the order in which Jedi searches params.
search_param_modules = ['.']
def search_params(param):
def scan_array(arr):
""" Returns the function Calls that match func_name """
result = []
for sub in arr:
for s in sub:
if isinstance(s, parsing.Array):
result += scan_array(s)
elif isinstance(s, parsing.Call):
if str(s.name) == func_name:
result.append(s)
return result
def get_params_for_module(module):
result = []
try:
possible_stmts = current_module.used_names[func_name]
except KeyError:
return []
calls = []
for stmt in possible_stmts:
calls += scan_array(stmt.get_assignment_calls())
for c in calls:
if not c.execution:
continue
# now check if the call is actually the same method
c.execution, temp = None, c.execution
possible_executions = evaluate.follow_call(c)
is_same_method = False
for e in possible_executions:
is_same_method = e == func \
or isinstance(e, evaluate.Function) and e.base_func == func
if not is_same_method:
continue
c.execution = temp
try:
p = c.execution[param_nr]
except IndexError:
pass
else:
result += evaluate.follow_call_list([p])
return result
func = param.get_parent_until(parsing.Function)
func_name = str(func.name)
current_module = param.get_parent_until()
for i, p in enumerate(func.params):
param_nr = i
result = get_params_for_module(current_module)
# TODO check other modules
return result

View File

@@ -31,6 +31,7 @@ import debug
import builtin
import imports
import helpers
import dynamic
memoize_caches = []
statement_path = []
@@ -476,6 +477,7 @@ class Execution(Executable):
new_param.parent = parent_stmt
new_param._assignment_calls_calculated = True
new_param._assignment_calls = calls
new_param.is_generated = True
name = copy.copy(param.get_name())
name.parent = new_param
return name
@@ -887,6 +889,14 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
res_new += get_scopes_for_name(r.parent,
str(token_name))
else:
# generated objects are used within executions, where
if isinstance(r, parsing.Param) and not r.is_generated:
res_new += dynamic.search_params(r)
if not r.assignment_details:
# this means that there are no default params, so
# just ignore it.
continue
scopes = follow_statement(r, seek_name=name_str)
res_new += remove_statements(scopes)
else:

View File

@@ -5,6 +5,7 @@ import evaluate
import modules
import debug
import imports
# TODO use os.path.sep and similar things
import os

View File

@@ -712,6 +712,7 @@ class Statement(Simple):
raise ParserError("Brackets don't match: %s. This is not normal "
"behaviour. Please submit a bug" % level)
self._assignment_calls_calculated = True
self._assignment_calls = top
return top
@@ -729,6 +730,7 @@ class Param(Statement):
# this is defined by the parser later on, not at the initialization
# it is the position in the call (first argument, second...)
self.position = None
self.is_generated = False
def get_name(self):
""" get the name of the param """
@@ -929,16 +931,6 @@ class Name(Simple):
def __str__(self):
return self.get_code()
def __eq__(self, other):
return self.names == other.names and self.start_pos == other.end_pos
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return hash(self.names) + hash(self.start_pos[0]) \
+ hash(self.start_pos[1])
def __len__(self):
return len(self.names)
@@ -1276,7 +1268,10 @@ class PyFuzzyParser(object):
self._check_user_stmt(stmt)
if not isinstance(stmt, Param):
for tok_name in self.module.temp_used_names:
self.module.used_names[tok_name] = stmt
try:
self.module.used_names[tok_name].append(stmt)
except KeyError:
self.module.used_names[tok_name] = [stmt]
self.module.temp_used_names = []
if is_return:
# add returns to the scope

View File

@@ -0,0 +1,14 @@
"""
This is used for dynamic object completion.
Jedi tries to guess the types with a backtracking approach.
"""
def func(a):
#? int() str()
return a
#? int()
func(1)
func
int(1) + (int(2))+ func('')

View File

@@ -70,6 +70,12 @@ def a(a=3):
a(2)
#? []
a(2).func
a_param = 3
def func(a_param):
# should not be int
#? []
a_param.
# -----------------
# class
# -----------------