Eclipse - `open call hierarchy`得到了错误的结果

时间:2014-03-11 06:17:58

标签: java eclipse eclipse-jdt

这是我的示例java代码:

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 {}
}

当我从Eclipse(kepler)打开方法query(Foo.InnerKey key)的调用层次结构时,我得到了foo& bar方法,bar不期望。

enter image description here

但是在netbeans(7.3.1)中,调用层次结构是正常的:

enter image description here

这是Eclipse的错误吗?感谢。

2 个答案:

答案 0 :(得分:10)

这绝对是一个应该报告的JDT错误。并且该bug与调用层次结构没有直接关系,而是与org.eclipse.jdt.core搜索API直接相关,在搜索方法引用时,参数是另一种类型的成员类型(例如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())语句,它是为修复Bug 41018而引入的。该评论还指出,对于成员类型,仅比较源名称。如果删除了这个if语句,那么bug就会消失,调用层次结构会显示正确的引用(但我想这当然会重新引入bug 41018 - 我没有对此进行测试)。

修改

另外,在MyIF#query(Bar.InnerKey)显示源代码Javadoc时似乎也存在一个错误 - 无论是在方法上使用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语句时也无法解决...

答案 1 :(得分:1)

我认为这可能与this existing bug的问题相同(尽管您的示例更简单,IMO)。我建议您在该错误报告中添加评论和示例。

此外,可能与被怀疑是另一个人的罪魁祸首的https://bugs.eclipse.org/bugs/show_bug.cgi?id=123836有关,https://bugs.eclipse.org/bugs/show_bug.cgi?id=394475