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...