forked from VimPlug/jedi
A lot of small improvements.
This commit is contained in:
@@ -137,7 +137,7 @@ class Script(object):
|
|||||||
parser = FastParser(self._grammar, self._source, self.path)
|
parser = FastParser(self._grammar, self._source, self.path)
|
||||||
save_parser(self.path, parser, pickling=False)
|
save_parser(self.path, parser, pickling=False)
|
||||||
|
|
||||||
module = self._evaluator.wrap(parser.module)
|
module = self._evaluator.wrap(parser.module, parent_context=None)
|
||||||
imports.add_module(self._evaluator, unicode(module.name), module)
|
imports.add_module(self._evaluator, unicode(module.name), module)
|
||||||
return parser.module
|
return parser.module
|
||||||
|
|
||||||
@@ -188,7 +188,9 @@ class Script(object):
|
|||||||
leaf = self._get_module().get_leaf_for_position(self._pos)
|
leaf = self._get_module().get_leaf_for_position(self._pos)
|
||||||
if leaf is None:
|
if leaf is None:
|
||||||
return []
|
return []
|
||||||
definitions = helpers.evaluate_goto_definition(self._evaluator, leaf)
|
|
||||||
|
context = self._evaluator.create_context(leaf)
|
||||||
|
definitions = helpers.evaluate_goto_definition(self._evaluator, context, leaf)
|
||||||
|
|
||||||
names = [s.name for s in definitions]
|
names = [s.name for s in definitions]
|
||||||
defs = [classes.Definition(self._evaluator, name) for name in names]
|
defs = [classes.Definition(self._evaluator, name) for name in names]
|
||||||
@@ -299,9 +301,11 @@ class Script(object):
|
|||||||
if call_signature_details is None:
|
if call_signature_details is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
context = self._evaluator.create_context(call_signature_details.bracket_leaf)
|
||||||
with common.scale_speed_settings(settings.scale_call_signatures):
|
with common.scale_speed_settings(settings.scale_call_signatures):
|
||||||
definitions = helpers.cache_call_signatures(
|
definitions = helpers.cache_call_signatures(
|
||||||
self._evaluator,
|
self._evaluator,
|
||||||
|
context,
|
||||||
call_signature_details.bracket_leaf,
|
call_signature_details.bracket_leaf,
|
||||||
self._code_lines,
|
self._code_lines,
|
||||||
self._pos
|
self._pos
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class BaseDefinition(object):
|
|||||||
"""
|
"""
|
||||||
#self._definition = list(self._name.infer())[0]
|
#self._definition = list(self._name.infer())[0]
|
||||||
#self.is_keyword = isinstance(self._definition, keywords.Keyword)
|
#self.is_keyword = isinstance(self._definition, keywords.Keyword)
|
||||||
|
self._definition = None
|
||||||
|
|
||||||
# generate a path to the definition
|
# generate a path to the definition
|
||||||
self._module = name.parent_context.get_root_context()
|
self._module = name.parent_context.get_root_context()
|
||||||
@@ -83,7 +84,7 @@ class BaseDefinition(object):
|
|||||||
|
|
||||||
:rtype: str or None
|
:rtype: str or None
|
||||||
"""
|
"""
|
||||||
return unicode(self._name)
|
return self._name.string_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def start_pos(self):
|
def start_pos(self):
|
||||||
@@ -198,7 +199,7 @@ class BaseDefinition(object):
|
|||||||
>>> print(d.module_name) # doctest: +ELLIPSIS
|
>>> print(d.module_name) # doctest: +ELLIPSIS
|
||||||
json
|
json
|
||||||
"""
|
"""
|
||||||
return str(self._module.name)
|
return self._module.name.string_name
|
||||||
|
|
||||||
def in_builtin_module(self):
|
def in_builtin_module(self):
|
||||||
"""Whether this is a builtin module."""
|
"""Whether this is a builtin module."""
|
||||||
@@ -417,7 +418,7 @@ class Completion(BaseDefinition):
|
|||||||
if 'trailer' in node_names and 'argument' not in node_names:
|
if 'trailer' in node_names and 'argument' not in node_names:
|
||||||
append += '='
|
append += '='
|
||||||
|
|
||||||
name = str(self._name)
|
name = self._name.string_name
|
||||||
if like_name:
|
if like_name:
|
||||||
name = name[self._like_name_length:]
|
name = name[self._like_name_length:]
|
||||||
return name + append
|
return name + append
|
||||||
@@ -450,7 +451,8 @@ class Completion(BaseDefinition):
|
|||||||
def description(self):
|
def description(self):
|
||||||
"""Provide a description of the completion object."""
|
"""Provide a description of the completion object."""
|
||||||
if self._definition is None:
|
if self._definition is None:
|
||||||
return ''
|
return self._name.string_name
|
||||||
|
|
||||||
t = self.type
|
t = self.type
|
||||||
if t == 'statement' or t == 'import':
|
if t == 'statement' or t == 'import':
|
||||||
desc = self._definition.get_code()
|
desc = self._definition.get_code()
|
||||||
@@ -577,7 +579,7 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)):
|
|||||||
d = typ + ' ' + d.name.get_code()
|
d = typ + ' ' + d.name.get_code()
|
||||||
elif isinstance(d, iterable.Array):
|
elif isinstance(d, iterable.Array):
|
||||||
d = 'class ' + d.type
|
d = 'class ' + d.type
|
||||||
elif isinstance(d, (tree.Class, er.Class, er.Instance)):
|
elif isinstance(d, (tree.Class, er.ClassContext, er.Instance)):
|
||||||
d = 'class ' + unicode(d.name)
|
d = 'class ' + unicode(d.name)
|
||||||
elif isinstance(d, (er.Function, tree.Function)):
|
elif isinstance(d, (er.Function, tree.Function)):
|
||||||
d = 'def ' + unicode(d.name)
|
d = 'def ' + unicode(d.name)
|
||||||
@@ -589,6 +591,7 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)):
|
|||||||
if d.endswith(','):
|
if d.endswith(','):
|
||||||
d = d[:-1] # Remove the comma.
|
d = d[:-1] # Remove the comma.
|
||||||
else: # ExprStmt
|
else: # ExprStmt
|
||||||
|
return self._name.string_name
|
||||||
try:
|
try:
|
||||||
first_leaf = d.first_leaf()
|
first_leaf = d.first_leaf()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ def filter_names(evaluator, completion_names, stack, like_name):
|
|||||||
and name.string_name.lower().startswith(like_name.lower()) \
|
and name.string_name.lower().startswith(like_name.lower()) \
|
||||||
or name.string_name.startswith(like_name):
|
or name.string_name.startswith(like_name):
|
||||||
|
|
||||||
print(name, name.infer())
|
|
||||||
new = classes.Completion(
|
new = classes.Completion(
|
||||||
evaluator,
|
evaluator,
|
||||||
name,
|
name,
|
||||||
@@ -71,7 +70,7 @@ def get_user_scope(module, position):
|
|||||||
class Completion:
|
class Completion:
|
||||||
def __init__(self, evaluator, module, code_lines, position, call_signatures_method):
|
def __init__(self, evaluator, module, code_lines, position, call_signatures_method):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self._module = evaluator.wrap(module)
|
self._module = evaluator.wrap(module, parent_context=None)
|
||||||
self._code_lines = code_lines
|
self._code_lines = code_lines
|
||||||
|
|
||||||
# The first step of completions is to get the name
|
# The first step of completions is to get the name
|
||||||
@@ -175,7 +174,7 @@ class Completion:
|
|||||||
scope = get_user_scope(self._module, self._position)
|
scope = get_user_scope(self._module, self._position)
|
||||||
if not scope.is_scope(): # Might be a flow (if/while/etc).
|
if not scope.is_scope(): # Might be a flow (if/while/etc).
|
||||||
scope = scope.get_parent_scope()
|
scope = scope.get_parent_scope()
|
||||||
scope = self._evaluator.wrap(scope)
|
scope = self._evaluator.create_context(scope)
|
||||||
debug.dbg('global completion scope: %s', scope)
|
debug.dbg('global completion scope: %s', scope)
|
||||||
filters = get_global_filters(
|
filters = get_global_filters(
|
||||||
self._evaluator,
|
self._evaluator,
|
||||||
@@ -222,6 +221,7 @@ class Completion:
|
|||||||
"""
|
"""
|
||||||
Autocomplete inherited methods when overriding in child class.
|
Autocomplete inherited methods when overriding in child class.
|
||||||
"""
|
"""
|
||||||
|
return
|
||||||
leaf = self._module.get_leaf_for_position(self._position, include_prefixes=True)
|
leaf = self._module.get_leaf_for_position(self._position, include_prefixes=True)
|
||||||
cls = leaf.get_parent_until(tree.Class)
|
cls = leaf.get_parent_until(tree.Class)
|
||||||
if isinstance(cls, (tree.Class, tree.Function)):
|
if isinstance(cls, (tree.Class, tree.Function)):
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ def get_possible_completion_types(grammar, stack):
|
|||||||
return keywords, grammar_labels
|
return keywords, grammar_labels
|
||||||
|
|
||||||
|
|
||||||
def evaluate_goto_definition(evaluator, leaf):
|
def evaluate_goto_definition(evaluator, context, leaf):
|
||||||
if leaf.type == 'name':
|
if leaf.type == 'name':
|
||||||
# In case of a name we can just use goto_definition which does all the
|
# In case of a name we can just use goto_definition which does all the
|
||||||
# magic itself.
|
# magic itself.
|
||||||
@@ -207,7 +207,7 @@ def evaluate_goto_definition(evaluator, leaf):
|
|||||||
|
|
||||||
if node is None:
|
if node is None:
|
||||||
return []
|
return []
|
||||||
return evaluator.eval_element(node)
|
return evaluator.eval_element(context, node)
|
||||||
|
|
||||||
|
|
||||||
CallSignatureDetails = namedtuple(
|
CallSignatureDetails = namedtuple(
|
||||||
@@ -288,7 +288,7 @@ def get_call_signature_details(module, position):
|
|||||||
|
|
||||||
|
|
||||||
@time_cache("call_signatures_validity")
|
@time_cache("call_signatures_validity")
|
||||||
def cache_call_signatures(evaluator, bracket_leaf, code_lines, user_pos):
|
def cache_call_signatures(evaluator, context, bracket_leaf, code_lines, user_pos):
|
||||||
"""This function calculates the cache key."""
|
"""This function calculates the cache key."""
|
||||||
index = user_pos[0] - 1
|
index = user_pos[0] - 1
|
||||||
|
|
||||||
@@ -304,5 +304,6 @@ def cache_call_signatures(evaluator, bracket_leaf, code_lines, user_pos):
|
|||||||
yield (module_path, before_bracket, bracket_leaf.start_pos)
|
yield (module_path, before_bracket, bracket_leaf.start_pos)
|
||||||
yield evaluate_goto_definition(
|
yield evaluate_goto_definition(
|
||||||
evaluator,
|
evaluator,
|
||||||
|
context,
|
||||||
bracket_leaf.get_previous_leaf()
|
bracket_leaf.get_previous_leaf()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import keyword
|
|||||||
|
|
||||||
from jedi._compatibility import is_py3, is_py35
|
from jedi._compatibility import is_py3, is_py35
|
||||||
from jedi import common
|
from jedi import common
|
||||||
from jedi.evaluate.helpers import FakeName
|
from jedi.evaluate.filters import AbstractNameDefinition
|
||||||
from jedi.parser.tree import Leaf
|
from jedi.parser.tree import Leaf
|
||||||
try:
|
try:
|
||||||
from pydoc_data import topics as pydoc_topics
|
from pydoc_data import topics as pydoc_topics
|
||||||
@@ -66,11 +66,17 @@ keywords_only_valid_as_leaf = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KeywordName(AbstractNameDefinition):
|
||||||
|
def __init__(self, evaluator, name):
|
||||||
|
self.string_name = name
|
||||||
|
self.parent_context = evaluator.BUILTINS
|
||||||
|
|
||||||
|
|
||||||
class Keyword(object):
|
class Keyword(object):
|
||||||
type = 'completion_keyword'
|
type = 'completion_keyword'
|
||||||
|
|
||||||
def __init__(self, evaluator, name, pos):
|
def __init__(self, evaluator, name, pos):
|
||||||
self.name = FakeName(name, self, pos)
|
self.name = KeywordName(evaluator, name)
|
||||||
self.start_pos = pos
|
self.start_pos = pos
|
||||||
self.parent = evaluator.BUILTINS
|
self.parent = evaluator.BUILTINS
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class Evaluator(object):
|
|||||||
self.recursion_detector = recursion.RecursionDetector(self)
|
self.recursion_detector = recursion.RecursionDetector(self)
|
||||||
self.execution_recursion_detector = recursion.ExecutionRecursionDetector(self)
|
self.execution_recursion_detector = recursion.ExecutionRecursionDetector(self)
|
||||||
|
|
||||||
def wrap(self, element, parent_context=None):
|
def wrap(self, element, parent_context):
|
||||||
if isinstance(element, (er.Wrapper, er.InstanceElement,
|
if isinstance(element, (er.Wrapper, er.InstanceElement,
|
||||||
er.ModuleContext, er.FunctionExecution, er.Instance, compiled.CompiledObject)) or element is None:
|
er.ModuleContext, er.FunctionExecution, er.Instance, compiled.CompiledObject)) or element is None:
|
||||||
# TODO this is so ugly, please refactor.
|
# TODO this is so ugly, please refactor.
|
||||||
@@ -118,7 +118,7 @@ class Evaluator(object):
|
|||||||
if element.type == 'classdef':
|
if element.type == 'classdef':
|
||||||
return er.ClassContext(self, element, parent_context)
|
return er.ClassContext(self, element, parent_context)
|
||||||
elif element.type == 'funcdef':
|
elif element.type == 'funcdef':
|
||||||
return er.Function(self, element)
|
return er.Function(self, parent_context, element)
|
||||||
elif element.type == 'lambda':
|
elif element.type == 'lambda':
|
||||||
return er.LambdaWrapper(self, element)
|
return er.LambdaWrapper(self, element)
|
||||||
elif element.type == 'file_input':
|
elif element.type == 'file_input':
|
||||||
@@ -126,7 +126,7 @@ class Evaluator(object):
|
|||||||
else:
|
else:
|
||||||
return element
|
return element
|
||||||
|
|
||||||
def find_types(self, scope, name_str, position=None, search_global=False,
|
def find_types(self, context, name_str, position=None, search_global=False,
|
||||||
is_goto=False):
|
is_goto=False):
|
||||||
"""
|
"""
|
||||||
This is the search function. The most important part to debug.
|
This is the search function. The most important part to debug.
|
||||||
@@ -136,7 +136,7 @@ class Evaluator(object):
|
|||||||
:param position: Position of the last statement -> tuple of line, column
|
:param position: Position of the last statement -> tuple of line, column
|
||||||
:return: List of Names. Their parents are the types.
|
:return: List of Names. Their parents are the types.
|
||||||
"""
|
"""
|
||||||
f = finder.NameFinder(self, scope, name_str, position)
|
f = finder.NameFinder(self, context, name_str, position)
|
||||||
filters = f.get_filters(search_global)
|
filters = f.get_filters(search_global)
|
||||||
if is_goto:
|
if is_goto:
|
||||||
return f.filter_name(filters)
|
return f.filter_name(filters)
|
||||||
@@ -341,8 +341,7 @@ class Evaluator(object):
|
|||||||
if isinstance(atom, tree.Name):
|
if isinstance(atom, tree.Name):
|
||||||
# This is the first global lookup.
|
# This is the first global lookup.
|
||||||
stmt = atom.get_definition()
|
stmt = atom.get_definition()
|
||||||
scope = stmt.get_parent_until(tree.IsScope, include_current=True)
|
if isinstance(context, er.FunctionExecution):
|
||||||
if isinstance(scope, (tree.Function, er.FunctionExecution)):
|
|
||||||
# Adjust scope: If the name is not in the suite, it's a param
|
# Adjust scope: If the name is not in the suite, it's a param
|
||||||
# default or annotation and will be resolved as part of the
|
# default or annotation and will be resolved as part of the
|
||||||
# parent scope.
|
# parent scope.
|
||||||
@@ -355,7 +354,7 @@ class Evaluator(object):
|
|||||||
# We only need to adjust the start_pos for statements, because
|
# We only need to adjust the start_pos for statements, because
|
||||||
# there the name cannot be used.
|
# there the name cannot be used.
|
||||||
stmt = atom
|
stmt = atom
|
||||||
return self.find_types(scope, atom, stmt.start_pos, search_global=True)
|
return self.find_types(context, atom, stmt.start_pos, search_global=True)
|
||||||
elif isinstance(atom, tree.Literal):
|
elif isinstance(atom, tree.Literal):
|
||||||
return set([compiled.create(self, atom.eval())])
|
return set([compiled.create(self, atom.eval())])
|
||||||
else:
|
else:
|
||||||
@@ -421,7 +420,7 @@ class Evaluator(object):
|
|||||||
if self.is_analysis:
|
if self.is_analysis:
|
||||||
arguments.eval_all()
|
arguments.eval_all()
|
||||||
|
|
||||||
if obj.isinstance(er.Function):
|
if isinstance(obj, er.Function):
|
||||||
obj = obj.get_decorated_func()
|
obj = obj.get_decorated_func()
|
||||||
|
|
||||||
debug.dbg('execute: %s %s', obj, arguments)
|
debug.dbg('execute: %s %s', obj, arguments)
|
||||||
@@ -532,7 +531,15 @@ class Evaluator(object):
|
|||||||
search_global=True, is_goto=True)
|
search_global=True, is_goto=True)
|
||||||
|
|
||||||
def create_context(self, node):
|
def create_context(self, node):
|
||||||
scope = node.get_parent_scope()
|
def from_scope(scope):
|
||||||
if scope.get_parent_scope() is not None:
|
parent_context = None
|
||||||
raise NotImplementedError
|
parent_scope = scope.get_parent_scope()
|
||||||
return self.wrap(scope)
|
if parent_scope is not None:
|
||||||
|
parent_context = from_scope(parent_scope)
|
||||||
|
return self.wrap(scope, parent_context=parent_context)
|
||||||
|
|
||||||
|
if node.is_scope():
|
||||||
|
scope = node
|
||||||
|
else:
|
||||||
|
scope = node.get_parent_scope()
|
||||||
|
return from_scope(scope)
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ from functools import partial
|
|||||||
from jedi._compatibility import builtins as _builtins, unicode
|
from jedi._compatibility import builtins as _builtins, unicode
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.cache import underscore_memoization, memoize_method
|
from jedi.cache import underscore_memoization, memoize_method
|
||||||
from jedi.parser.tree import Param, Base, Operator
|
from jedi.parser.tree import Param, Operator
|
||||||
from jedi.evaluate.helpers import FakeName
|
from jedi.evaluate.helpers import FakeName
|
||||||
from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition
|
from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition
|
||||||
|
from jedi.evaluate.context import Context
|
||||||
from . import fake
|
from . import fake
|
||||||
|
|
||||||
|
|
||||||
@@ -36,22 +37,27 @@ class CheckAttribute(object):
|
|||||||
return partial(self.func, instance)
|
return partial(self.func, instance)
|
||||||
|
|
||||||
|
|
||||||
class CompiledObject(Base):
|
class CompiledObject(Context):
|
||||||
# comply with the parser
|
# comply with the parser
|
||||||
start_pos = 0, 0
|
start_pos = 0, 0
|
||||||
path = None # modules have this attribute - set it to None.
|
path = None # modules have this attribute - set it to None.
|
||||||
used_names = {} # To be consistent with modules.
|
used_names = {} # To be consistent with modules.
|
||||||
|
|
||||||
def __init__(self, evaluator, obj, parent=None):
|
def __init__(self, evaluator, obj, parent_context=None):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
self.parent = parent
|
self.parent_context = parent_context
|
||||||
|
|
||||||
|
def get_root_node(self):
|
||||||
|
# To make things a bit easier with filters we add this method here.
|
||||||
|
return self.get_root_context()
|
||||||
|
|
||||||
@CheckAttribute
|
@CheckAttribute
|
||||||
def py__call__(self, params):
|
def py__call__(self, params):
|
||||||
if inspect.isclass(self.obj):
|
if inspect.isclass(self.obj):
|
||||||
from jedi.evaluate.representation import Instance
|
from jedi.evaluate.representation import Instance
|
||||||
return set([Instance(self._evaluator, self, params)])
|
return set([self])
|
||||||
|
return set([Instance(self._evaluator, self.parent_context, self, params)])
|
||||||
else:
|
else:
|
||||||
return set(self._execute_function(params))
|
return set(self._execute_function(params))
|
||||||
|
|
||||||
@@ -206,7 +212,7 @@ class CompiledObject(Base):
|
|||||||
name = self._get_class().__name__
|
name = self._get_class().__name__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
name = repr(self.obj)
|
name = repr(self.obj)
|
||||||
return FakeName(name, self)
|
return CompiledContextName(self, name)
|
||||||
|
|
||||||
def _execute_function(self, params):
|
def _execute_function(self, params):
|
||||||
if self.type != 'funcdef':
|
if self.type != 'funcdef':
|
||||||
@@ -267,15 +273,21 @@ class CompiledName(AbstractNameDefinition):
|
|||||||
name = None
|
name = None
|
||||||
return '<%s: (%s).%s>' % (type(self).__name__, name, self.string_name)
|
return '<%s: (%s).%s>' % (type(self).__name__, name, self.string_name)
|
||||||
|
|
||||||
def is_definition(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def infer(self):
|
def infer(self):
|
||||||
module = self._compiled_obj.get_parent_until()
|
module = self._compiled_obj.get_root_context()
|
||||||
return [_create_from_name(self._evaluator, module, self._compiled_obj, self.string_name)]
|
return [_create_from_name(self._evaluator, module, self._compiled_obj, self.string_name)]
|
||||||
|
|
||||||
|
|
||||||
|
class CompiledContextName(AbstractNameDefinition):
|
||||||
|
def __init__(self, parent_context, name):
|
||||||
|
self.string_name = name
|
||||||
|
self.parent_context = parent_context
|
||||||
|
|
||||||
|
def infer(self):
|
||||||
|
return [self.parent_context]
|
||||||
|
|
||||||
|
|
||||||
class LazyNamesDict(object):
|
class LazyNamesDict(object):
|
||||||
"""
|
"""
|
||||||
A names_dict instance for compiled objects, resembles the parser.tree.
|
A names_dict instance for compiled objects, resembles the parser.tree.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import types
|
|||||||
from jedi._compatibility import is_py3, builtins, unicode, is_py34
|
from jedi._compatibility import is_py3, builtins, unicode, is_py34
|
||||||
from jedi.parser import ParserWithRecovery, load_grammar
|
from jedi.parser import ParserWithRecovery, load_grammar
|
||||||
from jedi.parser import tree as pt
|
from jedi.parser import tree as pt
|
||||||
from jedi.evaluate.helpers import FakeName
|
|
||||||
|
|
||||||
modules = {}
|
modules = {}
|
||||||
|
|
||||||
@@ -69,14 +68,14 @@ def _load_faked_module(module):
|
|||||||
if module_name == 'builtins' and not is_py3:
|
if module_name == 'builtins' and not is_py3:
|
||||||
# There are two implementations of `open` for either python 2/3.
|
# There are two implementations of `open` for either python 2/3.
|
||||||
# -> Rename the python2 version (`look at fake/builtins.pym`).
|
# -> Rename the python2 version (`look at fake/builtins.pym`).
|
||||||
open_func = search_scope(module, 'open')
|
open_func = _search_scope(module, 'open')
|
||||||
open_func.children[1] = FakeName('open_python3')
|
open_func.children[1].value = 'open_python3'
|
||||||
open_func = search_scope(module, 'open_python2')
|
open_func = _search_scope(module, 'open_python2')
|
||||||
open_func.children[1] = FakeName('open')
|
open_func.children[1].value = 'open'
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
|
||||||
def search_scope(scope, obj_name):
|
def _search_scope(scope, obj_name):
|
||||||
for s in scope.subscopes:
|
for s in scope.subscopes:
|
||||||
if str(s.name) == obj_name:
|
if str(s.name) == obj_name:
|
||||||
return s
|
return s
|
||||||
@@ -120,7 +119,7 @@ def _faked(module, obj, name):
|
|||||||
# for methods.
|
# for methods.
|
||||||
if name is None:
|
if name is None:
|
||||||
if inspect.isbuiltin(obj):
|
if inspect.isbuiltin(obj):
|
||||||
return search_scope(faked_mod, obj.__name__), faked_mod
|
return _search_scope(faked_mod, obj.__name__), faked_mod
|
||||||
elif not inspect.isclass(obj):
|
elif not inspect.isclass(obj):
|
||||||
# object is a method or descriptor
|
# object is a method or descriptor
|
||||||
try:
|
try:
|
||||||
@@ -128,22 +127,22 @@ def _faked(module, obj, name):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None, None
|
return None, None
|
||||||
else:
|
else:
|
||||||
cls = search_scope(faked_mod, objclass.__name__)
|
cls = _search_scope(faked_mod, objclass.__name__)
|
||||||
if cls is None:
|
if cls is None:
|
||||||
return None, None
|
return None, None
|
||||||
return search_scope(cls, obj.__name__), faked_mod
|
return _search_scope(cls, obj.__name__), faked_mod
|
||||||
else:
|
else:
|
||||||
if obj == module:
|
if obj == module:
|
||||||
return search_scope(faked_mod, name), faked_mod
|
return _search_scope(faked_mod, name), faked_mod
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
cls_name = obj.__name__
|
cls_name = obj.__name__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None, None
|
return None, None
|
||||||
cls = search_scope(faked_mod, cls_name)
|
cls = _search_scope(faked_mod, cls_name)
|
||||||
if cls is None:
|
if cls is None:
|
||||||
return None, None
|
return None, None
|
||||||
return search_scope(cls, name), faked_mod
|
return _search_scope(cls, name), faked_mod
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,35 +12,48 @@ from jedi.common import to_list
|
|||||||
class AbstractNameDefinition(object):
|
class AbstractNameDefinition(object):
|
||||||
start_pos = None
|
start_pos = None
|
||||||
string_name = None
|
string_name = None
|
||||||
|
parent_context = None
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def infer(self):
|
def infer(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_root_context(self):
|
||||||
|
if self.parent_context is None:
|
||||||
|
return self
|
||||||
|
return self.parent_context.get_root_context()
|
||||||
|
|
||||||
class TreeNameDefinition(AbstractNameDefinition):
|
def __repr__(self):
|
||||||
|
if self.start_pos is None:
|
||||||
|
return '<%s: %s>' % (type(self).__name__, self.string_name)
|
||||||
|
return '<%s: %s@%s>' % (type(self).__name__, self.string_name, self.start_pos)
|
||||||
|
|
||||||
|
|
||||||
|
class ContextName(AbstractNameDefinition):
|
||||||
def __init__(self, parent_context, name):
|
def __init__(self, parent_context, name):
|
||||||
self.parent_context = parent_context
|
self.parent_context = parent_context
|
||||||
self._name = name
|
self.name = name
|
||||||
|
|
||||||
def get_parent_flow_context(self):
|
|
||||||
return self.parent_context
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def string_name(self):
|
def string_name(self):
|
||||||
return self._name.value
|
return self.name.value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def start_pos(self):
|
def start_pos(self):
|
||||||
return self._name.start_pos
|
return self.name.start_pos
|
||||||
|
|
||||||
|
def infer(self):
|
||||||
|
return [self.parent_context]
|
||||||
|
|
||||||
|
|
||||||
|
class TreeNameDefinition(ContextName):
|
||||||
|
def get_parent_flow_context(self):
|
||||||
|
return self.parent_context
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
# Refactor this, should probably be here.
|
# Refactor this, should probably be here.
|
||||||
from jedi.evaluate.finder import _name_to_types
|
from jedi.evaluate.finder import _name_to_types
|
||||||
return _name_to_types(self.parent_context._evaluator, self.parent_context, self._name, None)
|
return _name_to_types(self.parent_context._evaluator, self.parent_context, self.name, None)
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<%s: %s@%s>' % (type(self).__name__, self.string_name, self.start_pos)
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractFilter(object):
|
class AbstractFilter(object):
|
||||||
@@ -102,8 +115,8 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
|
|||||||
def _check_flows(self, names):
|
def _check_flows(self, names):
|
||||||
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
||||||
stmt = name.get_definition()
|
stmt = name.get_definition()
|
||||||
name_scope = self._evaluator.wrap(stmt.get_parent_scope())
|
|
||||||
check = flow_analysis.UNSURE
|
check = flow_analysis.UNSURE
|
||||||
|
#name_scope = self._evaluator.wrap(stmt.get_parent_scope())
|
||||||
#check = flow_analysis.break_check(self._evaluator, name_scope,
|
#check = flow_analysis.break_check(self._evaluator, name_scope,
|
||||||
# stmt, self._origin_scope)
|
# stmt, self._origin_scope)
|
||||||
if check is not flow_analysis.UNREACHABLE:
|
if check is not flow_analysis.UNREACHABLE:
|
||||||
@@ -181,8 +194,7 @@ def get_global_filters(evaluator, context, until_position, origin_scope):
|
|||||||
until_position = None
|
until_position = None
|
||||||
in_func = True
|
in_func = True
|
||||||
|
|
||||||
node = context.parent_context
|
context = context.parent_context
|
||||||
context = evaluator.wrap(node)
|
|
||||||
|
|
||||||
# Add builtins to the global scope.
|
# Add builtins to the global scope.
|
||||||
for filter in evaluator.BUILTINS.get_filters(search_global=True):
|
for filter in evaluator.BUILTINS.get_filters(search_global=True):
|
||||||
|
|||||||
@@ -95,10 +95,10 @@ def filter_definition_names(names, origin, position=None):
|
|||||||
|
|
||||||
|
|
||||||
class NameFinder(object):
|
class NameFinder(object):
|
||||||
def __init__(self, evaluator, scope, name_str, position=None):
|
def __init__(self, evaluator, context, name_str, position=None):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
# Make sure that it's not just a syntax tree node.
|
# Make sure that it's not just a syntax tree node.
|
||||||
self.scope = evaluator.wrap(scope)
|
self.context = context
|
||||||
self.name_str = name_str
|
self.name_str = name_str
|
||||||
self.position = position
|
self.position = position
|
||||||
self._found_predefined_if_name = None
|
self._found_predefined_if_name = None
|
||||||
@@ -123,7 +123,7 @@ class NameFinder(object):
|
|||||||
if not isinstance(self.name_str, (str, unicode)): # TODO Remove?
|
if not isinstance(self.name_str, (str, unicode)): # TODO Remove?
|
||||||
if attribute_lookup:
|
if attribute_lookup:
|
||||||
analysis.add_attribute_error(self._evaluator,
|
analysis.add_attribute_error(self._evaluator,
|
||||||
self.scope, self.name_str)
|
self.context, self.name_str)
|
||||||
else:
|
else:
|
||||||
message = ("NameError: name '%s' is not defined."
|
message = ("NameError: name '%s' is not defined."
|
||||||
% self.name_str)
|
% self.name_str)
|
||||||
@@ -140,9 +140,9 @@ class NameFinder(object):
|
|||||||
origin_scope = None
|
origin_scope = None
|
||||||
|
|
||||||
if search_global:
|
if search_global:
|
||||||
return get_global_filters(self._evaluator, self.scope, self.position, origin_scope)
|
return get_global_filters(self._evaluator, self.context, self.position, origin_scope)
|
||||||
else:
|
else:
|
||||||
return self.scope.get_filters(search_global, self.position, origin_scope=origin_scope)
|
return self.context.get_filters(search_global, self.position, origin_scope=origin_scope)
|
||||||
|
|
||||||
def names_dict_lookup(self, names_dict, position):
|
def names_dict_lookup(self, names_dict, position):
|
||||||
def get_param(scope, el):
|
def get_param(scope, el):
|
||||||
@@ -167,7 +167,7 @@ class NameFinder(object):
|
|||||||
stmt = name.get_definition()
|
stmt = name.get_definition()
|
||||||
name_scope = self._evaluator.wrap(stmt.get_parent_scope())
|
name_scope = self._evaluator.wrap(stmt.get_parent_scope())
|
||||||
|
|
||||||
if isinstance(self.scope, er.Instance) and not isinstance(name_scope, er.Instance):
|
if isinstance(self.context, er.Instance) and not isinstance(name_scope, er.Instance):
|
||||||
# Instances should not be checked for positioning, because we
|
# Instances should not be checked for positioning, because we
|
||||||
# don't know in which order the functions are called.
|
# don't know in which order the functions are called.
|
||||||
last_names.append(name)
|
last_names.append(name)
|
||||||
@@ -210,7 +210,7 @@ class NameFinder(object):
|
|||||||
# deliver types.
|
# deliver types.
|
||||||
self._found_predefined_if_name = types
|
self._found_predefined_if_name = types
|
||||||
else:
|
else:
|
||||||
check = flow_analysis.break_check(self._evaluator, self.scope,
|
check = flow_analysis.break_check(self._evaluator, self.context,
|
||||||
origin_scope)
|
origin_scope)
|
||||||
if check is flow_analysis.UNREACHABLE:
|
if check is flow_analysis.UNREACHABLE:
|
||||||
self._found_predefined_if_name = set()
|
self._found_predefined_if_name = set()
|
||||||
@@ -249,7 +249,7 @@ class NameFinder(object):
|
|||||||
if names:
|
if names:
|
||||||
break
|
break
|
||||||
debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self.name_str,
|
debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self.name_str,
|
||||||
self.scope, names, self.position)
|
self.context, names, self.position)
|
||||||
return list(self._clean_names(names))
|
return list(self._clean_names(names))
|
||||||
|
|
||||||
def _clean_names(self, names):
|
def _clean_names(self, names):
|
||||||
@@ -311,13 +311,13 @@ class NameFinder(object):
|
|||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
new_types = name.infer()
|
new_types = name.infer()
|
||||||
if isinstance(self.scope, (er.ClassContext, er.Instance)) and attribute_lookup:
|
if isinstance(self.context, (er.ClassContext, er.Instance)) and attribute_lookup:
|
||||||
types |= set(self._resolve_descriptors(name, new_types))
|
types |= set(self._resolve_descriptors(name, new_types))
|
||||||
else:
|
else:
|
||||||
types |= set(new_types)
|
types |= set(new_types)
|
||||||
if not names and isinstance(self.scope, er.Instance):
|
if not names and isinstance(self.context, er.Instance):
|
||||||
# handling __getattr__ / __getattribute__
|
# handling __getattr__ / __getattribute__
|
||||||
return self._check_getattr(self.scope)
|
return self._check_getattr(self.context)
|
||||||
|
|
||||||
return types
|
return types
|
||||||
|
|
||||||
@@ -336,7 +336,7 @@ class NameFinder(object):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
result.add(r)
|
result.add(r)
|
||||||
else:
|
else:
|
||||||
result |= desc_return(self.scope)
|
result |= desc_return(self.context)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ def _name_to_types(evaluator, context, name, scope):
|
|||||||
for_types = iterable.py__iter__types(evaluator, container_types, typ.children[3])
|
for_types = iterable.py__iter__types(evaluator, container_types, typ.children[3])
|
||||||
types = check_tuple_assignments(evaluator, for_types, name)
|
types = check_tuple_assignments(evaluator, for_types, name)
|
||||||
elif isinstance(typ, tree.Param):
|
elif isinstance(typ, tree.Param):
|
||||||
types = _eval_param(evaluator, typ, scope)
|
types = _eval_param(evaluator, context, typ, scope)
|
||||||
elif typ.isinstance(tree.ExprStmt):
|
elif typ.isinstance(tree.ExprStmt):
|
||||||
types = _remove_statements(evaluator, context, typ, name)
|
types = _remove_statements(evaluator, context, typ, name)
|
||||||
elif typ.isinstance(tree.WithStmt):
|
elif typ.isinstance(tree.WithStmt):
|
||||||
@@ -373,7 +373,7 @@ def _name_to_types(evaluator, context, name, scope):
|
|||||||
elif isinstance(typ, tree.Import):
|
elif isinstance(typ, tree.Import):
|
||||||
types = imports.ImportWrapper(evaluator, name).follow()
|
types = imports.ImportWrapper(evaluator, name).follow()
|
||||||
elif typ.isinstance(tree.Function, tree.Class):
|
elif typ.isinstance(tree.Function, tree.Class):
|
||||||
types = [evaluator.wrap(typ)]
|
types = [evaluator.wrap(typ, parent_context=context)]
|
||||||
elif typ.type == 'global_stmt':
|
elif typ.type == 'global_stmt':
|
||||||
for s in _get_global_stmt_scopes(evaluator, typ, name):
|
for s in _get_global_stmt_scopes(evaluator, typ, name):
|
||||||
finder = NameFinder(evaluator, s, str(name))
|
finder = NameFinder(evaluator, s, str(name))
|
||||||
@@ -427,7 +427,7 @@ def _remove_statements(evaluator, context, stmt, name):
|
|||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
def _eval_param(evaluator, param, scope):
|
def _eval_param(evaluator, context, param, scope):
|
||||||
res_new = set()
|
res_new = set()
|
||||||
func = param.get_parent_scope()
|
func = param.get_parent_scope()
|
||||||
|
|
||||||
@@ -441,8 +441,9 @@ def _eval_param(evaluator, param, scope):
|
|||||||
if isinstance(scope, er.InstanceElement):
|
if isinstance(scope, er.InstanceElement):
|
||||||
res_new.add(scope.instance)
|
res_new.add(scope.instance)
|
||||||
else:
|
else:
|
||||||
inst = er.Instance(evaluator, evaluator.wrap(cls),
|
inst = er.Instance(evaluator, context.parent_context.parent_context, context.parent_context,
|
||||||
Arguments(evaluator, ()), is_generated=True)
|
Arguments(evaluator, context, ()),
|
||||||
|
is_generated=True)
|
||||||
res_new.add(inst)
|
res_new.add(inst)
|
||||||
return res_new
|
return res_new
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import copy
|
import copy
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
from jedi.evaluate.filters import AbstractNameDefinition
|
||||||
from jedi.parser import tree
|
from jedi.parser import tree
|
||||||
|
|
||||||
|
|
||||||
@@ -172,6 +173,7 @@ class FakeName(tree.Name):
|
|||||||
In case is_definition is defined (not None), that bool value will be
|
In case is_definition is defined (not None), that bool value will be
|
||||||
returned.
|
returned.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
super(FakeName, self).__init__(name_str, start_pos)
|
super(FakeName, self).__init__(name_str, start_pos)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self._is_definition = is_definition
|
self._is_definition = is_definition
|
||||||
@@ -186,15 +188,11 @@ class FakeName(tree.Name):
|
|||||||
return self._is_definition
|
return self._is_definition
|
||||||
|
|
||||||
|
|
||||||
class LazyName(FakeName):
|
class LazyName(AbstractNameDefinition):
|
||||||
def __init__(self, name, parent_callback, is_definition=None):
|
def __init__(self, name, parent_callback, is_definition=None):
|
||||||
super(LazyName, self).__init__(name, is_definition=is_definition)
|
# TODO remove is_definition
|
||||||
|
self.string_name = name
|
||||||
self._parent_callback = parent_callback
|
self._parent_callback = parent_callback
|
||||||
|
|
||||||
@property
|
def infer(self):
|
||||||
def parent(self):
|
|
||||||
return self._parent_callback()
|
return self._parent_callback()
|
||||||
|
|
||||||
@parent.setter
|
|
||||||
def parent(self, value):
|
|
||||||
pass # Do nothing, super classes can try to set the parent.
|
|
||||||
|
|||||||
@@ -777,7 +777,7 @@ def check_array_instances(evaluator, instance):
|
|||||||
|
|
||||||
ai = _ArrayInstance(evaluator, instance)
|
ai = _ArrayInstance(evaluator, instance)
|
||||||
from jedi.evaluate import param
|
from jedi.evaluate import param
|
||||||
return param.Arguments(evaluator, [AlreadyEvaluated([ai])])
|
return param.Arguments(evaluator, instance, [AlreadyEvaluated([ai])])
|
||||||
|
|
||||||
|
|
||||||
class _ArrayInstance(IterableWrapper):
|
class _ArrayInstance(IterableWrapper):
|
||||||
|
|||||||
@@ -130,6 +130,9 @@ class ExecutionRecursionDetector(object):
|
|||||||
self.recursion_level -= 1
|
self.recursion_level -= 1
|
||||||
|
|
||||||
def push_execution(self, execution):
|
def push_execution(self, execution):
|
||||||
|
self.execution_funcs.add(execution.base)
|
||||||
|
self.parent_execution_funcs.append(execution.base)
|
||||||
|
return True # Remove
|
||||||
in_par_execution_funcs = execution.base in self.parent_execution_funcs
|
in_par_execution_funcs = execution.base in self.parent_execution_funcs
|
||||||
in_execution_funcs = execution.base in self.execution_funcs
|
in_execution_funcs = execution.base in self.execution_funcs
|
||||||
self.recursion_level += 1
|
self.recursion_level += 1
|
||||||
|
|||||||
@@ -56,38 +56,17 @@ from jedi.evaluate import param
|
|||||||
from jedi.evaluate import flow_analysis
|
from jedi.evaluate import flow_analysis
|
||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
|
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
|
||||||
GlobalNameFilter, DictFilter
|
GlobalNameFilter, DictFilter, ContextName
|
||||||
|
from jedi.evaluate.context import Context
|
||||||
|
|
||||||
|
|
||||||
class Context(object):
|
class Executed(Context):
|
||||||
def __init__(self, evaluator, parent_context=None):
|
|
||||||
self._evaluator = evaluator
|
|
||||||
self.parent_context = parent_context
|
|
||||||
|
|
||||||
def get_parent_flow_context(self):
|
|
||||||
return self.parent_context
|
|
||||||
|
|
||||||
def get_root_context(self):
|
|
||||||
context = self
|
|
||||||
while True:
|
|
||||||
if context.parent_context is None:
|
|
||||||
return context
|
|
||||||
context = context.parent_context
|
|
||||||
|
|
||||||
|
|
||||||
class FlowContext(Context):
|
|
||||||
def get_parent_flow_context(self):
|
|
||||||
if 1:
|
|
||||||
return self.parent_context
|
|
||||||
|
|
||||||
|
|
||||||
class Executed(Context, tree.Base):
|
|
||||||
"""
|
"""
|
||||||
An instance is also an executable - because __init__ is called
|
An instance is also an executable - because __init__ is called
|
||||||
:param var_args: The param input array, consist of a parser node or a list.
|
:param var_args: The param input array, consist of a parser node or a list.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, base, var_args=()):
|
def __init__(self, evaluator, parent_context, base, var_args):
|
||||||
self._evaluator = evaluator
|
super(Executed, self).__init__(evaluator, parent_context=parent_context)
|
||||||
self.base = base
|
self.base = base
|
||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
|
|
||||||
@@ -97,25 +76,21 @@ class Executed(Context, tree.Base):
|
|||||||
def get_parent_until(self, *args, **kwargs):
|
def get_parent_until(self, *args, **kwargs):
|
||||||
return tree.Base.get_parent_until(self, *args, **kwargs)
|
return tree.Base.get_parent_until(self, *args, **kwargs)
|
||||||
|
|
||||||
@common.safe_property
|
|
||||||
def parent(self):
|
|
||||||
return self.base.parent
|
|
||||||
|
|
||||||
|
|
||||||
class Instance(use_metaclass(CachedMetaClass, Executed)):
|
class Instance(use_metaclass(CachedMetaClass, Executed)):
|
||||||
"""
|
"""
|
||||||
This class is used to evaluate instances.
|
This class is used to evaluate instances.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, base, var_args, is_generated=False):
|
def __init__(self, evaluator, parent_context, base, var_args, is_generated=False):
|
||||||
super(Instance, self).__init__(evaluator, base, var_args)
|
super(Instance, self).__init__(evaluator, parent_context, base, var_args)
|
||||||
self.decorates = None
|
self.decorates = None
|
||||||
# Generated instances are classes that are just generated by self
|
# Generated instances are classes that are just generated by self
|
||||||
# (No var_args) used.
|
# (No var_args) used.
|
||||||
self.is_generated = is_generated
|
self.is_generated = is_generated
|
||||||
|
|
||||||
self._init_execution = None
|
self._init_execution = None
|
||||||
if base.name.get_code() in ['list', 'set'] \
|
if base.name.string_name in ['list', 'set'] \
|
||||||
and evaluator.BUILTINS == base.get_parent_until():
|
and evaluator.BUILTINS == parent_context.get_root_context():
|
||||||
# compare the module path with the builtin name.
|
# compare the module path with the builtin name.
|
||||||
self.var_args = iterable.check_array_instances(evaluator, self)
|
self.var_args = iterable.check_array_instances(evaluator, self)
|
||||||
elif not is_generated:
|
elif not is_generated:
|
||||||
@@ -157,7 +132,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
func = self.get_subscope_by_name('__init__')
|
func = self.get_subscope_by_name('__init__')
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
return FunctionExecution(self._evaluator, func, self.var_args)
|
return FunctionExecution(self._evaluator, self, func, self.var_args)
|
||||||
|
|
||||||
def _get_func_self_name(self, func):
|
def _get_func_self_name(self, func):
|
||||||
"""
|
"""
|
||||||
@@ -280,8 +255,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
@property
|
@property
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def name(self):
|
def name(self):
|
||||||
name = self.base.name
|
return ContextName(self, self.base.name)
|
||||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'get_imports', 'type',
|
if name not in ['start_pos', 'end_pos', 'get_imports', 'type',
|
||||||
@@ -400,6 +374,7 @@ def get_instance_el(evaluator, instance, var, is_class_var=False):
|
|||||||
in quite a lot of cases, which includes Nodes like ``power``, that need to
|
in quite a lot of cases, which includes Nodes like ``power``, that need to
|
||||||
know where a self name comes from for example.
|
know where a self name comes from for example.
|
||||||
"""
|
"""
|
||||||
|
return var
|
||||||
if isinstance(var, tree.Name):
|
if isinstance(var, tree.Name):
|
||||||
parent = get_instance_el(evaluator, instance, var.parent, is_class_var)
|
parent = get_instance_el(evaluator, instance, var.parent, is_class_var)
|
||||||
return InstanceName(var, parent)
|
return InstanceName(var, parent)
|
||||||
@@ -465,8 +440,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)):
|
|||||||
@property
|
@property
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def name(self):
|
def name(self):
|
||||||
name = self.var.name
|
return ContextName(self.var.name, self)
|
||||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for el in self.var.__iter__():
|
for el in self.var.__iter__():
|
||||||
@@ -519,7 +493,7 @@ class Wrapper(tree.Base):
|
|||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def name(self):
|
def name(self):
|
||||||
name = self.base.name
|
name = self.base.name
|
||||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
return ContextName(self, name)
|
||||||
|
|
||||||
|
|
||||||
class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
||||||
@@ -574,7 +548,7 @@ class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
|||||||
return [compiled.create(self._evaluator, object)]
|
return [compiled.create(self._evaluator, object)]
|
||||||
|
|
||||||
def py__call__(self, params):
|
def py__call__(self, params):
|
||||||
return set([Instance(self._evaluator, self, params)])
|
return set([Instance(self._evaluator, self.parent_context, self, params)])
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return compiled.create(self._evaluator, type)
|
return compiled.create(self._evaluator, type)
|
||||||
@@ -628,13 +602,13 @@ class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
|||||||
return "<e%s of %s>" % (type(self).__name__, self.base)
|
return "<e%s of %s>" % (type(self).__name__, self.base)
|
||||||
|
|
||||||
|
|
||||||
class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
class Function(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
||||||
"""
|
"""
|
||||||
Needed because of decorators. Decorators are evaluated here.
|
Needed because of decorators. Decorators are evaluated here.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, func, is_decorated=False):
|
def __init__(self, evaluator, parent_context, func, is_decorated=False):
|
||||||
""" This should not be called directly """
|
""" This should not be called directly """
|
||||||
self._evaluator = evaluator
|
super(Function, self).__init__(evaluator, parent_context)
|
||||||
self.base = self.base_func = func
|
self.base = self.base_func = func
|
||||||
self.is_decorated = is_decorated
|
self.is_decorated = is_decorated
|
||||||
# A property that is set by the decorator resolution.
|
# A property that is set by the decorator resolution.
|
||||||
@@ -716,7 +690,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
if self.base.is_generator():
|
if self.base.is_generator():
|
||||||
return set([iterable.Generator(self._evaluator, self, params)])
|
return set([iterable.Generator(self._evaluator, self, params)])
|
||||||
else:
|
else:
|
||||||
return FunctionExecution(self._evaluator, self, params).get_return_types()
|
return FunctionExecution(self._evaluator, self.parent_context, self, params).get_return_types()
|
||||||
|
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def py__annotations__(self):
|
def py__annotations__(self):
|
||||||
@@ -767,24 +741,24 @@ class FunctionExecution(Executed):
|
|||||||
"""
|
"""
|
||||||
type = 'funcdef'
|
type = 'funcdef'
|
||||||
|
|
||||||
def __init__(self, evaluator, base, *args, **kwargs):
|
def __init__(self, evaluator, parent_context, base, var_args):
|
||||||
super(FunctionExecution, self).__init__(evaluator, base, *args, **kwargs)
|
super(FunctionExecution, self).__init__(evaluator, parent_context, base, var_args)
|
||||||
self._copy_dict = {}
|
self._copy_dict = {}
|
||||||
self._original_function = funcdef = base.base_func
|
self._original_function = funcdef = base
|
||||||
if isinstance(funcdef, mixed.MixedObject):
|
if isinstance(funcdef, mixed.MixedObject):
|
||||||
# The extra information in mixed is not needed anymore. We can just
|
# The extra information in mixed is not needed anymore. We can just
|
||||||
# unpack it and give it the tree object.
|
# unpack it and give it the tree object.
|
||||||
funcdef = funcdef.definition
|
funcdef = funcdef.definition
|
||||||
|
|
||||||
# Just overwrite the old version. We don't need it anymore.
|
# Just overwrite the old version. We don't need it anymore.
|
||||||
funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
|
#funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
|
||||||
for child in funcdef.children:
|
#for child in funcdef.children:
|
||||||
if child.type not in ('operator', 'keyword'):
|
#if child.type not in ('operator', 'keyword'):
|
||||||
# Not all nodes are properly copied by deep_ast_copy.
|
# Not all nodes are properly copied by deep_ast_copy.
|
||||||
child.parent = self
|
#child.parent = self
|
||||||
self.children = funcdef.children
|
#self.children = funcdef.children
|
||||||
self.names_dict = funcdef.names_dict
|
#self.names_dict = funcdef.names_dict
|
||||||
self._copied_funcdef = funcdef
|
#self._copied_funcdef = funcdef
|
||||||
|
|
||||||
@memoize_default(default=set())
|
@memoize_default(default=set())
|
||||||
@recursion.execution_recursion_decorator
|
@recursion.execution_recursion_decorator
|
||||||
@@ -940,6 +914,7 @@ class GlobalName(helpers.FakeName):
|
|||||||
We need to mark global names somehow. Otherwise they are just normal
|
We need to mark global names somehow. Otherwise they are just normal
|
||||||
names that are not definitions.
|
names that are not definitions.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
super(GlobalName, self).__init__(name.value, name.parent,
|
super(GlobalName, self).__init__(name.value, name.parent,
|
||||||
name.start_pos, is_definition=True)
|
name.start_pos, is_definition=True)
|
||||||
|
|
||||||
@@ -1010,7 +985,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
|
|||||||
@property
|
@property
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def name(self):
|
def name(self):
|
||||||
return helpers.FakeName(unicode(self.base.name), self, (1, 0))
|
return ContextName(self, self.base.name)
|
||||||
|
|
||||||
def _get_init_directory(self):
|
def _get_init_directory(self):
|
||||||
"""
|
"""
|
||||||
@@ -1101,6 +1076,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
|
|||||||
if path is not None and path.endswith(os.path.sep + '__init__.py'):
|
if path is not None and path.endswith(os.path.sep + '__init__.py'):
|
||||||
mods = pkgutil.iter_modules([os.path.dirname(path)])
|
mods = pkgutil.iter_modules([os.path.dirname(path)])
|
||||||
for module_loader, name, is_pkg in mods:
|
for module_loader, name, is_pkg in mods:
|
||||||
|
raise NotImplementedError
|
||||||
fake_n = helpers.FakeName(name)
|
fake_n = helpers.FakeName(name)
|
||||||
# It's obviously a relative import to the current module.
|
# It's obviously a relative import to the current module.
|
||||||
imp = helpers.FakeImport(fake_n, self, level=1)
|
imp = helpers.FakeImport(fake_n, self, level=1)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ def execute(evaluator, obj, arguments):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if obj.parent == evaluator.BUILTINS:
|
if obj.parent_context == evaluator.BUILTINS:
|
||||||
module_name = 'builtins'
|
module_name = 'builtins'
|
||||||
elif isinstance(obj.parent, tree.Module):
|
elif isinstance(obj.parent, tree.Module):
|
||||||
module_name = str(obj.parent.name)
|
module_name = str(obj.parent.name)
|
||||||
|
|||||||
@@ -189,16 +189,19 @@ class IntegrationTestCase(object):
|
|||||||
parser = Parser(load_grammar(), string, start_symbol='eval_input')
|
parser = Parser(load_grammar(), string, start_symbol='eval_input')
|
||||||
parser.get_root_node().move(self.line_nr)
|
parser.get_root_node().move(self.line_nr)
|
||||||
element = parser.get_parsed_node()
|
element = parser.get_parsed_node()
|
||||||
|
module = script._get_module()
|
||||||
|
# TODO remove
|
||||||
element.parent = jedi.api.completion.get_user_scope(
|
element.parent = jedi.api.completion.get_user_scope(
|
||||||
script._get_module(),
|
module,
|
||||||
(self.line_nr, self.column)
|
(self.line_nr, self.column)
|
||||||
)
|
)
|
||||||
results = evaluator.eval_element(element)
|
module_context = evaluator.wrap(module, parent_context=None)
|
||||||
|
results = evaluator.eval_element(module_context, element)
|
||||||
if not results:
|
if not results:
|
||||||
raise Exception('Could not resolve %s on line %s'
|
raise Exception('Could not resolve %s on line %s'
|
||||||
% (match.string, self.line_nr - 1))
|
% (match.string, self.line_nr - 1))
|
||||||
|
|
||||||
should_be |= set(Definition(evaluator, r) for r in results)
|
should_be |= set(Definition(evaluator, r.name) for r in results)
|
||||||
debug.dbg('Finished getting types', color='YELLOW')
|
debug.dbg('Finished getting types', color='YELLOW')
|
||||||
|
|
||||||
# Because the objects have different ids, `repr`, then compare.
|
# Because the objects have different ids, `repr`, then compare.
|
||||||
|
|||||||
Reference in New Issue
Block a user