forked from VimPlug/jedi
Finish the work on nodes_to_execute.
This commit is contained in:
@@ -222,9 +222,8 @@ def get_executable_nodes(module):
|
|||||||
|
|
||||||
------------ cared for:
|
------------ cared for:
|
||||||
global_stmt
|
global_stmt
|
||||||
exec_stmt
|
exec_stmt # no priority
|
||||||
assert_stmt
|
assert_stmt
|
||||||
compound_stmt
|
|
||||||
if_stmt
|
if_stmt
|
||||||
while_stmt
|
while_stmt
|
||||||
for_stmt
|
for_stmt
|
||||||
@@ -233,21 +232,16 @@ try_stmt
|
|||||||
with_stmt
|
with_stmt
|
||||||
(with_item)
|
(with_item)
|
||||||
(with_var)
|
(with_var)
|
||||||
|
print_stmt
|
||||||
|
del_stmt
|
||||||
|
return_stmt
|
||||||
|
raise_stmt
|
||||||
yield_expr
|
yield_expr
|
||||||
file_input
|
file_input
|
||||||
funcdef
|
funcdef
|
||||||
param
|
param
|
||||||
old_lambdef
|
old_lambdef
|
||||||
lambdef
|
lambdef
|
||||||
print_stmt
|
|
||||||
del_stmt
|
|
||||||
pass_stmt
|
|
||||||
flow_stmt
|
|
||||||
break_stmt
|
|
||||||
continue_stmt
|
|
||||||
return_stmt
|
|
||||||
raise_stmt
|
|
||||||
import_stmt
|
|
||||||
import_name
|
import_name
|
||||||
import_from
|
import_from
|
||||||
(import_as_name)
|
(import_as_name)
|
||||||
@@ -258,6 +252,7 @@ import_from
|
|||||||
classdef
|
classdef
|
||||||
comp_for
|
comp_for
|
||||||
(comp_if) ?
|
(comp_if) ?
|
||||||
|
decorator
|
||||||
|
|
||||||
----------- add basic
|
----------- add basic
|
||||||
test
|
test
|
||||||
@@ -298,8 +293,6 @@ simple_stmt
|
|||||||
testlist_comp # prob ignore and care about it with atom.
|
testlist_comp # prob ignore and care about it with atom.
|
||||||
dictorsetmaker
|
dictorsetmaker
|
||||||
trailer
|
trailer
|
||||||
|
|
||||||
decorator
|
|
||||||
decorators
|
decorators
|
||||||
decorated
|
decorated
|
||||||
|
|
||||||
@@ -312,7 +305,13 @@ vfplist # not in 3
|
|||||||
|
|
||||||
--------- not existing with parser reductions.
|
--------- not existing with parser reductions.
|
||||||
small_stmt
|
small_stmt
|
||||||
|
import_stmt
|
||||||
|
flow_stmt
|
||||||
|
compound_stmt
|
||||||
stmt
|
stmt
|
||||||
|
pass_stmt
|
||||||
|
break_stmt
|
||||||
|
continue_stmt
|
||||||
comp_op
|
comp_op
|
||||||
augassign
|
augassign
|
||||||
old_test
|
old_test
|
||||||
@@ -320,6 +319,7 @@ typedargslist # afaik becomes [param]
|
|||||||
varargslist # dito
|
varargslist # dito
|
||||||
vname
|
vname
|
||||||
comp_iter
|
comp_iter
|
||||||
|
test_nocond
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def check_children(node):
|
def check_children(node):
|
||||||
|
|||||||
@@ -485,6 +485,11 @@ class Node(BaseNode):
|
|||||||
"""Concrete implementation for interior nodes."""
|
"""Concrete implementation for interior nodes."""
|
||||||
__slots__ = ('type',)
|
__slots__ = ('type',)
|
||||||
|
|
||||||
|
_IGNORE_EXECUTE_NODES = set([
|
||||||
|
'suite', 'subscriptlist', 'subscript', 'simple_stmt', 'sliceop',
|
||||||
|
'testlist_comp', 'dictorsetmaker', 'trailer', 'decorators', 'decorated'
|
||||||
|
])
|
||||||
|
|
||||||
def __init__(self, type, children):
|
def __init__(self, type, children):
|
||||||
"""
|
"""
|
||||||
Initializer.
|
Initializer.
|
||||||
@@ -502,6 +507,9 @@ class Node(BaseNode):
|
|||||||
For static analysis.
|
For static analysis.
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
|
if self.type not in Node._IGNORE_EXECUTE_NODES:
|
||||||
|
result.append(self)
|
||||||
|
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
result += child.nodes_to_execute(last_added)
|
result += child.nodes_to_execute(last_added)
|
||||||
return result
|
return result
|
||||||
@@ -655,11 +663,25 @@ class Module(Scope):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
# Yield itself, class needs to be executed for decorator checks.
|
||||||
|
result = []
|
||||||
|
for child in self.children:
|
||||||
|
result += child.nodes_to_execute()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Decorator(BaseNode):
|
class Decorator(BaseNode):
|
||||||
type = 'decorator'
|
type = 'decorator'
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
if self.children[-2] == ')':
|
||||||
|
node = self.children[-3]
|
||||||
|
if node != '(':
|
||||||
|
return node.nodes_to_execute()
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class ClassOrFunc(Scope):
|
class ClassOrFunc(Scope):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -727,7 +749,7 @@ class Class(ClassOrFunc):
|
|||||||
# metaclass=
|
# metaclass=
|
||||||
raise NotImplementedError('Metaclasses not implemented')
|
raise NotImplementedError('Metaclasses not implemented')
|
||||||
# care for the class suite:
|
# care for the class suite:
|
||||||
for node_to_execute in self.children[-1].nodes_to_execute(False):
|
for node_to_execute in self.children[-1].nodes_to_execute():
|
||||||
yield node_to_execute
|
yield node_to_execute
|
||||||
|
|
||||||
|
|
||||||
@@ -840,7 +862,7 @@ class Function(ClassOrFunc):
|
|||||||
if param.default is not None:
|
if param.default is not None:
|
||||||
yield param.default
|
yield param.default
|
||||||
# care for the function suite:
|
# care for the function suite:
|
||||||
for node_to_execute in self.children[-1].nodes_to_execute(False):
|
for node_to_execute in self.children[-1].nodes_to_execute():
|
||||||
yield node_to_execute
|
yield node_to_execute
|
||||||
|
|
||||||
|
|
||||||
@@ -873,7 +895,7 @@ class Lambda(Function):
|
|||||||
if param.default is not None:
|
if param.default is not None:
|
||||||
yield param.default
|
yield param.default
|
||||||
# Care for the lambda test (last child):
|
# Care for the lambda test (last child):
|
||||||
for node_to_execute in self.children[-1].nodes_to_execute(False):
|
for node_to_execute in self.children[-1].nodes_to_execute():
|
||||||
yield node_to_execute
|
yield node_to_execute
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -885,7 +907,7 @@ class Flow(BaseNode):
|
|||||||
|
|
||||||
def nodes_to_execute(self, last_added=False):
|
def nodes_to_execute(self, last_added=False):
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
for node_to_execute in child.nodes_to_execute(False):
|
for node_to_execute in child.nodes_to_execute():
|
||||||
yield node_to_execute
|
yield node_to_execute
|
||||||
|
|
||||||
|
|
||||||
@@ -948,6 +970,16 @@ class TryStmt(Flow):
|
|||||||
elif node == 'except':
|
elif node == 'except':
|
||||||
yield None
|
yield None
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
result = []
|
||||||
|
for child in self.children[2::3]:
|
||||||
|
result += child.nodes_to_execute()
|
||||||
|
for child in self.children[0::3]:
|
||||||
|
if child.type == 'except_clause':
|
||||||
|
# Add the test node and ignore the `as NAME` definition.
|
||||||
|
result += child.children[1].nodes_to_execute()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class WithStmt(Flow):
|
class WithStmt(Flow):
|
||||||
type = 'with_stmt'
|
type = 'with_stmt'
|
||||||
@@ -968,6 +1000,16 @@ class WithStmt(Flow):
|
|||||||
if is_node(node, 'with_item'):
|
if is_node(node, 'with_item'):
|
||||||
return node.children[0]
|
return node.children[0]
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
result = []
|
||||||
|
for child in self.children[1::2]:
|
||||||
|
if child.type == 'with_item':
|
||||||
|
# Just ignore the `as EXPR` part - at least for now, because
|
||||||
|
# most times it's just a name.
|
||||||
|
child = child.children[0]
|
||||||
|
result += child.nodes_to_execute()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Import(BaseNode):
|
class Import(BaseNode):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -990,6 +1032,14 @@ class Import(BaseNode):
|
|||||||
def is_star_import(self):
|
def is_star_import(self):
|
||||||
return self.children[-1] == '*'
|
return self.children[-1] == '*'
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
"""
|
||||||
|
`nodes_to_execute` works a bit different for imports, because the names
|
||||||
|
itself cannot directly get resolved (except on itself).
|
||||||
|
"""
|
||||||
|
# TODO couldn't we return the names? Would be nicer.
|
||||||
|
return [self]
|
||||||
|
|
||||||
|
|
||||||
class ImportFrom(Import):
|
class ImportFrom(Import):
|
||||||
type = 'import_from'
|
type = 'import_from'
|
||||||
@@ -1114,7 +1164,10 @@ class ImportName(Import):
|
|||||||
class KeywordStatement(BaseNode):
|
class KeywordStatement(BaseNode):
|
||||||
"""
|
"""
|
||||||
For the following statements: `assert`, `del`, `global`, `nonlocal`,
|
For the following statements: `assert`, `del`, `global`, `nonlocal`,
|
||||||
`raise`, `return`, `yield`, `pass`, `continue`, `break`, `return`, `yield`.
|
`raise`, `return`, `yield`, `return`, `yield`.
|
||||||
|
|
||||||
|
`pass`, `continue` and `break` are not in there, because they are just
|
||||||
|
simple keywords and the parser reduces it to a keyword.
|
||||||
"""
|
"""
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
@@ -1130,6 +1183,12 @@ class KeywordStatement(BaseNode):
|
|||||||
def keyword(self):
|
def keyword(self):
|
||||||
return self.children[0].value
|
return self.children[0].value
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
result = []
|
||||||
|
for child in self.children:
|
||||||
|
result += child.nodes_to_execute(last_added)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class AssertStmt(KeywordStatement):
|
class AssertStmt(KeywordStatement):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -1147,6 +1206,13 @@ class GlobalStmt(KeywordStatement):
|
|||||||
def get_global_names(self):
|
def get_global_names(self):
|
||||||
return self.children[1::2]
|
return self.children[1::2]
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
"""
|
||||||
|
The global keyword allows to define any name. Even if it doesn't
|
||||||
|
exist.
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class ReturnStmt(KeywordStatement):
|
class ReturnStmt(KeywordStatement):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -1202,6 +1268,14 @@ class ExprStmt(BaseNode, DocstringMixin):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def nodes_to_execute(self, last_added=False):
|
||||||
|
# I think evaluating the statment (and possibly returned arrays),
|
||||||
|
# should be enough for static analysis.
|
||||||
|
result = [self]
|
||||||
|
for child in self.children:
|
||||||
|
result += child.nodes_to_execute(last_added=True)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Param(BaseNode):
|
class Param(BaseNode):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user