From 16c0844a481a252c86918b9f30d33037fb6e9103 Mon Sep 17 00:00:00 2001 From: "Andrew J. Mauer" Date: Tue, 16 Jan 2024 20:12:55 +0000 Subject: [PATCH] fix issue 134 - add quick fixes for CDI Produces and Disposes diagnostics --- .../plugin.xml | 10 +++- .../codeaction/JakartaCodeActionId.java | 1 + .../jdt/internal/cdi/Constants.java | 10 ++-- .../ManagedBeanDiagnosticsParticipant.java | 19 ++++++-- ...idInitializerParamAnnotationQuickFix.java} | 8 ++-- ...nvalidProducerParamAnnotationQuickFix.java | 46 +++++++++++++++++++ .../RemoveMethodParamAnnotationQuickFix.java | 11 ++++- .../lsp4jakarta/jdt/cdi/ManagedBeanTest.java | 36 +++++++++++++++ 8 files changed, 126 insertions(+), 15 deletions(-) rename jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/{RemoveInvalidInjectParamAnnotationQuickFix.java => RemoveInvalidInitializerParamAnnotationQuickFix.java} (77%) create mode 100644 jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidProducerParamAnnotationQuickFix.java diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml index e4b65a76..0486cffc 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml @@ -297,15 +297,21 @@ class="org.eclipse.lsp4jakarta.jdt.internal.cdi.InsertDefaultPublicConstructorToMBeanQuickFix" /> + class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidInitializerParamAnnotationQuickFix" /> + class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidProducerParamAnnotationQuickFix" /> + + \ No newline at end of file diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/commons/codeaction/JakartaCodeActionId.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/commons/codeaction/JakartaCodeActionId.java index edcf1984..0bac83b9 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/commons/codeaction/JakartaCodeActionId.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/commons/codeaction/JakartaCodeActionId.java @@ -64,6 +64,7 @@ public enum JakartaCodeActionId implements ICodeActionId { CDIInsertProtectedCtrtToClass, CDIInsertPublicCtrtToClass, CDIRemoveInvalidInjectAnnotations, + CDIRemoveInvalidProducesAnnotations, CDIRemoveProducesAnnotation, CDIRemoveInjectAnnotation, CDIRemoveScopeDeclarationAnnotationsButOne, diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/Constants.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/Constants.java index eb8453c6..395fdc9a 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/Constants.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/Constants.java @@ -48,9 +48,13 @@ public class Constants { public static final String DIAGNOSTIC_CODE_REDUNDANT_DISPOSES = "RemoveExtraDisposes"; - public static final Set INVALID_INJECT_PARAMS = new HashSet(Arrays.asList(DISPOSES, OBSERVES, OBSERVES_ASYNC)); - public static final String[] INVALID_INJECT_PARAMS_FQ = { DISPOSES_FQ_NAME, OBSERVES_FQ_NAME, - OBSERVES_ASYNC_FQ_NAME }; + public static final Set INVALID_INITIALIZER_PARAMS = new HashSet(Arrays.asList(DISPOSES, OBSERVES, OBSERVES_ASYNC)); + public static final String[] INVALID_INITIALIZER_PARAMS_FQ = { DISPOSES_FQ_NAME, OBSERVES_FQ_NAME, + OBSERVES_ASYNC_FQ_NAME }; + + public static final Set INVALID_PRODUCER_PARAMS = new HashSet(Arrays.asList(DISPOSES, OBSERVES, OBSERVES_ASYNC)); + public static final String[] INVALID_PRODUCER_PARAMS_FQ = { DISPOSES_FQ_NAME, OBSERVES_FQ_NAME, + OBSERVES_ASYNC_FQ_NAME }; // List can be found in the cdi doc here: // https://jakarta.ee/specifications/cdi/3.0/jakarta-cdi-spec-3.0.html#bean_defining_annotations diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/ManagedBeanDiagnosticsParticipant.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/ManagedBeanDiagnosticsParticipant.java index b38029ef..b9cbf0c0 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/ManagedBeanDiagnosticsParticipant.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/ManagedBeanDiagnosticsParticipant.java @@ -324,7 +324,7 @@ else if (Constants.INJECT_FQ_NAME.equals(annotation)) for (IAnnotation annotation : annotations) { String matchedAnnotation = DiagnosticUtils.getMatchedJavaElementName(type, annotation.getElementName(), - Constants.INVALID_INJECT_PARAMS_FQ); + Constants.INVALID_PRODUCER_PARAMS_FQ); if (Constants.DISPOSES_FQ_NAME.equals(matchedAnnotation)) { numDisposes++; } else if (Constants.OBSERVES_FQ_NAME.equals(matchedAnnotation) @@ -360,6 +360,8 @@ else if (Constants.INJECT_FQ_NAME.equals(annotation)) private void invalidParamsCheck(JavaDiagnosticsContext context, String uri, ICompilationUnit unit, List diagnostics, IType type, String target) throws JavaModelException { + // this method will be called to scan all methods looking for either @Produces annotations OR @Inject annotations. In either + // scenario this method will then check for disallowed parameter annotations and add diagnostics to be displayed if detected. for (IMethod method : type.getMethods()) { IAnnotation targetAnnotation = null; @@ -375,10 +377,19 @@ private void invalidParamsCheck(JavaDiagnosticsContext context, String uri, ICom Set invalidAnnotations = new TreeSet<>(); ILocalVariable[] params = method.getParameters(); + for (ILocalVariable param : params) { - List paramScopes = DiagnosticUtils.getMatchedJavaElementNames(type, - Stream.of(param.getAnnotations()).map(annotation -> annotation.getElementName()).toArray(String[]::new), - Constants.INVALID_INJECT_PARAMS_FQ); + List paramScopes; + // look at the params of any method annotated @Produces - check for invalid parameter annotations + if (Constants.PRODUCES_FQ_NAME.equals(target)) { + paramScopes = DiagnosticUtils.getMatchedJavaElementNames(type, + Stream.of(param.getAnnotations()).map(annotation -> annotation.getElementName()).toArray(String[]::new), + Constants.INVALID_PRODUCER_PARAMS_FQ); + } else { // look at the params of any method annotated @Inject - check for invalid parameter annotations + paramScopes = DiagnosticUtils.getMatchedJavaElementNames(type, + Stream.of(param.getAnnotations()).map(annotation -> annotation.getElementName()).toArray(String[]::new), + Constants.INVALID_INITIALIZER_PARAMS_FQ); + } for (String annotation : paramScopes) { invalidAnnotations.add("@" + DiagnosticUtils.getSimpleName(annotation)); } diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidInjectParamAnnotationQuickFix.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidInitializerParamAnnotationQuickFix.java similarity index 77% rename from jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidInjectParamAnnotationQuickFix.java rename to jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidInitializerParamAnnotationQuickFix.java index 975e948d..730a6455 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidInjectParamAnnotationQuickFix.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidInitializerParamAnnotationQuickFix.java @@ -19,13 +19,13 @@ * Removes the @Disposes, @Observes and @ObservesAsync annotations from * the declaring element. */ -public class RemoveInvalidInjectParamAnnotationQuickFix extends RemoveMethodParamAnnotationQuickFix { +public class RemoveInvalidInitializerParamAnnotationQuickFix extends RemoveMethodParamAnnotationQuickFix { /** * Constructor. */ - public RemoveInvalidInjectParamAnnotationQuickFix() { - super(Constants.INVALID_INJECT_PARAMS.toArray((String[]::new))); + public RemoveInvalidInitializerParamAnnotationQuickFix() { + super(Constants.INVALID_INITIALIZER_PARAMS.toArray((String[]::new))); } /** @@ -33,7 +33,7 @@ public RemoveInvalidInjectParamAnnotationQuickFix() { */ @Override public String getParticipantId() { - return RemoveInvalidInjectParamAnnotationQuickFix.class.getName(); + return RemoveInvalidInitializerParamAnnotationQuickFix.class.getName(); } /** diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidProducerParamAnnotationQuickFix.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidProducerParamAnnotationQuickFix.java new file mode 100644 index 00000000..e127e657 --- /dev/null +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveInvalidProducerParamAnnotationQuickFix.java @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright (c) 2023 IBM Corporation and others. +* +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v. 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0. +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* IBM Corporation - initial implementation +*******************************************************************************/ +package org.eclipse.lsp4jakarta.jdt.internal.cdi; + +import org.eclipse.lsp4jakarta.commons.codeaction.ICodeActionId; +import org.eclipse.lsp4jakarta.commons.codeaction.JakartaCodeActionId; + +/** + * Removes the @Disposes, @Observes and @ObservesAsync annotations from + * the declaring element. + */ +public class RemoveInvalidProducerParamAnnotationQuickFix extends RemoveMethodParamAnnotationQuickFix { + + /** + * Constructor. + */ + public RemoveInvalidProducerParamAnnotationQuickFix() { + super(Constants.INVALID_PRODUCER_PARAMS.toArray((String[]::new))); + } + + /** + * {@inheritDoc} + */ + @Override + public String getParticipantId() { + return RemoveInvalidProducerParamAnnotationQuickFix.class.getName(); + } + + /** + * {@inheritDoc} + */ + @Override + protected ICodeActionId getCodeActionId() { + return JakartaCodeActionId.CDIRemoveInvalidProducesAnnotations; + } +} diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveMethodParamAnnotationQuickFix.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveMethodParamAnnotationQuickFix.java index b1b8cc6d..5e27a695 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveMethodParamAnnotationQuickFix.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/cdi/RemoveMethodParamAnnotationQuickFix.java @@ -96,8 +96,15 @@ public List getCodeActions(JavaCodeActionContext context, } } - createCodeAction(diagnostic, context, codeActions, parameter, - (String[]) annotationsToRemove.toArray(new String[annotationsToRemove.size()])); + // in the case of a method sig: + // public String greetDisposesObservesObservesAsync(@Disposes String name1, String name2, @ObservesAsync String name3) + // parameter name2 will have no annotation to remove - but this is still in need of a QF because params 1 & 3 are in conflict + // when processing param 2 we need to account for the fact that no QF is needed for that particular param, but + // a QF is needed for param 3. Previously the fact that param2 had no annotation to remove caused an ArrayIndexOOB when creating the label (QF string) + if (annotationsToRemove.size() > 0) { + createCodeAction(diagnostic, context, codeActions, parameter, + (String[]) annotationsToRemove.toArray(new String[annotationsToRemove.size()])); + } } return codeActions; diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/cdi/ManagedBeanTest.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/cdi/ManagedBeanTest.java index ce0963b5..7e27d530 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/cdi/ManagedBeanTest.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/cdi/ManagedBeanTest.java @@ -441,6 +441,42 @@ public void producesAndDisposesObservesObservesAsync() throws Exception { assertJavaCodeAction(codeActionParams8, IJDT_UTILS, ca20, ca21); + JakartaJavaCodeActionParams codeActionParams9 = createCodeActionParams(uri, d9); + + TextEdit te22 = te(30, 40, 30, 50, ""); + TextEdit te23 = te(30, 64, 30, 74, ""); + CodeAction ca22 = ca(uri, "Remove the '@Disposes' modifier from parameter 'name1'", d9, te22); + CodeAction ca23 = ca(uri, "Remove the '@Observes' modifier from parameter 'name2'", d9, te23); + + assertJavaCodeAction(codeActionParams9, IJDT_UTILS, ca22, ca23); + + JakartaJavaCodeActionParams codeActionParams10 = createCodeActionParams(uri, d10); + + TextEdit te24 = te(42, 45, 42, 55, ""); + TextEdit te25 = te(42, 69, 42, 84, ""); + CodeAction ca24 = ca(uri, "Remove the '@Disposes' modifier from parameter 'name1'", d10, te24); + CodeAction ca25 = ca(uri, "Remove the '@ObservesAsync' modifier from parameter 'name2'", d10, te25); + + assertJavaCodeAction(codeActionParams10, IJDT_UTILS, ca24, ca25); + + JakartaJavaCodeActionParams codeActionParams11 = createCodeActionParams(uri, d11); + + TextEdit te26 = te(48, 53, 48, 63, ""); + TextEdit te27 = te(48, 77, 48, 87, ""); + TextEdit te28 = te(48, 101, 48, 116, ""); + CodeAction ca26 = ca(uri, "Remove the '@Disposes' modifier from parameter 'name1'", d11, te26); + CodeAction ca27 = ca(uri, "Remove the '@Observes' modifier from parameter 'name2'", d11, te27); + CodeAction ca28 = ca(uri, "Remove the '@ObservesAsync' modifier from parameter 'name3'", d11, te28); + + assertJavaCodeAction(codeActionParams11, IJDT_UTILS, ca26, ca27, ca28); + + JakartaJavaCodeActionParams codeActionParams12 = createCodeActionParams(uri, d12); + + TextEdit te30 = te(54, 54, 54, 89, ""); + CodeAction ca30 = ca(uri, + "Remove the '@Disposes', '@Observes', '@ObservesAsync' modifier from parameter 'name'", d12, te30); + + assertJavaCodeAction(codeActionParams12, IJDT_UTILS, ca30); } @Test