Fix properties.

This commit is contained in:
Dave Halter
2016-11-16 21:16:12 +01:00
parent 21e17b7762
commit ba03f1dcb9
4 changed files with 80 additions and 36 deletions

View File

@@ -364,7 +364,7 @@ class CompiledObjectFilter(AbstractFilter):
# lookups possible without having the actual attribute. However
# this makes proper completion possible.
return [FakeName(name, create(self._evaluator, None), is_definition=True)]
return [self.name_class(self._evaluator, self._compiled_obj, name)]
return [self._create(name)]
def values(self):
obj = self._compiled_obj.obj
@@ -380,6 +380,9 @@ class CompiledObjectFilter(AbstractFilter):
names += filter.values()
return names
def _create(self, name):
return self.name_class(self._evaluator, self._compiled_obj, name)
def dotted_from_fs_path(fs_path, sys_path):
"""

View File

@@ -59,7 +59,7 @@ class TreeNameDefinition(ContextName):
def infer(self):
# Refactor this, should probably be here.
from jedi.evaluate.finder import _name_to_types
return _name_to_types(self.parent_context.evaluator, self.parent_context, self.tree_name, None)
return _name_to_types(self.parent_context.evaluator, self.parent_context, self.tree_name)
class ParamName(ContextName):

View File

@@ -22,6 +22,7 @@ from jedi import debug
from jedi.common import unite
from jedi import settings
from jedi.evaluate import representation as er
from jedi.evaluate.instance import AbstractInstanceContext
from jedi.evaluate import dynamic
from jedi.evaluate import compiled
from jedi.evaluate import docstrings
@@ -32,9 +33,8 @@ from jedi.evaluate import analysis
from jedi.evaluate import flow_analysis
from jedi.evaluate import param
from jedi.evaluate import helpers
from jedi.evaluate.instance import AbstractInstanceContext
from jedi.evaluate.cache import memoize_default
from jedi.evaluate.filters import get_global_filters
from jedi.evaluate.filters import get_global_filters, ContextName
def filter_after_position(names, position, origin=None):
@@ -321,7 +321,8 @@ class NameFinder(object):
for name in names:
new_types = name.infer()
if isinstance(self.context, (er.ClassContext, er.Instance)) and attribute_lookup:
if isinstance(self.context, (er.ClassContext, AbstractInstanceContext)) \
and attribute_lookup:
types |= set(self._resolve_descriptors(name, new_types))
else:
types |= set(new_types)
@@ -334,6 +335,10 @@ class NameFinder(object):
return types
def _resolve_descriptors(self, name, types):
if not isinstance(name, ContextName):
# Compiled names and other stuff should just be ignored when it
# comes to descriptors.
return types
# The name must not be in the dictionary, but part of the class
# definition. __get__ is only called if the descriptor is defined in
# the class dictionary.
@@ -353,7 +358,7 @@ class NameFinder(object):
@memoize_default(set(), evaluator_is_first_arg=True)
def _name_to_types(evaluator, context, name, scope):
def _name_to_types(evaluator, context, name):
types = []
node = name.get_definition()
if node.isinstance(tree.ForStmt):
@@ -370,7 +375,7 @@ def _name_to_types(evaluator, context, name, scope):
types = check_tuple_assignments(evaluator, for_types, name)
elif isinstance(node, tree.Param):
return set() # TODO remove
types = _eval_param(evaluator, context, node, scope)
types = _eval_param(evaluator, context, node)
elif node.isinstance(tree.ExprStmt):
types = _remove_statements(evaluator, context, node, name)
elif node.isinstance(tree.WithStmt):
@@ -423,10 +428,10 @@ def _apply_decorators(evaluator, context, node):
for dec in reversed(node.get_decorators()):
debug.dbg('decorator: %s %s', dec, values)
dec_values = context.eval_node(dec.children[1])
trailer = dec.children[2:-1]
if trailer:
trailer_nodes = dec.children[2:-1]
if trailer_nodes:
# Create a trailer and evaluate it.
trailer = tree.Node('trailer', trailer)
trailer = tree.Node('trailer', trailer_nodes)
trailer.parent = dec
dec_values = evaluator.eval_trailer(context, dec_values, trailer)

View File

@@ -142,24 +142,10 @@ class AbstractInstanceContext(Context):
def name(self):
pass
def __repr__(self):
return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_context,
self.var_args)
class CompiledInstance(AbstractInstanceContext):
@property
def name(self):
return compiled.CompiledContextName(self, self.class_context.name.string_name)
class TreeInstance(AbstractInstanceContext):
@property
def name(self):
return filters.ContextName(self, self.class_context.name.tree_name)
@memoize_default()
def create_instance_context(self, class_context, node):
if node.parent.type in ('funcdef', 'classdef'):
node = node.parent
scope = node.get_parent_scope()
if scope == class_context.classdef:
return class_context
@@ -183,6 +169,28 @@ class TreeInstance(AbstractInstanceContext):
raise NotImplementedError
return class_context
def __repr__(self):
return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_context,
self.var_args)
class CompiledInstance(AbstractInstanceContext):
@property
def name(self):
return compiled.CompiledContextName(self, self.class_context.name.string_name)
def create_instance_context(self, class_context, node):
if node.get_parent_scope().type == 'classdef':
return class_context
else:
return super(CompiledInstance, self).create_instance_context(class_context, node)
class TreeInstance(AbstractInstanceContext):
@property
def name(self):
return filters.ContextName(self, self.class_context.name.tree_name)
class AnonymousInstance(TreeInstance):
def __init__(self, evaluator, parent_context, class_context):
@@ -194,7 +202,22 @@ class AnonymousInstance(TreeInstance):
)
class CompiledInstanceName(compiled.CompiledName):
def __init__(self, evaluator, instance, parent_context, name):
super(CompiledInstanceName, self).__init__(evaluator, parent_context, name)
self._instance = instance
def infer(self):
for v in super(CompiledInstanceName, self).infer():
if isinstance(v, er.FunctionContext):
yield BoundMethod(self._instance, self.parent_context, v)
else:
yield v
class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
name_class = CompiledInstanceName
def __init__(self, evaluator, instance, compiled_object):
super(CompiledInstanceClassFilter, self).__init__(
evaluator,
@@ -203,10 +226,8 @@ class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
)
self._instance = instance
def _filter(self, names):
names = super(CompiledInstanceClassFilter, self)._filter(names)
return [get_instance_el(self._evaluator, self._instance, name, True)
for name in names]
def _create(self, name):
return self.name_class(self._evaluator, self._instance, self._compiled_obj, name)
class BoundMethod(Context):
@@ -252,6 +273,20 @@ class LazyInstanceName(filters.TreeNameDefinition):
return self._instance.create_instance_context(self._class_context, self.tree_name)
class LazyInstanceName(filters.TreeNameDefinition):
"""
This name calculates the parent_context lazily.
"""
def __init__(self, instance, class_context, tree_name):
self._instance = instance
self._class_context = class_context
self.tree_name = tree_name
@property
def parent_context(self):
return self._instance.create_instance_context(self._class_context, self.tree_name)
class LazyInstanceClassName(LazyInstanceName):
def infer(self):
for v in super(LazyInstanceClassName, self).infer():
@@ -289,9 +324,6 @@ class InstanceClassFilter(filters.ParserTreeFilter):
names = super(InstanceClassFilter, self)._filter(names)
return [name for name in names if self._access_possible(name)]
def _check_flows(self, names):
return names
def _convert_names(self, names):
return [self.name_class(self.context, self._class_context, name) for name in names]
@@ -303,9 +335,10 @@ class SelfNameFilter(InstanceClassFilter):
names = self._filter_self_names(names)
if isinstance(self._parser_scope, compiled.CompiledObject):
# This would be for builtin skeletons, which are not yet supported.
return []
start, end = self._parser_scope.start_pos, self._parser_scope.end_pos
return [n for n in names if start < n.start_pos < end]
return list(names)
else:
start, end = self._parser_scope.start_pos, self._parser_scope.end_pos
return [n for n in names if start < n.start_pos < end]
def _filter_self_names(self, names):
for name in names:
@@ -323,6 +356,9 @@ class SelfNameFilter(InstanceClassFilter):
name = init_execution.name_for_position(name.start_pos)
yield name
def _check_flows(self, names):
return names
class ParamArguments(object):
"""