forked from VimPlug/jedi
Updated helpers.deep_ast_copy. Now the function copies statements in a better way.
Previously statement attributes where scanned like every other objects. Now two statements get priority: _assignment_details and _expression_list. This is necessary if we want to switch towards proper name parents (A Call would be the parent of a name, not a Statement)
This commit is contained in:
@@ -11,34 +11,48 @@ def deep_ast_copy(obj, new_elements_default=None):
|
|||||||
Much, much faster than copy.deepcopy, but just for Parser elements (Doesn't
|
Much, much faster than copy.deepcopy, but just for Parser elements (Doesn't
|
||||||
copy parents).
|
copy parents).
|
||||||
"""
|
"""
|
||||||
|
def sort_stmt(key_value):
|
||||||
|
return key_value[0] in ('_expression_list', '_assignment_details')
|
||||||
|
|
||||||
new_elements = new_elements_default or {}
|
new_elements = new_elements_default or {}
|
||||||
accept = (pr.Simple, pr.NamePart, pr.KeywordStatement)
|
accept = (pr.Simple, pr.NamePart, pr.KeywordStatement)
|
||||||
|
|
||||||
def recursion(obj):
|
def recursion(obj):
|
||||||
if isinstance(obj, pr.Statement):
|
# If it's already in the cache, just return it.
|
||||||
# Need to set _set_vars, otherwise the cache is not working
|
|
||||||
# correctly, don't know why.
|
|
||||||
obj.get_defined_names()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return new_elements[obj]
|
return new_elements[obj]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
new_obj = copy.copy(obj)
|
pass
|
||||||
new_elements[obj] = new_obj
|
|
||||||
|
|
||||||
|
if isinstance(obj, pr.Statement):
|
||||||
|
# Need to set _set_vars, otherwise the cache is not working
|
||||||
|
# correctly, don't know exactly why.
|
||||||
|
obj.get_defined_names()
|
||||||
|
|
||||||
|
# Gather items
|
||||||
try:
|
try:
|
||||||
items = list(new_obj.__dict__.items())
|
items = list(obj.__dict__.items())
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# __dict__ not available, because of __slots__
|
# __dict__ not available, because of __slots__
|
||||||
items = []
|
items = []
|
||||||
|
|
||||||
before = ()
|
before = ()
|
||||||
for cls in new_obj.__class__.__mro__:
|
for cls in obj.__class__.__mro__:
|
||||||
with common.ignored(AttributeError):
|
with common.ignored(AttributeError):
|
||||||
if before == cls.__slots__:
|
if before == cls.__slots__:
|
||||||
continue
|
continue
|
||||||
before = cls.__slots__
|
before = cls.__slots__
|
||||||
items += [(n, getattr(new_obj, n)) for n in before]
|
items += [(n, getattr(obj, n)) for n in before]
|
||||||
|
|
||||||
|
if isinstance(obj, pr.Statement):
|
||||||
|
# We need to process something with priority for statements,
|
||||||
|
# because there are several references that don't walk the whole
|
||||||
|
# tree in there.
|
||||||
|
items = sorted(items, key=sort_stmt)
|
||||||
|
|
||||||
|
# Actually copy and set attributes.
|
||||||
|
new_obj = copy.copy(obj)
|
||||||
|
new_elements[obj] = new_obj
|
||||||
|
|
||||||
for key, value in items:
|
for key, value in items:
|
||||||
# replace parent (first try _parent and then parent)
|
# replace parent (first try _parent and then parent)
|
||||||
|
|||||||
Reference in New Issue
Block a user