From 7c8963c4aaf31a768a2217fbb0bac6a48c6dad61 Mon Sep 17 00:00:00 2001 From: anusreelakshmi934 Date: Sat, 20 Jan 2024 12:21:39 +0530 Subject: [PATCH] Fixes #577 - Refactoring classes Base Class InsertAnnotationMissingQuickFix and child classes PersistenceAnnotationQuickFix, CompleteFilterAnnotationQuickFix, CompleteServletAnnotationQuickFix refactored. Added test classes for CompleteFilterAnnotationQuickFix and CompleteServletAnnotationQuickFix. --- .../InsertAnnotationMissingQuickFix.java | 40 +++-- .../PersistenceAnnotationQuickFix.java | 50 ++++--- .../CompleteFilterAnnotationQuickFix.java | 139 +++++++++++------- .../CompleteServletAnnotationQuickFix.java | 134 ++++++++++------- src/main/resources/META-INF/plugin.xml | 29 ++++ .../jdt/core/messages/messages.properties | 2 +- .../it/servlet/JakartaServletTest.java | 86 +++++++++++ .../servlet/DuplicateAttributeWebFilter.java | 10 ++ .../servlet/DuplicateAttributeWebServlet.java | 10 ++ .../jakarta/servlet/InvalidWebFilter.java | 11 ++ 10 files changed, 369 insertions(+), 142 deletions(-) create mode 100644 src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebFilter.java create mode 100644 src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebServlet.java create mode 100644 src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/InvalidWebFilter.java diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationMissingQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationMissingQuickFix.java index 8b910912e..51cd6d47a 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationMissingQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationMissingQuickFix.java @@ -16,14 +16,19 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.InsertAnnotationProposal; import org.eclipse.lsp4j.CodeAction; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; import java.util.*; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -33,9 +38,8 @@ * @author Angelo ZERR * */ -public class InsertAnnotationMissingQuickFix { +public abstract class InsertAnnotationMissingQuickFix implements IJavaCodeActionParticipant { private static final Logger LOGGER = Logger.getLogger(InsertAnnotationMissingQuickFix.class.getName()); - private static final String ANNOTATION_KEY = "annotation"; private final String[] annotations; @@ -73,6 +77,25 @@ public List getCodeActions(JavaCodeActionContext context, return codeActions; } + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + String name = getLabel(annotations); + PsiElement node = context.getCoveringNode(); + PsiModifierListOwner parentType = getBinding(node); + + ChangeCorrectionProposal proposal = new InsertAnnotationProposal(name, context.getCompilationUnit(), + context.getASTRoot(), parentType, 0, context.getSource().getCompilationUnit(), + annotations); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action", e); + } + return toResolve; + } + protected static PsiModifierListOwner getBinding(PsiElement node) { PsiModifierListOwner binding = PsiTreeUtil.getParentOfType(node, PsiVariable.class); if (binding != null) { @@ -103,17 +126,8 @@ protected void insertAnnotations(Diagnostic diagnostic, JavaCodeActionContext co protected void insertAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, List codeActions, String... annotations) { - String name = getLabel(annotations); - PsiElement node = context.getCoveringNode(); - PsiModifierListOwner parentType = getBinding(node); - - ChangeCorrectionProposal proposal = new InsertAnnotationProposal(name, context.getCompilationUnit(), - context.getASTRoot(), parentType, 0, context.getSource().getCompilationUnit(), - annotations); - CodeAction codeAction = context.convertToCodeAction(proposal, diagnostic); - if (codeAction != null) { - codeActions.add(codeAction); - } + String label = getLabel(annotations); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, label, getParticipantId())); } private static String getLabel(String[] annotations) { diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceAnnotationQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceAnnotationQuickFix.java index 4988250f1..9d3d8b170 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceAnnotationQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceAnnotationQuickFix.java @@ -14,18 +14,22 @@ import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyAnnotationProposal; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.quickfix.InsertAnnotationMissingQuickFix; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Collectors; /** @@ -43,6 +47,7 @@ * * Or only one code action to fix all annotations. */ public class PersistenceAnnotationQuickFix extends InsertAnnotationMissingQuickFix { + private static final Logger LOGGER = Logger.getLogger(PersistenceAnnotationQuickFix.class.getName()); public PersistenceAnnotationQuickFix() { super("jakarta.persistence.MapKeyJoinColumn"); @@ -52,32 +57,38 @@ public PersistenceAnnotationQuickFix() { protected void insertAnnotations(Diagnostic diagnostic, JavaCodeActionContext context, List codeActions) { String[] annotations = getAnnotations(); - insertAndReplaceAnnotation(diagnostic, context, codeActions, annotations); + insertAndReplaceAnnotation(diagnostic, context, codeActions); } - private static void insertAndReplaceAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, - List codeActions, String... annotations) { + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); ArrayList attributes = new ArrayList<>(); attributes.add("name"); attributes.add("referencedColumnName"); String name = Messages.getMessage("AddTheMissingAttributes"); PsiElement node = context.getCoveredNode(); - PsiModifierListOwner binding = getBinding(node); // field or method in this case - List annotationNodes = getAnnotations(binding, annotations); - CodeAction codeAction = null; - + PsiModifierListOwner binding = getBinding(node); + List annotationNodes = getAnnotations(binding, this.getAnnotations()); for (PsiAnnotation annotationNode : annotationNodes) { ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, context.getSource().getCompilationUnit(), - context.getASTRoot(), binding, annotationNode, 0, attributes, annotations); - - // Convert the proposal to LSP4J CodeAction - // We need to fix all the annotations so all the changes are combined in this one context. - // Therefore, we only need to save the last code action. - codeAction = context.convertToCodeAction(proposal, diagnostic); - } - if (codeAction != null) { - codeActions.add(codeAction); + context.getASTRoot(), binding, annotationNode, 0, attributes, this.getAnnotations()); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action.", e); + } } + + return toResolve; + } + + private void insertAndReplaceAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, + List codeActions) { + String name = Messages.getMessage("AddTheMissingAttributes"); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, name, getParticipantId())); + } private static List getAnnotations(PsiElement e, String... names) { @@ -94,4 +105,9 @@ private static List getAnnotations(PsiElement e, String... names) } return result; } + + @Override + public String getParticipantId() { + return PersistenceAnnotationQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteFilterAnnotationQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteFilterAnnotationQuickFix.java index ce977d316..0f79bbd09 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteFilterAnnotationQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteFilterAnnotationQuickFix.java @@ -18,16 +18,24 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifierListOwner; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyAnnotationProposal; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.quickfix.InsertAnnotationMissingQuickFix; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; /** * QuickFix for fixing {@link ServletConstants#DIAGNOSTIC_CODE_FILTER_MISSING_ATTRIBUTE} error @@ -52,6 +60,10 @@ * */ public class CompleteFilterAnnotationQuickFix extends InsertAnnotationMissingQuickFix { + private static final Logger LOGGER = Logger.getLogger(CompleteServletAnnotationQuickFix.class.getName()); + private static final String DIAGNOSTIC_CODE_KEY = "diagnosticCode"; + private static final String ATTRIBUTE_KEY = "attribute"; + private static final String ANNOTATION_KEY = "annotation"; public CompleteFilterAnnotationQuickFix() { super("jakarta.servlet.annotation.WebFilter"); @@ -66,66 +78,82 @@ protected void insertAnnotations(Diagnostic diagnostic, JavaCodeActionContext co } } - private static void insertAndReplaceAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, - List codeActions, String annotation) { - - // Insert the annotation and the proper import by using JDT Core Manipulation - // API - - - // if missing an attribute, do value insertion + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); PsiElement node = null; PsiModifierListOwner parentType = null; PsiAnnotation annotationNode = null; - if (diagnostic.getCode().getLeft().equals(ServletConstants.DIAGNOSTIC_CODE_FILTER_MISSING_ATTRIBUTE)) { - ArrayList attributes = new ArrayList<>(); - attributes.add("value"); attributes.add("urlPatterns");attributes.add("servletNames"); - // Code Action 1: add value attribute to the WebServlet annotation - // Code Action 2: add urlPatterns attribute to the WebServlet annotation - for (int i = 0; i < attributes.size(); i++) { - String attribute = attributes.get(i); - JavaCodeActionContext targetContext = context.copy(); - node = targetContext.getCoveringNode(); - parentType = getBinding(node); - annotationNode = getAnnotation(node); - - ArrayList attributesToAdd = new ArrayList<>(); - attributesToAdd.add(attribute); + CodeActionResolveData data = (CodeActionResolveData) toResolve.getData(); + String diagnosticCode = (String) data.getExtendedDataEntry(DIAGNOSTIC_CODE_KEY); + String attribute = (String) data.getExtendedDataEntry(ATTRIBUTE_KEY); + String annotation = (String) data.getExtendedDataEntry(ANNOTATION_KEY); + + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_FILTER_MISSING_ATTRIBUTE)) { + node = context.getCoveringNode(); + parentType = getBinding(node); + annotationNode = getAnnotation(node); + + ArrayList attributesToAdd = new ArrayList<>(); + attributesToAdd.add(attribute); + String name = getLabel(annotation, attribute, "Add"); + ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, context.getSource().getCompilationUnit(), + context.getASTRoot(), parentType, annotationNode, 0, annotation, attributesToAdd); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action.", e); + } + } + + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_FILTER_DUPLICATE_ATTRIBUTES)) { + node = context.getCoveringNode(); + parentType = getBinding(node); + annotationNode = getAnnotation(node); + + ArrayList attributesToRemove = new ArrayList<>(); + attributesToRemove.add(attribute); + String name = getLabel(annotation, attribute, "Remove"); + ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, context.getSource().getCompilationUnit(), + context.getASTRoot(), parentType, annotationNode, 0, annotation, new ArrayList(), attributesToRemove); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action.", e); + } + } + return toResolve; + } + + private void insertAndReplaceAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, + List codeActions, String annotation) { + + ArrayList attributes = new ArrayList<>(); + attributes.add("value"); + attributes.add("urlPatterns"); + attributes.add("servletNames"); + + String diagnosticCode = diagnostic.getCode().getLeft(); + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_FILTER_MISSING_ATTRIBUTE)) { + for (String attribute : attributes) { String name = getLabel(annotation, attribute, "Add"); - ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, targetContext.getSource().getCompilationUnit(), - targetContext.getASTRoot(), parentType, annotationNode, 0, annotation, attributesToAdd); - // Convert the proposal to LSP4J CodeAction - CodeAction codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - codeAction.setTitle(name); - if (codeAction != null) { - codeActions.add(codeAction); - } + Map extendedData = new HashMap<>(); + extendedData.put(DIAGNOSTIC_CODE_KEY, diagnosticCode); + extendedData.put(ATTRIBUTE_KEY, attribute); + extendedData.put(ANNOTATION_KEY, annotation); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, name, getParticipantId(), extendedData)); } } - // if duplicate attributes exist in annotations, remove attributes from annotation - if (diagnostic.getCode().getLeft().equals(ServletConstants.DIAGNOSTIC_CODE_FILTER_DUPLICATE_ATTRIBUTES)) { - ArrayList attributes = new ArrayList<>(); - attributes.add("value"); attributes.add("urlPatterns"); - // Code Action 1: remove value attribute from the WebServlet annotation - // Code Action 2: remove urlPatterns attribute from the WebServlet annotation - for (int i = 0; i < attributes.size(); i++) { - String attribute = attributes.get(i); - JavaCodeActionContext targetContext = context.copy(); - node = targetContext.getCoveringNode(); - parentType = getBinding(node); - annotationNode = getAnnotation(node); - - ArrayList attributesToRemove = new ArrayList<>(); - attributesToRemove.add(attribute); + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_FILTER_DUPLICATE_ATTRIBUTES)) { + for (String attribute : attributes) { String name = getLabel(annotation, attribute, "Remove"); - ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, targetContext.getSource().getCompilationUnit(), - targetContext.getASTRoot(), parentType, annotationNode, 0, annotation, new ArrayList(), attributesToRemove); - // Convert the proposal to LSP4J CodeAction - CodeAction codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - codeAction.setTitle(name); - if (codeAction != null) { - codeActions.add(codeAction); - } + Map extendedData = new HashMap<>(); + extendedData.put(DIAGNOSTIC_CODE_KEY, diagnosticCode); + extendedData.put(ATTRIBUTE_KEY, attribute); + extendedData.put(ANNOTATION_KEY, annotation); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, name, getParticipantId(), extendedData)); } } } @@ -134,9 +162,10 @@ private static String getLabel(String annotation, String attribute, String label String annotationName = annotation.substring(annotation.lastIndexOf('.') + 1, annotation.length()); annotationName = "@" + annotationName; if (labelType.equals("Remove")) { - return Messages.getMessage("RemoveTheAttriubuteFrom", attribute, annotationName); + return Messages.getMessage("RemoveTheAttributeFrom", attribute, annotationName); } - return Messages.getMessage("AddTheAttributeTo", attribute, annotationName); } + return Messages.getMessage("AddTheAttributeTo", attribute, annotationName); + } private static PsiAnnotation getAnnotation(PsiElement e) { if (e instanceof PsiAnnotation) { diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteServletAnnotationQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteServletAnnotationQuickFix.java index c8bdc651c..ff8e8f8b3 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteServletAnnotationQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/CompleteServletAnnotationQuickFix.java @@ -15,20 +15,27 @@ package io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.servlet; import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifierListOwner; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyAnnotationProposal; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.quickfix.InsertAnnotationMissingQuickFix; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; /** * QuickFix for fixing @@ -52,6 +59,10 @@ * */ public class CompleteServletAnnotationQuickFix extends InsertAnnotationMissingQuickFix { + private static final Logger LOGGER = Logger.getLogger(CompleteServletAnnotationQuickFix.class.getName()); + private static final String DIAGNOSTIC_CODE_KEY = "diagnosticCode"; + private static final String ATTRIBUTE_KEY = "attribute"; + private static final String ANNOTATION_KEY = "annotation"; public CompleteServletAnnotationQuickFix() { super("jakarta.servlet.annotation.WebServlet"); @@ -66,69 +77,80 @@ protected void insertAnnotations(Diagnostic diagnostic, JavaCodeActionContext co } } - private static void insertAndReplaceAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, - List codeActions, String annotation) { - - // Insert the annotation and the proper import by using JDT Core Manipulation - // API - - // if missing an attribute, do value insertion + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); PsiElement node = null; PsiModifierListOwner parentType = null; PsiAnnotation annotationNode = null; + CodeActionResolveData data = (CodeActionResolveData) toResolve.getData(); + String diagnosticCode = (String) data.getExtendedDataEntry(DIAGNOSTIC_CODE_KEY); + String attribute = (String) data.getExtendedDataEntry(ATTRIBUTE_KEY); + String annotation = (String) data.getExtendedDataEntry(ANNOTATION_KEY); - if (diagnostic.getCode().getLeft().equals(ServletConstants.DIAGNOSTIC_CODE_MISSING_ATTRIBUTE)) { - ArrayList attributes = new ArrayList<>(); - attributes.add("value"); - attributes.add("urlPatterns"); - // Code Action 1: add value attribute to the WebServlet annotation - // Code Action 2: add urlPatterns attribute to the WebServlet annotation - for (int i = 0; i < attributes.size(); i++) { - String attribute = attributes.get(i); - JavaCodeActionContext targetContext = context.copy(); - node = targetContext.getCoveringNode(); - parentType = getBinding(node); - annotationNode = getAnnotation(node); + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_MISSING_ATTRIBUTE)) { + node = context.getCoveringNode(); + parentType = getBinding(node); + annotationNode = getAnnotation(node); - ArrayList attributesToAdd = new ArrayList<>(); - attributesToAdd.add(attribute); - String name = getLabel(annotation, attribute, "Add"); - ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, targetContext.getSource().getCompilationUnit(), - targetContext.getASTRoot(), parentType, annotationNode, 0, annotation, attributesToAdd); - // Convert the proposal to LSP4J CodeAction - CodeAction codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - codeAction.setTitle(name); - if (codeAction != null) { - codeActions.add(codeAction); - } + ArrayList attributesToAdd = new ArrayList<>(); + attributesToAdd.add(attribute); + String name = getLabel(annotation, attribute, "Add"); + ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, context.getSource().getCompilationUnit(), + context.getASTRoot(), parentType, annotationNode, 0, annotation, attributesToAdd); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action.", e); + } + } + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_DUPLICATE_ATTRIBUTES)) { + node = context.getCoveringNode(); + parentType = getBinding(node); + annotationNode = getAnnotation(node); + + ArrayList attributesToRemove = new ArrayList<>(); + attributesToRemove.add(attribute); + String name = getLabel(annotation, attribute, "Remove"); + ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, context.getSource().getCompilationUnit(), + context.getASTRoot(), parentType, annotationNode, 0, annotation, new ArrayList(), attributesToRemove); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action.", e); } } - // if duplicate attributes exist in annotations, remove attributes from - // annotation - if (diagnostic.getCode().getLeft().equals(ServletConstants.DIAGNOSTIC_CODE_DUPLICATE_ATTRIBUTES)) { - ArrayList attributes = new ArrayList<>(); - attributes.add("value"); - attributes.add("urlPatterns"); - // Code Action 1: remove value attribute from the WebServlet annotation - // Code Action 2: remove urlPatterns attribute from the WebServlet annotation - for (int i = 0; i < attributes.size(); i++) { - String attribute = attributes.get(i); - JavaCodeActionContext targetContext = context.copy(); - node = targetContext.getCoveringNode(); - parentType = getBinding(node); - annotationNode = getAnnotation(node); - ArrayList attributesToRemove = new ArrayList<>(); - attributesToRemove.add(attribute); + return toResolve; + } + + private void insertAndReplaceAnnotation(Diagnostic diagnostic, JavaCodeActionContext context, + List codeActions, String annotation) { + ArrayList attributes = new ArrayList<>(); + attributes.add("value"); + attributes.add("urlPatterns"); + + String diagnosticCode = diagnostic.getCode().getLeft(); + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_MISSING_ATTRIBUTE)) { + for (String attribute : attributes) { + String name = getLabel(annotation, attribute, "Add"); + Map extendedData = new HashMap<>(); + extendedData.put(DIAGNOSTIC_CODE_KEY, diagnosticCode); + extendedData.put(ATTRIBUTE_KEY, attribute); + extendedData.put(ANNOTATION_KEY, annotation); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, name, getParticipantId(), extendedData)); + } + } + if (diagnosticCode.equals(ServletConstants.DIAGNOSTIC_CODE_DUPLICATE_ATTRIBUTES)) { + for (String attribute : attributes) { String name = getLabel(annotation, attribute, "Remove"); - ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(name, targetContext.getSource().getCompilationUnit(), - targetContext.getASTRoot(), parentType, annotationNode, 0, annotation, new ArrayList(), attributesToRemove); - // Convert the proposal to LSP4J CodeAction - CodeAction codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - codeAction.setTitle(name); - if (codeAction != null) { - codeActions.add(codeAction); - } + Map extendedData = new HashMap<>(); + extendedData.put(DIAGNOSTIC_CODE_KEY, diagnosticCode); + extendedData.put(ATTRIBUTE_KEY, attribute); + extendedData.put(ANNOTATION_KEY, annotation); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, name, getParticipantId(), extendedData)); } } } @@ -137,7 +159,7 @@ private static String getLabel(String annotation, String attribute, String label String annotationName = annotation.substring(annotation.lastIndexOf('.') + 1, annotation.length()); annotationName = "@" + annotationName; if (labelType.equals("Remove")) { - return Messages.getMessage("RemoveTheAttriubuteFrom", attribute, annotationName); + return Messages.getMessage("RemoveTheAttributeFrom", attribute, annotationName); } return Messages.getMessage("AddTheAttributeTo", attribute, annotationName); } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 9600d9365..77d0818ca 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -261,6 +261,35 @@ targetDiagnostic="jakarta-cdi#InvalidManagedBeanConstructor" implementationClass="io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.cdi.ManagedBeanNoArgConstructorQuickFix"/> + + + + + + + + diff --git a/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties b/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties index e8a9d72e1..7e99a1a4f 100644 --- a/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties +++ b/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties @@ -148,7 +148,7 @@ MultipleMapKeyJoinColumnField = A field with multiple @MapKeyJoinColumn annotati # CompleteFilterAnnotationQuickFix AddTheAttributeTo = Add the `{0}` attribute to {1} -RemoveTheAttriubuteFrom = Remove the `{0}` attribute from {1} +RemoveTheAttributeFrom = Remove the `{0}` attribute from {1} # FilterDiagnosticsCollector WebFilterMustImplement = Annotated classes with @WebFilter must implement the Filter interface. diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java index 9a2e1989a..2de908b23 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java @@ -101,4 +101,90 @@ public void CompleteWebServletAnnotation() throws Exception { } } + @Test + public void RemoveDuplicateAttribute() throws Exception { + Module module = createMavenModule(new File("src/test/resources/projects/maven/jakarta-sample")); + IPsiUtils utils = PsiUtilsLSImpl.getInstance(myProject); + + VirtualFile javaFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(ModuleUtilCore.getModuleDirPath(module) + + "/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebServlet.java"); + String uri = VfsUtilCore.virtualToIoFile(javaFile).toURI().toString(); + + JakartaDiagnosticsParams diagnosticsParams = new JakartaDiagnosticsParams(); + diagnosticsParams.setUris(Arrays.asList(uri)); + + Diagnostic d = JakartaForJavaAssert.d(9, 0, 13, + "The @WebServlet annotation cannot have both 'value' and 'urlPatterns' attributes specified at once.", + DiagnosticSeverity.Error, "jakarta-servlet", "InvalidHttpServletAttribute"); + + JakartaForJavaAssert.assertJavaDiagnostics(diagnosticsParams, utils, d); + + if (CHECK_CODE_ACTIONS) { + JakartaJavaCodeActionParams codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d); + TextEdit te1 = JakartaForJavaAssert.te(9, 0, 10, 0, ""); + CodeAction ca1 = JakartaForJavaAssert.ca(uri, "Remove the `value` attribute from @WebServlet", d, te1); + + TextEdit te2 = JakartaForJavaAssert.te(9, 0, 10, 0, ""); + CodeAction ca2 = JakartaForJavaAssert.ca(uri, "Remove the `urlPatterns` attribute from @WebServlet", d, te2); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1, ca2); + } + } + + @Test + public void CompleteWebFilterAnnotation() throws Exception { + Module module = createMavenModule(new File("src/test/resources/projects/maven/jakarta-sample")); + IPsiUtils utils = PsiUtilsLSImpl.getInstance(myProject); + + VirtualFile javaFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(ModuleUtilCore.getModuleDirPath(module) + + "/src/main/java/io/openliberty/sample/jakarta/servlet/InvalidWebFilter.java"); + String uri = VfsUtilCore.virtualToIoFile(javaFile).toURI().toString(); + + JakartaDiagnosticsParams diagnosticsParams = new JakartaDiagnosticsParams(); + diagnosticsParams.setUris(Arrays.asList(uri)); + + Diagnostic d = JakartaForJavaAssert.d(9, 0, 13, + "The annotation @WebFilter must define the attribute 'urlPatterns', 'servletNames' or 'value'.", + DiagnosticSeverity.Error, "jakarta-servlet", "CompleteWebFilterAttributes"); + + JakartaForJavaAssert.assertJavaDiagnostics(diagnosticsParams, utils, d); + + if (CHECK_CODE_ACTIONS) { + JakartaJavaCodeActionParams codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d); + TextEdit te1 = JakartaForJavaAssert.te(9, 0, 10, 0, "@WebFilter(value = \"\")\n"); + CodeAction ca1 = JakartaForJavaAssert.ca(uri, "Add the `value` attribute to @WebFilter", d, te1); + + TextEdit te2 = JakartaForJavaAssert.te(9, 0, 10, 0, "@WebFilter(urlPatterns = \"\")\n"); + CodeAction ca2 = JakartaForJavaAssert.ca(uri, "Add the `urlPatterns` attribute to @WebFilter", d, te2); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1, ca2); + } + } + + @Test + public void RemoveDuplicateAttributes() throws Exception { + Module module = createMavenModule(new File("src/test/resources/projects/maven/jakarta-sample")); + IPsiUtils utils = PsiUtilsLSImpl.getInstance(myProject); + + VirtualFile javaFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(ModuleUtilCore.getModuleDirPath(module) + + "/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebFilter.java"); + String uri = VfsUtilCore.virtualToIoFile(javaFile).toURI().toString(); + + JakartaDiagnosticsParams diagnosticsParams = new JakartaDiagnosticsParams(); + diagnosticsParams.setUris(Arrays.asList(uri)); + + Diagnostic d = JakartaForJavaAssert.d(9, 0, 13, + "The annotation @WebFilter can not have both 'value' and 'urlPatterns' attributes specified at once.", + DiagnosticSeverity.Error, "jakarta-servlet", "InvalidWebFilterAttribute"); + + JakartaForJavaAssert.assertJavaDiagnostics(diagnosticsParams, utils, d); + + if (CHECK_CODE_ACTIONS) { + JakartaJavaCodeActionParams codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d); + TextEdit te1 = JakartaForJavaAssert.te(9, 0, 10, 0, ""); + CodeAction ca1 = JakartaForJavaAssert.ca(uri, "Remove the `value` attribute from @WebFilter", d, te1); + + TextEdit te2 = JakartaForJavaAssert.te(9, 0, 10, 0, ""); + CodeAction ca2 = JakartaForJavaAssert.ca(uri, "Remove the `urlPatterns` attribute from @WebFilter", d, te2); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1, ca2); + } + } } diff --git a/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebFilter.java b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebFilter.java new file mode 100644 index 000000000..184d404c7 --- /dev/null +++ b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebFilter.java @@ -0,0 +1,10 @@ +package io.openliberty.sample.jakarta.servlet; + +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.Filter; + +@WebFilter(urlPatterns = "", value = "") +public abstract class DuplicateAttributeWebFilter implements Filter { + +} + diff --git a/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebServlet.java b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebServlet.java new file mode 100644 index 000000000..3614d0a1e --- /dev/null +++ b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/DuplicateAttributeWebServlet.java @@ -0,0 +1,10 @@ +package io.openliberty.sample.jakarta.servlet; + +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; + +@WebServlet(urlPatterns = "", value = "") +public class DuplicateAttributeWebServlet extends HttpServlet { + +} + diff --git a/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/InvalidWebFilter.java b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/InvalidWebFilter.java new file mode 100644 index 000000000..1cdc89842 --- /dev/null +++ b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/servlet/InvalidWebFilter.java @@ -0,0 +1,11 @@ +package io.openliberty.sample.jakarta.servlet; + +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; + +@WebFilter() +public abstract class InvalidWebFilter implements Filter { + +} + +