1
0
forked from VimPlug/jedi

Compiled objects should also have a names_dict.

This commit is contained in:
Dave Halter
2014-12-26 12:49:40 +01:00
parent bfaef9815c
commit ed3cf5577e
3 changed files with 63 additions and 18 deletions

View File

@@ -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

View File

@@ -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):

View File

@@ -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,