forked from VimPlug/jedi
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:
@@ -106,7 +106,8 @@ class NameFinder(object):
|
|||||||
else:
|
else:
|
||||||
check = flow_analysis.break_check(self._evaluator,
|
check = flow_analysis.break_check(self._evaluator,
|
||||||
name_list_scope,
|
name_list_scope,
|
||||||
er.wrap(self._evaluator, scope))
|
er.wrap(self._evaluator, scope),
|
||||||
|
self.scope)
|
||||||
if check is not flow_analysis.UNREACHABLE:
|
if check is not flow_analysis.UNREACHABLE:
|
||||||
result.append(name)
|
result.append(name)
|
||||||
if check is flow_analysis.REACHABLE:
|
if check is flow_analysis.REACHABLE:
|
||||||
|
|||||||
@@ -32,11 +32,21 @@ UNREACHABLE = Status(False, 'unreachable')
|
|||||||
UNSURE = Status(None, 'unsure')
|
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
|
from jedi.evaluate.representation import wrap
|
||||||
base_scope = wrap(evaluator, base_scope)
|
base_scope = wrap(evaluator, base_scope)
|
||||||
element_scope = wrap(evaluator, element_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
|
reachable = REACHABLE
|
||||||
if isinstance(element_scope, Flow):
|
if isinstance(element_scope, Flow):
|
||||||
if element_scope.command == 'else':
|
if element_scope.command == 'else':
|
||||||
|
|||||||
@@ -182,3 +182,26 @@ isinst(1.0)
|
|||||||
isinst(False)
|
isinst(False)
|
||||||
#? int()
|
#? int()
|
||||||
isinst('')
|
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
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ def test_signature_is_definition():
|
|||||||
# Now compare all the attributes that a CallSignature must also have.
|
# Now compare all the attributes that a CallSignature must also have.
|
||||||
for attr_name in dir(definition):
|
for attr_name in dir(definition):
|
||||||
dont_scan = ['defined_names', 'line_nr', 'start_pos', 'documentation',
|
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:
|
if attr_name.startswith('_') or attr_name in dont_scan:
|
||||||
continue
|
continue
|
||||||
attribute = getattr(definition, attr_name)
|
attribute = getattr(definition, attr_name)
|
||||||
|
|||||||
Reference in New Issue
Block a user