1
0
forked from VimPlug/jedi

Now overloaded functions exist, but the matching doesn't work, yet

This commit is contained in:
Dave Halter
2018-08-26 19:39:55 +02:00
parent 05d07c23ab
commit 5261cdf4a1
3 changed files with 90 additions and 3 deletions

View File

@@ -104,12 +104,24 @@ class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)):
""" """
@classmethod @classmethod
def from_context(cls, context, tree_node): def from_context(cls, context, tree_node):
def create(tree_node):
return cls(context.evaluator, parent_context=context, tree_node=tree_node)
from jedi.evaluate.context import AbstractInstanceContext from jedi.evaluate.context import AbstractInstanceContext
overloaded_funcs = list(_find_overload_functions(context, tree_node))
while context.is_class() or isinstance(context, AbstractInstanceContext): while context.is_class() or isinstance(context, AbstractInstanceContext):
context = context.parent_context context = context.parent_context
return cls(context.evaluator, parent_context=context, tree_node=tree_node) function = create(tree_node)
if len(overloaded_funcs) > 1:
return OverloadedFunctionContext(
function,
ContextSet.from_iterable(create(f) for f in overloaded_funcs)
)
return function
def get_function_execution(self, arguments=None): def get_function_execution(self, arguments=None):
if arguments is None: if arguments is None:
@@ -255,3 +267,76 @@ class FunctionExecutionContext(TreeContext):
@evaluator_method_cache() @evaluator_method_cache()
def get_executed_params(self): def get_executed_params(self):
return self.var_args.get_executed_params(self) return self.var_args.get_executed_params(self)
class OverloadedFunctionContext(object):
def __init__(self, function, overloaded_functions):
self._function = function
self._overloaded_functions = overloaded_functions
def py__call__(self, arguments):
return ContextSet.from_sets(
f.py__call__(arguments=arguments)
for f in self._overloaded_functions
if signature_matches(f, arguments)
)
def __getattr__(self, name):
return getattr(self._function, name)
def signature_matches(function_context, arguments):
unpacked_arguments = arguments.unpack()
for param_node in function_context.tree_node.get_params():
key, argument = next(unpacked_arguments, (None, None))
print(param_node)
if argument is None:
# This signature has an parameter more than arguments were given.
return False
if key is not None:
# TODO this is obviously wrong, we cannot just ignore keyword
# arguments, but it's easier for now.
return False
if param_node.annotation is not None:
annotation_result = function_context.evaluator.eval_node(
function_context.parent_context,
param_node.annotation
)
print(annotation_result)
return True
def _find_overload_functions(context, tree_node):
def _is_overload_decorated(funcdef):
if funcdef.parent.type == 'decorated':
decorators = funcdef.parent.children[0]
if decorators.type == 'decorator':
decorators = [decorators]
else:
decorators = decorators.children
for decorator in decorators:
dotted_name = decorator.children[1]
if dotted_name.type == 'name' and dotted_name.value == 'overload':
# TODO check with contexts if it's the right overload
return True
return False
if _is_overload_decorated(tree_node):
yield tree_node
while True:
filter = ParserTreeFilter(
context.evaluator,
context,
until_position=tree_node.start_pos
)
names = filter.get(tree_node.name.value)
for name in names:
funcdef = name.tree_name.parent
if funcdef.type == 'funcdef' and _is_overload_decorated(funcdef):
yield funcdef
break # By default break

View File

@@ -296,6 +296,7 @@ class TypeVar(Context):
def execute_annotation(self): def execute_annotation(self):
if self._bound_lazy_context is not None: if self._bound_lazy_context is not None:
return self._bound_lazy_context.infer().execute_annotation() return self._bound_lazy_context.infer().execute_annotation()
debug.warning('Tried to infer a TypeVar without a given type')
return NO_CONTEXTS return NO_CONTEXTS
def __repr__(self): def __repr__(self):
@@ -305,5 +306,5 @@ class TypeVar(Context):
class OverloadFunction(_BaseTypingContext): class OverloadFunction(_BaseTypingContext):
@repack_with_argument_clinic('func, /') @repack_with_argument_clinic('func, /')
def py__call__(self, func_context_set): def py__call__(self, func_context_set):
debug.warning('overload used %s', func_context_set) # Just pass arguments through.
return func_context_set return func_context_set

View File

@@ -9,7 +9,8 @@ from jedi.cache import memoize_method
from jedi.evaluate.base_context import ContextSet, iterator_to_context_set from jedi.evaluate.base_context import ContextSet, iterator_to_context_set
from jedi.evaluate.filters import AbstractTreeName, ParserTreeFilter, \ from jedi.evaluate.filters import AbstractTreeName, ParserTreeFilter, \
TreeNameDefinition TreeNameDefinition
from jedi.evaluate.context import ModuleContext, FunctionContext, ClassContext from jedi.evaluate.context import ModuleContext, FunctionContext, \
ClassContext, BoundMethod
from jedi.evaluate.context.typing import TypingModuleFilterWrapper, \ from jedi.evaluate.context.typing import TypingModuleFilterWrapper, \
TypingModuleName TypingModuleName
from jedi.evaluate.compiled import CompiledObject from jedi.evaluate.compiled import CompiledObject