Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signature help does not display all overloaded methods #3052

Closed
hopehadfield opened this issue Feb 9, 2024 · 4 comments · Fixed by #3073
Closed

Signature help does not display all overloaded methods #3052

hopehadfield opened this issue Feb 9, 2024 · 4 comments · Fixed by #3073

Comments

@hopehadfield
Copy link
Contributor

In the case that a method contains less parameters in a superclass than the respective extended method in a subclass, all overloaded methods further extended from the superclass are not displayed in signature help. See the below example.

public class MovingObject {
    public void speed(int x, int y, int z){}
}
public class Vehicle extends MovingObject{
    public void speed(){}
}
public class Car extends Vehicle{
    public void speed(int x){}
    public void speed(int x, int y){}
}

Screenshot from 2024-02-09 14-06-27

There should be 4 overloaded methods displayed in signature help, but instead only the methods from Vehicle and MovingObject are visible.

@rgrunber
Copy link
Contributor

rgrunber commented Feb 9, 2024

Seems slightly similar to what @snjeza reported in #2014 (comment) . It's worth checking if the calls to completion return all the overloads, and if so, we should be able to figure out why signature help isn't displaying all of them.

@rgrunber
Copy link
Contributor

rgrunber commented Feb 13, 2024

The problem is here :

while (declaringType != null) {
String unqualifiedName = declaringType.getErasure().getName().replace(";", "");
typeNames.add(unqualifiedName);
declaringType = declaringType.getSuperclass();
}
this.declaringTypeNames = typeNames;

We get the declaring type based on the specific method that is selected (eg. for test.speed(), even though test is a Car, speed() is declared in Vehicle. From there we only discover the super classes of Vehicle, which are MovingObject, and java.lang.Object. Once we get to :

public void accept(CompletionProposal proposal) {
if (!isIgnored(proposal.getKind())) {
if (proposal.getKind() == CompletionProposal.METHOD_REF && !Objects.equals(proposal.getName() == null ? null : new String(proposal.getName()), methodName)) {
return;
}
if (this.declaringTypeNames != null) {
char[] declarationSignature = proposal.getDeclarationSignature();
if (declarationSignature != null) {
String proposalTypeSimpleName = SignatureHelpUtils.getSimpleTypeName(String.valueOf(declarationSignature));
for (String typeName : this.declaringTypeNames) {
String declaringTypeSimpleName = Signature.getSimpleName(typeName);
if (Objects.equals(proposalTypeSimpleName, declaringTypeSimpleName)) {
proposals.putIfAbsent(String.valueOf(proposal.getSignature()), proposal);
return;
}
}
return;
}
}
proposals.putIfAbsent(String.valueOf(proposal.getSignature()), proposal);
}
}

we do get speed(int), speed(int, int) from the completion engine, but we dismiss them because Car is not in declaringTypeNames.

I think we need to revisit this logic because it is definitely broken. The name comparison is there because completion invocation within the parameter "area" was always a bit buggy and we had to dismiss some odd values, but computing subtypes (in addition to supertypes) could get expensive. Do we need to compute the types at all or can we just go by the rule of "accept any method whose name matches".

@rgrunber
Copy link
Contributor

rgrunber commented Mar 7, 2024

As a note the following is now an issue for signature help :

Test.java

package test1;

public class Test {

    public String[] getQuestions(boolean onlyMultipleChoice) {
        return null;
    }

    public String[] getQuestions() {
        return null;
    }
}

Exam.java

package test1;

public class Exam extends Test {

    public String[] getQuestions(int number) {
        return null;
    }
}

Main.java

package test1;

public class Main {
    public void doStuff() {
        Test ex = new Test();
        ((Exam) ex).getQuestions(|)
    }

    public String[] getQuestions(int number, String section, boolean multiple) {
        return null;
    }
}

image

It's an improvement over the issue of missing overloads.

@jdneo
Copy link
Contributor

jdneo commented Mar 7, 2024

As a note the following is now an issue for signature help

Ah, that might be the reason why declaring type is preserved. Let's file an issue first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants