JsniChecker should resolve methods defined by super interfaces.
Review by: bobv
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7280 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java b/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
index 07c2361..dea6347 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
@@ -56,8 +56,11 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;
+import java.util.Arrays;
+import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
+import java.util.Queue;
import java.util.Set;
import java.util.Stack;
@@ -374,13 +377,23 @@
}
}
} else {
- while (clazz != null) {
+ Queue<ReferenceBinding> work = new LinkedList<ReferenceBinding>();
+ work.add(clazz);
+ while (!work.isEmpty()) {
+ clazz = work.remove();
for (MethodBinding findMethod : clazz.getMethods(methodName.toCharArray())) {
if (paramTypesMatch(findMethod, jsniRef)) {
return findMethod;
}
}
- clazz = clazz.superclass();
+ ReferenceBinding[] superInterfaces = clazz.superInterfaces();
+ if (superInterfaces != null) {
+ work.addAll(Arrays.asList(superInterfaces));
+ }
+ ReferenceBinding superclass = clazz.superclass();
+ if (superclass != null) {
+ work.add(superclass);
+ }
}
}
return null;
diff --git a/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java b/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java
index 1e45512..0f19de7 100644
--- a/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java
+++ b/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java
@@ -357,6 +357,28 @@
"Parameter 1 of method \'Buggy.print\': type 'long' may not be passed out of JSNI code");
}
+ /**
+ * Test JSNI references to methods defined in superclass/superinterfaces.
+ */
+ public void testMethodInheritance() {
+ StringBuffer code = new StringBuffer();
+ code.append("class Buggy {\n");
+ code.append(" interface A1 { void a1(); }\n");
+ code.append(" interface A2 extends A1 { void a2(); }\n");
+ code.append(" static abstract class C1 implements A2 { public abstract void c1(); }\n");
+ code.append(" native void jsniMeth(Object o) /*-{\n");
+ code.append(" o.@Buggy.A1::a1()();\n");
+ code.append(" o.@Buggy.A2::a1()();\n");
+ code.append(" o.@Buggy.A2::a2()();\n");
+ code.append(" o.@Buggy.C1::a1()();\n");
+ code.append(" o.@Buggy.C1::a2()();\n");
+ code.append(" o.@Buggy.C1::c1()();\n");
+ code.append(" }-*/;\n");
+ code.append("}\n");
+
+ shouldGenerateNoWarning(code);
+ }
+
public void testMethodReturn() {
StringBuffer code = new StringBuffer();
code.append("class Buggy {\n");