mirror of
https://github.com/davidhalter/jedi.git
synced 2026-01-01 09:43:21 +08:00
Improve flow analysis a bit.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from jedi.parser.representation import Flow
|
||||
from jedi.parser import representation as pr
|
||||
|
||||
|
||||
class Status(object):
|
||||
@@ -32,10 +32,10 @@ UNREACHABLE = Status(False, 'unreachable')
|
||||
UNSURE = Status(None, 'unsure')
|
||||
|
||||
|
||||
def break_check(evaluator, base_scope, element_scope, origin_scope=None):
|
||||
def break_check(evaluator, base_scope, stmt, origin_scope=None):
|
||||
from jedi.evaluate.representation import wrap
|
||||
base_scope = wrap(evaluator, base_scope)
|
||||
element_scope = wrap(evaluator, element_scope)
|
||||
element_scope = wrap(evaluator, stmt.parent)
|
||||
|
||||
# Direct parents get resolved, we filter scopes that are separate branches.
|
||||
# This makes sense for autocompletion and static analysis. For actual
|
||||
@@ -48,17 +48,18 @@ def break_check(evaluator, base_scope, element_scope, origin_scope=None):
|
||||
s = s.parent
|
||||
|
||||
reachable = REACHABLE
|
||||
if isinstance(element_scope, Flow):
|
||||
if element_scope.command == 'else':
|
||||
check_scope = element_scope
|
||||
while check_scope.previous is not None:
|
||||
check_scope = check_scope.previous
|
||||
reachable = _check_flow(evaluator, check_scope)
|
||||
if isinstance(element_scope, pr.IfStmt):
|
||||
if element_scope.node_after_else(stmt):
|
||||
for check_node in element_scope.check_nodes():
|
||||
reachable = _check_if(evaluator, check_node)
|
||||
if reachable in (REACHABLE, UNSURE):
|
||||
break
|
||||
reachable = reachable.invert()
|
||||
else:
|
||||
reachable = _check_flow(evaluator, element_scope)
|
||||
node = element_scope.node_in_which_check_node(stmt)
|
||||
reachable = _check_if(evaluator, node)
|
||||
elif isinstance(element_scope, (pr.TryStmt, pr.WhileStmt)):
|
||||
return UNSURE
|
||||
|
||||
# Only reachable branches need to be examined further.
|
||||
if reachable in (UNREACHABLE, UNSURE):
|
||||
@@ -69,15 +70,10 @@ def break_check(evaluator, base_scope, element_scope, origin_scope=None):
|
||||
return reachable
|
||||
|
||||
|
||||
def _check_flow(evaluator, flow):
|
||||
if flow.command in ('elif', 'if') and flow.inputs:
|
||||
types = evaluator.eval_statement(flow.inputs[0])
|
||||
values = set(x.py__bool__() for x in types)
|
||||
if len(values) == 1:
|
||||
return Status.lookup_table[values.pop()]
|
||||
else:
|
||||
return UNSURE
|
||||
elif flow.command in ('try', 'except', 'finally', 'while'):
|
||||
def _check_if(evaluator, node):
|
||||
types = evaluator.eval_element(node)
|
||||
values = set(x.py__bool__() for x in types)
|
||||
if len(values) == 1:
|
||||
return Status.lookup_table[values.pop()]
|
||||
else:
|
||||
return UNSURE
|
||||
else: # for loop
|
||||
return REACHABLE
|
||||
|
||||
Reference in New Issue
Block a user