mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
dynamic array additions are working with list.append
This commit is contained in:
64
dynamic.py
64
dynamic.py
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
For dynamic completion.
|
||||
"""
|
||||
import copy
|
||||
|
||||
import parsing
|
||||
import evaluate
|
||||
|
||||
@@ -79,3 +81,65 @@ def search_params(param):
|
||||
func.listeners.remove(listener)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@evaluate.memoize_default([])
|
||||
def check_array_additions(array, is_list=True):
|
||||
"""
|
||||
Checks if a `parsing.Array` has "add" statements:
|
||||
>>> a = [""]
|
||||
>>> a.append(1)
|
||||
"""
|
||||
def scan_array(arr, search_name):
|
||||
""" 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, search_name)
|
||||
elif isinstance(s, parsing.Call):
|
||||
n = s.name
|
||||
if isinstance(n, parsing.Name) and search_name in n.names:
|
||||
result.append(s)
|
||||
return result
|
||||
|
||||
def check_calls(calls, add_name):
|
||||
result = []
|
||||
for c in calls:
|
||||
call_path = list(c.generate_call_path())
|
||||
separate_index = call_path.index(add_name)
|
||||
if not len(call_path) > separate_index + 1:
|
||||
# this means that there is no execution -> [].append
|
||||
continue
|
||||
backtrack_path = iter(call_path[:separate_index])
|
||||
|
||||
position = c.parent_stmt.start_pos
|
||||
scope = c.parent_stmt.parent
|
||||
print 'd', call_path
|
||||
e = evaluate.follow_call_path(backtrack_path, scope, position)
|
||||
print 'e', e
|
||||
if not array in e:
|
||||
# the `append`, etc. belong to other arrays
|
||||
continue
|
||||
|
||||
if add_name in ['append', 'add']:
|
||||
result += evaluate.follow_call_list(call_path[separate_index + 1])
|
||||
elif add_name in ['extend', 'update']:
|
||||
result += evaluate.follow_call_list(call_path[separate_index + 1])
|
||||
return result
|
||||
|
||||
stmt = array._array.parent_stmt
|
||||
current_module = stmt.get_parent_until()
|
||||
search_names = ['append', 'extend', 'insert'] if is_list else \
|
||||
['add', 'update']
|
||||
possible_stmts = []
|
||||
result = []
|
||||
for n in search_names:
|
||||
try:
|
||||
possible_stmts += current_module.used_names[n]
|
||||
except KeyError:
|
||||
continue
|
||||
for stmt in possible_stmts:
|
||||
result += check_calls(scan_array(stmt.get_assignment_calls(), n), n)
|
||||
|
||||
return result
|
||||
|
||||
11
evaluate.py
11
evaluate.py
@@ -1171,9 +1171,14 @@ def follow_call_list(call_list):
|
||||
def follow_call(call):
|
||||
""" Follow a call is following a function, variable, string, etc. """
|
||||
scope = call.parent_stmt.parent
|
||||
path = call.generate_call_list()
|
||||
path = call.generate_call_path()
|
||||
|
||||
position = call.parent_stmt.start_pos
|
||||
return follow_call_path(path, scope, position)
|
||||
|
||||
|
||||
def follow_call_path(path, scope, position):
|
||||
""" Follows a path generated by `parsing.Call.generate_call_path()` """
|
||||
current = next(path)
|
||||
|
||||
if isinstance(current, parsing.Array):
|
||||
@@ -1239,7 +1244,9 @@ def follow_path(path, scope, position=None):
|
||||
if isinstance(current, parsing.Array):
|
||||
# This must be an execution, either () or [].
|
||||
if current.type == parsing.Array.LIST:
|
||||
result = scope.get_index_types(current)
|
||||
result = list(scope.get_index_types(current))
|
||||
if isinstance(scope, Array):
|
||||
result += dynamic.check_array_additions(scope)
|
||||
elif current.type not in [parsing.Array.DICT]:
|
||||
# Scope must be a class or func - make an instance or execution.
|
||||
debug.dbg('exe', scope)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import re
|
||||
|
||||
import parsing
|
||||
import dynamic # must be before evaluate, because it needs to be loaded first.
|
||||
import evaluate
|
||||
import modules
|
||||
import debug
|
||||
|
||||
@@ -137,6 +137,12 @@ class frozenset():
|
||||
def copy(self):
|
||||
return self
|
||||
|
||||
class tuple():
|
||||
def index(self):
|
||||
return 1
|
||||
|
||||
def count(self):
|
||||
return 1
|
||||
|
||||
#--------------------------------------------------------
|
||||
# basic types
|
||||
|
||||
@@ -657,6 +657,7 @@ class Statement(Simple):
|
||||
c_type = Call.NUMBER
|
||||
|
||||
if is_chain:
|
||||
#print 'chain', self, tok, result
|
||||
call = Call(tok, c_type, parent=result)
|
||||
result = result.set_next_chain_call(call)
|
||||
is_chain = False
|
||||
@@ -807,17 +808,17 @@ class Call(object):
|
||||
call.parent = self
|
||||
return call
|
||||
|
||||
def generate_call_list(self):
|
||||
def generate_call_path(self):
|
||||
try:
|
||||
for name_part in self.name.names:
|
||||
yield name_part
|
||||
except AttributeError:
|
||||
yield self
|
||||
if self.execution is not None:
|
||||
for y in self.execution.generate_call_list():
|
||||
for y in self.execution.generate_call_path():
|
||||
yield y
|
||||
if self.next is not None:
|
||||
for y in self.next.generate_call_list():
|
||||
for y in self.next.generate_call_path():
|
||||
yield y
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
@@ -162,6 +162,13 @@ dic2 = {'asdf': 3, 'b': 'str'}
|
||||
#? int()
|
||||
dic2[index]
|
||||
|
||||
# -----------------
|
||||
# chaining
|
||||
# -----------------
|
||||
|
||||
#? int()
|
||||
[tuple()].index()
|
||||
|
||||
# -----------------
|
||||
# __getitem__
|
||||
# -----------------
|
||||
|
||||
@@ -74,8 +74,46 @@ class A():
|
||||
def __init__(self, a):
|
||||
#? int()
|
||||
a
|
||||
self.a = a
|
||||
|
||||
def test(self, a):
|
||||
#? float()
|
||||
a
|
||||
|
||||
def test2(self):
|
||||
##? int()
|
||||
self.a
|
||||
|
||||
A(3).test(2.0)
|
||||
A(3).test2()
|
||||
|
||||
# -----------------
|
||||
# list.append/insert
|
||||
# -----------------
|
||||
arr = []
|
||||
for a in [1,2]:
|
||||
arr.append(a);
|
||||
|
||||
arr.append # should not cause an exception
|
||||
|
||||
#? int()
|
||||
arr[10]
|
||||
|
||||
arr = [tuple()]
|
||||
for a in [1,2]:
|
||||
arr.append(a);
|
||||
|
||||
#? int() tuple()
|
||||
arr[10]
|
||||
#? int()
|
||||
arr[10].index()
|
||||
|
||||
arr = [""]
|
||||
arr.insert(0, 1.0)
|
||||
#? float() str()
|
||||
arr[10]
|
||||
|
||||
|
||||
# -----------------
|
||||
# set.append
|
||||
# -----------------
|
||||
|
||||
Reference in New Issue
Block a user