blob: 837de9a16bf2cdd89169a99185768160f7eca258 [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.javac;
import com.google.gwt.dev.javac.testing.impl.JavaResourceBase;
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
/**
* Test access to longs from JSNI.
*/
public class JsniReferenceResolverTest extends CheckerTestCase {
/**
* JSNI references to anonymous inner classes is deprecated.
*/
public void testAnoymousJsniRef() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static void main() {",
" new Object() {",
" int foo = 3;",
" };",
" }",
" native void jsniMeth(Object o) /*-{",
" o.@Buggy$1::foo;",
" }-*/;",
"}");
shouldGenerateError(buggy, 8, "Referencing class 'Buggy$1': "
+ "unable to resolve class");
}
/**
* JSNI references to anonymous inner classes is deprecated.
*/
public void testAnoymousJsniRefNested() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static void main() {",
" new Object() {",
" class A {",
" int foo = 3;",
" };",
" };",
" }",
" native void jsniMeth(Object o) /*-{",
" o.@Buggy$1.A::foo;",
" }-*/;",
"}");
shouldGenerateError(buggy, 10, "Referencing class 'Buggy$1.A': "
+ "unable to resolve class");
}
public void testArrayBadMember() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy[][]::blah;",
" }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Referencing member 'Buggy[][].blah': 'class' is the only legal reference for arrays and " +
"primitive types");
}
public void testArrayClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy[][]::class;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy::class;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testClassAssignment() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy::class = null;",
" }-*/;",
"}");
shouldGenerateError(buggy, 3,
"Illegal assignment to class literal 'Buggy.class'");
}
public void testCyclicReferences() {
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static int anint = 3;",
" native void jsniMeth() /*-{",
" $wnd.alert(@Extra::along);",
" }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Extra",
"class Extra {",
" static long along = 3;",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy::anint);",
" }-*/;",
"}");
shouldGenerateError(buggy, extra, 4, "Referencing field 'Extra.along': "
+ "type 'long' is not safe to access in JSNI code");
}
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" Extra anExtra = new Extra();",
" static int anint = 3;",
" native void jsniMeth() /*-{",
" $wnd.alert(@Extra::along);",
" }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Extra",
"class Extra {",
" Buggy mattress = new Buggy();",
" static long along = 3;",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy::anint);",
" }-*/;",
"}");
shouldGenerateError(buggy, extra, 5, "Referencing field 'Extra.along': "
+ "type 'long' is not safe to access in JSNI code");
}
}
public void testDeprecationField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" @Deprecated static int bar;",
"}",
"class Other {",
" native void jsniMethod() /*-{",
" @Buggy::bar;",
" }-*/;",
"}");
shouldGenerateWarning(buggy, 6,
"Referencing field 'Buggy.bar': field 'Buggy.bar' is deprecated");
}
public void testDeprecationField_inEnclosingClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" @Deprecated static int bar;",
" static class Inner {",
" static class InnerInner {",
" native void jsniMethod() /*-{",
" @Buggy::bar;",
" }-*/;",
" }",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
public void testDeprecationField_deprecatedbyClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated",
"class Buggy {",
" static int bar;",
" native void jsniMethod() /*-{",
" @Buggy::bar;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testDeprecationField_deprecatedbyClass_fromOtherClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated",
"class DeprecatedClass {",
" @Deprecated static int bar;",
"}",
"class Buggy {",
" native void jsniMethod() /*-{",
" @DeprecatedClass::bar;",
" }-*/;",
"}");
shouldGenerateWarnings(buggy,
warning(7,"Referencing deprecated class 'DeprecatedClass'"),
warning(7,
"Referencing field 'DeprecatedClass.bar': field 'DeprecatedClass.bar' is deprecated"));
}
public void testDeprecationMethod() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" @Deprecated static void foo(){}",
"}",
"class Other {",
" native void jsniMethod() /*-{",
" @Buggy::foo();",
" }-*/;",
"}");
shouldGenerateWarning(buggy, 6,
"Referencing method 'Buggy.foo': method 'Buggy.foo()' is deprecated");
}
public void testDeprecationMethod_deprecatedbyClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated",
"class Buggy {",
" static void foo(){}",
" native void jsniMethod() /*-{",
" @Buggy::foo();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testDeprecationMethod_deprecatedbyClass_fromOtherClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated",
"class DeprecatedClass {",
" @Deprecated static void foo(){}",
"}",
"class Buggy {",
" native void jsniMethod() /*-{",
" @DeprecatedClass::foo();",
" }-*/;",
"}");
shouldGenerateWarnings(buggy,
warning(7,"Referencing deprecated class 'DeprecatedClass'"),
warning(7,"Referencing method 'DeprecatedClass.foo': "
+ "method 'DeprecatedClass.foo()' is deprecated"));
}
public void testDeprecationSuppression() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated class D {",
" static int bar;",
"}",
"class Buggy {",
" @Deprecated static void foo(){}",
" @Deprecated static int bar;",
" @SuppressWarnings(\"deprecation\")",
" native void jsniMethod1() /*-{",
" @Buggy::foo();",
" @Buggy::bar;",
" @D::bar;",
" }-*/;",
" @SuppressWarnings({\"deprecation\", \"other\"})",
" native void jsniMethod2() /*-{",
" @Buggy::foo();",
" @Buggy::bar;",
" @D::bar;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
// Check inherited suppress warnings.
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated class D {",
" static int bar;",
"}",
"@SuppressWarnings(\"deprecation\")",
"class Buggy {",
" @Deprecated static void foo(){}",
" @Deprecated static int bar;",
" native void jsniMethod1() /*-{",
" @Buggy::foo();",
" @Buggy::bar;",
" @D::bar;",
" }-*/;",
" native void jsniMethod2() /*-{",
" @Buggy::foo();",
" @Buggy::bar;",
" @D::bar;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
/**
* Test for issue 8093.
*/
public void testSuppressionNotStrintLiteral1() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" private static final String RAWTYPES = \"rawtypes\";",
" @SuppressWarnings(RAWTYPES)",
" public void method1() {",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
/**
* Test for issue 8093.
*/
public void testSuppressionNotStringLiteral2() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" private static final String UNCHECKED = \"unchecked\";",
" @SuppressWarnings({\"rawtypes\", UNCHECKED})",
" public void method1() {",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
public void testDeprecationType() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"@Deprecated class D {",
" static int bar;",
"}",
"class Buggy {",
" native void jsniMethod() /*-{",
" @D::bar;",
" }-*/;",
"}");
shouldGenerateWarning(buggy, 6, "Referencing deprecated class 'D'");
}
public void testField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" int foo = 3;",
" native void jsniMethod() /*-{",
" this.@Buggy::foo;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testFieldAccess() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
"volatile long x = -1;",
"native void jsniMeth() /*-{",
" $wnd.alert(\"x is: \"+this.@Buggy::x); }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Referencing field 'Buggy.x': type 'long' is not safe to access in JSNI code");
}
public void testFieldAssignment() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" int foo = 3;",
" native void jsniMethod() /*-{",
" this.@Buggy::foo = 4;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testFieldAssignmentStatic() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static int foo = 3;",
" native void jsniMethod() /*-{",
" @Buggy::foo = 4;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testFieldConstant() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static final int foo = 3;",
" native void jsniMethod() /*-{",
" @Buggy::foo;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testFieldConstantAssignment() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static final int foo = 3;",
" native void jsniMethod() /*-{",
" @Buggy::foo = 4;",
" }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Illegal assignment to compile-time constant 'Buggy.foo'");
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static final String foo = \"asdf\";",
" native void jsniMethod() /*-{",
" @Buggy::foo = null;",
" }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Illegal assignment to compile-time constant 'Buggy.foo'");
// Not a compile-time constant.
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static final Object foo = new Object();",
" native void jsniMethod() /*-{",
" @Buggy::foo = null;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testAssignment_InstanceMethod_toField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Some",
"public class Some {",
" public void callback() {",
" }",
" native void installCallback(Some o) /*-{",
" $wnd.someCallback = o.@Some::callback();",
" }-*/;",
"}");
shouldGenerateWarning(buggy, 5,
"Instance method reference 'Some.callback' loses its instance ('o') when assigned; "
+ "to remove this warning either assign to a local variable or construct "
+ "the proper closure using an anonymous function or by calling "
+ "Function.prototype.bind");
}
public void testAssignment_InstanceMethod_toVariable() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Some",
"public class Some {",
" public void callback() {",
" }",
" native void installCallback(Some o) /*-{",
" var a = o.@Some::callback();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testJsoStaticMethod() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMeth(Object o) /*-{",
" @com.google.gwt.core.client.JavaScriptObject::createObject()();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testAllowsJsoSubclassStaticMethod() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static final class Foo extends com.google.gwt.core.client.JavaScriptObject {",
" protected Foo() { };",
" static void foo() { };",
" }",
" native void jsniMeth(Object o) /*-{",
" @Buggy.Foo::foo()();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testFieldStatic() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static int foo = 3;",
" native void jsniMethod() /*-{",
" @Buggy::foo;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testFieldStaticQualified() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static int foo = 3;",
" native void jsniMethod() /*-{",
" this.@Buggy::foo;",
" }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Unnecessary qualifier on static field 'Buggy.foo'");
}
public void testFieldUnqualified() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" int foo = 3;",
" native void jsniMethod() /*-{",
" @Buggy::foo;",
" }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Missing qualifier on instance field 'Buggy.foo'");
}
public void testEnclosingClassField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" int foo = 3;",
" native void jsniMethod() /*-{",
" this.@Buggy::foo;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testEnclosingClassFieldNotFound() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" int foo = 3;",
" native void jsniMethod() /*-{",
" this.@Buggy::bar;",
" }-*/;",
"}");
shouldGenerateError(buggy, 5,
"Referencing field 'Buggy.bar': unable to resolve field in class 'some.Buggy'");
}
public void testImportedClassField_PartialMatch() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.pack.OtherPackageClass;",
"class Buggy {",
" native void jsniMethod() /*-{",
" this.@PackageClass::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("other.pack.OtherPackageClass",
"package other.pack;",
"public class OtherPackageClass {",
" public int f;",
"}");
shouldGenerateError(
buggy,
otherPackageClass,
5,
"Referencing class 'PackageClass': unable to resolve class");
}
public void testImportedClassField_Precedence() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.pack.B;",
"class Buggy {",
" class B {",
" int f;",
" }",
" native void jsniMethod() /*-{",
" this.@B::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("other.pack.B",
"package other.pack;",
"public class B {",
"}");
shouldGenerateNoError(buggy, otherPackageClass);
}
public void testImportedClassField_InnerClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.pack.OtherPackageClass.Inner;",
"class Buggy {",
" native void jsniMethod() /*-{",
" this.@Inner::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("other.pack.OtherPackageClass",
"package other.pack;",
"public class OtherPackageClass {",
" public class Inner {",
" public int f;",
" }",
"}");
shouldGenerateNoWarning(buggy, otherPackageClass);
}
public void testImportedClassField_InnerClassThroughOuter() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.pack.OtherPackageClass;",
"class Buggy {",
" native void jsniMethod() /*-{",
" this.@OtherPackageClass.Inner::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("other.pack.OtherPackageClass",
"package other.pack;",
"public class OtherPackageClass {",
" public class Inner {",
" public int f;",
" }",
"}");
shouldGenerateNoWarning(buggy, otherPackageClass);
}
public void testImportedClassField_InnerClassTest1() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" public class Inner {",
" public int f;",
" }",
" native void jsniMethod() /*-{",
" this.@Inner::f;",
" this.@Buggy.Inner::f;",
" this.@some.Buggy.Inner::f;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testImportedClassField_InnerClassTest2() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" public class Inner {",
" public int f;",
" native void jsniMethod() /*-{",
" this.@Inner::f;",
" this.@Buggy.Inner::f;",
" this.@some.Buggy.Inner::f;",
" }-*/;",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
public void testImportedClassField_InnerClassTest3() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" public class OtherInner {",
" native void jsniMethod() /*-{",
" this.@Inner::f;",
" this.@Buggy.Inner::f;",
" this.@some.Buggy.Inner::f;",
" }-*/;",
" }",
" public class Inner {",
" public int f;",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
public void testImportedClassField_InnerClassTest4() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" public class OtherInner {",
" public class Inner {",
" public int f;",
" }",
" native void jsniMethod() /*-{",
" this.@OtherInner.Inner::f;",
" this.@Buggy.OtherInner.Inner::f;",
" this.@some.Buggy.OtherInner.Inner::f;",
" }-*/;",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
public void testImportedClassField_InnerClassTest5() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" public class OtherInner {",
" public class Inner {",
" public int f;",
" }",
" native void jsniMethod() /*-{",
" this.@Inner::f;",
" }-*/;",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
public void testImplicitImport() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" native void jsniMethod(String s) /*-{",
" s.@String::length()();",
" }-*/;",
"}");
shouldGenerateNoError(buggy);
}
public void testImportedClassField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.pack.OtherPackageClass;",
"class Buggy {",
" native void jsniMethod() /*-{",
" this.@OtherPackageClass::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("other.pack.OtherPackageClass",
"package other.pack;",
"public class OtherPackageClass {",
" public int f;",
"}");
shouldGenerateNoWarning(buggy, otherPackageClass);
}
public void testImportedClassField_CurrentPackage() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"class Buggy {",
" native void jsniMethod() /*-{",
" this.@SamePackageClass::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("some.SamePackageClass",
"package some;",
"public class SamePackageClass {",
" public int f;",
"}");
shouldGenerateNoWarning(buggy, otherPackageClass);
}
public void testImportedStarClassField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.pack.*;",
"class Buggy {",
" native void jsniMethod() /*-{",
" this.@OtherPackageClass::f;",
" }-*/;",
"}");
MockJavaResource otherPackageClass =
JavaResourceBase.createMockJavaResource("other.pack.OtherPackageClass",
"package other.pack;",
"public class OtherPackageClass {",
" public int f;",
"}");
shouldGenerateNoWarning(buggy, otherPackageClass);
}
public void testInnerClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" static class Inner {",
" static long x = 3;",
" }",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy.Inner::x);",
" }-*/;",
"}");
shouldGenerateError(buggy, 6, "Referencing field 'Buggy.Inner.x': "
+ "type 'long' is not safe to access in JSNI code");
}
public void testInnerClassDollar() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" static class Inner {",
" static long x = 3;",
" }",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy$Inner::x);",
" }-*/;",
"}");
shouldGenerateError(buggy, 6, "Referencing field 'Buggy$Inner.x': "
+ "type 'long' is not safe to access in JSNI code");
}
public void testInnerNew() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" class Inner {",
" long x = 3;",
" Inner(boolean b) { };",
" }",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy.Inner::new(Z)(true).toString());",
" }-*/;",
"}");
// Cannot resolve, missing synthetic enclosing instance.
shouldGenerateError(buggy, 7, "Referencing method 'Buggy.Inner.new(Z)': "
+ "unable to resolve method in class 'Buggy.Inner'");
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" static class Inner {",
" long x = 3;",
" Inner(boolean b) { };",
" }",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy.Inner::new(Z)(this, true).toString());",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"public class Buggy {",
" class Inner {",
" long x = 3;",
" Inner(boolean b) { };",
" }",
" native void jsniMeth() /*-{",
" $wnd.alert(@Buggy.Inner::new(LBuggy;Z)(this, true).toString());",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
/**
* The proper behavior here is a close call. In Development Mode, Java arrays
* are completely unusable in JavaScript, so the current reasoning is to allow
* them.
*/
public void testLongArray() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" long[] m() { return new long[] { -1 }; }",
" native void jsniMeth() /*-{",
" $wnd.alert(this.@Buggy::m()()); }-*/;",
"}");
shouldGenerateNoError(buggy);
}
public void testLongParameter() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMeth(long x) /*-{ return; }-*/;",
"}");
shouldGenerateError(buggy, 2,
"Parameter 'x': type 'long' is not safe to access in JSNI code");
}
public void testLongReturn() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native long jsniMeth() /*-{ return 0; }-*/;",
"}");
shouldGenerateError(buggy, 2,
"Type 'long' may not be returned from a JSNI method");
}
public void testMalformedJsniRef() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy;",
" }-*/;",
"}");
shouldGenerateError(buggy, 3,
"Expected \":\" in JSNI reference\n> @Buggy;\n" + "> ----------^");
}
public void testMethod() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" void foo() { }",
" native void jsniMethod() /*-{",
" this.@Buggy::foo()();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testMethodArgument() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" void print(long x) { }",
" native void jsniMeth() /*-{ this.@Buggy::print(J)(0); }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Parameter 1 of method 'Buggy.print': type 'long' may not be passed out of JSNI code");
}
public void testMethodAssignment() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" void foo() { }",
" native void jsniMethod() /*-{",
" this.@Buggy::foo() = null;",
" }-*/;",
"}");
shouldGenerateError(buggy, 4, "Illegal assignment to method 'Buggy.foo'");
}
/**
* Test JSNI references to methods defined in superclass/superinterfaces.
*/
public void testMethodInheritance() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" interface A1 { void a1(); }",
" interface A2 extends A1 { void a2(); }",
" static abstract class C1 implements A2 { public abstract void c1(); }",
" native void jsniMeth(Object o) /*-{",
" o.@Buggy.A1::a1()();",
" o.@Buggy.A2::a1()();",
" o.@Buggy.A2::a2()();",
" o.@Buggy.C1::a1()();",
" o.@Buggy.C1::a2()();",
" o.@Buggy.C1::c1()();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testMethodReturn() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" long m() { return -1; }",
" native void jsniMeth() /*-{",
" $wnd.alert(this.@Buggy::m()()); }-*/;",
"}");
shouldGenerateError(
buggy,
4,
"Referencing method 'Buggy.m': return type 'long' is not safe to access in JSNI code");
}
public void testMethodStatic() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static void foo() { }",
" native void jsniMethod() /*-{",
" @Buggy::foo()();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testMethodStaticQualified() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static void foo() { }",
" native void jsniMethod() /*-{",
" this.@Buggy::foo()();",
" }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Unnecessary qualifier on static method 'Buggy.foo'");
}
public void testMethodUnqualified() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" void foo() { }",
" native void jsniMethod() /*-{",
" @Buggy::foo()();",
" }-*/;",
"}");
shouldGenerateError(buggy, 4,
"Missing qualifier on instance method 'Buggy.foo'");
}
public void testNew() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static native Object main() /*-{",
" return @Buggy::new()();",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" Buggy(boolean b) { }",
" static native Object main() /*-{",
" return @Buggy::new(Z)(true);",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testOldStyleNullField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static native Object main() /*-{",
" return @null::nullField;",
" }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Referencing class 'null': unable to resolve class");
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static native Object main() /*-{",
" return @null::foo;",
" }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Referencing class 'null': unable to resolve class");
}
public void testOldStyleNullMethod() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static native Object main() /*-{",
" return @null::nullMethod()();",
" }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Referencing class 'null': unable to resolve class");
buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" static native Object main() /*-{",
" return @null::foo()();",
" }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Referencing class 'null': unable to resolve class");
}
public void testOverloadedMethodWithNoWarning() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" long m(int x) { return -1; }",
" int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" $wnd.alert(this.@Buggy::m(Ljava/lang/String;)(\"hello\")); }-*/;",
"}");
shouldGenerateNoError(buggy);
}
public void testOverloadedMethodWithWarning() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" long m(int x) { return -1; }",
" int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" $wnd.alert(this.@Buggy::m(I)(10)); }-*/;",
"}");
shouldGenerateError(
buggy,
5,
"Referencing method 'Buggy.m': return type 'long' is not safe to access in JSNI code");
}
public void testPrimitiveBadMember() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @boolean::blah;",
" }-*/;",
"}");
shouldGenerateError(
buggy,
3,
"Referencing member 'boolean.blah': "
+ "'class' is the only legal reference for arrays and primitive types");
}
public void testPrimitiveClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @boolean::class;",
" }-*/;",
"}");
shouldGenerateNoWarning(buggy);
}
public void testPrimitiveClassRemovedDeprecated() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Z::class;",
" }-*/;",
"}");
shouldGenerateError(buggy, 3,
"Referencing class 'Z': unable to resolve class");
}
public void testRefInString() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"import com.google.gwt.core.client.UnsafeNativeLong;",
"class Buggy {",
" void print(long x) { }",
" native void jsniMeth() /*-{ 'this.@Buggy::print(J)(0)'; }-*/;",
"}");
shouldGenerateNoError(buggy);
}
public void testAmbiguityResolution_NestedClasses() {
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.A",
"package some;",
"class A {",
" static Object f;",
" static class B {",
" static Object f;",
" native void jsniMethod() /*-{",
" @CC::f;",
" }-*/;",
" static class CC {",
" static Object f;",
" }",
" }",
" static class B1 {",
" static Object f;",
" static class CC {",
" }",
" }",
"}");
shouldGenerateNoWarning(buggy);
}
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.A",
"package some;",
"class A {",
" static Object f;",
" static class B {",
" static Object f;",
" native void jsniMethod() /*-{",
" @CC::f;",
" }-*/;",
" static class CC {",
" }",
" }",
" static class B1 {",
" static Object f;",
" static class CC {",
" static Object f;",
" }",
" }",
"}");
// Note that the ambiguous CC is resolved to some.A.B.CC and not to A.B1.CC.
shouldGenerateError(buggy, 7 ,
"Referencing field 'CC.f': unable to resolve field in class 'some.A.B.CC'");
}
}
public void testSuperFieldAccess() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" native void jsniMeth() /*-{",
" this.@Buggy::x; ",
" }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" public long x = -1;",
"}");
shouldGenerateError(buggy, extra,
3,
"Referencing field 'Buggy.x': unable to resolve field in class 'Buggy'");
}
public void testUnresolvedClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Foo::x;",
" }-*/;",
"}");
shouldGenerateError(buggy, 3,
"Referencing class 'Foo': unable to resolve class");
}
public void testUnresolvedField() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy::x;",
" }-*/;",
"}");
shouldGenerateError(buggy, 3,
"Referencing field 'Buggy.x': unable to resolve field in class 'Buggy'");
}
public void testUnresolvedMethod() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMethod() /*-{",
" @Buggy::x(Ljava/lang/String);",
" }-*/;",
"}");
shouldGenerateError(buggy, 3, "Referencing method 'Buggy.x(Ljava/lang/String)': "
+ "unable to resolve method in class 'Buggy'");
}
public void testUnsafeAnnotation() {
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"import com.google.gwt.core.client.UnsafeNativeLong;",
"class Buggy {",
" void print(long x) { }",
" @UnsafeNativeLong",
" native void jsniMeth() /*-{ this.@Buggy::print(J)(0); }-*/;",
"}");
shouldGenerateNoError(buggy);
}
}
public void testViolator() {
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMeth() /*-{",
" $wnd.alert(@Extra.Inner::x);",
" }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Extra",
"class Extra {",
" private static class Inner { ",
" private static int x = 3;",
" }",
"}");
shouldGenerateNoError(buggy, extra);
}
{
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" native void jsniMeth() /*-{",
" $wnd.alert(@Extra.Inner::x);",
" }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Extra",
"class Extra {",
" private static class Inner { ",
" private static long x = 3;",
" }",
"}");
shouldGenerateError(
buggy,
extra,
3,
"Referencing field 'Extra.Inner.x': type 'long' is not safe to access in JSNI code");
}
}
public void testWildcardMethodAccess() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
shouldGenerateNoError(buggy);
}
public void testWilcardMethodAccess_Ambiguous_withinClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy {",
" int m(String x) { return -1; }",
" int m(Integer x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
shouldGenerateError(
buggy,
5,
"Referencing method 'Buggy.m(*)': ambiguous wildcard match; "
+ "both 'Buggy.m(Ljava/lang/String;)' and "
+ "'Buggy.m(Ljava/lang/Integer;)' match");
}
public void testWildcardMethodAccess_Ambiguous_withSuperClass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Extra{",
" public int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Extra",
"class Extra {",
" public int m(Integer x) { return -1; }",
"}");
shouldGenerateError(
buggy,
extra,
4,
"Referencing method 'Buggy.m(*)': ambiguous wildcard match; "
+ "both 'public Buggy.m(Ljava/lang/String;)' and "
+ "'public Extra.m(Ljava/lang/Integer;)' match");
}
public void testWildcardMethodAccess_NoConflict_OverrideFromSuperclass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Extra {",
" public int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Extra",
"class Extra {",
" public int m(String x) { return -1; }",
"}");
shouldGenerateNoError(buggy, extra);
}
public void testWildcardMethodAccess_Conflict_WithSuperclass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" protected int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" public int m(Object x) { return -1; }",
"}");
shouldGenerateError(buggy, extra,
4,
"Referencing method 'Buggy.m(*)': ambiguous wildcard match; "
+ "both 'protected Buggy.m(Ljava/lang/String;)' and "
+ "'public Super.m(Ljava/lang/Object;)' match");
}
public void testWildcardMethodAccess_Conflict_PrivateWithSuperclass() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" private int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" public int m(Object x) { return -1; }",
"}");
shouldGenerateError(buggy, extra,
4,
"Referencing method 'Buggy.m(*)': ambiguous wildcard match; "
+ "both 'private Buggy.m(Ljava/lang/String;)' and "
+ "'public Super.m(Ljava/lang/Object;)' match");
}
public void testWildcardSuperclassMethod_PackagePrivate_DifferentPackage() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.Super;",
"class Buggy extends Super {",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("other.Super",
"package other;",
"public class Super {",
" int m(Object x) { return -1; }",
"}");
shouldGenerateError(buggy, extra,
5,
"Referencing method 'Buggy.m(*)': unable to resolve method in class 'some.Buggy'");
}
public void testWildcardSuperclassMethod_PackagePrivate_SamePackage() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" int m(Object x) { return -1; }",
"}");
shouldGenerateNoError(buggy, extra);
}
public void testWildcardSuperclassMethod_Private() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" private int m(Object x) { return -1; }",
"}");
shouldGenerateError(buggy, extra,
3,
"Referencing method 'Buggy.m(*)': unable to resolve method in class 'Buggy'");
}
public void testWildcardSuperclassMethod_Protected() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("some.Buggy",
"package some;",
"import other.Super;",
"class Buggy extends Super {",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("other.Super",
"package other;",
"public class Super {",
" protected int m(Object x) { return -1; }",
"}");
shouldGenerateNoError(buggy, extra);
}
public void testWildcardSuperclassMethod_Public() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" public int m(Object x) { return -1; }",
"}");
shouldGenerateNoError(buggy, extra);
}
public void testWildcardMethodAccess_PotentialConflict() {
MockJavaResource buggy = JavaResourceBase.createMockJavaResource("Buggy",
"class Buggy extends Super {",
" int m(String x) { return -1; }",
" native void jsniMeth() /*-{",
" this.@Buggy::m(*)(\"hello\"); }-*/;",
"}");
MockJavaResource extra = JavaResourceBase.createMockJavaResource("Super",
"class Super {",
" private int m(Object x) { return -1; }",
"}");
shouldGenerateNoError(buggy, extra);
}
}