Index: src/org/eclipse/jdt/core/tests/compiler/regression/NonNullAnnotationTest.java =================================================================== RCS file: src/org/eclipse/jdt/core/tests/compiler/regression/NonNullAnnotationTest.java diff -N src/org/eclipse/jdt/core/tests/compiler/regression/NonNullAnnotationTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jdt/core/tests/compiler/regression/NonNullAnnotationTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1001 @@ +package org.eclipse.jdt.core.tests.compiler.regression; + +import java.util.Map; + +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +import junit.framework.Test; + +/** + * Testing of @NonNull annotation. + *

+ * See the bug 186342 : https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342 + *

+ * Modified from {@link org.eclipse.jdt.core.tests.compiler.regression.NullReferenceTest}. + * + */ +public class NonNullAnnotationTest extends AbstractRegressionTest { +public NonNullAnnotationTest(String name) { + super(name); +} +public static Test suite() { + return buildMinimalComplianceTestSuite(testClass(), F_1_5); +} + +public static Class testClass() { + return NonNullAnnotationTest.class; +} +protected Map getCompilerOptions() { + Map options = super.getCompilerOptions(); + options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5); + options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5); + options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5); + options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED); + options.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_ReportPotentialNullReference, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR); + options.put(CompilerOptions.OPTION_NonNullAnnotations, "org.NonNull;X.NonNull"); + return options; +} +/** using NonNull annotation for a method */ +public void test_validNonNullAnnotation() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "org/NonNull.java", + "package org;\n" + + "public @interface NonNull { }\n", + "X.java", + "public class X {\n" + + " @org.NonNull Object foo() {\n" + + " return new Object();\n" + + " }\n" + + "}\n" + }, + ""); + } +} + +/** using null initialization in a NonNull annotated local variable declaration */ +public void test_nonNullLocalVariableDeclarationInitializedWithNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo() {\n" + + " @NonNull Object o = null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + "\t@NonNull Object o = null;\n" + + "\t ^^^^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n"); + } +} +/** using null initialization in an invalid NonNull annotated local variable declaration */ +public void test_invalidNonNullAnnotations() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo() {\n" + + " @invalid.NonNull Object o = null;\n" + + " @invalid.C.NonNull Object o2 = null;\n" + + " }\n" + + "}\n", + "invalid/NonNull.java", + "package invalid;\n" + + "public @interface NonNull { }\n", + "invalid/C.java", + "package invalid;\n" + + "public class C {\n" + + " public @interface NonNull { }\n" + + "}\n", + }, + ""); + } +} +/** assigning null in a NonNull annotated local variable */ +public void test_nonNullLocalVariableAssignedWithNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo() {\n" + + " @NonNull Object o;\n" + + " o = null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + "\to = null;\n" + + "\t ^^^^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n"); + } +} +/** assigning new object to a NonNull annotated local variable */ +public void test_nonNullLocalVariablesAssignedWithNew() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo() {\n" + + " @NonNull Object o;\n" + + " @NonNull String s;\n" + + " @NonNull Integer i;\n" + + " @NonNull Integer[] ia;\n" + + " @NonNull String[] sa;\n" + + " @NonNull int[] ia_;\n" + + " o = new Object();\n" + + " s = \"\";\n" + + " i = new Integer(4);\n" + + " ia = new Integer[1];\n" + + " sa = new String[] { \"test\" };\n" + + " ia_ = new int[0];\n" + + " }\n" + + "}\n" + }, + ""); + } +} +/** assigning new object to a NonNull annotated local variable */ +public void test_localVariableDeclarationWithNew() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo() {\n" + + " @NonNull Object o = new Object();\n" + + " @NonNull String s = \"a\";\n" + + " @NonNull Integer i = new Integer(1);\n" + + " @NonNull Integer[] ia = new Integer[0];\n" + + " @NonNull String[] sa = new String[] { \"hey\" };\n" + + " @NonNull int[] ia_ = new int[2];\n" + + " }\n" + + "}\n" + }, + ""); + } +} +/** using null initialization in a weird NonNull annotated local variable declaration */ +//public void test_localVariableDecl004() { +// if (this.complianceLevel >= ClassFileConstants.JDK1_5) { +// this.runNegativeTest( +// new String[] { +// "X.java", +// "public class X {\n" + +// " public @interface NonNull { }\n" + +// " void foo() {\n" + +// " @NonNull Object o = (o = null);\n" + +// " }\n" + +// "}\n" +// }, +// "----------\n" + +// "1. ERROR in X.java (at line 5)\n" + +// "\to = null;\n" + +// "\t ^^^^\n" + +// "Cannot assign null or potentially null reference to o because of @NonNull annotation\n" + +// "----------\n"); +// } +//} +/** using null initialization in a final NonNull local variable declaration */ +public void test_initializingNonNullFinalLocalVariableWithNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo() {\n" + + " final @NonNull Object o = null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + "\tfinal @NonNull Object o = null;\n" + + "\t ^^^^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n"); + } +} +/** using unknown variable in a NonNull annotated local variable declaration */ +public void test_initializingNonNulllocalVariableWithRegularLocalVariable() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " Object bar() {\n" + + " return new Object();\n" + + " }\n" + + " void foo() {\n" + + " Object b = bar();\n" + + " @NonNull Object o = b;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 8)\n" + + "\t@NonNull Object o = b;\n" + + "\t ^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n"); + } +} +/** assigning null to a NonNull annotated method argument */ +public void test_assigningNullToANonNullMethodArgument() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo(@NonNull Object o) {\n" + + " o = null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + "\to = null;\n" + + "\t ^^^^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n"); + } +} +/** assigning unknown variable to a NonNull annotated method argument */ +public void test_assigningRegularLocalVariableToNonNullArgument() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " Object bar() {\n" + + " return new Object();\n" + + " }\n" + + " void foo(@NonNull Object o) {\n" + + " Object b = bar();\n" + + " o = b;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 8)\n" + + "\to = b;\n" + + "\t ^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n"); + } +} +/** checking that NonNull argument is not null is always true */ +public void test_checkingThatNonNullArgumentIsNotNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " int length(@NonNull String s) {\n" + + " if (s != null)\n" + + " return s.length();\n" + + " return 0;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + "\tif (s != null)\n" + + "\t ^\n" + + "Redundant null check: The variable s cannot be null at this location\n" + + "----------\n"); + } +} +/** checking that NonNull argument is null is always false */ +public void test_checkingThatNonNullArgumentIsNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " int hash(@NonNull String s) {\n" + + " if (s == null)\n" + + " return 0;\n" + + " return s.hashCode();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + "\tif (s == null)\n" + + "\t ^\n" + + "Null comparison always yields false: The variable s cannot be null at this location\n" + + "----------\n"); + } +} +/** checking that NonNull local variable is null is always false */ +public void test_checkingThatNonNullLocalIsNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " int foo() {\n" + + " @NonNull Object o = new Object();\n" + + " if (o == null)\n" + + " return 0;\n" + + " return o.hashCode();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + "\tif (o == null)\n" + + "\t ^\n" + + "Null comparison always yields false: The variable o cannot be null at this location\n" + + "----------\n"); + } +} +/** checking that NonNull method is null is always false */ +public void test_checkingThatNonNullMethodIsNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " @NonNull String getName() {\n" + + " return \"name\";\n" + + " }\n" + + " int foo() {\n" + + " if (getName() == null)\n" + + " return 0;\n" + + " return getName().hashCode();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + "\tif (getName() == null)\n" + + "\t ^^^^^^^^^\n" + + "Cannot return null or potentially null expression because of @NonNull annotation\n" + + "----------\n"); + } +} +/** checking that NonNull method is null is always false */ +public void test_checkingThatNonNullMethodIsNull2() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " @NonNull String getName() {\n" + + " return \"name\";\n" + + " }\n" + + " int foo() {\n" + + " if ((Object)getName() == null)\n" + + " return 0;\n" + + " return getName().hashCode();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + "\tif ((Object)getName() == null)\n" + + "\t ^^^^^^^^^^^^^^^^^\n" + + "Cannot return null or potentially null expression because of @NonNull annotation\n" + + "----------\n"); + } +} +/** checking that NonNull-method-returned-value assigned to local variable is null is always false */ +public void test_checkingThatNonNullMethodAssignedToLocalIsNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " @NonNull String getName() {\n" + + " return \"name\";\n" + + " }\n" + + " int foo() {\n" + + " String s = getName();\n" + + " if (s == null)\n" + + " return 0;\n" + + " return getName().hashCode();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 8)\n" + + "\tif (s == null)\n" + + "\t ^\n" + + "Null comparison always yields false: The variable s cannot be null at this location\n" + + "----------\n"); + } +} +/** checking that NonNull-method-returned-value assigned to argument is null is always false */ +public void test_checkingThatNonNullMethodAssignedToArgumentIsNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " @NonNull String getName() {\n" + + " return \"name\";\n" + + " }\n" + + " int foo(String s) {\n" + + " s = getName();\n" + + " if (s == null)\n" + + " return 0;\n" + + " return getName().hashCode();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 8)\n" + + "\tif (s == null)\n" + + "\t ^\n" + + "Null comparison always yields false: The variable s cannot be null at this location\n" + + "----------\n"); + } +} +/** too complex : checking that NonNull method is null is always false */ +//public void test_checkingThatNonNullMethodIsNull2() { +// if (this.complianceLevel >= ClassFileConstants.JDK1_5) { +// this.runNegativeTest( +// new String[] { +// "X.java", +// "public class X {\n" + +// " public @interface NonNull { }\n" + +// " @NonNull String getName() {\n" + +// " return \"name\";\n" + +// " }\n" + +// " boolean test() {\n" + +// " return true;\n" + +// " }\n" + +// " int foo() {\n" + +// " if ((test() ? getName() : \"\") == null)\n" + +// " return 0;\n" + +// " return getName().hashCode();\n" + +// " }\n" + +// "}\n" +// }, +// "----------\n" + +// "1. ERROR in X.java (at line 5)\n" + +// "\tif (o == null)\n" + +// "\t ^\n" + +// "Null comparison always yields false: The variable o cannot be null at this location\n" + +// "----------\n"); +// } +//} +/** Overriding super class annotated method must be annotated */ +public void test_overridingSuperClassAnnotatedethodRequireAnnotation() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " @NonNull String foo() {\n" + + " return \"foo\";\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " String foo() {\n" + + " return \"foo2\";\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Y.java (at line 2)\n" + + "\tString foo() {\n" + + "\t ^^^^^\n" + + "Method foo() isn't NonNull annotated while overridden method in X is\n" + + "----------\n"); + } +} +/** Overriding interface annotated method must be annotated */ +public void test_overridingInterfaceAnnotatedMethodRequireAnnotation() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " public String foo() {\n" + + " return \"foo\";\n" + + " }\n" + + "}\n", + "I.java", + "public interface I {\n" + + " @X.NonNull String foo();\n" + + "}\n", + "Y.java", + "public class Y extends X implements I {\n" + + " public String foo() {\n" + + " return \"foo2\";\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Y.java (at line 2)\n" + + "\tpublic String foo() {\n" + + "\t ^^^^^\n" + + "Method foo() isn't NonNull annotated while overridden method in I is\n" + + "----------\n"); + } +} +/** Overriding method with annotated argument */ +public void test_overridingMethodWithAnnotatedArgument() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " int length(@NonNull String foo) {\n" + + " return foo.length();\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " int length(String bar) {\n" + + " return bar.length() + 1;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Y.java (at line 2)\n" + + "\tint length(String bar) {\n" + + "\t ^^^\n" + + "Argument bar in method length(String) isn't NonNull annotated while overridden method in type X is\n" + + "----------\n"); + } +} +/** overriding method and annotate argument */ +public void test_overridingMethodAndAnnotateArgument() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo(Object o) {\n" + + " o.toString();\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " void foo(@NonNull Object o) {\n" + + " o.toString();\n" + + " }\n" + + "}\n" + }, + ""); + } +} +/** overriding method and annotate the method */ +public void test_overridingMethodAndAnnotatintIt() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " @NonNull Object foo() {\n" + + " return new Object();\n" + + " }\n" + + "}\n" + }, + ""); + } +} +/** passing null as argument to method which is annotated in overriding class */ +public void test_passingNullAsArgument() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo(Object o) {\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " void foo(@NonNull Object o) {\n" + + " }\n" + + "}\n", + "Z.java", + "public class Z {\n" + + " void foo(X x) {\n" + + " x.foo(null);\n" + + " }\n" + + "}\n" + }, + ""); + } +} +/** */ +public void test_overridingMethodReturnsNonNull() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " @NonNull Object foo() {\n" + + " return new Object();\n" + + " }\n" + + "}\n", + "Z.java", + "public class Z {\n" + + " void foo(Y y) {\n" + + " @X.NonNull Object o = y.foo();\n" + + " }\n" + + "}\n" + }, + ""); + } +} +/** */ +public void test_overridedMethodReturns() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " @NonNull Object foo() {\n" + + " return new Object();\n" + + " }\n" + + "}\n", + "Z.java", + "public class Z {\n" + + " void foo(X x) {\n" + + " @X.NonNull Object o = x.foo();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Z.java (at line 3)\n" + + "\t@X.NonNull Object o = x.foo();\n" + + "\t ^^^^^^^\n" + + "Cannot assign null or potentially null expression to o because of @NonNull annotation\n" + + "----------\n" + ); + } +} +/** checking annotation on method through more than one class */ +public void test_methodAnnotationInClassHierarchy() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " @NonNull Object foo() {\n" + + " return new Object();\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + "}\n", + "Z.java", + "public class Z extends Y {\n" + + " Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Z.java (at line 2)\n" + + "\tObject foo() {\n" + + "\t ^^^^^\n" + + "Method foo() isn't NonNull annotated while overridden method in Y is\n" + + "----------\n" + ); + } +} +/** checking annotation on argument through more than one class */ +public void test_argumentAnnotationInClassHierarchy() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo(@NonNull Object o) {\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + "}\n", + "Z.java", + "public class Z extends Y {\n" + + " void foo(Object o) {\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Z.java (at line 2)\n" + + "\tvoid foo(Object o) {\n" + + "\t ^\n" + + "Argument o in method foo(Object) isn't NonNull annotated while overridden method in type Y is\n" + + "----------\n" + ); + } +} +///** better report error for Z too, not only for Y */ +//public void test_2OverridingProblems() { +// if (this.complianceLevel >= ClassFileConstants.JDK1_5) { +// this.runNegativeTest( +// new String[] { +// "X.java", +// "public class X {\n" + +// " public @interface NonNull { }\n" + +// " @NonNull Object foo() {\n" + +// " return new Object();\n" + +// " }\n" + +// "}\n", +// "Y.java", +// "public class Y extends X {\n" + +// " Object foo() {\n" + +// " return null;\n" + +// " }\n" + +// "}\n", +// "Z.java", +// "public class Z extends Y {\n" + +// " Object foo() {\n" + +// " return null;\n" + +// " }\n" + +// "}\n" +// }, +// "----------\n" + +// "1. ERROR in Y.java (at line 3)\n" + +// "\tObject foo() {\n" + +// "\t ^^^^^\n" + +// "Method foo() is not annotated with @NonNull while is overriding foo()\n" + +// "2. ERROR in Z.java (at line 3)\n" + +// "\tObject foo() {\n" + +// "\t ^^^^^\n" + +// "Method foo() is not annotated with @NonNull while is overriding foo()\n" + +// "----------\n" +// ); +// } +//} +/** OK : almost overriding */ +public void test_2OverridingProblems2() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public @interface NonNull { }\n" + + " void foo(@NonNull Object o) {\n" + + " }\n" + + "}\n", + "Y.java", + "public class Y extends X {\n" + + " void foo() {\n" + + " }\n" + + "}\n" + }, + "" + ); + } +} +/** overriding method must be non-null annotated because of 1 interface */ +public void test_OverridingNeedsAnnotationFromOneInterface() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "org/NonNull.java", + "package org;\n" + + "public @interface NonNull { }\n", + "X.java", + "public class X implements I1, I2 {\n" + + " public Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n", + "I1.java", + "public interface I1 {\n" + + " Object foo();\n" + + "}\n", + "I2.java", + "public interface I2 {\n" + + " @org.NonNull Object foo();\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 2)\n" + + "\tpublic Object foo() {\n" + + "\t ^^^^^\n" + + "Method foo() isn't NonNull annotated while overridden method in I2 is\n" + + "----------\n" + ); + } +} +/** overriding method must be non-null annotated because of an ancestor interface */ +public void test_OverridingNeedsAnnotationFromAnAncestorInterface() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "org/NonNull.java", + "package org;\n" + + "public @interface NonNull { }\n", + "X.java", + "public class X implements I3 {\n" + + " public Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n", + "I1.java", + "public interface I1 {\n" + + " @org.NonNull Object foo();\n" + + "}\n", + "I2.java", + "public interface I2 extends I1 {\n" + + "}\n", + "I3.java", + "public interface I3 extends I2{\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 2)\n" + + "\tpublic Object foo() {\n" + + "\t ^^^^^\n" + + "Method foo() isn't NonNull annotated while overridden method in I1 is\n" + + "----------\n" + ); + } +} +/** overriding method must be non-null annotated because of an ancestor interface */ +public void test_OverridingInterfaceNeedsAnnotationFromAncestorInterface() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "org/NonNull.java", + "package org;\n" + + "public @interface NonNull { }\n", + "I1.java", + "public interface I1 {\n" + + " @org.NonNull Object foo();\n" + + "}\n", + "I2.java", + "public interface I2 extends I1 {\n" + + "}\n", + "I3.java", + "public interface I3 extends I2{\n" + + " Object foo();\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in I3.java (at line 3)\n" + + "\tObject foo() {\n" + + "\t ^^^^^\n" + + "Method foo() is not annotated with @NonNull while is overriding foo()\n" + + "----------\n" + ); + } +} + +///** When an argument is NonNull annotated in one interface and the other in another */ +//public void test_2OverridingProblems4() { +// if (this.complianceLevel >= ClassFileConstants.JDK1_5) { +// this.runNegativeTest( +// new String[] { +// "org/NonNull.java", +// "public @interface NonNull { }\n", +// "X.java", +// "public class X implements I {\n" + +// " void foo(Object o1, Object o2) {\n" + +// " return null;\n" + +// " }\n" + +// "}\n", +// "I.java", +// "public interface I1 {\n" + +// " void foo(@org.NonNull Object o1, Object o2);\n" + +// "}\n", +// "I2.java", +// "public interface I2 extends I3 {\n" + +// "}\n", +// "I3.java", +// "public interface I3 {\n" + +// " @org.NonNull Object foo();\n" + +// "}\n" +// }, +// "----------\n" + +// "1. ERROR in Y.java (at line 3)\n" + +// "\tObject foo() {\n" + +// "\t ^^^^^\n" + +// "Method foo() is not annotated with @NonNull while is overriding foo()\n" + +// "2. ERROR in Z.java (at line 3)\n" + +// "\tObject foo() {\n" + +// "\t ^^^^^\n" + +// "Method foo() is not annotated with @NonNull while is overriding foo()\n" + +// "----------\n" +// ); +// } +//} + +/** */ +public void test_MixOfAnnotatedParametersFromTwoInterfaces() { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { + this.runNegativeTest( + new String[] { + "org/NonNull.java", + "package org;\n" + + "public @interface NonNull { }\n", + "X.java", + "public class X implements I1, I2 {\n" + + " public void foo(Object o1, Object o2) {\n" + + " }\n" + + "}\n", + "I1.java", + "public interface I1 {\n" + + " void foo(@org.NonNull Object o1, Object o2);\n" + + "}\n", + "I2.java", + "public interface I2 {\n" + + " void foo(Object o1, @org.NonNull Object o2);\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 2)\n" + + "\tpublic void foo(Object o1, Object o2) {\n" + + "\t ^^\n" + + "Argument o1 in method foo(Object, Object) isn't NonNull annotated while overridden method in type I1 is\n" + + "----------\n" + + "2. ERROR in X.java (at line 2)\n" + + "\tpublic void foo(Object o1, Object o2) {\n" + + "\t ^^\n" + + "Argument o2 in method foo(Object, Object) isn't NonNull annotated while overridden method in type I2 is\n" + + "----------\n" + ); + } +} + +}