eclipse-jdtls / eclipse.jdt.ls

Java language server
1.79k stars 399 forks source link

wrong newText for completion item that overrides method in anonymous class #1371

Closed Eskibear closed 2 years ago

Eskibear commented 4 years ago

Originally reported in https://github.com/MicrosoftDocs/intellicode/issues/173

Sample code to reproduce:

class Hello {
    ThreadLocal<Integer> fLocal = new ThreadLocal<Integer>(){
            initialValue<trigger completion here>
    };
}

bug

It only occurs when you initialize a field member in declaration. I tried the same thing within a method body, and it worked well.

Below is the response, we can see textEdit.newText is wrong.

{
            "label": "initialValue() : Integer",
            "kind": 2,
            "detail": "Override method in 'ThreadLocal'",
            "sortText": "999999259",
            "filterText": "initialValue",
            "insertText": "initialValue",
            "insertTextFormat": 2,
            "textEdit": {
                "range": {
                    "start": {
                        "line": 30,
                        "character": 2
                    },
                    "end": {
                        "line": 30,
                        "character": 14
                    }
                },
                "newText": "null"
            },
            "data": {
                "decl_signature": "Ljava.lang.ThreadLocal<Ljava.lang.Integer;>;",
                "signature": "()Ljava.lang.Integer;",
                "name": "initialValue",
                "pid": "0",
                "rid": "5",
                "uri": "file:///path-to-file.java"
            }
        },
akaroml commented 4 years ago

@Eskibear please go ahead with a fix :)

fbricon commented 4 years ago

@Eskibear are you gonna fix this one for this release?

Eskibear commented 4 years ago

TLDR

I did some investigation, it's not a low-hanging bug, I'm not going to work on it right now.

Root cause

The CompilationUnit returned by upstream utility JavaCore.createCompilationUnitFrom(resource) is incomplete, so JDTLS is not aware that the position is in an anonymous class.

Workaround for users

To trigger the completion directly without inputting the hint

More details

E.g. for sample code below

package com.example.demo;

public class Hello {
    ThreadLocal<Integer> fieldVar = new ThreadLocal<Integer>() {
        initialValue
    };

    public static void foo() {
        ThreadLocal<Integer> localVar = new ThreadLocal<Integer>() {
            initialValue
        }
    }
}

The compilationUnit misses the anonymous class part.

CompilationUnit@2359 "[Working copy] Hello.java [in com.example.demo [in src/main/java [in demo]]]
  package com.example.demo
  class Hello
    ThreadLocal<Integer> fieldVar
    static void foo()
      class <anonymous #1>"

BUT, if we trigger completion directly (removing the hint "initialValue"), the unit is correct, with a subnode of the anonymous class.

...
public class Hello {
    ThreadLocal<Integer> fieldVar = new ThreadLocal<Integer>() {
        [CURSOR]
    };
...
CompilationUnit@2373 "[Working copy] Hello.java [in com.example.demo [in src/main/java [in demo]]]
  package com.example.demo
  class Hello
    ThreadLocal<Integer> fieldVar
      class <anonymous #1>                             <-----HERE
    static void foo()
      class <anonymous #1>"
jdneo commented 2 years ago

Don't know when but at least it's gone in the latest

completion1