Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2016-04-15 11:06:49 +0000
committerManoj Palat2016-04-18 02:23:24 +0000
commitd6cbb5f758ded5eeca102e76e753b701b04256d0 (patch)
tree7a7b8866891098a588515526174d66c249932d23
parentfb827f06601fdcd90551f67eba805b5f12b452c5 (diff)
downloadeclipse.jdt.core-d6cbb5f758ded5eeca102e76e753b701b04256d0.tar.gz
eclipse.jdt.core-d6cbb5f758ded5eeca102e76e753b701b04256d0.tar.xz
eclipse.jdt.core-d6cbb5f758ded5eeca102e76e753b701b04256d0.zip
Fix for Bug 484367 call hierarchy does not finds calls via method
references on interface implementations
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java108
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java41
2 files changed, 147 insertions, 2 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
index 373dc70ea3..748b8dfb51 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
@@ -4761,6 +4761,114 @@ public void testBug485805_001() throws CoreException {
assertFalse("Failed", true);
}
}
+public void testBug484367_0001() throws CoreException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+ "interface Bar {\n" +
+ " public void print();\n" +
+ "}\n" +
+ "\n" +
+ "@FunctionalInterface\n" +
+ "interface Foo {\n" +
+ " void process(Bar bar);\n" +
+ "}\n" +
+ "class BarImpl implements Bar{\n" +
+ " @Override\n" +
+ "//call hierarchy on print does not finds invocation in the below TestMethod class \n" +
+ " public void print() {}\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " public void test(){\n" +
+ " Foo foo1 = (bar)->bar.print();\n" +
+ " Foo foo2 = Bar::print;\n" +
+ " }\n" +
+ "}\n"
+ );
+ IType type = this.workingCopies[0].getType("BarImpl");
+ IMethod method = type.getMethod("print", null);
+ search(method, REFERENCES, EXACT_RULE);
+ assertSearchResults(
+ "src/X.java void void X.test():<lambda #1>.process(Bar) [print()] EXACT_MATCH\n" +
+ "src/X.java void X.test() [print] EXACT_MATCH"
+ );
+}
+public void testBug484367_0002() throws CoreException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+ "interface Bar2 {\n" +
+ " public void print();\n" +
+ "}\n" +
+ "interface Bar1 extends Bar2 {\n" +
+ " public void print();\n" +
+ "}\n" +
+ "class Bar implements Bar1 {\n" +
+ "\n" +
+ " @Override\n" +
+ " public void print() {}\n" +
+ "}\n" +
+ "\n" +
+ "@FunctionalInterface\n" +
+ "interface Foo {\n" +
+ " void process(Bar bar);\n" +
+ "}\n" +
+ "class BarImpl extends Bar{\n" +
+ " public void print() {}\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"unused\")\n" +
+ " public void test(){\n" +
+ " Foo foo1 = (bar)->bar.print();\n" +
+ " Foo foo2 = Bar::print;\n" +
+ " }\n" +
+ "}\n"
+ );
+ IType type = this.workingCopies[0].getType("Bar1");
+ IMethod method = type.getMethod("print", null);
+ search(method, REFERENCES, EXACT_RULE);
+ assertSearchResults(
+ "src/X.java void void X.test():<lambda #1>.process(Bar) [print()] EXACT_MATCH\n" +
+ "src/X.java void X.test() [print] EXACT_MATCH"
+ );
+}
+
+public void testBug484367_0003() throws CoreException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+ "interface Bar1 {\n" +
+ " public void print();\n" +
+ "}\n" +
+ "class Bar implements Bar1 {\n" +
+ "\n" +
+ " @Override\n" +
+ " public void print() {}\n" +
+ "}\n" +
+ "\n" +
+ "@FunctionalInterface\n" +
+ "interface Foo {\n" +
+ " void process(Bar bar);\n" +
+ "}\n" +
+ "class BarImpl extends Bar{\n" +
+ " public void print() {}\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"unused\")\n" +
+ " public void test(){\n" +
+ " Foo foo1 = (bar)->bar.print();\n" +
+ " Foo foo2 = Bar::print;\n" +
+ " }\n" +
+ "}\n"
+ );
+ IType type = this.workingCopies[0].getType("Bar");
+ IMethod method = type.getMethod("print", null);
+ search(method, REFERENCES, EXACT_RULE);
+ assertSearchResults(
+ "src/X.java void void X.test():<lambda #1>.process(Bar) [print()] EXACT_MATCH\n" +
+ "src/X.java void X.test() [print] EXACT_MATCH"
+ );
+}
// Add new tests in JavaSearchBugs8Tests
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
index f31cbae336..eb56de5f6b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -150,6 +150,22 @@ protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend)
&& !(method.isDefault() && this.pattern.focus != null
&& !CharOperation.equals(this.pattern.declaringPackageName, method.declaringClass.qualifiedPackageName()));
}
+protected ReferenceBinding checkMethodRef(MethodBinding method, ReferenceExpression referenceExpression) {
+ boolean result = (!method.isStatic() && !method.isPrivate()
+ && referenceExpression.isMethodReference()
+ && !(method.isDefault() && this.pattern.focus != null
+ && !CharOperation.equals(this.pattern.declaringPackageName, method.declaringClass.qualifiedPackageName())));
+ if (result) {
+ Expression lhs = referenceExpression.lhs;
+ if (lhs instanceof NameReference) {
+ Binding binding = ((NameReference) lhs).binding;
+ if (binding instanceof ReferenceBinding)
+ return (ReferenceBinding) binding;
+ }
+ }
+
+ return null;
+}
public int match(ASTNode node, MatchingNodeSet nodeSet) {
int declarationsLevel = IMPOSSIBLE_MATCH;
if (this.pattern.findReferences) {
@@ -793,7 +809,28 @@ protected int resolveLevel(ReferenceExpression referenceExpression) {
// receiver type
if (this.pattern.declaringSimpleName == null && this.pattern.declaringQualification == null) return methodLevel; // since any declaring class will do
- int declaringLevel = resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass);
+ int declaringLevel;
+ ReferenceBinding ref = checkMethodRef(method, referenceExpression);
+ if (ref != null) {
+ declaringLevel = resolveLevelAsSubtype(this.pattern.declaringSimpleName, this.pattern.declaringQualification, ref, method.selector, method.parameters, ref.qualifiedPackageName(), method.isDefault());
+ if (declaringLevel == IMPOSSIBLE_MATCH) {
+ if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) {
+ declaringLevel = INACCURATE_MATCH;
+ } else {
+ char[][][] superTypeNames = (method.isDefault() && this.pattern.focus == null) ? this.samePkgSuperDeclaringTypeNames: this.allSuperDeclaringTypeNames;
+ if (superTypeNames != null && resolveLevelAsSuperInvocation(ref, method.parameters, superTypeNames, true)) {
+ declaringLevel = methodLevel // since this is an ACCURATE_MATCH so return the possibly weaker match
+ | SUPER_INVOCATION_FLAVOR; // TODO: not an invocation really but ref -> add flavor to returned level
+ }
+ }
+ }
+ if ((declaringLevel & FLAVORS_MASK) != 0) {
+ // level got some flavors => return it
+ return declaringLevel;
+ }
+ } else {
+ declaringLevel = resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass);
+ }
return (methodLevel & MATCH_LEVEL_MASK) > (declaringLevel & MATCH_LEVEL_MASK) ? declaringLevel : methodLevel; // return the weaker match
}

Back to the top