mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 23:34:45 +08:00
use weakrefs for parents now: functions.py
This commit is contained in:
28
functions.py
28
functions.py
@@ -1,4 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
|
import weakref
|
||||||
|
|
||||||
import parsing
|
import parsing
|
||||||
import dynamic # must be before evaluate, because it needs to be loaded first.
|
import dynamic # must be before evaluate, because it needs to be loaded first.
|
||||||
@@ -28,17 +29,17 @@ class Completion(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return str(self.name.parent)
|
return str(self.name.parent())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def help(self):
|
def help(self):
|
||||||
try:
|
try:
|
||||||
return str(self.name.parent.docstr)
|
return str(self.name.parent().docstr)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
return type(self.name.parent)
|
return type(self.name.parent())
|
||||||
|
|
||||||
def get_vim_type(self):
|
def get_vim_type(self):
|
||||||
"""
|
"""
|
||||||
@@ -94,8 +95,8 @@ class Definition(object):
|
|||||||
def module_path(self):
|
def module_path(self):
|
||||||
par = self.definition
|
par = self.definition
|
||||||
while True:
|
while True:
|
||||||
if par.parent is not None:
|
if par.parent() is not None:
|
||||||
par = par.parent
|
par = par.parent()
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -118,7 +119,7 @@ class Definition(object):
|
|||||||
if isinstance(d, evaluate.InstanceElement):
|
if isinstance(d, evaluate.InstanceElement):
|
||||||
d = d.var
|
d = d.var
|
||||||
if isinstance(d, evaluate.parsing.Name):
|
if isinstance(d, evaluate.parsing.Name):
|
||||||
d = d.parent
|
d = d.parent()
|
||||||
|
|
||||||
if isinstance(d, (evaluate.Class, evaluate.Instance)):
|
if isinstance(d, (evaluate.Class, evaluate.Instance)):
|
||||||
d = 'class ' + str(d.name)
|
d = 'class ' + str(d.name)
|
||||||
@@ -223,7 +224,7 @@ def prepare_goto(source, position, source_path, module, goto_path,
|
|||||||
raise NotFoundError()
|
raise NotFoundError()
|
||||||
else:
|
else:
|
||||||
stmt.start_pos = position
|
stmt.start_pos = position
|
||||||
stmt.parent = scope
|
stmt.parent = weakref.ref(scope)
|
||||||
scopes = evaluate.follow_statement(stmt)
|
scopes = evaluate.follow_statement(stmt)
|
||||||
return scopes
|
return scopes
|
||||||
|
|
||||||
@@ -284,7 +285,7 @@ def goto(source, line, column, source_path):
|
|||||||
"""
|
"""
|
||||||
new_names = []
|
new_names = []
|
||||||
for n in names:
|
for n in names:
|
||||||
par = n.parent
|
par = n.parent()
|
||||||
# This is a special case: If the Import is "virtual" (which
|
# This is a special case: If the Import is "virtual" (which
|
||||||
# means the position is not defined), follow those modules.
|
# means the position is not defined), follow those modules.
|
||||||
if isinstance(par, parsing.Import) and not par.start_pos[0]:
|
if isinstance(par, parsing.Import) and not par.start_pos[0]:
|
||||||
@@ -321,3 +322,14 @@ def set_debug_function(func_cb):
|
|||||||
|
|
||||||
def _clear_caches():
|
def _clear_caches():
|
||||||
evaluate.clear_caches()
|
evaluate.clear_caches()
|
||||||
|
import gc
|
||||||
|
#gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS)
|
||||||
|
#gc.collect()
|
||||||
|
count = 0
|
||||||
|
for o in gc.get_objects():
|
||||||
|
if isinstance(o, parsing.Module):
|
||||||
|
pass
|
||||||
|
count += 1
|
||||||
|
#print o
|
||||||
|
print count
|
||||||
|
#exit()
|
||||||
|
|||||||
75
parsing.py
75
parsing.py
@@ -34,6 +34,7 @@ from _compatibility import (next, literal_eval, tokenize_func, BytesIO,
|
|||||||
import tokenize
|
import tokenize
|
||||||
import re
|
import re
|
||||||
import keyword
|
import keyword
|
||||||
|
import weakref
|
||||||
|
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@@ -73,13 +74,13 @@ class Simple(Base):
|
|||||||
def __init__(self, start_pos, end_pos=(None, None)):
|
def __init__(self, start_pos, end_pos=(None, None)):
|
||||||
self.start_pos = start_pos
|
self.start_pos = start_pos
|
||||||
self.end_pos = end_pos
|
self.end_pos = end_pos
|
||||||
self.parent = None
|
self.parent = lambda: None
|
||||||
|
|
||||||
def get_parent_until(self, *classes):
|
def get_parent_until(self, *classes):
|
||||||
""" Takes always the parent, until one class (not a Class) """
|
""" Takes always the parent, until one class (not a Class) """
|
||||||
scope = self
|
scope = self
|
||||||
while not (scope.parent is None or scope.__class__ in classes):
|
while not (scope.parent() is None or scope.__class__ in classes):
|
||||||
scope = scope.parent
|
scope = scope.parent()
|
||||||
return scope
|
return scope
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -109,8 +110,8 @@ class Scope(Simple):
|
|||||||
self.docstr = docstr
|
self.docstr = docstr
|
||||||
|
|
||||||
def add_scope(self, sub, decorators):
|
def add_scope(self, sub, decorators):
|
||||||
# print 'push scope: [%s@%s]' % sub.start_pos
|
print 'push scope @%s,%s' % sub.start_pos
|
||||||
sub.parent = self
|
sub.parent = weakref.ref(self)
|
||||||
sub.decorators = decorators
|
sub.decorators = decorators
|
||||||
for d in decorators:
|
for d in decorators:
|
||||||
# the parent is the same, because the decorator has not the scope
|
# the parent is the same, because the decorator has not the scope
|
||||||
@@ -124,7 +125,7 @@ class Scope(Simple):
|
|||||||
Used to add a Statement or a Scope.
|
Used to add a Statement or a Scope.
|
||||||
A statement would be a normal command (Statement) or a Scope (Flow).
|
A statement would be a normal command (Statement) or a Scope (Flow).
|
||||||
"""
|
"""
|
||||||
stmt.parent = self
|
stmt.parent = weakref.ref(self)
|
||||||
self.statements.append(stmt)
|
self.statements.append(stmt)
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@ class Scope(Simple):
|
|||||||
|
|
||||||
def add_import(self, imp):
|
def add_import(self, imp):
|
||||||
self.imports.append(imp)
|
self.imports.append(imp)
|
||||||
imp.parent = self
|
imp.parent = weakref.ref(self)
|
||||||
|
|
||||||
def get_imports(self):
|
def get_imports(self):
|
||||||
""" Gets also the imports within flow statements """
|
""" Gets also the imports within flow statements """
|
||||||
@@ -291,10 +292,10 @@ class Class(Scope):
|
|||||||
def __init__(self, name, supers, start_pos, docstr=''):
|
def __init__(self, name, supers, start_pos, docstr=''):
|
||||||
super(Class, self).__init__(start_pos, docstr)
|
super(Class, self).__init__(start_pos, docstr)
|
||||||
self.name = name
|
self.name = name
|
||||||
name.parent = self
|
name.parent = weakref.ref(self)
|
||||||
self.supers = supers
|
self.supers = supers
|
||||||
for s in self.supers:
|
for s in self.supers:
|
||||||
s.parent = self
|
s.parent = weakref.ref(self)
|
||||||
self.decorators = []
|
self.decorators = []
|
||||||
|
|
||||||
def get_code(self, first_indent=False, indention=" "):
|
def get_code(self, first_indent=False, indention=" "):
|
||||||
@@ -326,10 +327,10 @@ class Function(Scope):
|
|||||||
def __init__(self, name, params, start_pos, docstr=''):
|
def __init__(self, name, params, start_pos, docstr=''):
|
||||||
Scope.__init__(self, start_pos, docstr)
|
Scope.__init__(self, start_pos, docstr)
|
||||||
self.name = name
|
self.name = name
|
||||||
name.parent = self
|
name.parent = weakref.ref(self)
|
||||||
self.params = params
|
self.params = params
|
||||||
for p in params:
|
for p in params:
|
||||||
p.parent = self
|
p.parent = weakref.ref(self)
|
||||||
self.decorators = []
|
self.decorators = []
|
||||||
self.returns = []
|
self.returns = []
|
||||||
self.is_generator = False
|
self.is_generator = False
|
||||||
@@ -378,30 +379,37 @@ class Flow(Scope):
|
|||||||
:type set_vars: list
|
:type set_vars: list
|
||||||
"""
|
"""
|
||||||
def __init__(self, command, inits, start_pos, set_vars=None):
|
def __init__(self, command, inits, start_pos, set_vars=None):
|
||||||
self._parent = None
|
|
||||||
self.next = None
|
|
||||||
super(Flow, self).__init__(start_pos, '')
|
super(Flow, self).__init__(start_pos, '')
|
||||||
|
self.next = None
|
||||||
|
#self.top_flow = weakref.ref(self)
|
||||||
self.command = command
|
self.command = command
|
||||||
# These have to be statements, because of with, which takes multiple.
|
# These have to be statements, because of with, which takes multiple.
|
||||||
self.inits = inits
|
self.inits = inits
|
||||||
for s in inits:
|
for s in inits:
|
||||||
s.parent = self
|
s.parent = weakref.ref(self)
|
||||||
if set_vars == None:
|
if set_vars == None:
|
||||||
self.set_vars = []
|
self.set_vars = []
|
||||||
else:
|
else:
|
||||||
self.set_vars = set_vars
|
self.set_vars = set_vars
|
||||||
for s in self.set_vars:
|
for s in self.set_vars:
|
||||||
s.parent = self
|
s.parent = weakref.ref(self)
|
||||||
|
|
||||||
@property
|
"""
|
||||||
def parent(self):
|
def parent(self):
|
||||||
return self._parent
|
if self._parent is None:
|
||||||
|
return self.top_flow().parent()
|
||||||
|
else:
|
||||||
|
return self._parent()
|
||||||
|
# TODO REMOVE
|
||||||
|
"""
|
||||||
|
|
||||||
@parent.setter
|
def set_parent(self, value):
|
||||||
def parent(self, value):
|
"""
|
||||||
self._parent = value
|
Normally this would be a setter, but since parents are normally
|
||||||
if self.next:
|
weakrefs (and therefore require execution),
|
||||||
self.next.parent = value
|
I use a java like setter here.
|
||||||
|
"""
|
||||||
|
self._parent = weakref.ref(value)
|
||||||
|
|
||||||
def get_code(self, first_indent=False, indention=" "):
|
def get_code(self, first_indent=False, indention=" "):
|
||||||
if self.set_vars:
|
if self.set_vars:
|
||||||
@@ -451,7 +459,9 @@ class Flow(Scope):
|
|||||||
return self.next.set_next(next)
|
return self.next.set_next(next)
|
||||||
else:
|
else:
|
||||||
self.next = next
|
self.next = next
|
||||||
next.parent = self.parent
|
self.next.parent = self.parent
|
||||||
|
print 'n', self.next
|
||||||
|
#next.top_flow = self.top_flow
|
||||||
return next
|
return next
|
||||||
|
|
||||||
|
|
||||||
@@ -491,15 +501,15 @@ class Import(Simple):
|
|||||||
|
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
if namespace:
|
if namespace:
|
||||||
namespace.parent = self
|
namespace.parent = weakref.ref(self)
|
||||||
|
|
||||||
self.alias = alias
|
self.alias = alias
|
||||||
if alias:
|
if alias:
|
||||||
alias.parent = self
|
alias.parent = weakref.ref(self)
|
||||||
|
|
||||||
self.from_ns = from_ns
|
self.from_ns = from_ns
|
||||||
if from_ns:
|
if from_ns:
|
||||||
from_ns.parent = self
|
from_ns.parent = weakref.ref(self)
|
||||||
|
|
||||||
self.star = star
|
self.star = star
|
||||||
self.relative_count = relative_count
|
self.relative_count = relative_count
|
||||||
@@ -561,7 +571,7 @@ class Statement(Simple):
|
|||||||
self.used_vars = used_vars
|
self.used_vars = used_vars
|
||||||
self.token_list = token_list
|
self.token_list = token_list
|
||||||
for s in set_vars + used_funcs + used_vars:
|
for s in set_vars + used_funcs + used_vars:
|
||||||
s.parent = self
|
s.parent = weakref.ref(self)
|
||||||
|
|
||||||
# cache
|
# cache
|
||||||
self._assignment_calls = None
|
self._assignment_calls = None
|
||||||
@@ -938,7 +948,8 @@ class Name(Simple):
|
|||||||
def __init__(self, names, start_pos, end_pos, parent=None):
|
def __init__(self, names, start_pos, end_pos, parent=None):
|
||||||
super(Name, self).__init__(start_pos, end_pos)
|
super(Name, self).__init__(start_pos, end_pos)
|
||||||
self.names = tuple(NamePart(n) for n in names)
|
self.names = tuple(NamePart(n) for n in names)
|
||||||
self.parent = parent
|
if parent is not None:
|
||||||
|
self.parent = weakref.ref(parent)
|
||||||
|
|
||||||
def get_code(self):
|
def get_code(self):
|
||||||
""" Returns the names in a full string format """
|
""" Returns the names in a full string format """
|
||||||
@@ -1326,7 +1337,7 @@ class PyFuzzyParser(object):
|
|||||||
"""
|
"""
|
||||||
buf = BytesIO(self.code)
|
buf = BytesIO(self.code)
|
||||||
self.gen = tokenize_func(buf.readline)
|
self.gen = tokenize_func(buf.readline)
|
||||||
self.currentscope = self.scope
|
self.currentscope = self.scope # TODO remove?
|
||||||
|
|
||||||
extended_flow = ['else', 'elif', 'except', 'finally']
|
extended_flow = ['else', 'elif', 'except', 'finally']
|
||||||
statement_toks = ['{', '[', '(', '`']
|
statement_toks = ['{', '[', '(', '`']
|
||||||
@@ -1338,6 +1349,8 @@ class PyFuzzyParser(object):
|
|||||||
token_type, tok = self.next()
|
token_type, tok = self.next()
|
||||||
#debug.dbg('main: tok=[%s] type=[%s] indent=[%s]'\
|
#debug.dbg('main: tok=[%s] type=[%s] indent=[%s]'\
|
||||||
# % (tok, token_type, start_position[0]))
|
# % (tok, token_type, start_position[0]))
|
||||||
|
print('main: tok=[%s] type=[%s] indent=[%s]'
|
||||||
|
% (tok, tokenize.tok_name[token_type], self.start_pos[0]))
|
||||||
|
|
||||||
while token_type == tokenize.DEDENT \
|
while token_type == tokenize.DEDENT \
|
||||||
and self.scope != self.module:
|
and self.scope != self.module:
|
||||||
@@ -1345,7 +1358,7 @@ class PyFuzzyParser(object):
|
|||||||
token_type, tok = self.next()
|
token_type, tok = self.next()
|
||||||
if self.start_pos[1] <= self.scope.start_pos[1]:
|
if self.start_pos[1] <= self.scope.start_pos[1]:
|
||||||
self.scope.end_pos = self.start_pos
|
self.scope.end_pos = self.start_pos
|
||||||
self.scope = self.scope.parent
|
self.scope = self.scope.parent()
|
||||||
|
|
||||||
# check again for unindented stuff. this is true for syntax
|
# check again for unindented stuff. this is true for syntax
|
||||||
# errors. only check for names, because thats relevant here. If
|
# errors. only check for names, because thats relevant here. If
|
||||||
@@ -1355,7 +1368,7 @@ class PyFuzzyParser(object):
|
|||||||
and self.scope != self.module:
|
and self.scope != self.module:
|
||||||
debug.dbg('syntax: dedent @%s - %s<=%s', self.start_pos)
|
debug.dbg('syntax: dedent @%s - %s<=%s', self.start_pos)
|
||||||
self.scope.end_pos = self.start_pos
|
self.scope.end_pos = self.start_pos
|
||||||
self.scope = self.scope.parent
|
self.scope = self.scope.parent()
|
||||||
|
|
||||||
first_pos = self.start_pos
|
first_pos = self.start_pos
|
||||||
if tok == 'def':
|
if tok == 'def':
|
||||||
|
|||||||
Reference in New Issue
Block a user