Skip to content

Commit

Permalink
NPE in CompilationUnitProblemFinder.java:326 (eclipse-jdt#2060)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephan-herrmann authored Mar 14, 2024
1 parent 7061736 commit 560a301
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;

Expand Down Expand Up @@ -277,9 +278,26 @@ void checkNullSpecInheritance(MethodBinding currentMethod, AbstractMethodDeclara
if (inheritedNullnessBits != 0) {
if (hasReturnNonNullDefault) {
// both inheritance and default: check for conflict?
if (shouldComplain && inheritedNullnessBits == TagBits.AnnotationNullable)
scope.problemReporter().conflictingNullAnnotations(currentMethod, ((MethodDeclaration) srcMethod).returnType, inheritedMethod);
// still use the inherited bits to avoid incompatibility
if (shouldComplain && inheritedNullnessBits == TagBits.AnnotationNullable) {
ASTNode location = null;
if (srcMethod instanceof MethodDeclaration) {
location = ((MethodDeclaration) srcMethod).returnType;
} else if (currentMethod instanceof SyntheticMethodBinding) {
SyntheticMethodBinding synth = (SyntheticMethodBinding) currentMethod;
switch (synth.purpose) {
case SyntheticMethodBinding.FieldReadAccess:
if (synth.recordComponentBinding != null) {
RecordComponent sourceRecordComponent = synth.sourceRecordComponent();
if (sourceRecordComponent != null)
location = sourceRecordComponent.type;
}
}
}
if (location == null)
location = (ASTNode) scope.referenceContext(); // fallback just in case
scope.problemReporter().conflictingNullAnnotations(currentMethod, location, inheritedMethod);
// still use the inherited bits to avoid incompatibility
}
}
if (inheritedNonNullnessInfos != null && srcMethod != null) {
recordDeferredInheritedNullness(scope, ((MethodDeclaration) srcMethod).returnType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
Expand Down Expand Up @@ -665,6 +666,13 @@ public LambdaExpression sourceLambda() {
return this.lambda;
}

@Override
public RecordComponent sourceRecordComponent() {
if (this.recordComponentBinding != null)
return this.recordComponentBinding.sourceRecordComponent();
return null;
}

@Override
public ParameterNonNullDefaultProvider hasNonNullDefaultForParameter(AbstractMethodDeclaration srcMethod) {
switch (this.purpose) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@
936 = Null comparison always yields false: The method {0} cannot return null
937 = Redundant null check: The field {0} is specified as @{1}
938 = Null comparison always yields false: The field {0} is specified as @{1}
939 = The default ''@{0}'' conflicts with the inherited ''@{1}'' annotation in the overridden method from {2}
939 = The default ''@{0}'' conflicts with the inherited ''@{1}'' annotation in the overridden method from {2}
940 = Conflict between inherited null annotations ''@{0}'' declared in {1} versus ''@{2}'' declared in {3}
941 = Redundant null check: The field {0} cannot be null at this location (ignoring concurrency)
942 = Null comparison always yields false: The field {0} cannot be null at this location (ignoring concurrency)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6245,12 +6245,12 @@ public void testBug388281_07() {
"1. ERROR in p2\\Sub.java (at line 6)\n" +
" public Object m(Object arg) { // (a)+(b) conflict at arg and return\n" +
" ^^^^^^\n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from Super \n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from Super\n" +
"----------\n" +
"2. ERROR in p2\\Sub.java (at line 6)\n" +
" public Object m(Object arg) { // (a)+(b) conflict at arg and return\n" +
" ^^^\n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from Super \n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from Super\n" +
"----------\n" +
"3. ERROR in p2\\Sub.java (at line 7)\n" +
" System.out.println(arg.toString()); // (1)\n" +
Expand Down Expand Up @@ -6303,12 +6303,12 @@ public void testBug388281_08() {
"1. ERROR in ctest\\Ctest.java (at line 8)\n" +
" public String m2(Object a2) { // (a) conflict at return\n" +
" ^^^^^^\n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from I \n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from I\n" +
"----------\n" +
"2. ERROR in ctest\\Ctest.java (at line 11)\n" +
" public String m1(Object o1, Object o2) { // (b) conflict at o1\n" +
" ^^\n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from II \n" +
"The default \'@NonNull\' conflicts with the inherited \'@Nullable\' annotation in the overridden method from II\n" +
"----------\n" +
"3. ERROR in ctest\\Ctest.java (at line 12)\n" +
" System.out.println(o1.toString()); // (1) inherited @Nullable\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1035,4 +1035,64 @@ public static void main(final String[] args)
runner.classLibraries = this.LIBS;
runner.runConformTest();
}
public void testGH1771() {
Runner runner = new Runner();
runner.customOptions = getCompilerOptions();
runner.customOptions.put(CompilerOptions.OPTION_ReportNullSpecViolation, CompilerOptions.ERROR);
runner.customOptions.put(CompilerOptions.OPTION_InheritNullAnnotations, CompilerOptions.ENABLED);
runner.testFiles = new String[] {
"p/Foo.java",
"""
package p;
public interface Foo
{
@org.eclipse.jdt.annotation.NonNullByDefault
record Bar(Object foo) implements
Foo
{
}
@org.eclipse.jdt.annotation.Nullable
Object foo();
}
"""
};
runner.classLibraries = this.LIBS;
runner.expectedCompilerLog = """
----------
1. ERROR in p\\Foo.java (at line 6)
record Bar(Object foo) implements
^^^^^^
The default '@NonNull' conflicts with the inherited '@Nullable' annotation in the overridden method from Foo
----------
""";
runner.runNegativeTest();
}
public void testGH1771_corrected() {
Runner runner = new Runner();
runner.customOptions = getCompilerOptions();
runner.customOptions.put(CompilerOptions.OPTION_ReportNullSpecViolation, CompilerOptions.ERROR);
runner.customOptions.put(CompilerOptions.OPTION_InheritNullAnnotations, CompilerOptions.ENABLED);
runner.testFiles = new String[] {
"p/Foo.java",
"""
package p;
public interface Foo
{
@org.eclipse.jdt.annotation.NonNullByDefault
record Bar(@org.eclipse.jdt.annotation.Nullable Object foo) implements
Foo
{
}
@org.eclipse.jdt.annotation.Nullable
Object foo();
}
"""
};
runner.classLibraries = this.LIBS;
runner.runConformTest();
}
}

0 comments on commit 560a301

Please sign in to comment.