forked from VimPlug/jedi
First decorator implementations.
This commit is contained in:
@@ -166,7 +166,7 @@ class Evaluator(object):
|
|||||||
|
|
||||||
@memoize_default(evaluator_is_first_arg=True)
|
@memoize_default(evaluator_is_first_arg=True)
|
||||||
def eval_element(self, element):
|
def eval_element(self, element):
|
||||||
debug.dbg('eval_element %s', element)
|
debug.dbg('eval_element %s@%s', element, element.start_pos)
|
||||||
if isinstance(element, (pr.Name, pr.Literal)) or pr.is_node(element, 'atom'):
|
if isinstance(element, (pr.Name, pr.Literal)) or pr.is_node(element, 'atom'):
|
||||||
return self._eval_atom(element)
|
return self._eval_atom(element)
|
||||||
elif isinstance(element, pr.Keyword):
|
elif isinstance(element, pr.Keyword):
|
||||||
|
|||||||
@@ -160,8 +160,7 @@ class NameFinder(object):
|
|||||||
# current scope.
|
# current scope.
|
||||||
if isinstance(stmt, (pr.Param, pr.Import)) \
|
if isinstance(stmt, (pr.Param, pr.Import)) \
|
||||||
or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \
|
or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \
|
||||||
or isinstance(scope, compiled.CompiledObject) \
|
or isinstance(scope, compiled.CompiledObject):
|
||||||
or isinstance(stmt, pr.ExprStmt) and stmt.is_global():
|
|
||||||
# Always reachable.
|
# Always reachable.
|
||||||
names.append(name)
|
names.append(name)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ from itertools import chain
|
|||||||
from jedi._compatibility import use_metaclass, unicode, Python3Method
|
from jedi._compatibility import use_metaclass, unicode, Python3Method
|
||||||
from jedi.parser import representation as pr
|
from jedi.parser import representation as pr
|
||||||
from jedi.parser.tokenize import Token
|
from jedi.parser.tokenize import Token
|
||||||
|
from jedi.parser.pytree import python_symbols
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import common
|
from jedi import common
|
||||||
from jedi.cache import underscore_memoization
|
from jedi.cache import underscore_memoization
|
||||||
@@ -152,7 +153,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
if sub.name.value == '__init__':
|
if sub.name.value == '__init__':
|
||||||
# ``__init__`` is special because the params need are injected
|
# ``__init__`` is special because the params need are injected
|
||||||
# this way. Therefore an execution is necessary.
|
# this way. Therefore an execution is necessary.
|
||||||
if not sub.decorators:
|
if not sub.get_decorators():
|
||||||
# __init__ decorators should generally just be ignored,
|
# __init__ decorators should generally just be ignored,
|
||||||
# because to follow them and their self variables is too
|
# because to follow them and their self variables is too
|
||||||
# complicated.
|
# complicated.
|
||||||
@@ -464,9 +465,16 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
|
|
||||||
# Only enter it, if has not already been processed.
|
# Only enter it, if has not already been processed.
|
||||||
if not self.is_decorated:
|
if not self.is_decorated:
|
||||||
for dec in reversed(self.base_func.decorators):
|
for dec in reversed(self.base_func.get_decorators()):
|
||||||
debug.dbg('decorator: %s %s', dec, f)
|
debug.dbg('decorator: %s %s', dec, f)
|
||||||
dec_results = self._evaluator.eval_statement(dec)
|
dec.children
|
||||||
|
dec_results = self._evaluator.eval_element(dec.children[1])
|
||||||
|
trailer = dec.children[2:-1]
|
||||||
|
if trailer:
|
||||||
|
# Create a trailer and evaluate it.
|
||||||
|
trailer = pr.Node(python_symbols.trailer, trailer)
|
||||||
|
dec_results = self._evaluator.eval_trailer(trailer)
|
||||||
|
|
||||||
if not len(dec_results):
|
if not len(dec_results):
|
||||||
debug.warning('decorator not found: %s on %s', dec, self.base_func)
|
debug.warning('decorator not found: %s on %s', dec, self.base_func)
|
||||||
return None
|
return None
|
||||||
@@ -474,6 +482,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
if dec_results:
|
if dec_results:
|
||||||
debug.warning('multiple decorators found %s %s',
|
debug.warning('multiple decorators found %s %s',
|
||||||
self.base_func, dec_results)
|
self.base_func, dec_results)
|
||||||
|
|
||||||
# Create param array.
|
# Create param array.
|
||||||
old_func = Function(self._evaluator, f, is_decorated=True)
|
old_func = Function(self._evaluator, f, is_decorated=True)
|
||||||
|
|
||||||
@@ -526,7 +535,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
dec_func = self._decorated_func()
|
dec_func = self._decorated_func()
|
||||||
dec = ''
|
dec = ''
|
||||||
if not self.is_decorated and self.base_func.decorators:
|
if not self.is_decorated and self.base_func.get_decorators():
|
||||||
dec = " is " + repr(dec_func)
|
dec = " is " + repr(dec_func)
|
||||||
return "<e%s of %s%s>" % (type(self).__name__, self.base_func, dec)
|
return "<e%s of %s%s>" % (type(self).__name__, self.base_func, dec)
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class Parser(object):
|
|||||||
'while_stmt': pr.WhileStmt,
|
'while_stmt': pr.WhileStmt,
|
||||||
'try_stmt': pr.TryStmt,
|
'try_stmt': pr.TryStmt,
|
||||||
'comp_for': pr.CompFor,
|
'comp_for': pr.CompFor,
|
||||||
|
'decorator': pr.Decorator,
|
||||||
}
|
}
|
||||||
|
|
||||||
self._ast_mapping = dict((getattr(pytree.python_symbols, k), v)
|
self._ast_mapping = dict((getattr(pytree.python_symbols, k), v)
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ class Scope(Simple, DocstringMixin):
|
|||||||
if include_imports:
|
if include_imports:
|
||||||
checks += self.imports
|
checks += self.imports
|
||||||
if self.isinstance(Function):
|
if self.isinstance(Function):
|
||||||
checks += self.decorators
|
checks += self.get_decorators()
|
||||||
checks += [r for r in self.returns if r is not None]
|
checks += [r for r in self.returns if r is not None]
|
||||||
if self.isinstance(Flow):
|
if self.isinstance(Flow):
|
||||||
checks += self.inputs
|
checks += self.inputs
|
||||||
@@ -699,6 +699,10 @@ class SubModule(Scope, Module):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Decorator(Simple):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ClassOrFunc(Scope):
|
class ClassOrFunc(Scope):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
@@ -706,6 +710,16 @@ class ClassOrFunc(Scope):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return self.children[1]
|
return self.children[1]
|
||||||
|
|
||||||
|
def get_decorators(self):
|
||||||
|
decorated = self.parent
|
||||||
|
if is_node(decorated, 'decorated'):
|
||||||
|
if is_node(decorated.children[0], 'decorators'):
|
||||||
|
return decorated.children[0].children
|
||||||
|
else:
|
||||||
|
return decorated.children[:1]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class Class(ClassOrFunc):
|
class Class(ClassOrFunc):
|
||||||
"""
|
"""
|
||||||
@@ -718,11 +732,9 @@ class Class(ClassOrFunc):
|
|||||||
:param start_pos: The start position (line, column) of the class.
|
:param start_pos: The start position (line, column) of the class.
|
||||||
:type start_pos: tuple(int, int)
|
:type start_pos: tuple(int, int)
|
||||||
"""
|
"""
|
||||||
__slots__ = ('decorators')
|
|
||||||
|
|
||||||
def __init__(self, children):
|
def __init__(self, children):
|
||||||
super(Class, self).__init__(children)
|
super(Class, self).__init__(children)
|
||||||
self.decorators = []
|
|
||||||
|
|
||||||
def get_super_arglist(self):
|
def get_super_arglist(self):
|
||||||
if len(self.children) == 4: # Has no parentheses
|
if len(self.children) == 4: # Has no parentheses
|
||||||
@@ -762,11 +774,10 @@ class Function(ClassOrFunc):
|
|||||||
:param start_pos: The start position (line, column) the Function.
|
:param start_pos: The start position (line, column) the Function.
|
||||||
:type start_pos: tuple(int, int)
|
:type start_pos: tuple(int, int)
|
||||||
"""
|
"""
|
||||||
__slots__ = ('decorators', 'listeners', 'params')
|
__slots__ = ('listeners', 'params')
|
||||||
|
|
||||||
def __init__(self, children):
|
def __init__(self, children):
|
||||||
super(Function, self).__init__(children)
|
super(Function, self).__init__(children)
|
||||||
self.decorators = []
|
|
||||||
self.listeners = set() # not used here, but in evaluation.
|
self.listeners = set() # not used here, but in evaluation.
|
||||||
self.params = self._params()
|
self.params = self._params()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user