forked from VimPlug/jedi
Compiled objects should also have a names_dict.
This commit is contained in:
@@ -149,16 +149,15 @@ def underscore_memoization(func):
|
||||
return wrapper
|
||||
|
||||
|
||||
def memoize(func):
|
||||
def memoize_method(method):
|
||||
"""A normal memoize function."""
|
||||
dct = {}
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
dct = self.__dict__.setdefault('_memoize_method_dct', {})
|
||||
key = (args, frozenset(kwargs.items()))
|
||||
try:
|
||||
return dct[key]
|
||||
except KeyError:
|
||||
result = func(*args, **kwargs)
|
||||
result = method(self, *args, **kwargs)
|
||||
dct[key] = result
|
||||
return result
|
||||
return wrapper
|
||||
|
||||
@@ -6,12 +6,13 @@ import re
|
||||
import sys
|
||||
import os
|
||||
from functools import partial
|
||||
from itertools import chain
|
||||
|
||||
from jedi._compatibility import builtins as _builtins, unicode
|
||||
from jedi import debug
|
||||
from jedi.cache import underscore_memoization, memoize
|
||||
from jedi.cache import underscore_memoization, memoize_method
|
||||
from jedi.evaluate.sys_path import get_sys_path
|
||||
from jedi.parser.tree import Param, SubModule, Base, Operator
|
||||
from jedi.parser.tree import Param, Base
|
||||
from jedi.evaluate.helpers import FakeName
|
||||
from . import fake
|
||||
|
||||
@@ -137,11 +138,19 @@ class CompiledObject(Base):
|
||||
return self
|
||||
|
||||
def get_defined_names(self):
|
||||
return list(chain.from_iterable(self.names_dict.values()))
|
||||
|
||||
# TODO still used?
|
||||
if inspect.ismodule(self.obj):
|
||||
return self.instance_names()
|
||||
else:
|
||||
return type_names + self.instance_names()
|
||||
|
||||
@property
|
||||
@underscore_memoization
|
||||
def names_dict(self):
|
||||
return LazyNamesDict(self._cls())
|
||||
|
||||
def scope_names_generator(self, position=None, add_class_vars=True):
|
||||
yield self, self.get_defined_names()
|
||||
|
||||
@@ -237,6 +246,38 @@ class CompiledObject(Base):
|
||||
return [] # Builtins don't have imports
|
||||
|
||||
|
||||
class LazyNamesDict(object):
|
||||
"""
|
||||
A names_dict instance for compiled objects, resembles the parser.tree.
|
||||
"""
|
||||
def __init__(self, compiled_obj):
|
||||
self._compiled_obj = compiled_obj
|
||||
|
||||
@memoize_method
|
||||
def __getitem__(self, name):
|
||||
try:
|
||||
getattr(self._compiled_obj.obj, name)
|
||||
except AttributeError:
|
||||
raise KeyError('%s in %s not found.' % (name, self._compiled_obj))
|
||||
return [CompiledName(self._compiled_obj, name)]
|
||||
|
||||
def values(self):
|
||||
obj = self._compiled_obj.obj
|
||||
names = dir(obj)
|
||||
|
||||
values = []
|
||||
for name in names:
|
||||
try:
|
||||
values.append(self[name])
|
||||
except KeyError:
|
||||
# The dir function can be wrong.
|
||||
pass
|
||||
|
||||
if not inspect.ismodule(obj):
|
||||
values.append(type_names)
|
||||
return values
|
||||
|
||||
|
||||
class CompiledName(FakeName):
|
||||
def __init__(self, obj, name):
|
||||
super(CompiledName, self).__init__(name)
|
||||
@@ -250,6 +291,9 @@ class CompiledName(FakeName):
|
||||
name = None
|
||||
return '<%s: (%s).%s>' % (type(self).__name__, name, self.name)
|
||||
|
||||
def is_definition(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
@underscore_memoization
|
||||
def parent(self):
|
||||
@@ -408,14 +452,10 @@ def _parse_function_doc(doc):
|
||||
return param_str, ret
|
||||
|
||||
|
||||
class Builtin(CompiledObject, Base):
|
||||
@memoize
|
||||
class Builtin(CompiledObject):
|
||||
@memoize_method
|
||||
def get_by_name(self, name):
|
||||
item = [n for n in self.get_defined_names() if n.get_code() == name][0]
|
||||
return item.parent
|
||||
|
||||
def is_scope(self):
|
||||
return True
|
||||
return self.names_dict[name][0].parent
|
||||
|
||||
|
||||
def _a_generator(foo):
|
||||
|
||||
@@ -88,14 +88,18 @@ class NameFinder(object):
|
||||
# Only the names defined in the last position are valid definitions.
|
||||
last_names = []
|
||||
for name in reversed(sorted(names, key=lambda name: name.start_pos)):
|
||||
if isinstance(name, compiled.CompiledName):
|
||||
last_names.append(name)
|
||||
continue
|
||||
|
||||
if isinstance(self.name_str, pr.Name):
|
||||
origin_scope = self.name_str.get_definition().parent
|
||||
else:
|
||||
origin_scope = None
|
||||
check = flow_analysis.break_check(self._evaluator,
|
||||
scope,
|
||||
name.get_definition(),
|
||||
origin_scope)
|
||||
stmt = name.get_definition()
|
||||
if isinstance(stmt.parent, compiled.CompiledObject):
|
||||
continue
|
||||
check = flow_analysis.break_check(self._evaluator, scope, stmt, origin_scope)
|
||||
if check is not flow_analysis.UNREACHABLE:
|
||||
last_names.append(name)
|
||||
if check is flow_analysis.REACHABLE:
|
||||
@@ -166,8 +170,10 @@ class NameFinder(object):
|
||||
or isinstance(name_list_scope, (pr.Lambda, er.Instance, InterpreterNamespace)) \
|
||||
or isinstance(scope, compiled.CompiledObject):
|
||||
# Always reachable.
|
||||
print('nons', scope)
|
||||
names.append(name)
|
||||
else:
|
||||
print('yess', scope)
|
||||
check = flow_analysis.break_check(self._evaluator,
|
||||
name_list_scope,
|
||||
stmt,
|
||||
|
||||
Reference in New Issue
Block a user