1
0
forked from VimPlug/jedi

Finish the work on nodes_to_execute.

This commit is contained in:
Dave Halter
2015-09-18 01:45:44 +02:00
parent de836a6575
commit e09b0a2aab
2 changed files with 92 additions and 18 deletions

View File

@@ -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):

View File

@@ -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):
""" """