Make sure classmethod param completion works better for the first param

This commit is contained in:
Dave Halter
2019-12-25 03:39:37 +01:00
parent 110d89724e
commit 3b2dddd1d3
3 changed files with 50 additions and 13 deletions

View File

@@ -19,7 +19,7 @@ from jedi.inference.value.function import \
BaseFunctionExecutionContext, FunctionExecutionContext BaseFunctionExecutionContext, FunctionExecutionContext
from jedi.inference.value.klass import ClassFilter from jedi.inference.value.klass import ClassFilter
from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance
from jedi.parser_utils import function_is_static_method from jedi.parser_utils import function_is_staticmethod, function_is_classmethod
class InstanceExecutedParamName(ParamName): class InstanceExecutedParamName(ParamName):
@@ -41,9 +41,19 @@ class AnonymousMethodExecutionFilter(AnonymousFunctionExecutionFilter):
self._instance = instance self._instance = instance
def _convert_param(self, param, name): def _convert_param(self, param, name):
if param.position_index == 0 \ if param.position_index == 0:
and not function_is_static_method(self._function_value.tree_node): if function_is_classmethod(self._function_value.tree_node):
return InstanceExecutedParamName(self._instance, self._function_value, name) return InstanceExecutedParamName(
self._instance.py__class__(),
self._function_value,
name
)
elif not function_is_staticmethod(self._function_value.tree_node):
return InstanceExecutedParamName(
self._instance,
self._function_value,
name
)
return super(AnonymousMethodExecutionFilter, self)._convert_param(param, name) return super(AnonymousMethodExecutionFilter, self)._convert_param(param, name)

View File

@@ -297,9 +297,21 @@ def get_string_quote(leaf):
return re.match(r'\w*("""|\'{3}|"|\')', leaf.value).group(1) return re.match(r'\w*("""|\'{3}|"|\')', leaf.value).group(1)
def function_is_static_method(function_node): def _function_is_x_method(method_name):
for decorator in function_node.get_decorators(): def wrapper(function_node):
dotted_name = decorator.children[1] """
if dotted_name.get_code() == 'staticmethod': This is a heuristic. It will not hold ALL the times, but it will be
return True correct pretty much for anyone that doesn't try to beat it.
return False staticmethod/classmethod are builtins and unless overwritten, this will
be correct.
"""
for decorator in function_node.get_decorators():
dotted_name = decorator.children[1]
if dotted_name.get_code() == method_name:
return True
return False
return wrapper
function_is_staticmethod = _function_is_x_method('staticmethod')
function_is_classmethod = _function_is_x_method('classmethod')

View File

@@ -318,13 +318,28 @@ class F():
#? #?
return param return param
@classmethod
def my_method_without_call(cls, param):
#?
cls.my_variable
#? ['my_method', 'my_method_without_call']
cls.my_meth
#?
return param
@classmethod @classmethod
def my_method(cls, param): def my_method(cls, param):
#? [] #?
param.my_method cls.my_variable
#? ['my_method', 'my_method_without_call']
cls.my_meth
#?
return param
#? str()
F.my_func('') F.my_func('')
#? str()
F.my_method('')
# ----------------- # -----------------
# Unknown metaclass # Unknown metaclass