forked from VimPlug/jedi
add a Flow.previous attribute to be able to access the if flow from an else clause.
This commit is contained in:
@@ -243,7 +243,7 @@ def save_parser(path, name, parser, pickling=True):
|
|||||||
|
|
||||||
class ParserPickling(object):
|
class ParserPickling(object):
|
||||||
|
|
||||||
version = 13
|
version = 14
|
||||||
"""
|
"""
|
||||||
Version number (integer) for file system cache.
|
Version number (integer) for file system cache.
|
||||||
|
|
||||||
|
|||||||
7
jedi/evaluate/flow_analysis.py
Normal file
7
jedi/evaluate/flow_analysis.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
NOT_REACHABLE = object()
|
||||||
|
REACHABLE = object()
|
||||||
|
UNSURE = object()
|
||||||
|
|
||||||
|
def break_check(scope):
|
||||||
|
return UNSURE
|
||||||
@@ -47,7 +47,10 @@ def fast_parent_copy(obj):
|
|||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
setattr(new_obj, key, list_rec(value))
|
setattr(new_obj, key, list_rec(value))
|
||||||
elif isinstance(value, pr.Simple):
|
elif isinstance(value, pr.Simple):
|
||||||
setattr(new_obj, key, recursion(value))
|
try: # because of the circular Flow.previous/Flow.next
|
||||||
|
setattr(new_obj, key, new_elements[value])
|
||||||
|
except KeyError:
|
||||||
|
setattr(new_obj, key, recursion(value))
|
||||||
return new_obj
|
return new_obj
|
||||||
|
|
||||||
def list_rec(list_obj):
|
def list_rec(list_obj):
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from jedi.evaluate import iterable
|
|||||||
from jedi.evaluate import docstrings
|
from jedi.evaluate import docstrings
|
||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate import param
|
from jedi.evaluate import param
|
||||||
|
from jedi.evaluate import flow_analysis
|
||||||
|
|
||||||
|
|
||||||
class Executed(pr.IsScope):
|
class Executed(pr.IsScope):
|
||||||
@@ -471,8 +472,14 @@ class FunctionExecution(Executed):
|
|||||||
|
|
||||||
types = list(docstrings.find_return_types(self._evaluator, func))
|
types = list(docstrings.find_return_types(self._evaluator, func))
|
||||||
for r in self.returns:
|
for r in self.returns:
|
||||||
if r is not None:
|
if r is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
check = flow_analysis.break_check(r.parent.parent)
|
||||||
|
if check is not flow_analysis.NOT_REACHABLE:
|
||||||
types += self._evaluator.eval_statement(r)
|
types += self._evaluator.eval_statement(r)
|
||||||
|
if check is flow_analysis.REACHABLE:
|
||||||
|
break
|
||||||
return types
|
return types
|
||||||
|
|
||||||
@memoize_default(default=())
|
@memoize_default(default=())
|
||||||
|
|||||||
@@ -538,9 +538,9 @@ class Parser(object):
|
|||||||
|
|
||||||
f = pr.Flow(self.module, command, inputs, first_pos)
|
f = pr.Flow(self.module, command, inputs, first_pos)
|
||||||
if command in extended_flow:
|
if command in extended_flow:
|
||||||
# the last statement has to be another part of
|
# The last statement has to be another part of the flow
|
||||||
# the flow statement, because a dedent releases the
|
# statement, because a dedent releases the main scope, so
|
||||||
# main scope, so just take the last statement.
|
# just take the last statement.
|
||||||
try:
|
try:
|
||||||
s = self._scope.statements[-1].set_next(f)
|
s = self._scope.statements[-1].set_next(f)
|
||||||
except (AttributeError, IndexError):
|
except (AttributeError, IndexError):
|
||||||
@@ -565,8 +565,9 @@ class Parser(object):
|
|||||||
if stmt is not None:
|
if stmt is not None:
|
||||||
stmt.parent = use_as_parent_scope
|
stmt.parent = use_as_parent_scope
|
||||||
try:
|
try:
|
||||||
func.statements.append(pr.KeywordStatement(tok_str, s,
|
kw_stmt = pr.KeywordStatement(tok_str, s,
|
||||||
use_as_parent_scope, stmt))
|
use_as_parent_scope, stmt)
|
||||||
|
self._scope.statements.append(kw_stmt)
|
||||||
func.returns.append(stmt)
|
func.returns.append(stmt)
|
||||||
# start_pos is the one of the return statement
|
# start_pos is the one of the return statement
|
||||||
stmt.start_pos = s
|
stmt.start_pos = s
|
||||||
|
|||||||
@@ -637,10 +637,11 @@ class Flow(Scope):
|
|||||||
:param start_pos: Position (line, column) of the Flow statement.
|
:param start_pos: Position (line, column) of the Flow statement.
|
||||||
:type start_pos: tuple(int, int)
|
:type start_pos: tuple(int, int)
|
||||||
"""
|
"""
|
||||||
__slots__ = ('next', 'command', '_parent', 'inputs', 'set_vars')
|
__slots__ = ('next', 'previous', 'command', '_parent', 'inputs', 'set_vars')
|
||||||
|
|
||||||
def __init__(self, module, command, inputs, start_pos):
|
def __init__(self, module, command, inputs, start_pos):
|
||||||
self.next = None
|
self.next = None
|
||||||
|
self.previous = None
|
||||||
self.command = command
|
self.command = command
|
||||||
super(Flow, self).__init__(module, start_pos)
|
super(Flow, self).__init__(module, start_pos)
|
||||||
self._parent = None
|
self._parent = None
|
||||||
@@ -706,6 +707,7 @@ class Flow(Scope):
|
|||||||
else:
|
else:
|
||||||
self.next = next
|
self.next = next
|
||||||
self.next.parent = self.parent
|
self.next.parent = self.parent
|
||||||
|
self.next.previous = self
|
||||||
return next
|
return next
|
||||||
|
|
||||||
def scope_names_generator(self, position=None):
|
def scope_names_generator(self, position=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user