1
0
forked from VimPlug/jedi

use weakrefs for parents now: evaluate.py

This commit is contained in:
David Halter
2012-08-12 01:32:34 +02:00
parent ed07e91d88
commit a2611c5db6

View File

@@ -22,6 +22,7 @@ from _compatibility import next, property, hasattr, is_py3k
import sys import sys
import itertools import itertools
import copy import copy
import weakref
import parsing import parsing
import debug import debug
@@ -127,9 +128,8 @@ class Executable(parsing.Base):
def get_parent_until(self, *args): def get_parent_until(self, *args):
return self.base.get_parent_until(*args) return self.base.get_parent_until(*args)
@property
def parent(self): def parent(self):
return self.base.parent return self.base.parent()
class Instance(Executable): class Instance(Executable):
@@ -253,10 +253,9 @@ class InstanceElement():
self.instance = instance self.instance = instance
self.var = var self.var = var
@property
@memoize_default() @memoize_default()
def parent(self): def parent(self):
par = self.var.parent par = self.var.parent()
if not isinstance(par, (parsing.Module, Class)): if not isinstance(par, (parsing.Module, Class)):
par = InstanceElement(self.instance, par) par = InstanceElement(self.instance, par)
return par return par
@@ -498,7 +497,7 @@ class Execution(Executable):
new_param._assignment_calls = calls new_param._assignment_calls = calls
new_param.is_generated = True new_param.is_generated = True
name = copy.copy(param.get_name()) name = copy.copy(param.get_name())
name.parent = new_param name.parent = weakref.ref(new_param)
return name return name
result = [] result = []
@@ -507,7 +506,7 @@ class Execution(Executable):
# Care for self -> just exclude it and add the instance # Care for self -> just exclude it and add the instance
start_offset = 1 start_offset = 1
self_name = copy.copy(self.base.params[0].get_name()) self_name = copy.copy(self.base.params[0].get_name())
self_name.parent = self.base.instance self_name.parent = weakref.ref(self.base.instance)
result.append(self_name) result.append(self_name)
param_dict = {} param_dict = {}
@@ -656,7 +655,7 @@ class Execution(Executable):
temp, element.parent = element.parent, None temp, element.parent = element.parent, None
copied = copy.deepcopy(element) copied = copy.deepcopy(element)
element.parent = temp element.parent = temp
copied.parent = self copied.parent = weakref.ref(self)
if isinstance(copied, parsing.Function): if isinstance(copied, parsing.Function):
copied = Function(copied) copied = Function(copied)
objects.append(copied) objects.append(copied)
@@ -704,9 +703,7 @@ class Generator(parsing.Base):
for n in ('close', 'throw') + executes_generator: for n in ('close', 'throw') + executes_generator:
name = parsing.Name([n], none_pos, none_pos) name = parsing.Name([n], none_pos, none_pos)
if n in executes_generator: if n in executes_generator:
name.parent = self name.parent = weakref.ref(self)
else:
name.parent = None
names.append(name) names.append(name)
debug.dbg('generator names', names) debug.dbg('generator names', names)
return names return names
@@ -719,9 +716,8 @@ class Generator(parsing.Base):
debug.warning('Tried to get array access on a generator', self) debug.warning('Tried to get array access on a generator', self)
return [] return []
@property
def parent(self): def parent(self):
return self.func.parent return self.func.parent()
def __repr__(self): def __repr__(self):
return "<%s of %s>" % (self.__class__.__name__, self.func) return "<%s of %s>" % (self.__class__.__name__, self.func)
@@ -802,7 +798,6 @@ class Array(parsing.Base):
def get_contents(self): def get_contents(self):
return self._array return self._array
@property
def parent(self): def parent(self):
""" """
Return the builtin scope as parent, because the arrays are builtins Return the builtin scope as parent, because the arrays are builtins
@@ -870,7 +865,7 @@ def get_names_for_scope(scope, position=None, star_search=True,
in_scope) in_scope)
except StopIteration: except StopIteration:
raise MultiLevelStopIteration('StopIteration raised somewhere') raise MultiLevelStopIteration('StopIteration raised somewhere')
scope = scope.parent scope = scope.parent()
# This is used, because subscopes (Flow scopes) would distort the # This is used, because subscopes (Flow scopes) would distort the
# results. # results.
if isinstance(scope, (Function, parsing.Function, Execution)): if isinstance(scope, (Function, parsing.Function, Execution)):
@@ -908,7 +903,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
if r.is_global(): if r.is_global():
for token_name in r.token_list[1:]: for token_name in r.token_list[1:]:
if isinstance(token_name, parsing.Name): if isinstance(token_name, parsing.Name):
res_new += get_scopes_for_name(r.parent, res_new += get_scopes_for_name(r.parent(),
str(token_name)) str(token_name))
else: else:
# generated objects are used within executions, where # generated objects are used within executions, where
@@ -948,17 +943,17 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
def handle_non_arrays(name): def handle_non_arrays(name):
result = [] result = []
if isinstance(scope, InstanceElement) \ if isinstance(scope, InstanceElement) \
and scope.var == name.parent.parent: and scope.var == name.parent().parent():
name = InstanceElement(scope.instance, name) name = InstanceElement(scope.instance, name)
par = name.parent par = name.parent()
if par.isinstance(parsing.Flow): if par.isinstance(parsing.Flow):
if par.command == 'for': if par.command == 'for':
result += handle_for_loops(par) result += handle_for_loops(par)
else: else:
debug.warning('Flow: Why are you here? %s' % par.command) debug.warning('Flow: Why are you here? %s' % par.command)
elif isinstance(par, parsing.Param) \ elif isinstance(par, parsing.Param) \
and par.parent is not None \ and par.parent() is not None \
and isinstance(par.parent.parent, parsing.Class) \ and isinstance(par.parent().parent(), parsing.Class) \
and par.position == 0: and par.position == 0:
# This is where self gets added - this happens at another # This is where self gets added - this happens at another
# place, if the var_args are clear. But sometimes the class is # place, if the var_args are clear. But sometimes the class is
@@ -967,7 +962,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
if isinstance(scope, InstanceElement): if isinstance(scope, InstanceElement):
inst = scope.instance inst = scope.instance
else: else:
inst = Instance(Class(par.parent.parent)) inst = Instance(Class(par.parent().parent()))
result.append(inst) result.append(inst)
else: else:
result.append(par) result.append(par)
@@ -980,7 +975,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
break_scopes = [] break_scopes = []
# here is the position stuff happening (sorting of variables) # here is the position stuff happening (sorting of variables)
for name in sorted(name_list, key=comparison_func, reverse=True): for name in sorted(name_list, key=comparison_func, reverse=True):
p = name.parent.parent if name.parent else None p = name.parent().parent() if name.parent() else None
if isinstance(p, InstanceElement) \ if isinstance(p, InstanceElement) \
and isinstance(p.var, parsing.Class): and isinstance(p.var, parsing.Class):
p = p.var p = p.var
@@ -991,7 +986,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
s = scope.base if isinstance(scope, Class) else scope s = scope.base if isinstance(scope, Class) else scope
# this means that a definition was found and is not e.g. # this means that a definition was found and is not e.g.
# in if/else. # in if/else.
if not name.parent or p == s: if not name.parent() or p == s:
break break
break_scopes.append(p) break_scopes.append(p)
# if there are results, ignore the other scopes # if there are results, ignore the other scopes
@@ -1185,7 +1180,7 @@ def follow_call_list(call_list):
def follow_call(call): def follow_call(call):
""" Follow a call is following a function, variable, string, etc. """ """ Follow a call is following a function, variable, string, etc. """
scope = call.parent_stmt.parent scope = call.parent_stmt.parent()
path = call.generate_call_path() path = call.generate_call_path()
position = call.parent_stmt.start_pos position = call.parent_stmt.start_pos