eclipse-jdtls / eclipse.jdt.ls

Java language server
1.79k stars 399 forks source link

`textDocument/implementation` Fails when arguments are present #3297

Open TomKrcmar opened 2 weeks ago

TomKrcmar commented 2 weeks ago

I am running Milestone 1.39.0

Given

The following is my test directory: Main.java

class Main {
    static void main(String[] args) {
        IPerson person = new Person("Test", "User", 25);
        System.out.println("Hello, "+person.toStr(true)+"!");
    }
}

IPerson.java

interface IPerson {
    public String getName();
    public String getAge(boolean testBool);
    public String toStr(boolean testBool);
}

Person.java

class Person implements IPerson {
    String firstName;
    String lastName;
    int age;

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    public String getName() {
        return this.firstName + " " + this.lastName;
    }
    public String getAge(boolean testBool) {
        return this.age + " years";
    }
    public String toStr(boolean testBool) {
        return "Name: " + this.getName() + "\nAge: " + this.getAge(testBool);
    }
}

When

When running textDocument/implementation on every position contained in the entire IPosition.java file, I would expect to get 4 hits (One for the interface implemented by the Person class, and one for each method implemented by the Person class).

Then

Instead, I get 2 hits, one for the Person implementer, then another for the getName() implementer.

If I remove the boolean testBool argument from getAge(), then textDocument/implementation returns 3 hits across the file, including getAge(). The same happens if I then remove testBool from toStr. All 4 expected hits work, only when the methods have no arguments. If I add an argument to one, it breaks and is no longer returned by textDocument/implementation.

Maybe I am missing something or have a wrong assumption? Even if so, the behavior seems bizarre to me.

Test Details

To clarify, I am running the request on every position in the file, because I've had some inconsistent behavior with range vs selectionRange coming from other responses by JDTLS, so I'm just testing across entire files to make sure of the behavior first. Maybe this will help. The following was generated by outputting . if 0 textDocument/implementation hits were found, and outputting the character at this position if more than 0 hits were found. For each position in IPerson.java. So you can see IPerson was a hit, and getName() was a hit, but not the other methods:

..........IPerson .
...............getName(..
........................................
.......................................

If I remove the boolean argument from getAge(), the mask looks like this:

..........IPerson .
...............getName(..
...............getAge(..
.......................................
rgrunber commented 1 day ago

What client are you using with JDT-LS ? Or are you writing your own from scratch ? I tried what you described for getAge and it seems to be working for vscode-java.

(line 2 (0-based) in IPerson.java corresponds to getAge and line 13 in Person.java corresponds to its implementation)

[Trace - 14:02:27] Sending request 'textDocument/implementation - (435)'.
Params: {
    "textDocument": {
        "uri": "file:///tmp/foo/IPerson.java"
    },
    "position": {
        "line": 2,
        "character": 19
    }
}

[Trace - 14:02:27] Received notification 'window/logMessage'.
Params: {
    "type": 3,
    "message": "Oct 25, 2024, 2:02:27 p.m. >> document/implementation"
}

[Info  - 14:02:27] Oct 25, 2024, 2:02:27 p.m. >> document/implementation
[Trace - 14:02:27] Received request 'window/workDoneProgress/create - (108)'.
Params: {
    "token": "586819f2-6a2e-40e7-a20e-e2ac3951d6c7"
}

[Trace - 14:02:27] Sending response 'window/workDoneProgress/create - (108)'. Processing request took 0ms
No result returned.

[Trace - 14:02:27] Received notification '$/progress'.
Params: {
    "token": "586819f2-6a2e-40e7-a20e-e2ac3951d6c7",
    "value": {
        "kind": "begin",
        "title": "Background task",
        "message": "Background task"
    }
}

[Trace - 14:02:27] Received notification '$/progress'.
Params: {
    "token": "586819f2-6a2e-40e7-a20e-e2ac3951d6c7",
    "value": {
        "kind": "report",
        "message": "Background task - 0% ",
        "percentage": 0
    }
}

[Trace - 14:02:28] Received notification '$/progress'.
Params: {
    "token": "586819f2-6a2e-40e7-a20e-e2ac3951d6c7",
    "value": {
        "kind": "end",
        "message": "Searching for implementors of 'IPerson.getAge(...)'..."
    }
}

[Trace - 14:02:28] Received response 'textDocument/implementation - (435)' in 112ms.
Result: [
    {
        "uri": "file:///tmp/foo/Person.java",
        "range": {
            "start": {
                "line": 13,
                "character": 15
            },
            "end": {
                "line": 13,
                "character": 21
            }
        }
    }
]

I could try to perform this in an even more basic manner on JDT-LS and just send over the raw json requests to really be sure. Are you able to detect if any errors have been reported ?