Fix issues with unreachable flows.

This benefits static analysis as well as autocompletion: Unreachable code (things like code within 'if 0:') should still be resolveable.
This commit is contained in:
Dave Halter
2014-09-03 00:05:37 +02:00
parent ea5b98905e
commit bcc84820fe
4 changed files with 37 additions and 3 deletions

View File

@@ -106,7 +106,8 @@ class NameFinder(object):
else:
check = flow_analysis.break_check(self._evaluator,
name_list_scope,
er.wrap(self._evaluator, scope))
er.wrap(self._evaluator, scope),
self.scope)
if check is not flow_analysis.UNREACHABLE:
result.append(name)
if check is flow_analysis.REACHABLE:

View File

@@ -32,11 +32,21 @@ UNREACHABLE = Status(False, 'unreachable')
UNSURE = Status(None, 'unsure')
def break_check(evaluator, base_scope, element_scope):
def break_check(evaluator, base_scope, element_scope, origin_scope=None):
from jedi.evaluate.representation import wrap
base_scope = wrap(evaluator, base_scope)
element_scope = wrap(evaluator, element_scope)
# Direct parents get resolved, we filter scopes that are separate branches.
# This makes sense for autocompletion and static analysis. For actual
# Python it doesn't matter, because we're talking about potentially
# unreachable code.
s = origin_scope
while s is not None:
if element_scope == s:
return REACHABLE
s = s.parent
reachable = REACHABLE
if isinstance(element_scope, Flow):
if element_scope.command == 'else':

View File

@@ -182,3 +182,26 @@ isinst(1.0)
isinst(False)
#? int()
isinst('')
# -----------------
# flows that are not reachable should be able to access parent scopes.
# -----------------
foobar = ''
if 0:
within_flow = 1.0
#? float()
within_flow
#? str()
foobar
if 0:
nested = 1
#? int()
nested
#? float()
within_flow
#? str()
foobar
#?
nested

View File

@@ -207,7 +207,7 @@ def test_signature_is_definition():
# Now compare all the attributes that a CallSignature must also have.
for attr_name in dir(definition):
dont_scan = ['defined_names', 'line_nr', 'start_pos', 'documentation',
'doc', 'parent']
'doc', 'parent', 'goto_assignments']
if attr_name.startswith('_') or attr_name in dont_scan:
continue
attribute = getattr(definition, attr_name)