Skip to content

Commit

Permalink
fix issue 134 - add quick fixes for CDI Produces and Disposes diagnos…
Browse files Browse the repository at this point in the history
…tics
  • Loading branch information
ajm01 committed Jan 19, 2024
1 parent ac60a4a commit b8ad90f
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 15 deletions.
10 changes: 8 additions & 2 deletions jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,21 @@
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.InsertDefaultPublicConstructorToMBeanQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-cdi#InvalidInjectAnnotatedMethodParamAnnotation"
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidInjectParamAnnotationQuickFix" />
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidInitOrInjectParamAnnotationQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-cdi#InvalidInjectAnnotatedMethodParamAnnotation"
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInjectAnnotationQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-cdi#InvalidProducerMethodParamAnnotation"
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidInjectParamAnnotationQuickFix" />
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidProducerParamAnnotationQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-cdi#InvalidProducerMethodParamAnnotation"
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveProduceAnnotationQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-cdi#InvalidDisposesAnnotationOnMultipleMethodParams"
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidProducerParamAnnotationQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-cdi#InvalidDisposerMethodParamAnnotation"
class="org.eclipse.lsp4jakarta.jdt.internal.cdi.RemoveInvalidProducerParamAnnotationQuickFix" />
</extension>
</plugin>
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public enum JakartaCodeActionId implements ICodeActionId {
CDIInsertProtectedCtrtToClass,
CDIInsertPublicCtrtToClass,
CDIRemoveInvalidInjectAnnotations,
CDIRemoveInvalidProducesAnnotations,
CDIRemoveProducesAnnotation,
CDIRemoveInjectAnnotation,
CDIRemoveScopeDeclarationAnnotationsButOne,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ public class Constants {

public static final String DIAGNOSTIC_CODE_REDUNDANT_DISPOSES = "RemoveExtraDisposes";

public static final Set<String> INVALID_INJECT_PARAMS = new HashSet<String>(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<String> INVALID_INIT_OR_INJECT_PARAMS = new HashSet<String>(Arrays.asList(DISPOSES, OBSERVES, OBSERVES_ASYNC));
public static final String[] INVALID_INIT_OR_INJECT_PARAMS_FQ = { DISPOSES_FQ_NAME, OBSERVES_FQ_NAME,
OBSERVES_ASYNC_FQ_NAME };

public static final Set<String> INVALID_PRODUCER_PARAMS = new HashSet<String>(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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -360,6 +360,8 @@ else if (Constants.INJECT_FQ_NAME.equals(annotation))

private void invalidParamsCheck(JavaDiagnosticsContext context, String uri, ICompilationUnit unit,
List<Diagnostic> 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;

Expand All @@ -375,10 +377,19 @@ private void invalidParamsCheck(JavaDiagnosticsContext context, String uri, ICom

Set<String> invalidAnnotations = new TreeSet<>();
ILocalVariable[] params = method.getParameters();

for (ILocalVariable param : params) {
List<String> paramScopes = DiagnosticUtils.getMatchedJavaElementNames(type,
Stream.of(param.getAnnotations()).map(annotation -> annotation.getElementName()).toArray(String[]::new),
Constants.INVALID_INJECT_PARAMS_FQ);
List<String> 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_INIT_OR_INJECT_PARAMS_FQ);
}
for (String annotation : paramScopes) {
invalidAnnotations.add("@" + DiagnosticUtils.getSimpleName(annotation));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@
* Removes the @Disposes, @Observes and @ObservesAsync annotations from
* the declaring element.
*/
public class RemoveInvalidInjectParamAnnotationQuickFix extends RemoveMethodParamAnnotationQuickFix {
public class RemoveInvalidInitOrInjectParamAnnotationQuickFix extends RemoveMethodParamAnnotationQuickFix {

/**
* Constructor.
*/
public RemoveInvalidInjectParamAnnotationQuickFix() {
super(Constants.INVALID_INJECT_PARAMS.toArray((String[]::new)));
public RemoveInvalidInitOrInjectParamAnnotationQuickFix() {
super(Constants.INVALID_INIT_OR_INJECT_PARAMS.toArray((String[]::new)));
}

/**
* {@inheritDoc}
*/
@Override
public String getParticipantId() {
return RemoveInvalidInjectParamAnnotationQuickFix.class.getName();
return RemoveInvalidInitOrInjectParamAnnotationQuickFix.class.getName();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,15 @@ public List<? extends CodeAction> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b8ad90f

Please sign in to comment.