forked from VimPlug/jedi
Fix comprehensions type issues.
This commit is contained in:
@@ -30,6 +30,7 @@ from jedi.evaluate import Evaluator
|
||||
from jedi.evaluate import representation as er
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate.param import try_iter_content
|
||||
from jedi.evaluate.cache import memoize_default
|
||||
from jedi.evaluate.helpers import FakeName, get_module_names
|
||||
from jedi.evaluate.finder import global_names_dict_generator, filter_definition_names
|
||||
@@ -524,32 +525,27 @@ class Script(object):
|
||||
for o in origins if hasattr(o, 'py__call__')]
|
||||
|
||||
def _analysis(self):
|
||||
def check_types(types):
|
||||
for typ in types:
|
||||
try:
|
||||
f = typ.iter_content
|
||||
except AttributeError:
|
||||
pass
|
||||
self._evaluator.is_analysis = True
|
||||
try:
|
||||
for node in self._parser.module().nodes_to_execute():
|
||||
if node.type in ('funcdef', 'classdef'):
|
||||
if node.type == 'classdef':
|
||||
continue
|
||||
raise NotImplementedError
|
||||
er.Function(self._evaluator, node).get_decorated_func()
|
||||
elif isinstance(node, tree.Import):
|
||||
import_names = set(node.get_defined_names())
|
||||
if node.is_nested():
|
||||
import_names |= set(path[-1] for path in node.paths())
|
||||
for n in import_names:
|
||||
imports.ImportWrapper(self._evaluator, n).follow()
|
||||
else:
|
||||
check_types(f())
|
||||
try_iter_content(self._evaluator.eval_element(node))
|
||||
|
||||
for node in self._parser.module().nodes_to_execute():
|
||||
if node.type in ('funcdef', 'classdef'):
|
||||
if node.type == 'classdef':
|
||||
continue
|
||||
raise NotImplementedError
|
||||
er.Function(self._evaluator, node).get_decorated_func()
|
||||
elif isinstance(node, tree.Import):
|
||||
import_names = set(node.get_defined_names())
|
||||
if node.is_nested():
|
||||
import_names |= set(path[-1] for path in node.paths())
|
||||
for n in import_names:
|
||||
imports.ImportWrapper(self._evaluator, n).follow()
|
||||
else:
|
||||
check_types(self._evaluator.eval_element(node))
|
||||
|
||||
ana = [a for a in self._evaluator.analysis if self.path == a.path]
|
||||
return sorted(set(ana), key=lambda x: x.line)
|
||||
ana = [a for a in self._evaluator.analysis if self.path == a.path]
|
||||
return sorted(set(ana), key=lambda x: x.line)
|
||||
finally:
|
||||
self._evaluator.is_analysis = False
|
||||
|
||||
|
||||
class Interpreter(Script):
|
||||
|
||||
@@ -89,6 +89,7 @@ class Evaluator(object):
|
||||
self.execution_recursion_detector = recursion.ExecutionRecursionDetector()
|
||||
self.analysis = []
|
||||
self.predefined_if_name_dict_dict = {}
|
||||
self.is_analysis = False
|
||||
|
||||
def wrap(self, element):
|
||||
if isinstance(element, tree.Class):
|
||||
@@ -343,6 +344,9 @@ class Evaluator(object):
|
||||
if not isinstance(arguments, param.Arguments):
|
||||
arguments = param.Arguments(self, arguments, trailer)
|
||||
|
||||
if self.is_analysis:
|
||||
arguments.eval_all()
|
||||
|
||||
if obj.isinstance(er.Function):
|
||||
obj = obj.get_decorated_func()
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ class Comprehension(IterableWrapper):
|
||||
return [self._evaluator.eval_element(self.eval_node())[index]]
|
||||
|
||||
def __repr__(self):
|
||||
return "<e%s of %s>" % (type(self).__name__, self._atom)
|
||||
return "<%s of %s>" % (type(self).__name__, self._atom)
|
||||
|
||||
|
||||
class ArrayMixin(object):
|
||||
|
||||
@@ -12,6 +12,17 @@ from jedi.evaluate.helpers import FakeName
|
||||
from jedi.cache import underscore_memoization
|
||||
|
||||
|
||||
def try_iter_content(types):
|
||||
"""Helper method for static analysis."""
|
||||
for typ in types:
|
||||
try:
|
||||
f = typ.iter_content
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
try_iter_content(f())
|
||||
|
||||
|
||||
class Arguments(tree.Base):
|
||||
def __init__(self, evaluator, argument_node, trailer=None):
|
||||
"""
|
||||
@@ -160,6 +171,16 @@ class Arguments(tree.Base):
|
||||
else:
|
||||
return None
|
||||
|
||||
def eval_all(self, func=None):
|
||||
"""
|
||||
Evaluates all arguments as a support for static analysis
|
||||
(normally Jedi).
|
||||
"""
|
||||
for key, element_values in self.unpack():
|
||||
for element in element_values:
|
||||
types = self._evaluator.eval_element(element)
|
||||
try_iter_content(types)
|
||||
|
||||
|
||||
class ExecutedParam(tree.Param):
|
||||
"""Fake a param and give it values."""
|
||||
|
||||
@@ -517,7 +517,7 @@ class Node(BaseNode):
|
||||
For static analysis.
|
||||
"""
|
||||
result = []
|
||||
if self.type not in Node._IGNORE_EXECUTE_NODES:
|
||||
if self.type not in Node._IGNORE_EXECUTE_NODES and not last_added:
|
||||
result.append(self)
|
||||
last_added = True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user