Question

Here is my sample java code:

public class Test {
    public static void foo() {
        Foo.InnerKey key = new Foo.InnerKey();
        getInstance().query(key);
    }

    public static void bar() {
        Bar.InnerKey key = new Bar.InnerKey();
        getInstance().query(key);
    }

    public static MyIF getInstance(){
        // TODO code to get instance
        return null;
    }

}


interface MyIF {
    public void query(Foo.InnerKey key); // Method to open call hierarchy
    public void query(Bar.InnerKey key);
}


class Foo {
    static class InnerKey  {}
}

class Bar {
    static class InnerKey {}
}

When I open call hierarchy of method query(Foo.InnerKey key) from Eclipse(kepler), I got both foo & bar methods, which bar is not expected.

enter image description here

But in netbeans(7.3.1), the result of call hierarchy is OK:

enter image description here

Is it a bug of Eclipse? Thanks.

Was it helpful?

Solution

This is definitely a JDT bug that should be reported. And the bug is not directly related to the call hierarchy, but instead to the org.eclipse.jdt.core search API, when searching for method references, where the parameter is a member type of another type (as e.g. Foo.InnerKey). Therefore this bug manifests itself for every JDT functionality, that relies on finding method references by using the JDT search engine. For example you will also get wrong results when showing the references to MyIF#query(Foo.InnerKey) or when using the Java search, to search for the methodMyIF#query(Foo.InnerKey). In these cases the search engine will not only return references to MyIF#query(Foo.InnerKey), as would be expected, but also to MyIF#query(Bar.InnerKey).

The relevant code, where this bug occurs, is in org.eclipse.jdt.internal.core.search.matching.MethodLocator#matchMethod(MethodBinding, boolean). And it seems, that the bug was introduced by fixing JDT Bug 41018.

Here is a snippet of the relevant code in the class MethodLocator:

protected int matchMethod(MethodBinding method, boolean skipImpossibleArg) {
    [...]
    // verify each parameter
    for (int i = 0; i < parameterCount; i++) {
        TypeBinding argType = method.parameters[i];
        int newLevel = IMPOSSIBLE_MATCH;
        if (argType.isMemberType()) {
            // only compare source name for member type (bug 41018)
            newLevel = CharOperation.match(this.pattern.parameterSimpleNames[i], argType.sourceName(), this.isCaseSensitive)
                ? ACCURATE_MATCH
                : IMPOSSIBLE_MATCH;
        } else {
            // TODO (frederic) use this call to refine accuracy on parameter types
            // newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], this.pattern.parametersTypeArguments[i], 0, argType);
            newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], argType);
            [...]
        }
    }
    [...]
}

The problem here is the if (argType.isMemberType()) statement, that was introduced to fix Bug 41018. The comment also states that for member types only the source name gets compared. If this if-statement is removed, the bug goes away and the call hierarchy shows the correct references (but I guess this would of course re-introduce bug 41018 - I didn't test this).

Edit

On a side note, there also seems to be a bug when displaying the source codes Javadoc for MyIF#query(Bar.InnerKey) - both when using the Javadoc-Hover over the method or when showing the method in the Javadoc view.

public interface MyIF {
    /**
     * Javadoc for: query(Foo.InnerKey key)
     */
    public void query(Foo.InnerKey key); // Method to open call hierarchy
    /**
     * Javadoc for: query(Bar.InnerKey key)
     */
    public void query(Bar.InnerKey key);
}

When hovering over a query method reference in the Test class (e.g. getInstance().query(key)), both methods are found and one is able to select one (without the ability to differentiate between the two).

When opening the Javadoc view and selecting any of the query method references in the Test class, the Javadoc view always displays only the Javadoc of the first found method in the source class (i.e. MyIF#query(Foo.InnerKey)).

This doesn't seem to be directly related to the bug described above, and it will also not be resolved, when removing the if-statement mentioned above...

OTHER TIPS

I think it may be the same issue as this existing bug (although your example is simpler, IMO). I suggest you add a comment and your example to that bug report.

Also, could be related to https://bugs.eclipse.org/bugs/show_bug.cgi?id=123836 which is suspected as a culprit for another, https://bugs.eclipse.org/bugs/show_bug.cgi?id=394475

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top