Revision: 7034
Author: [email protected]
Date: Thu Nov 19 13:48:22 2009
Log: JsniChecker should support the "::new" syntax.

Review by: bobv
http://code.google.com/p/google-web-toolkit/source/detail?r=7034

Modified:
  /trunk/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
  /trunk/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java       Thu Nov 
 
19 13:48:07 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java       Thu Nov 
 
19 13:48:22 2009
@@ -45,8 +45,10 @@
  import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
  import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
  import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
  import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
  import org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;
@@ -307,9 +309,37 @@

      private MethodBinding getMethod(ReferenceBinding clazz, JsniRef  
jsniRef) {
        assert jsniRef.isMethod();
-      for (MethodBinding findMethod :  
clazz.getMethods(jsniRef.memberName().toCharArray())) {
-        if (paramTypesMatch(findMethod, jsniRef)) {
-          return findMethod;
+      String methodName = jsniRef.memberName();
+      if ("new".equals(methodName)) {
+        for (MethodBinding findMethod : clazz.getMethods(INIT_CTOR_CHARS))  
{
+          StringBuilder methodSig = new StringBuilder();
+          if (clazz instanceof NestedTypeBinding) {
+            // Match synthetic args for enclosing instances.
+            NestedTypeBinding nestedBinding = (NestedTypeBinding) clazz;
+            if (nestedBinding.enclosingInstances != null) {
+              for (int i = 0; i < nestedBinding.enclosingInstances.length;  
++i) {
+                SyntheticArgumentBinding arg =  
nestedBinding.enclosingInstances[i];
+                methodSig.append(arg.type.signature());
+              }
+            }
+          }
+          if (findMethod.parameters != null) {
+            for (TypeBinding binding : findMethod.parameters) {
+              methodSig.append(binding.signature());
+            }
+          }
+          if (methodSig.toString().equals(jsniRef.paramTypesString())) {
+            return findMethod;
+          }
+        }
+      } else {
+        while (clazz != null) {
+          for (MethodBinding findMethod :  
clazz.getMethods(methodName.toCharArray())) {
+            if (paramTypesMatch(findMethod, jsniRef)) {
+              return findMethod;
+            }
+          }
+          clazz = clazz.superclass();
          }
        }
        return null;
@@ -373,6 +403,8 @@
        return String.valueOf(type.shortReadableName());
      }
    }
+
+  private static final char[] INIT_CTOR_CHARS = "<init>".toCharArray();

    private static final char[][] UNSAFE_LONG_ANNOTATION_CHARS =  
CharOperation.splitOn(
        '.', UnsafeNativeLong.class.getName().toCharArray());
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java  Thu  
Nov 19 13:48:07 2009
+++ /trunk/dev/core/test/com/google/gwt/dev/javac/JsniCheckerTest.java  Thu  
Nov 19 13:48:22 2009
@@ -235,6 +235,47 @@
      shouldGenerateError(code, 6, "Referencing field 'Buggy$Inner.x': "
          + "type 'long' is not safe to access in JSNI code");
    }
+
+  public void testInnerNew() {
+    StringBuffer code = new StringBuffer();
+    code.append("public class Buggy {\n");
+    code.append("  class Inner {\n");
+    code.append("    long x = 3;\n");
+    code.append("    Inner(boolean b) { };\n");
+    code.append("  }\n");
+    code.append("  native void jsniMeth() /*-{\n");
+    code.append("     
$wnd.alert(@Buggy.Inner::new(Z)(true).toString());\n");
+    code.append("  }-*/;\n");
+    code.append("}\n");
+
+    // Cannot resolve, missing synthetic enclosing instance.
+    shouldGenerateWarning(code, 7, "Referencing  
method 'Buggy.Inner.new(Z)': "
+        + "unable to resolve method, expect subsequent failures");
+
+    code = new StringBuffer();
+    code.append("public class Buggy {\n");
+    code.append("  static class Inner {\n");
+    code.append("    long x = 3;\n");
+    code.append("    Inner(boolean b) { };\n");
+    code.append("  }\n");
+    code.append("  native void jsniMeth() /*-{\n");
+    code.append("    $wnd.alert(@Buggy.Inner::new(Z)(this,  
true).toString());\n");
+    code.append("  }-*/;\n");
+    code.append("}\n");
+    shouldGenerateNoWarning(code);
+
+    code = new StringBuffer();
+    code.append("public class Buggy {\n");
+    code.append("  class Inner {\n");
+    code.append("    long x = 3;\n");
+    code.append("    Inner(boolean b) { };\n");
+    code.append("  }\n");
+    code.append("  native void jsniMeth() /*-{\n");
+    code.append("    $wnd.alert(@Buggy.Inner::new(LBuggy;Z)(this,  
true).toString());\n");
+    code.append("  }-*/;\n");
+    code.append("}\n");
+    shouldGenerateNoWarning(code);
+  }

    /**
     * The proper behavior here is a close call. In hosted mode, Java arrays  
are
@@ -308,6 +349,25 @@
          4,
          "Referencing method 'Buggy.m': return type 'long' is not safe to  
access in JSNI code");
    }
+
+  public void testNew() {
+    StringBuffer code = new StringBuffer();
+    code.append("class Buggy {\n");
+    code.append("  static native Object main() /*-{\n");
+    code.append("    return @Buggy::new()();\n");
+    code.append("  }-*/;\n");
+    code.append("}\n");
+    shouldGenerateNoWarning(code);
+
+    code = new StringBuffer();
+    code.append("class Buggy {\n");
+    code.append("  Buggy(boolean b) { }\n");
+    code.append("  static native Object main() /*-{\n");
+    code.append("    return @Buggy::new(Z)(true);\n");
+    code.append("  }-*/;\n");
+    code.append("}\n");
+    shouldGenerateNoWarning(code);
+  }

    public void testNullField() {
      StringBuffer code = new StringBuffer();

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to