Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2014-03-09 23:20:50 +0000
committerStephan Herrmann2014-03-11 16:17:32 +0000
commitdc444b8320482476925f9f5e1514794476164a28 (patch)
tree168bdca960fd7c53bcbf37a275ca95498324f4b3
parentc92099fc5b6f140409692775e015990a59416465 (diff)
downloadeclipse.jdt.core-dc444b8320482476925f9f5e1514794476164a28.tar.gz
eclipse.jdt.core-dc444b8320482476925f9f5e1514794476164a28.tar.xz
eclipse.jdt.core-dc444b8320482476925f9f5e1514794476164a28.zip
Bug 424624 - [1.8][null] if a static-object with annotation @NonNull is
used, a warning is shown
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java168
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java77
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java59
3 files changed, 278 insertions, 26 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
index ba135b7e6b..44f66afb74 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
@@ -6821,4 +6821,172 @@ public void testBug420313() {
"Missing non-null annotation: inherited method from UntypedBase specifies this parameter as @NonNull\n" +
"----------\n");
}
+// original test
+public void testBug424624() {
+ runConformTestWithLibs(
+ new String[] {
+ "Test3.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class Test3 {\n" +
+ "\n" +
+ " public Test3() {\n" +
+ " }\n" +
+ "\n" +
+ " static public class Test3aa extends Object {}\n" +
+ " static public final @NonNull Test3aa Test3a = new Test3aa();\n" +
+ "\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ "");
+ runConformTestWithLibs(
+ new String[] {
+ "Test4.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class Test4 {\n" +
+ "\n" +
+ " public Test4() {\n" +
+ " }\n" +
+ " \n" +
+ " public void test() {\n" +
+ " test1( Test3.Test3a);\n" +
+ " }\n" +
+ " \n" +
+ " public void test1( @NonNull Object object) {\n" +
+ " }\n" +
+ "\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+}
+// other nesting levels, binary case
+public void testBug424624a() {
+ runConformTestWithLibs(
+ new String[] {
+ "test/Test3.java",
+ "package test;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ (this.complianceLevel >= ClassFileConstants.JDK1_8 ?
+ "import java.lang.annotation.*;\n" +
+ "@Target(ElementType.TYPE_USE) @interface Marker {}\n"
+ :
+ ""
+ )+
+ "\n" +
+ "public class Test3 {\n" +
+ "\n" +
+ " public Test3() {\n" +
+ " }\n" +
+ "\n" +
+ " public class Inner extends Object {\n" +
+ " class DeepInner {}\n" +
+ " }\n" +
+ " public static class Nested extends Object {\n" +
+ " class InnerInNested {}\n" +
+ " static class DeepNested {}\n" +
+ " }\n" +
+ " static public final @NonNull Inner field1 = new Test3().new Inner();\n" +
+ (this.complianceLevel < ClassFileConstants.JDK1_8 ?
+ " static public final @NonNull Inner.DeepInner field2 = field1.new DeepInner();\n" +
+ " static public final @NonNull Nested.InnerInNested field3 = new Nested().new InnerInNested();\n" +
+ " static public final @NonNull Nested.DeepNested field4 = new Nested.DeepNested();\n"
+ :
+ " static public final @Marker Inner.@NonNull DeepInner field2 = field1.new DeepInner();\n" +
+ " static public final Nested.@NonNull InnerInNested field3 = new Nested().new InnerInNested();\n" +
+ " static public final Nested.@NonNull DeepNested field4 = new Nested.DeepNested();\n"
+ ) +
+ "\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ "");
+ runConformTestWithLibs(
+ new String[] {
+ "Test4.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import test.Test3;\n" +
+ "\n" +
+ "public class Test4 {\n" +
+ "\n" +
+ " public Test4() {\n" +
+ " }\n" +
+ " \n" +
+ " public void test() {\n" +
+ " test1( Test3.field1);\n" +
+ " test1( Test3.field2);\n" +
+ " test1( Test3.field3);\n" +
+ " test1( Test3.field4);\n" +
+ " }\n" +
+ " \n" +
+ " public void test1( @NonNull Object object) {\n" +
+ " }\n" +
+ "\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+}
+// same as previous, source case for reference
+public void testBug424624b() {
+ runConformTestWithLibs(
+ new String[] {
+ "Test3.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ (this.complianceLevel >= ClassFileConstants.JDK1_8 ?
+ "import java.lang.annotation.*;\n" +
+ "@Target(ElementType.TYPE_USE) @interface Marker {}\n"
+ :
+ ""
+ )+
+ "\n" +
+ "public class Test3 {\n" +
+ "\n" +
+ " public Test3() {\n" +
+ " }\n" +
+ "\n" +
+ " public class Inner extends Object {\n" +
+ " class DeepInner {}\n" +
+ " }\n" +
+ " public static class Nested extends Object {\n" +
+ " class InnerInNested {}\n" +
+ " static class DeepNested {}\n" +
+ " }\n" +
+ " static public final @NonNull Inner field1 = new Test3().new Inner();\n" +
+ (this.complianceLevel < ClassFileConstants.JDK1_8 ?
+ " static public final @NonNull Inner.DeepInner field2 = field1.new DeepInner();\n" +
+ " static public final @NonNull Nested.InnerInNested field3 = new Nested().new InnerInNested();\n" +
+ " static public final @NonNull Nested.DeepNested field4 = new Nested.DeepNested();\n"
+ :
+ " static public final @Marker Inner.@NonNull DeepInner field2 = field1.new DeepInner();\n" +
+ " static public final Nested.@NonNull InnerInNested field3 = new Nested().new InnerInNested();\n" +
+ " static public final Nested.@NonNull DeepNested field4 = new Nested.DeepNested();\n"
+ ) +
+ "\n" +
+ "}\n",
+ "Test4.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class Test4 {\n" +
+ "\n" +
+ " public Test4() {\n" +
+ " }\n" +
+ " \n" +
+ " public void test() {\n" +
+ " test1( Test3.field1);\n" +
+ " test1( Test3.field2);\n" +
+ " test1( Test3.field3);\n" +
+ " test1( Test3.field4);\n" +
+ " }\n" +
+ " \n" +
+ " public void test1( @NonNull Object object) {\n" +
+ " }\n" +
+ "\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
index 555c4dadfc..e7571a89af 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
@@ -2078,6 +2078,83 @@ public class TypeBindingTests308 extends ConverterTestSetup {
removeLibrary(javaProject, jarName, srcName);
}
}
+ // Variants where superclass in binary is an annotated inner/nested class
+ public void testBinaryWithoutGenericSignature_b() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Superclass.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value() default 0;\n" +
+ "}\n" +
+ "@T(1)\n" +
+ "public abstract class Superclass extends @T(2) Object implements @T(3) Runnable {\n" +
+ " @T(9)\n" +
+ " Superclass () {}\n" +
+ " @T(10)\n" +
+ " class Inner {}\n" +
+ " @T(11)\n" +
+ " class SubInner extends @T(12) Inner {}\n" +
+ " @T(13)\n" +
+ " static class Nested {}\n" +
+ " @T(14)\n" +
+ " static class SubNested extends @T(15) Nested {}\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "@T(21)\n" +
+ "public abstract class X extends @T(22) Superclass implements @T(23) Runnable {\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ ITypeBinding typeBinding = typeDecl.resolveBinding();
+ IAnnotationBinding[] annotations = typeBinding.getAnnotations();
+ assertTrue("Should be 1", annotations.length == 1);
+ assertEquals("Annotation mismatch", "@T(value = 21)", annotations[0].toString());
+
+ ITypeBinding superclass = typeBinding.getSuperclass();
+ ITypeBinding[] inners = superclass.getDeclaredTypes();
+ assertTrue("Should be 2", inners.length == 4);
+
+ ITypeBinding subInner = inners[2];
+ assertEquals("Type name mismatch", "SubInner", subInner.getName());
+ annotations = subInner.getAnnotations();
+ assertTrue("Should be 1", annotations.length == 1);
+ assertEquals("Annotation mismatch", "@T(value = 11)", annotations[0].toString());
+
+ annotations = subInner.getSuperclass().getTypeAnnotations();
+ assertTrue("Should be 1", annotations.length == 1);
+ assertEquals("Annotation mismatch", "@T(value = 12)", annotations[0].toString());
+
+ ITypeBinding subNested = inners[3];
+ annotations = subNested.getAnnotations();
+ assertTrue("Should be 1", annotations.length == 1);
+ assertEquals("Annotation mismatch", "@T(value = 14)", annotations[0].toString());
+
+ annotations = subNested.getSuperclass().getTypeAnnotations();
+ assertTrue("Should be 1", annotations.length == 1);
+ assertEquals("Annotation mismatch", "@T(value = 15)", annotations[0].toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=419918, [1.8][compiler] Annotations are not restored from class files in a few situations.
public void testBinaryAnnotationType() throws CoreException, IOException {
String jarName = "TypeBindingTests308.jar";
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index d3c68a02f8..6ff5e28ce3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -27,6 +27,7 @@
* Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Bug 416190 - [1.8][null] detect incompatible overrides due to null type annotations
+ * Bug 424624 - [1.8][null] if a static-object with annotation @NonNull is used, a warning is shown
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -1228,19 +1229,7 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
}
ReferenceBinding binding = getTypeFromCompoundName(compoundName, isParameterized, wasMissingType);
if (walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
- final int depth = binding.depth();
- AnnotationBinding [][] annotations = null;
- for (int i = 0; i <= depth; i++) {
- AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
- if (annots != null && annots.length > 0) {
- if (annotations == null)
- annotations = new AnnotationBinding[depth + 1][];
- annotations[i] = annots;
- }
- walker = walker.toNextNestedType();
- }
- if (annotations != null)
- binding = (ReferenceBinding) createAnnotatedType(binding, annotations);
+ binding = (ReferenceBinding) annotateType(binding, walker, missingTypeNames);
}
return binding;
}
@@ -1326,19 +1315,7 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean i
}
if (walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
- final int depth = binding.depth();
- AnnotationBinding [][] annotations = null;
- for (int i = 0; i <= depth; i++) {
- AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
- if (annots != null && annots.length > 0) {
- if (annotations == null)
- annotations = new AnnotationBinding[depth + 1][];
- annotations[i] = annots;
- }
- walker = walker.toNextNestedType();
- }
- if (annotations != null)
- binding = createAnnotatedType(binding, annotations);
+ binding = annotateType(binding, walker, missingTypeNames);
}
if (dimension != 0)
@@ -1347,6 +1324,36 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean i
return binding;
}
+private TypeBinding annotateType(TypeBinding binding, TypeAnnotationWalker walker, char[][][] missingTypeNames) {
+ int depth = binding.depth() + 1;
+ if (depth > 1) {
+ // need to count non-static nesting levels, resolved binding required for precision
+ if (binding.isUnresolvedType())
+ binding = ((UnresolvedReferenceBinding) binding).resolve(this, true);
+ TypeBinding currentBinding = binding;
+ depth = 0;
+ while (currentBinding != null) {
+ depth++;
+ if (currentBinding.isStatic())
+ break;
+ currentBinding = currentBinding.enclosingType();
+ }
+ }
+ AnnotationBinding [][] annotations = null;
+ for (int i = 0; i < depth; i++) {
+ AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ if (annots != null && annots.length > 0) {
+ if (annotations == null)
+ annotations = new AnnotationBinding[depth][];
+ annotations[i] = annots;
+ }
+ walker = walker.toNextNestedType();
+ }
+ if (annotations != null)
+ binding = createAnnotatedType(binding, annotations);
+ return binding;
+}
+
boolean qualifiedNameMatchesSignature(char[][] name, char[] signature) {
int s = 1; // skip 'L'
for (int i = 0; i < name.length; i++) {

Back to the top