From b57eccf9577c92914c2e174f7a0baae14b57fc4b Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Wed, 19 Jun 2024 10:46:07 -0400 Subject: [PATCH] Fix adding null annotation to qualified type of parameter (#1463) * Fix adding null annotation to qualified type of parameter - fix NullAnnotationsRewriteOperations.ParameterAnnotationRewriteOperation to check for a SimpleType with qualified name or a NameQualifiedType and end up with a NameQualifiedType with the new annotation added - add new tests to NullAnnotationsQuickFixTest - fixes #1462 --- .../quickfix/NullAnnotationsQuickFixTest.java | 184 ++++++++++++++++-- .../fix/NullAnnotationsRewriteOperations.java | 51 +++-- 2 files changed, 202 insertions(+), 33 deletions(-) diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest.java index d633bd6033d..87eaee4d511 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 GK Software AG and others. + * Copyright (c) 2012, 2024 GK Software AG and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -938,9 +938,9 @@ void foo(Exception e1) { String str2= """ package test1; - + import org.eclipse.jdt.annotation.Nullable; - + public class E2 extends E { void foo(@Nullable Exception e1) { e1.printStackTrace(); @@ -988,9 +988,9 @@ void foo(Exception e1) { String str2= """ package test1; - + import org.eclipse.jdt.annotation.NonNull; - + public class E2 extends E { void foo(@NonNull Exception e1) { e1.printStackTrace(); @@ -1105,9 +1105,9 @@ void test(E e, Object in) { String str2= """ package test1; - + import org.eclipse.jdt.annotation.NonNull; - + public class E2 { void test(E e, @NonNull Object in) { e.foo(in); @@ -1245,9 +1245,9 @@ void foo(@org.eclipse.jdt.annotation.NonNull Object o) { String str1= """ package test1; - + import org.eclipse.jdt.annotation.Nullable; - + public class E { void foo(@Nullable Object o) { if (o == null) System.out.print("NOK"); @@ -1460,9 +1460,9 @@ Object foo() { String str2= """ package test1; - + import org.eclipse.jdt.annotation.NonNull; - + public class E2 extends E { @NonNull Object foo() { @@ -1522,9 +1522,9 @@ public Object foo() { String str3= """ package test1; - + import org.eclipse.jdt.annotation.Nullable; - + public class E2 extends E implements IE { public @Nullable Object foo() { return this; @@ -1541,9 +1541,9 @@ public class E2 extends E implements IE { String str4= """ package test1; - + import org.eclipse.jdt.annotation.NonNull; - + public class E2 extends E implements IE { public @NonNull Object foo() { return this; @@ -1675,9 +1675,9 @@ public Object foo(E e) { String str3= """ package test1; - + import org.eclipse.jdt.annotation.Nullable; - + public class E2 { public @Nullable Object foo(E e) { return e.bar(); @@ -1754,9 +1754,9 @@ public Object foo(E e) { String str2= """ package test1; - + import org.eclipse.jdt.annotation.Nullable; - + public class E2 { public @Nullable Object foo(E e) { return e.bar(); @@ -2085,9 +2085,9 @@ public double foo(boolean b) { String str1= """ package test1; - + import org.eclipse.jdt.annotation.NonNull; - + public class E { public double foo(boolean b) { @NonNull @@ -2536,6 +2536,148 @@ public class E2 { } } @Test + public void testBug513423a() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String str= """ + package test1; + import org.eclipse.jdt.annotation.NonNullByDefault; + + @NonNullByDefault + public class E extends RuntimeException { + private static final long serialVersionUID = 1L; + + public void printStackTrace( + // Illegal redefinition of parameter s, inherited method from Throwable + // does not constrain this parameter + java.io.PrintStream s) { + if (s != null) { + synchronized (s) { + s.print(getClass().getName() + ": "); + s.print(getStackTrace()); + } + } + } + } + """; + ICompilationUnit cu= pack1.createCompilationUnit("E.java", str, false, null); + + CompilationUnit astRoot= getASTRoot(cu); + ArrayList proposals= collectCorrections(cu, astRoot, 2); + assertNumberOfProposals(proposals, 2); // ignore 2nd ("add @SW") + + CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0); + + assertEqualString(proposal.getDisplayString(), "Change parameter 's' to '@Nullable'"); + + String preview= getPreviewContent(proposal); + + String str1= """ + package test1; + import org.eclipse.jdt.annotation.NonNullByDefault; + import org.eclipse.jdt.annotation.Nullable; + + @NonNullByDefault + public class E extends RuntimeException { + private static final long serialVersionUID = 1L; + + public void printStackTrace( + // Illegal redefinition of parameter s, inherited method from Throwable + // does not constrain this parameter + java.io.@Nullable PrintStream s) { + if (s != null) { + synchronized (s) { + s.print(getClass().getName() + ": "); + s.print(getStackTrace()); + } + } + } + } + """; + assertEqualString(preview, str1); + + } + @Test + public void testBug513423b() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String str0= """ + package test1; + + import static java.lang.annotation.ElementType.TYPE_USE; + + import java.lang.annotation.Documented; + import java.lang.annotation.ElementType; + import java.lang.annotation.Retention; + import java.lang.annotation.RetentinPolicy; + import java.lang.annotation.Target; + + @Documented + @Retention(RetentionPolicy.CLASS) + @Target({ TYPE_USE }) + public @interface SomeAnnotation { + // marker annotation with no members + } + """; + pack1.createCompilationUnit("SomeAnnotation.java", str0, false, null); + + String str= """ + package test1; + import org.eclipse.jdt.annotation.NonNullByDefault; + + @NonNullByDefault + public class E extends RuntimeException { + private static final long serialVersionUID = 1L; + + public void printStackTrace( + // Illegal redefinition of parameter s, inherited method from Throwable + // does not constrain this parameter + java.io.@SomeAnnotation PrintStream s) { + if (s != null) { + synchronized (s) { + s.print(getClass().getName() + ": "); + s.print(getStackTrace()); + } + } + } + } + """; + ICompilationUnit cu= pack1.createCompilationUnit("E.java", str, false, null); + + CompilationUnit astRoot= getASTRoot(cu); + ArrayList proposals= collectCorrections(cu, astRoot, 2); + assertNumberOfProposals(proposals, 2); // ignore 2nd ("add @SW") + + CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0); + + assertEqualString(proposal.getDisplayString(), "Change parameter 's' to '@Nullable'"); + + String preview= getPreviewContent(proposal); + + String str1= """ + package test1; + import org.eclipse.jdt.annotation.NonNullByDefault; + import org.eclipse.jdt.annotation.Nullable; + + @NonNullByDefault + public class E extends RuntimeException { + private static final long serialVersionUID = 1L; + + public void printStackTrace( + // Illegal redefinition of parameter s, inherited method from Throwable + // does not constrain this parameter + java.io.@SomeAnnotation @Nullable PrintStream s) { + if (s != null) { + synchronized (s) { + s.print(getClass().getName() + ": "); + s.print(getStackTrace()); + } + } + } + } + """; + assertEqualString(preview, str1); + + } + @Test public void testGH1294() throws Exception { IPackageFragment my= fSourceFolder.createPackageFragment("my", false, null); ICompilationUnit cu= my.createCompilationUnit("Test.java", diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java index 6598694bcea..99bac376c72 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2018 GK Software AG and others. + * Copyright (c) 2011, 2024 GK Software AG and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -51,8 +51,11 @@ import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Name; +import org.eclipse.jdt.core.dom.NameQualifiedType; import org.eclipse.jdt.core.dom.PackageDeclaration; +import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; import org.eclipse.jdt.core.dom.Type; @@ -286,19 +289,43 @@ private ParameterAnnotationRewriteOperation(IMethodBinding methodBinding, List