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 69ca5cb..45b209a 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 @@ -410,6 +410,123 @@ "Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + "----------\n" /* compiler output */); } +// null is passed to a non-null parameter in a qualified allocation expression, across CUs +public void test_nonnull_parameter_010() { + Map customOptions = getCompilerOptions(); + customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR); + runNegativeTestWithLibs( + new String[] { + "ContainingInner2.java", + "public class ContainingInner2 {\n" + + " public ContainingInner2 (@org.eclipse.jdt.annotation.NonNull Object o) {\n" + + " }\n" + + " public class Inner {\n" + + " public Inner (@org.eclipse.jdt.annotation.NonNull Object o) {\n" + + " }\n" + + " }\n" + + "}\n", + "X.java", + "public class X {\n" + + " void create() {\n" + + " ContainingInner2 container = new ContainingInner2(null);\n" + + " ContainingInner2.Inner inner = container.new Inner(null);\n" + + " }\n" + + "}\n"}, + customOptions, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " ContainingInner2 container = new ContainingInner2(null);\n" + + " ^^^^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n" + + "2. ERROR in X.java (at line 4)\n" + + " ContainingInner2.Inner inner = container.new Inner(null);\n" + + " ^^^^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n" /* compiler output */); +} +// null is passed to a non-null parameter in a qualified allocation expression, target class read from .class +public void test_nonnull_parameter_011() { + Map customOptions = getCompilerOptions(); + customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR); + runConformTestWithLibs( + new String[] { + "ContainingInner2.java", + "public class ContainingInner2 {\n" + + " public ContainingInner2 (@org.eclipse.jdt.annotation.NonNull Object o) {\n" + + " }\n" + + " public class Inner {\n" + + " public Inner (@org.eclipse.jdt.annotation.NonNull Object o) {\n" + + " }\n" + + " }\n" + + "}\n", + }, + null /*customOptions*/, + ""); + runNegativeTestWithLibs( + false, // flush directory + new String[] { + "X.java", + "public class X {\n" + + " void create() {\n" + + " ContainingInner2 container = new ContainingInner2(null);\n" + + " ContainingInner2.Inner inner = container.new Inner(null);\n" + + " }\n" + + "}\n"}, + customOptions, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " ContainingInner2 container = new ContainingInner2(null);\n" + + " ^^^^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n" + + "2. ERROR in X.java (at line 4)\n" + + " ContainingInner2.Inner inner = container.new Inner(null);\n" + + " ^^^^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n" /* compiler output */); +} +//null is passed to a non-null parameter in a qualified allocation expression, generic constructor, target class read from .class +public void test_nonnull_parameter_012() { + Map customOptions = getCompilerOptions(); + customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR); + runConformTestWithLibs( + new String[] { + "ContainingInner2.java", + "public class ContainingInner2 {\n" + + " public ContainingInner2 (@org.eclipse.jdt.annotation.NonNull Object o) {\n" + + " }\n" + + " public class Inner {\n" + + " public Inner (@org.eclipse.jdt.annotation.NonNull T o) {\n" + + " }\n" + + " }\n" + + "}\n", + }, + null /*customOptions*/, + ""); + runNegativeTestWithLibs( + false, // flush directory + new String[] { + "X.java", + "public class X {\n" + + " void create() {\n" + + " ContainingInner2 container = new ContainingInner2(null);\n" + + " ContainingInner2.Inner inner = container.new Inner(null);\n" + + " }\n" + + "}\n"}, + customOptions, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " ContainingInner2 container = new ContainingInner2(null);\n" + + " ^^^^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n" + + "2. ERROR in X.java (at line 4)\n" + + " ContainingInner2.Inner inner = container.new Inner(null);\n" + + " ^^^^\n" + + "Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + + "----------\n" /* compiler output */); +} // assigning potential null to a nonnull local variable public void test_nonnull_local_001() { runNegativeTest( diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java index 26da081..3cd62b0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; @@ -270,6 +271,9 @@ public IBinaryAnnotation[] getParameterAnnotations(int index) { return null; } +public int getNumParameterAnnotations() { + return 0; +} /** * Answer the name of the method. * diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParameterAnnotations.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParameterAnnotations.java index 9d871b1..2aad9f8 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParameterAnnotations.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParameterAnnotations.java @@ -8,6 +8,7 @@ * Contributors: * tyeung@bea.com - initial API and implementation * IBM Corporation - fix for bug 342757 + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; @@ -36,6 +37,9 @@ public IBinaryAnnotation[] getParameterAnnotations(int index) { return this.parameterAnnotations[index]; } +public int getNumParameterAnnotations() { + return this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length; +} protected void initialize() { for (int i = 0, l = this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length; i < l; i++) { AnnotationInfo[] infos = this.parameterAnnotations[i]; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java index d75686b..68b63f6 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.env; @@ -66,6 +67,13 @@ IBinaryAnnotation[] getParameterAnnotations(int index); /** + * Answer the number of parameter annotations that can be retrieved + * using {@link #getParameterAnnotations(int)}. + * @return one beyond the highest legal argument to {@link #getParameterAnnotations(int)}. + */ +int getNumParameterAnnotations(); + +/** * Answer the name of the method. * * For a constructor, answer & for a clinit method. diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index c296801..63d5fcb 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -1178,8 +1178,10 @@ // parameters: TypeBinding[] parameters = methodBinding.parameters; - for (int j = 0; j < parameters.length; j++) { - IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j); + int numVisibleParams = parameters.length; + int startIndex = method.getNumParameterAnnotations() - numVisibleParams; + for (int j = 0; j < numVisibleParams; j++) { + IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j+startIndex); if (paramAnnotations != null) { for (int i = 0; i < paramAnnotations.length; i++) { char[] annotationTypeName = paramAnnotations[i].getTypeName(); @@ -1188,12 +1190,12 @@ char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';' if (CharOperation.equals(typeName, nonNullAnnotationName)) { if (methodBinding.parameterNonNullness == null) - methodBinding.parameterNonNullness = new Boolean[parameters.length]; + methodBinding.parameterNonNullness = new Boolean[numVisibleParams]; methodBinding.parameterNonNullness[j] = Boolean.TRUE; break; } else if (CharOperation.equals(typeName, nullableAnnotationName)) { if (methodBinding.parameterNonNullness == null) - methodBinding.parameterNonNullness = new Boolean[parameters.length]; + methodBinding.parameterNonNullness = new Boolean[numVisibleParams]; methodBinding.parameterNonNullness[j] = Boolean.FALSE; break; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java index 5efc685..37d0536 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -27,6 +28,7 @@ mostSpecificExceptions, originalMethod.declaringClass); this.originalMethod = originalMethod; + this.parameterNonNullness = originalMethod.parameterNonNullness; } public MethodBinding original() { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java index 1eb176f..31710c4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -301,6 +302,7 @@ ? originalMethod.returnType // no substitution if original was static : Scope.substitute(rawType, originalMethod.returnType)); this.wasInferred = false; // not resulting from method invocation inferrence + this.parameterNonNullness = originalMethod.parameterNonNullness; } /** @@ -342,6 +344,7 @@ } } this.wasInferred = true;// resulting from method invocation inferrence + this.parameterNonNullness = originalMethod.parameterNonNullness; } /* diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java index 22b5afa..c7f8ad3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -38,6 +39,7 @@ * is substituted by a raw type. */ this.tagBits = originalMethod.tagBits & ~TagBits.HasMissingType; + this.parameterNonNullness = originalMethod.parameterNonNullness; final TypeVariableBinding[] originalVariables = originalMethod.typeVariables; Substitution substitution = null; @@ -150,6 +152,7 @@ * is substituted by a raw type. */ this.tagBits = originalMethod.tagBits & ~TagBits.HasMissingType; + this.parameterNonNullness = originalMethod.parameterNonNullness; final TypeVariableBinding[] originalVariables = originalMethod.typeVariables; Substitution substitution = null; diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java index e894759..e146520 100644 --- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java +++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking *******************************************************************************/ package org.eclipse.jdt.internal.eval; @@ -64,6 +65,9 @@ public IBinaryAnnotation[] getParameterAnnotations(int index) { return null; } + public int getNumParameterAnnotations() { + return 0; + } public char[] getSelector() { return this.selector; }