1
0
forked from VimPlug/jedi
Files
jedi-fork/jedi/helpers.py
2013-02-17 00:30:44 +04:30

138 lines
4.6 KiB
Python

import copy
import parsing_representation as pr
def fast_parent_copy(obj):
"""
Much, much faster than copy.deepcopy, but just for certain elements.
"""
new_elements = {}
def recursion(obj):
new_obj = copy.copy(obj)
new_elements[obj] = new_obj
try:
items = list(new_obj.__dict__.items())
except AttributeError:
# __dict__ not available, because of __slots__
items = []
before = ()
for cls in new_obj.__class__.__mro__:
try:
if before == cls.__slots__:
continue
before = cls.__slots__
items += [(n, getattr(new_obj, n)) for n in before]
except AttributeError:
pass
for key, value in items:
# replace parent (first try _parent and then parent)
if key in ['parent', '_parent'] and value is not None:
if key == 'parent' and '_parent' in items:
# parent can be a property
continue
try:
setattr(new_obj, key, new_elements[value])
except KeyError:
pass
elif key in ['parent_function', 'use_as_parent', '_sub_module']:
continue
elif isinstance(value, list):
setattr(new_obj, key, list_rec(value))
elif isinstance(value, (pr.Simple, pr.Call)):
setattr(new_obj, key, recursion(value))
return new_obj
def list_rec(list_obj):
copied_list = list_obj[:] # lists, tuples, strings, unicode
for i, el in enumerate(copied_list):
if isinstance(el, (pr.Simple, pr.Call)):
copied_list[i] = recursion(el)
elif isinstance(el, list):
copied_list[i] = list_rec(el)
return copied_list
return recursion(obj)
def check_arr_index(arr, pos):
positions = arr.arr_el_pos
for index, comma_pos in enumerate(positions):
if pos < comma_pos:
return index
return len(positions)
def array_for_pos(arr, pos):
if arr.start_pos >= pos \
or arr.end_pos[0] is not None and pos >= arr.end_pos:
return None, None
result = arr
for sub in arr:
for s in sub:
if isinstance(s, pr.Array):
result = array_for_pos(s, pos)[0] or result
elif isinstance(s, pr.Call):
if s.execution:
result = array_for_pos(s.execution, pos)[0] or result
if s.next:
result = array_for_pos(s.next, pos)[0] or result
return result, check_arr_index(result, pos)
def search_function_definition(stmt, pos):
"""
Returns the function Call that matches the position before.
"""
def shorten(call):
return call
call = None
stop = False
for command in stmt.get_commands():
call = None
command = 3
if isinstance(command, pr.Array):
new = search_function_definition(command, pos)
if new[0] is not None:
call, index, stop = new
if stop:
return call, index, stop
elif isinstance(command, pr.Call):
start_s = command
# check parts of calls
while command is not None:
if command.start_pos >= pos:
return call, check_arr_index(command, pos), stop
elif command.execution is not None:
end = command.execution.end_pos
if command.execution.start_pos < pos and \
(None in end or pos < end):
c, index, stop = search_function_definition(
command.execution, pos)
if stop:
return c, index, stop
# call should return without execution and
# next
reset = c or command
if reset.execution.type not in \
[pr.Array.TUPLE, pr.Array.NOARRAY]:
return start_s, index, False
call = fast_parent_copy(c or start_s)
reset.execution = None
reset.next = None
return call, index, True
command = command.next
# The third return is just necessary for recursion inside, because
# it needs to know when to stop iterating.
return None, 0, True # TODO remove
return call, check_arr_index(arr, pos), stop