diff options
author | Stephan Herrmann | 2011-11-05 18:10:32 +0000 |
---|---|---|
committer | Stephan Herrmann | 2011-11-05 18:10:32 +0000 |
commit | c28ab561189bf67eba84fc2315932206628b0e83 (patch) | |
tree | befefc59b2b9c7ab57d9df8a270dfb2f2c0a7dfd /contrib | |
parent | a3cb202c6c00240d096f25e38d76ff4ff8209b1d (diff) | |
download | org.eclipse.objectteams-c28ab561189bf67eba84fc2315932206628b0e83.tar.gz org.eclipse.objectteams-c28ab561189bf67eba84fc2315932206628b0e83.tar.xz org.eclipse.objectteams-c28ab561189bf67eba84fc2315932206628b0e83.zip |
- abandon @NullableByDefault,
- add a boolean parameter to @NonNullByDefault for canceling defaults
- implementation uses new TagBits.AnnotationNullUnspecifiedByDefault to represent @NonNullByDefault(false),
- similarly, Constants NULL_UNSPECIFIED represents explicit absence of a null annotation
- new warning for redundant @NonNull within a scope with default
- new error if annotation name is not a FQN
- abandon warning token "nullcontract", subsume under "null"
Diffstat (limited to 'contrib')
5 files changed, 170 insertions, 80 deletions
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NonNullByDefault.java b/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NonNullByDefault.java index bb6d06b6c..19b62039d 100644 --- a/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NonNullByDefault.java +++ b/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NonNullByDefault.java @@ -36,7 +36,7 @@ import java.lang.annotation.*; * @author stephan */ @Retention(RetentionPolicy.CLASS) -@Target({PACKAGE,TYPE}) +@Target({PACKAGE,TYPE,METHOD,CONSTRUCTOR}) public @interface NonNullByDefault { - + boolean value() default true; } diff --git a/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NullableByDefault.java b/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NullableByDefault.java deleted file mode 100644 index a4f3c432c..000000000 --- a/contrib/org.eclipse.objectteams.jdt.nullity.tests/annotations/org/eclipse/jdt/annotation/NullableByDefault.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 GK Software AG 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 - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Stephan Herrmann - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.annotation; - -import static java.lang.annotation.ElementType.*; -import java.lang.annotation.*; - -/** - * This annotation can be applied to a package or a type in order to define that - * all contained entities for which a null annotation is otherwise lacking - * should be considered as @{@link Nullable}. - * <dl> - * <dt>Interaction with inheritance</dt> - * <dd>This annotation has lower precedence than null contract inheritance, - * i.e., for a method with no explicit null annotations first inheritance - * from the super-method (overridden or implemented) are considered. - * Only if that search yields no null annotation the default defined using - * <code>@NullableByDefault</code> is applied.</dd> - * <dt>Nested defaults</dt> - * <dd>If a <code>@NullableByDefault</code> - * annotation is used within the scope of a <code>@NonNullByDefault</code> - * annotation the inner most annotation defines the default applicable at - * any given position.</dd> - * </dl> - * Note that for applying an annotation to a package a file by the name - * <code>package-info.java</code> is used. - * - * @author stephan - */ -@Retention(RetentionPolicy.CLASS) -@Target({PACKAGE,TYPE}) -public @interface NullableByDefault { - -} diff --git a/contrib/org.eclipse.objectteams.jdt.nullity.tests/lib/nullAnnotations.jar b/contrib/org.eclipse.objectteams.jdt.nullity.tests/lib/nullAnnotations.jar Binary files differindex 5adb40e3e..2a7296549 100644 --- a/contrib/org.eclipse.objectteams.jdt.nullity.tests/lib/nullAnnotations.jar +++ b/contrib/org.eclipse.objectteams.jdt.nullity.tests/lib/nullAnnotations.jar diff --git a/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationModelTests.java b/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationModelTests.java index 9a997d06c..a14447625 100644 --- a/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationModelTests.java +++ b/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationModelTests.java @@ -56,7 +56,7 @@ public class NullAnnotationModelTests extends ReconcilerTests { // Resources creation IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", ANNOTATION_LIB}, "bin", "1.5"); p.setOption(NullCompilerOptions.OPTION_AnnotationBasedNullAnalysis, JavaCore.ENABLED); - p.setOption(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + p.setOption(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); this.createFolder("/P/p1"); String c1SourceString = @@ -109,7 +109,7 @@ public class NullAnnotationModelTests extends ReconcilerTests { new String[] {"JCL15_LIB", ANNOTATION_LIB, testJarPath("example.jar")}, "bin", "1.5"); p.setOption(NullCompilerOptions.OPTION_AnnotationBasedNullAnalysis, JavaCore.ENABLED); - p.setOption(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + p.setOption(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); // example.jar contains p1/C1.java just like testConvertedSourceType1() diff --git a/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationTest.java b/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationTest.java index 1b6fb69d9..63243e92f 100644 --- a/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationTest.java +++ b/contrib/org.eclipse.objectteams.jdt.nullity.tests/src/org/eclipse/objectteams/jdt/nullity/tests/NullAnnotationTest.java @@ -54,7 +54,7 @@ public NullAnnotationTest(String name) { // Static initializer to specify tests subset using TESTS_* static variables // All specified tests which do not belong to the class are skipped... static { -// TESTS_NAMES = new String[] { "test_constructor_with_nested_class" }; +// TESTS_NAMES = new String[] { "test_nonnull_var_in_constrol_structure_3" }; // TESTS_NUMBERS = new int[] { 561 }; // TESTS_RANGE = new int[] { 1, 2049 }; } @@ -118,8 +118,7 @@ void runNegativeTestWithLibs(boolean shouldFlushOutputDirectory, String[] testFi LIBS, customOptions, expectedErrorLog, - "",/* expected output */ - "",/* expected error */ + // runtime options JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } void runNegativeTestWithLibs(String[] testFiles, Map customOptions, String expectedErrorLog) { @@ -950,22 +949,22 @@ public void test_parameter_specification_inheritance_014() { "1. ERROR in p1\\Y.java (at line 2)\n" + " public class Y extends X implements IY {\n" + " ^\n" + - "The method getString1(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints. \n" + + "The method getString1(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + "----------\n" + "2. ERROR in p1\\Y.java (at line 2)\n" + " public class Y extends X implements IY {\n" + " ^\n" + - "The method getString2(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints. \n" + + "The method getString2(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + "----------\n" + "3. ERROR in p1\\Y.java (at line 2)\n" + " public class Y extends X implements IY {\n" + " ^\n" + - "The method getString5(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints. \n" + + "The method getString5(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + "----------\n" + "4. ERROR in p1\\Y.java (at line 2)\n" + " public class Y extends X implements IY {\n" + " ^\n" + - "The method getString3(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints. \n" + + "The method getString3(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + "----------\n"); } // a nullable return value is dereferenced without a check @@ -1320,6 +1319,24 @@ public void test_nonnull_return_013() { customOptions, ""); } +//suppress an error regarding null-spec violation +public void test_suppress_001() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED); + runConformTestWithLibs( + new String[] { + "X.java", + "import org.eclipse.jdt.annotation.*;\n" + + "public class X {\n" + + " @SuppressWarnings(\"null\")\n" + + " @NonNull Object getObject(@Nullable Object o) {\n" + + " return o;\n" + // 'o' is only potentially null + " }\n" + + "}\n" + }, + customOptions, + ""); +} // mixed use of fully qualified name / explicit import public void test_annotation_import_001() { Map customOptions = getCompilerOptions(); @@ -1466,7 +1483,7 @@ public void test_annotation_import_007() { customOptions.put(NullCompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull"); customOptions.put(NullCompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull"); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); runNegativeTest( true/*shouldFlushOutputDirectory*/, new String[] { @@ -1508,38 +1525,35 @@ public void test_illegal_annotation_001() { "The annotation @NonNull is disallowed for this location\n" + "----------\n", LIBS, - false/*shouldFlush*/); + false/*shouldFlush*/); } +// this test has been removed: // setting default to nullable, default applies to a parameter -public void test_default_nullness_001() { +// public void test_default_nullness_001() + +// a null annotation is illegally defined by its simple name +public void test_illegal_annotation_002() { Map customOptions = getCompilerOptions(); - customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NULLABLE); + customOptions.put(NullCompilerOptions.OPTION_NonNullAnnotationName, "NichtNull"); runNegativeTestWithLibs( new String[] { "X.java", - "import org.eclipse.jdt.annotation.*;\n" + "public class X {\n" + - " @NonNull Object getObject(Object o) {\n" + - " return o;\n" + // illegal due to default @Nullable of parameter - " }\n" + - "}\n", - + "}\n" }, customOptions, "----------\n" + - "1. ERROR in X.java (at line 4)\n" + - " return o;\n" + - " ^\n" + - "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + + "1. ERROR in X.java (at line 0)\n" + + " public class X {\n" + + " ^\n" + + "Cannot use the unqualified name \'NichtNull\' as an annotation name for null specification\n" + "----------\n"); } public void test_default_nullness_002() { Map customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); runNegativeTestWithLibs( new String[] { "X.java", @@ -1773,7 +1787,7 @@ public void test_default_nullness_007() { Map customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); runNegativeTestWithLibs( new String[] { "X.java", @@ -1796,12 +1810,119 @@ public void test_default_nullness_007() { "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + "----------\n"); } + +// cancel type level default to comply with super specification +public void test_default_nullness_008() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); + customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); + runConformTestWithLibs( + new String[] { + "p1/X.java", + "package p1;\n" + + "public class X {\n" + + " protected Object getObject(Object o) {\n" + + " return new Object();\n" + + " }\n" + + "}\n", + "p2/Y.java", + "package p2;\n" + + "import org.eclipse.jdt.annotation.*;\n" + + "@NonNullByDefault\n" + + "public class Y extends p1.X {\n" + + " @Override\n" + + " @NonNullByDefault(false)\n" + + " protected Object getObject(Object o) {\n" + + " if (o.toString().length() == 0)\n" + // dereference without a warning + " return null;\n" + // return null without a warning + " return o.toString();\n" + + " }\n" + + "}\n" + }, + customOptions, + ""); +} + +// cancel outer type level default to comply with super specification +public void test_default_nullness_009() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); + customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); + runNegativeTestWithLibs( + new String[] { + "p1/X.java", + "package p1;\n" + + "public class X {\n" + + " protected Object getObject(Object o) {\n" + + " return new Object();\n" + + " }\n" + + "}\n", + "p2/Y.java", + "package p2;\n" + + "import org.eclipse.jdt.annotation.*;\n" + + "@NonNullByDefault\n" + + "public class Y { \n" + + " @NonNullByDefault(false)\n" + + " static class Z extends p1.X {\n" + + " @Override\n" + + " protected Object getObject(Object o) {\n" + + " if (o.toString().length() == 0) {\n" + + " o = null;\n" + // assign null without a warning + " bar(o); // error: arg is declared @NonNull\n" + + " return null;\n" + + " }\n" + + " return o.toString();\n" + + " }\n" + + " String bar(@NonNull Object o) {\n" + + " return getObject(o).toString();" + + " }\n" + + " }\n" + + "}\n" + }, + customOptions, + "----------\n" + + "1. ERROR in p2\\Y.java (at line 11)\n" + + " bar(o); // error: arg is declared @NonNull\n" + + " ^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n"); +} +// non-null declarations are redundant within a default scope. +public void test_default_nullness_010() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); + customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); + runConformTestWithLibs( + new String[] { + "p2/Y.java", + "package p2;\n" + + "import org.eclipse.jdt.annotation.*;\n" + + "@NonNullByDefault\n" + + "public class Y {\n" + + " protected @NonNull Object getObject(@NonNull Object o) {\n" + + " return o;\n" + + " }\n" + + "}\n" + }, + customOptions, + "----------\n" + + "1. WARNING in p2\\Y.java (at line 5)\n" + + " protected @NonNull Object getObject(@NonNull Object o) {\n" + + " ^^^^^^^^^^^^^^^\n" + + "The nullness annotation is redundant with a default that applies to this location\n" + + "----------\n" + + "2. WARNING in p2\\Y.java (at line 5)\n" + + " protected @NonNull Object getObject(@NonNull Object o) {\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "The nullness annotation is redundant with a default that applies to this location\n" + + "----------\n"); +} // a nonnull variable is dereferenced in a loop public void test_nonnull_var_in_constrol_structure_1() { Map customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); runNegativeTestWithLibs( new String[] { "X.java", @@ -1828,15 +1949,25 @@ public void test_nonnull_var_in_constrol_structure_1() { }, customOptions, "----------\n" + - "1. ERROR in X.java (at line 9)\n" + + "1. WARNING in X.java (at line 3)\n" + + " void print4(@NonNull String s) {\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "The nullness annotation is redundant with a default that applies to this location\n" + + "----------\n" + + "2. ERROR in X.java (at line 9)\n" + " print(s);\n" + " ^\n" + "Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + "----------\n" + - "2. ERROR in X.java (at line 14)\n" + + "3. ERROR in X.java (at line 14)\n" + " print(s);\n" + " ^\n" + "Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + + "----------\n" + + "4. WARNING in X.java (at line 16)\n" + + " void print(@NonNull String s) {\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "The nullness annotation is redundant with a default that applies to this location\n" + "----------\n"); } // a nonnull variable is dereferenced in a finally block @@ -1844,13 +1975,13 @@ public void test_nonnull_var_in_constrol_structure_2() { Map customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); runNegativeTestWithLibs( new String[] { "X.java", "import org.eclipse.jdt.annotation.*;\n" + "public class X {\n" + - " void print4(@NonNull String s) {\n" + + " void print4(String s) {\n" + " try { /*empty*/ } finally {\n" + " print(s);\n" + " }\n" + @@ -1866,7 +1997,7 @@ public void test_nonnull_var_in_constrol_structure_2() { " print(s);\n" + " }\n" + " }\n" + - " void print(@NonNull String s) {\n" + + " void print(String s) {\n" + " System.out.print(s);\n" + " }\n" + "}\n", @@ -1890,7 +2021,8 @@ public void test_nonnull_var_in_constrol_structure_3() { Map customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); + customOptions.put(NullCompilerOptions.OPTION_ReportRedundantNullAnnotation, CompilerOptions.IGNORE); runNegativeTestWithLibs( new String[] { "X.java", @@ -1934,12 +2066,12 @@ public void test_nonnull_var_in_constrol_structure_3() { "Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + "----------\n"); } -//a nonnull variable is dereferenced method of a nested type +// a nonnull variable is dereferenced method of a nested type public void test_nesting_1() { Map customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); customOptions.put(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); - customOptions.put(NullCompilerOptions.OPTION_NullnessDefault, NullCompilerOptions.NONNULL); + customOptions.put(NullCompilerOptions.OPTION_NonNullIsDefault, NullCompilerOptions.ENABLED); runNegativeTestWithLibs( new String[] { "X.java", |