davidhalter / jedi

Awesome autocompletion, static analysis and refactoring library for python
http://jedi.readthedocs.io
Other
5.73k stars 503 forks source link

Completion fails when variable name is identical to type name #1988

Closed pyscripter closed 2 months ago

pyscripter commented 3 months ago

The following is valid python code:

class Test:
    str: str = 'abc'

print(Test.str)

Code completion fails though at the last dot below.

Test.str.

If you change the variable name "str" to anything else, code completion works. The problem is caused when the variable name is identical to the type name. This is an issue with certain stub files (e.g. delphivcl) in which variable type annotations such as Bitmap: Bitmap are quite common.

davidhalter commented 3 months ago

Yes, this surprisingly does not work.

pyscripter commented 3 months ago

@davidhalter

Here is my fix. In syntax_tree.py, method tree_name_to_values, I have added 4 lines after the statement found_annotation = True

def tree_name_to_values(inference_state, context, tree_name):
    value_set = NO_VALUES
    module_node = context.get_root_context().tree_node
    # First check for annotations, like: `foo: int = 3`
    if module_node is not None:
        names = module_node.get_used_names().get(tree_name.value, [])
        found_annotation = False
        for name in names:
            expr_stmt = name.parent

            if expr_stmt.type == "expr_stmt" and expr_stmt.children[1].type == "annassign":
                correct_scope = parser_utils.get_parent_scope(name) == context.tree_node
                if correct_scope:
                    found_annotation = True
                    if (expr_stmt.children[1].children[1].type == 'name') and \
                        (expr_stmt.children[1].children[1].value == tree_name.value) and \
                        context.parent_context:
                        context = context.parent_context
                    value_set |= annotation.infer_annotation(
                        context, expr_stmt.children[1].children[1]
                    ).execute_annotation()

If you agree with the change, I can submit PR. Please let me know.

davidhalter commented 3 months ago

@pyscripter. I generally agree with the analysis of the problem. A PR would be appreciated.

However I feel like thes solution would probably be better like this:

ann_assign = expr_stmt.children[1]
if correct_scope and name.start_pos < ann_assign.start_pos:

We just need to make sure that the name is part of the annotation assignment before the annotation. That's probably easier to understand.

pyscripter commented 3 months ago

@davidhalter I have submitted a PR. I have added the check of start_pos you suggested and makes sense. You still need to check after that, whether the variable name is identical to type name and if this is true search for the type in the parent context.