diff options
author | Stephan Herrmann | 2020-01-06 22:12:39 +0000 |
---|---|---|
committer | Stephan Herrmann | 2020-01-06 22:53:43 +0000 |
commit | c68c1e4999fba991c5c5d3410da33a3f909b3462 (patch) | |
tree | 1fd2de334d192501279590979fb1bb9ebd5ae97c | |
parent | f6ca35bc46a58901d24a836b1dc77576044bdb13 (diff) | |
download | eclipse.jdt.core-c68c1e4999fba991c5c5d3410da33a3f909b3462.tar.gz eclipse.jdt.core-c68c1e4999fba991c5c5d3410da33a3f909b3462.tar.xz eclipse.jdt.core-c68c1e4999fba991c5c5d3410da33a3f909b3462.zip |
Bug 466477 - [null] Improve error message "...inherited method ...I20200106-1805
specifies ..."
Change-Id: I2851d539bbcb6965f942a8f8f0d6968b2e98f230
6 files changed, 88 insertions, 35 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java index 7e4e8c3434..5dcaae8a35 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java @@ -628,6 +628,7 @@ public void test011_problem_categories() { expectedProblemAttributes.put("InheritedIncompatibleReturnType", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); expectedProblemAttributes.put("InheritedMethodHidesEnclosingName", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); expectedProblemAttributes.put("InheritedMethodReducesVisibility", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); + expectedProblemAttributes.put("InheritedParameterLackingNonNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); expectedProblemAttributes.put("InheritedTypeHidesEnclosingName", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); expectedProblemAttributes.put("InitializerMustCompleteNormally", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("InstanceFieldDuringConstructorInvocation", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); @@ -1610,6 +1611,7 @@ public void test012_compiler_problems_tuning() { expectedProblemAttributes.put("InheritedIncompatibleReturnType", SKIP); expectedProblemAttributes.put("InheritedMethodHidesEnclosingName", SKIP); expectedProblemAttributes.put("InheritedMethodReducesVisibility", SKIP); + expectedProblemAttributes.put("InheritedParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED)); expectedProblemAttributes.put("InheritedTypeHidesEnclosingName", SKIP); expectedProblemAttributes.put("InitializerMustCompleteNormally", SKIP); expectedProblemAttributes.put("InstanceFieldDuringConstructorInvocation", SKIP); 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 cae1036973..658c2e1e77 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 @@ -1286,44 +1286,44 @@ public void test_parameter_specification_inheritance_014() { "----------\n" + "1. ERROR in p1\\Y.java (at line 2)\n" + " public class Y extends X implements IY {\n" + - " ^\n" + + " ^\n" + "The method getString1(String) from X cannot implement the corresponding method from 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" + + " ^\n" + "The method getString2(String) from X cannot implement the corresponding method from 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" + + " ^\n" + "The method getString5(String) from X cannot implement the corresponding method from 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" + + " ^\n" + "The method getString3(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" + "----------\n" : // at 1.8 we show null type annotations in the message: "----------\n" + "1. ERROR in p1\\Y.java (at line 2)\n" + " public class Y extends X implements IY {\n" + - " ^\n" + + " ^\n" + "The method @Nullable String getString1(String) from X cannot implement the corresponding method from 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" + + " ^\n" + "The method String getString2(String) from X cannot implement the corresponding method from 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" + + " ^\n" + "The method getString5(@NonNull String) from X cannot implement the corresponding method from 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" + + " ^\n" + "The method getString3(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" + "----------\n")); } @@ -1411,8 +1411,8 @@ public void test_parameter_specification_inheritance_017() { "----------\n" + "1. WARNING in XSub.java (at line 1)\n" + " public class XSub extends X implements IX {\n" + - " ^^^^\n" + - "Missing non-null annotation: inherited method from IX specifies this parameter as @NonNull\n" + + " ^\n" + + "Parameter 1 of method foo(String) lacks a @NonNull annotation as specified in type IX\n" + "----------\n"); } @@ -6123,24 +6123,24 @@ public void testBug388281_06() { "----------\n" + "1. ERROR in ctest\\C.java (at line 2)\n" + " public class C extends c.C2 implements i2.I2A {\n" + - " ^\n" + + " ^^^^\n" + "The method m2(Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" + "----------\n" + "2. ERROR in ctest\\C.java (at line 2)\n" + " public class C extends c.C2 implements i2.I2A {\n" + - " ^\n" + + " ^^^^\n" + "The method m1(Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" + "----------\n" : // at 1.8 we show null type annotations: "----------\n" + "1. ERROR in ctest\\C.java (at line 2)\n" + " public class C extends c.C2 implements i2.I2A {\n" + - " ^\n" + + " ^^^^\n" + "The method m2(@NonNull Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" + "----------\n" + "2. ERROR in ctest\\C.java (at line 2)\n" + " public class C extends c.C2 implements i2.I2A {\n" + - " ^\n" + + " ^^^^\n" + "The method m1(@NonNull Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" + "----------\n"), libs, @@ -9138,24 +9138,24 @@ public void testBug502214() { "----------\n" + "1. ERROR in test\\X.java (at line 22)\n" + " class Y extends A implements I {\n" + - " ^\n" + + " ^\n" + "The method m2() from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" + "----------\n" + "2. ERROR in test\\X.java (at line 22)\n" + " class Y extends A implements I {\n" + - " ^\n" + + " ^\n" + "The method m1(Object) from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" + "----------\n" : "----------\n" + "1. ERROR in test\\X.java (at line 22)\n" + " class Y extends A implements I {\n" + - " ^\n" + + " ^\n" + "The method @Nullable String m2() from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" + "----------\n" + "2. ERROR in test\\X.java (at line 22)\n" + " class Y extends A implements I {\n" + - " ^\n" + + " ^\n" + "The method m1(Object) from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" + "----------\n" ) @@ -11076,4 +11076,35 @@ public void testBug459397() { "Redundant null check: The variable dc cannot be null at this location\n" + "----------\n"); } +public void testBug466477() { + runNegativeTestWithLibs( + new String[] { + "SuperI.java", + "import org.eclipse.jdt.annotation.*;\n" + + "\n" + + "public interface SuperI {\n" + + " void testNN(@NonNull String s);\n" + + " void testNu(@Nullable String s);\n" + + "}\n", + "Base.java", + "public class Base {\n" + + " public void testNN(String s) { }\n" + + " public void testNu(String s) { }\n" + + "}\n", + "Custom.java", + "public class Custom extends Base implements SuperI {\n" + + "}" + }, + "----------\n" + + "1. ERROR in Custom.java (at line 1)\n" + + " public class Custom extends Base implements SuperI {\n" + + " ^^^^\n" + + "The method testNu(String) from Base cannot implement the corresponding method from SuperI due to incompatible nullness constraints\n" + + "----------\n" + + "2. WARNING in Custom.java (at line 1)\n" + + " public class Custom extends Base implements SuperI {\n" + + " ^^^^\n" + + "Parameter 1 of method testNN(String) lacks a @NonNull annotation as specified in type SuperI\n" + + "----------\n"); +} } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index de77baa45d..7119bbaf56 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java @@ -1833,6 +1833,8 @@ void setSourceStart(int sourceStart); int RedundantNullCheckOnConstNonNullField = Internal + 944; /** @since 3.20 */ int ConstNonNullFieldComparisonYieldsFalse = Internal + 945; + /** @since 3.21 */ + int InheritedParameterLackingNonNullAnnotation = MethodRelated + 946; /** @since 3.10 */ int ArrayReferencePotentialNullReference = Internal + 951; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java index 95594bd7bb..8161215460 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2018 GK Software AG, IBM Corporation and others. + * Copyright (c) 2012, 2020 GK Software SE, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -25,6 +25,7 @@ import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching; import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; /** @@ -436,10 +437,13 @@ public class ImplicitNullAnnotationVerifier { if (TypeBinding.equalsEquals(inheritedMethod.declaringClass, one.declaringClass) && getParameterNonNullness(one, i, useTypeAnnotations) != Boolean.TRUE) continue parameterLoop; } - scope.problemReporter().parameterLackingNonnullAnnotation( - currentArgument, - inheritedMethod.declaringClass, - annotationName); + if (currentArgument != null) { + scope.problemReporter().parameterLackingNonnullAnnotation(currentArgument, inheritedMethod.declaringClass, annotationName); + } else { + TypeDeclaration type = scope.classScope().referenceContext; + ASTNode location = type.superclass != null ? type.superclass : type; + scope.problemReporter().inheritedParameterLackingNonnullAnnotation(currentMethod, i+1, inheritedMethod.declaringClass, location, annotationName); + } continue; } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 74b69a03a9..6932f0aa86 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -478,6 +478,7 @@ public static int getIrritant(int problemID) { return CompilerOptions.NonNullTypeVariableFromLegacyInvocation; case IProblem.ParameterLackingNonNullAnnotation: + case IProblem.InheritedParameterLackingNonNullAnnotation: return CompilerOptions.NonnullParameterAnnotationDropped; case IProblem.RequiredNonNullButProvidedPotentialNull: @@ -10089,20 +10090,26 @@ public void parameterLackingNullableAnnotation(Argument argument, ReferenceBindi argument.type.sourceEnd); } public void parameterLackingNonnullAnnotation(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) { - int sourceStart = 0, sourceEnd = 0; - if (argument != null) { - sourceStart = argument.type.sourceStart; - sourceEnd = argument.type.sourceEnd; - } else if (this.referenceContext instanceof TypeDeclaration) { - sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart; - sourceEnd = ((TypeDeclaration) this.referenceContext).sourceEnd; - } this.handle( IProblem.ParameterLackingNonNullAnnotation, new String[] { new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)}, new String[] { new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])}, - sourceStart, - sourceEnd); + argument.type.sourceStart, + argument.type.sourceEnd); +} +public void inheritedParameterLackingNonnullAnnotation(MethodBinding currentMethod, int paramRank, ReferenceBinding specificationType, + ASTNode location, char[][] annotationName) { + this.handle(IProblem.InheritedParameterLackingNonNullAnnotation, + new String[] { + String.valueOf(paramRank), new String(currentMethod.readableName()), + new String(specificationType.readableName()), CharOperation.toString(annotationName) + }, + new String[] { + String.valueOf(paramRank), new String(currentMethod.shortReadableName()), + new String(specificationType.shortReadableName()), new String(annotationName[annotationName.length-1]) + }, + location.sourceStart, location.sourceEnd + ); } public void illegalParameterRedefinition(Argument argument, ReferenceBinding declaringClass, TypeBinding inheritedParameter) { int sourceStart = argument.type.sourceStart; @@ -10260,8 +10267,14 @@ public void expressionPotentialNullReference(ASTNode location) { public void cannotImplementIncompatibleNullness(ReferenceContext context, MethodBinding currentMethod, MethodBinding inheritedMethod, boolean showReturn) { int sourceStart = 0, sourceEnd = 0; if (context instanceof TypeDeclaration) { - sourceStart = ((TypeDeclaration) context).sourceStart; - sourceEnd = ((TypeDeclaration) context).sourceEnd; + TypeDeclaration type = (TypeDeclaration) context; + if (type.superclass != null) { + sourceStart = type.superclass.sourceStart; + sourceEnd = type.superclass.sourceEnd; + } else { + sourceStart = type.sourceStart; + sourceEnd = type.sourceEnd; + } } String[] problemArguments = { showReturn diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index a64e5f35ec..a09df397f3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -818,6 +818,7 @@ 943 = Nullness default is redundant with a default specified for the enclosing module {0} 944 = Redundant null check: The field {0} is a nonnull constant 945 = Null comparison always yields false: The field {0} is a nonnull constant +946 = Parameter {0} of method {1} lacks a @{3} annotation as specified in type {2} 951 = Potential null pointer access: array element may be null |