Ответ 1
Это определенно ошибка JDT, о которой следует сообщить. И ошибка не связана напрямую с иерархией вызовов, а вместо этого в API поиска org.eclipse.jdt.core при поиске ссылок на методы, где параметр является типом-членом другого типа (например, Foo.InnerKey
). Поэтому эта ошибка проявляется для каждой функциональности JDT, которая опирается на поиск ссылок на методы с помощью поисковой системы JDT. Например, вы также получите неправильные результаты при показе ссылок на MyIF#query(Foo.InnerKey)
или при использовании поиска Java для поиска метода MyIF#query(Foo.InnerKey)
. В этих случаях поисковая система не только вернет ссылки на MyIF#query(Foo.InnerKey)
, как и следовало ожидать, но также и на MyIF#query(Bar.InnerKey)
.
Соответствующий код, где происходит эта ошибка, находится в org.eclipse.jdt.internal.core.search.matching.MethodLocator#matchMethod(MethodBinding, boolean)
. И кажется, что ошибка была введена путем исправления JDT Bug 41018.
Вот фрагмент соответствующего кода в классе 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);
[...]
}
}
[...]
}
Проблема здесь - это оператор if (argType.isMemberType())
, который был введен для исправления Ошибка 41018. В комментарии также указано, что для типов членов сравнивается только исходное имя. Если этот оператор if удален, ошибка исчезает, и иерархия вызовов показывает правильные ссылки (но, я думаю, это, конечно, повторит ошибку 41018 - я не тестировал это).
Edit
На стороне примечания также появляется ошибка при отображении исходных кодов Javadoc для MyIF#query(Bar.InnerKey)
- как при использовании Javadoc-Hover над методом, так и при показе метода в представлении Javadoc.
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);
}
При наведении указателя метода запроса в классе Test (например, getInstance().query(key)
) оба метода найдены, и один из них может выбрать один (без возможности разграничения между ними).
При открытии представления Javadoc и выборе любой из ссылок метода запроса в классе Test, представление Javadoc всегда отображает только Javadoc первого найденного метода в исходном классе (т.е. MyIF#query(Foo.InnerKey)
).
Это, похоже, напрямую не связано с описанной выше ошибкой, и это также не будет устранено при удалении упомянутого выше оператора if...