diff --git a/jedi/inference/gradual/typing.py b/jedi/inference/gradual/typing.py index 0f5b74ad..30eb1ddf 100644 --- a/jedi/inference/gradual/typing.py +++ b/jedi/inference/gradual/typing.py @@ -34,7 +34,7 @@ _TYPE_ALIAS_TYPES = { 'Deque': 'collections.deque', } _PROXY_TYPES = ['Optional', 'Union', 'ClassVar', 'Annotated', 'Final'] -_IGNORE_ANNOTATION_PARTS = ['ClassVar', 'Annotated', 'Final'] +IGNORE_ANNOTATION_PARTS = ['ClassVar', 'Annotated', 'Final'] class TypingModuleName(NameWrapper): @@ -115,7 +115,7 @@ class ProxyWithGenerics(BaseTypingClassWithGenerics): elif string_name == 'Type': # The type is actually already given in the index_value return self._generics_manager[0] - elif string_name in _IGNORE_ANNOTATION_PARTS: + elif string_name in IGNORE_ANNOTATION_PARTS: # For now don't do anything here, ClassVars are always used. return self._generics_manager[0].execute_annotation() diff --git a/jedi/inference/syntax_tree.py b/jedi/inference/syntax_tree.py index 9baf3bf4..780b682e 100644 --- a/jedi/inference/syntax_tree.py +++ b/jedi/inference/syntax_tree.py @@ -30,6 +30,7 @@ from jedi.inference.names import TreeNameDefinition from jedi.inference.context import CompForContext from jedi.inference.value.decorator import Decoratee from jedi.plugins import plugin_manager +from jedi.inference.gradual.typing import ProxyTypingValue, IGNORE_ANNOTATION_PARTS operator_to_magic_method = { '+': '__add__', @@ -701,16 +702,24 @@ def tree_name_to_values(inference_state, context, tree_name): correct_scope = parser_utils.get_parent_scope(name) == context.tree_node ann_assign = expr_stmt.children[1] if correct_scope: - found_annotation = True if ( (ann_assign.children[1].type == 'name') and (ann_assign.children[1].value == tree_name.value) and context.parent_context ): context = context.parent_context - value_set |= annotation.infer_annotation( + found = annotation.infer_annotation( context, expr_stmt.children[1].children[1] - ).execute_annotation() + ) + set_found_annotation = True + if len(found) == 1: + first = next(iter(found)) + set_found_annotation = not ( + isinstance(first, ProxyTypingValue) + and first.name.string_name in IGNORE_ANNOTATION_PARTS + ) + found_annotation = set_found_annotation + value_set |= found.execute_annotation() if found_annotation: return value_set diff --git a/test/completion/pep0484_typing.py b/test/completion/pep0484_typing.py index db111bda..89c290ac 100644 --- a/test/completion/pep0484_typing.py +++ b/test/completion/pep0484_typing.py @@ -555,15 +555,3 @@ def typed_dict_test_foo(arg: Bar): arg['an_int'] #? int() arg['another_variable'] - -# ------------------------- -# Final -# ------------------------- - -x: Final[str] = 1 -y: Final = 1 -#? str() -x -# TODO -#? -y diff --git a/test/completion/pep0526_variables.py b/test/completion/pep0526_variables.py index 1a77f383..739db8a3 100644 --- a/test/completion/pep0526_variables.py +++ b/test/completion/pep0526_variables.py @@ -59,6 +59,7 @@ class VarClass: var_class1: typing.ClassVar[str] = 1 var_class2: typing.ClassVar[bytes] var_class3 = None + var_class4: typing.ClassVar = "" def __init__(self): #? int() @@ -71,7 +72,7 @@ class VarClass: d.var_class2 #? [] d.int - #? ['var_class1', 'var_class2', 'var_instance1', 'var_instance2', 'var_class3'] + #? ['var_class1', 'var_class2', 'var_instance1', 'var_instance2', 'var_class3', 'var_class4'] self.var_ class VarClass2(VarClass): @@ -81,7 +82,7 @@ class VarClass2(VarClass): #? int() self.var_class3 -#? ['var_class1', 'var_class2', 'var_instance1', 'var_class3', 'var_instance2'] +#? ['var_class1', 'var_class2', 'var_class4', 'var_instance1', 'var_class3', 'var_instance2'] VarClass.var_ #? int() VarClass.var_instance1 @@ -91,11 +92,13 @@ VarClass.var_instance2 VarClass.var_class1 #? bytes() VarClass.var_class2 +#? str() +VarClass.var_class4 #? [] VarClass.int d = VarClass() -#? ['var_class1', 'var_class2', 'var_class3', 'var_instance1', 'var_instance2'] +#? ['var_class1', 'var_class2', 'var_class3', 'var_class4', 'var_instance1', 'var_instance2'] d.var_ #? int() d.var_instance1 @@ -105,6 +108,8 @@ d.var_instance2 d.var_class1 #? bytes() d.var_class2 +#? str() +d.var_class4 #? [] d.int @@ -117,3 +122,39 @@ class DC: #? int() DC().name + +# ------------------------- +# Final +# ------------------------- + +# TODO this is wrong, but shouldn't matter that much +#? 0 int() +x: typing.Final[str] = 1 +#? 0 int() +y: typing.Final = 1 +#? str() +x +#? int() +y + +def f(x: typing.Final[str]): + #? str() + x + +class C: + x: typing.Final[bytes] = 1 + #? 4 str() + y: typing.Final = "" + #? bytes() + x + #? str() + y + +#? bytes() +C.x +#? str() +C.y +#? bytes() +C().x +#? str() +C().y