From f78f8f3709a05491837a344b83356872472b911a Mon Sep 17 00:00:00 2001 From: "Andrew J. Mauer" Date: Tue, 13 Feb 2024 23:55:11 +0000 Subject: [PATCH] address review comments --- .../plugin.xml | 5 +- .../codeaction/JakartaCodeActionId.java | 1 + .../proposal/ModifyAnnotationProposal.java | 153 ++++++++++++------ .../AnnotationDiagnosticsParticipant.java | 16 +- .../jdt/internal/annotations/ErrorCode.java | 1 + ...sourceAnnotationToResourcesAnnotation.java | 46 ++++++ .../jdt/core/messages/messages.properties | 1 + .../jakarta/annotations/MyException.java | 15 ++ .../jakarta/annotations/MyException.java | 13 ++ .../annotations/ResourceAnnotation.java | 5 +- .../annotations/ResourcesAnnotation.java | 16 ++ .../annotations/ResourceAnnotationTest.java | 37 ++--- .../annotations/ResourcesAnnotationTest.java | 78 +++++++++ jakarta.jdt/pom.xml | 2 +- 14 files changed, 310 insertions(+), 79 deletions(-) create mode 100644 jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/InsertDefaultResourceAnnotationToResourcesAnnotation.java create mode 100644 jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/demo-servlet-no-diagnostics/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java create mode 100644 jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java create mode 100644 jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourcesAnnotation.java create mode 100644 jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourcesAnnotationTest.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..750353b6 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml @@ -58,6 +58,9 @@ + @@ -84,7 +87,7 @@ class="org.eclipse.lsp4jakarta.jdt.internal.annotations.RemovePreDestroyAnnotationQuickFix" /> + class="org.eclipse.lsp4jakarta.jdt.internal.annotations.RemoveAllMethodParametersQuickFix" /> 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..b6b05b70 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 @@ -28,6 +28,7 @@ public enum JakartaCodeActionId implements ICodeActionId { ChangeReturnTypeToVoid, InsertResourceAnnotationTypeAttribute, InsertResourceAnnotationNameAttribute, + InsertDefaultResourceAnnotationToResourcesAnnotation, RemoveAllParameters, RemoveAnnotationPreDestroy, RemoveAnnotationPostConstruct, diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/core/java/corrections/proposal/ModifyAnnotationProposal.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/core/java/corrections/proposal/ModifyAnnotationProposal.java index a55d5b57..2ca8ae07 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/core/java/corrections/proposal/ModifyAnnotationProposal.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/core/java/corrections/proposal/ModifyAnnotationProposal.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 IBM Corporation and others. + * Copyright (c) 2021, 2022, 2024 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 @@ -198,7 +198,7 @@ protected ASTRewrite getRewrite() throws CoreException { if (!existingAnnotations.isEmpty()) { for (Annotation a : existingAnnotations) { if (a instanceof SingleMemberAnnotation) { - // this type of annotation contains a single valuie which may be a list of other annotations, + // this type of annotation contains a single value which may be a list of other annotations, // some of which need to be fixed newAnnotationToWrite = processSingleMemberAnnotation(ast, imports, importRewriteContext, annotations, (SingleMemberAnnotation) a); } else if (a instanceof NormalAnnotation) { @@ -242,27 +242,60 @@ private SingleMemberAnnotation processSingleMemberAnnotation(AST ast, ImportRewr // This method will process the annotations in the list, one by one, for quick // fix actions on any applicable sub annotations + // Create a new SingleMemebrAnnotation Object that will be used to store the + // updates + // and used ny the TextEdit to write them to the file SingleMemberAnnotation newSingleMemberAnnotation = ast.newSingleMemberAnnotation(); + + // Internally the SingleMemberAnnotation maintains an ArrayInitilaizer which + // wraps a List + // of NormalAnnotations - create a new empty ArrayInitializer within the new + // SingleMemberAnnotation ArrayInitializer newAIInstance = (ArrayInitializer) ast.createInstance(ArrayInitializer.class); newSingleMemberAnnotation.setTypeName( ast.newName(imports.addImport(annotationToProcess.getTypeName().toString(), importRWCtx))); + + // Get the empty new List of NormalAnnotations from the new + // SingleMemberAnnotation object. This List will hold processed NormalAnnotations from the + // original SingleMemberAnnotation object passed into this method above. List newCompositeAnnotationContents = newAIInstance.expressions(); - // An ArrayInitializer is the object that holds the list of sub annotations within the SingleMemberAnnotation + // An ArrayInitializer 'ai' is the object that holds the list of sub annotations + // within the original SingleMemberAnnotation ArrayInitializer ai = (ArrayInitializer) ((SingleMemberAnnotation) annotationToProcess).getValue(); - // get the list of annotations to process + // get the List of existing NormalAnnotations to process - the 'expressions()' method + // returns List List normalAnnotations = ai.expressions(); - // for each annotation in the list, process it for the quick fix edit - for (NormalAnnotation na : normalAnnotations) { - NormalAnnotation newNormalAnnotation = processNormalAnnotation(ast, imports, importRWCtx, annotations, - na); - newCompositeAnnotationContents.add(newNormalAnnotation); + if (normalAnnotations.isEmpty()) { + // We are fixing an invalid annotation of the form: + // @Resources ({}) - + // add a single default sub-annotation + NormalAnnotation newChildDefaultAnnotation = processNormalAnnotation(ast, imports, importRWCtx, annotations, + null); + newCompositeAnnotationContents.add(newChildDefaultAnnotation); + } else { + + // for each original annotation in the list, process it for the quick fix edit + for (NormalAnnotation na : normalAnnotations) { + // processNormalAnnotation will create a new NormalAnnotation containing the + // results of the quick fix + NormalAnnotation newNormalAnnotation = processNormalAnnotation(ast, imports, importRWCtx, annotations, + na); + // add this new updated NormalAnnotation directly to the new List of + // NormalAnnotations + newCompositeAnnotationContents.add(newNormalAnnotation); + } } - // now add the processed annotations to the new SingleMemberAnnotation to be written into the file + // now add all of the processed annotations to the new SingleMemberAnnotation to + // be written into the file + // The ArrayInitializer newAIInstance contains the Lst of NormalAnnotations via + // the + // newCompositeAnnotationContents.add(newNormalAnnotation); call in + // the previous for loop newSingleMemberAnnotation.setValue(newAIInstance); return newSingleMemberAnnotation; @@ -271,54 +304,84 @@ private SingleMemberAnnotation processSingleMemberAnnotation(AST ast, ImportRewr private NormalAnnotation processNormalAnnotation(AST ast, ImportRewrite imports, ImportRewriteContext importRWCtx, String[] annotations, NormalAnnotation annotationToProcess) { + // A NormalAnnotation is an annotation that contains within it a name value pair + // IE: + // + // @Resource(name = "aaa", type = Object.class) + // + // 'name = "aaa"' is a MemberValuePair of the NormalAnnotation as is 'type = Object.class' + // + // This method will process this annotation in the list for quick + // fix actions on any applicable NormalAnnotation that is passed into this method NormalAnnotation newNormalAnnotation = ast.newNormalAnnotation(); - // for every annotation we are fixing + // for every annotation type we are fixing for (String annotation : annotations) { - // create a new NormalAnnotation to be written + // create a new NormalAnnotation to be written back to the file newNormalAnnotation.setTypeName(ast.newName(imports.addImport(annotation, importRWCtx))); List values = newNormalAnnotation.values(); - // get the existing name/value pairs - List existingValues = ((NormalAnnotation) annotationToProcess).values(); - for (MemberValuePair mvp : existingValues) { - boolean containsAttributeToAdd = this.attributesToAdd.contains(mvp.getName().getFullyQualifiedName()); - boolean containsAllToAdd = this.attributesToAdd.stream().allMatch(attr -> existingValues.stream().anyMatch(v -> v.equals(attr))); - boolean removeAttribute = this.attributesToRemove.contains(mvp.getName().getFullyQualifiedName()); - - if (!containsAttributeToAdd || !containsAllToAdd) { - - // do not add attribute to be removed - if (!removeAttribute) { - // copy the existing values into the new Annotation - MemberValuePair existingMemberValuePair = ast.newMemberValuePair(); - existingMemberValuePair.setName(ast.newSimpleName(mvp.getName().getFullyQualifiedName())); - - if (mvp.getValue() instanceof StringLiteral) { - existingMemberValuePair.setValue((StringLiteral) mvp.getValue().copySubtree(ast, mvp.getValue())); - } else if (mvp.getValue() instanceof TypeLiteral) { - existingMemberValuePair.setValue((TypeLiteral) mvp.getValue().copySubtree(ast, mvp.getValue())); - + if (annotationToProcess == null) { + // We are adding a new required default @Resource annotation to an empty + // @Resources annotation. + addNewAttributes(ast, values); + } else { + // get the existing name/value pairs from the existing NormalAnnotation that was + // passed into this method above + List existingValues = ((NormalAnnotation) annotationToProcess).values(); + for (MemberValuePair mvp : existingValues) { + // does the current existing mvp contain the attribute that needs to be added by + // this quickfix? + boolean containsAttributeToAdd = this.attributesToAdd.contains(mvp.getName().getFullyQualifiedName()); + // does the current existing mvp contain all the attributes that need to be + // added by this quickfix? + boolean containsAllToAdd = this.attributesToAdd.stream().allMatch(attr -> existingValues.stream().anyMatch(v -> v.equals(attr))); + // does the current existing mvp contain an attribute that is due to be removed + // by this quickfix? + boolean removeAttribute = this.attributesToRemove.contains(mvp.getName().getFullyQualifiedName()); + + if (!containsAttributeToAdd || !containsAllToAdd) { + // the existing NormalAnnotation currently being processed does not contain the + // attribute to be added by this quickfix + // so the quickfix should be applied to it. + // But the current existing MVP entry within the NormalAnnotation is valid and + // should continue to exist. + // Copy over any existing valid mvp pairs into a new MVP that will be written + // back to the file as part of this quickfix action + + // (but) do not add an existing mvp that is to be removed by this quick fix + if (!removeAttribute) { + // create a new MVP to hold the existing mvp + MemberValuePair newMemberValuePair = ast.newMemberValuePair(); + // copy the existing name portion of the MVP into the new MVP + newMemberValuePair.setName(ast.newSimpleName(mvp.getName().getFullyQualifiedName())); + + // copy the existing value into the new MVP, depending on what type it is + if (mvp.getValue() instanceof StringLiteral) { + newMemberValuePair.setValue((StringLiteral) mvp.getValue().copySubtree(ast, mvp.getValue())); + } else if (mvp.getValue() instanceof TypeLiteral) { + newMemberValuePair.setValue((TypeLiteral) mvp.getValue().copySubtree(ast, mvp.getValue())); + + } + + // add this new MVP into the new NormalAnnotation + values.add(newMemberValuePair); } - - values.add(existingMemberValuePair); + } else { + // the current NormalAnnotation being processed already contains the attribute + // to be added by this quick fix action + // and so is not the one to have the quickfix applied to it + // return an as-is copy of the existing annotation + newNormalAnnotation = (NormalAnnotation) annotationToProcess.copySubtree(ast, annotationToProcess); + return newNormalAnnotation; } - // add new String attributes - //values = addNewAttributes(ast, values); - } else { - // the current member annotation already contains the attribute and so is not - // the one to have the quickfix applied to it - // return an as-is copy of the exsiting (and removed) annotation. - newNormalAnnotation = (NormalAnnotation) annotationToProcess.copySubtree(ast, annotationToProcess); - return newNormalAnnotation; } + // now add the attribute for this quickfix action to the new NormalAnnotation + values = addNewAttributes(ast, values); } - - // add new String attributes - values = addNewAttributes(ast, values); } return newNormalAnnotation; } diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/AnnotationDiagnosticsParticipant.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/AnnotationDiagnosticsParticipant.java index d994d410..def640d4 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/AnnotationDiagnosticsParticipant.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/AnnotationDiagnosticsParticipant.java @@ -184,6 +184,17 @@ public List collectDiagnostics(JavaDiagnosticsContext context, IProg if (element instanceof IType) { for (IMemberValuePair internalAnnotation : annotation.getMemberValuePairs()) { Object[] valuePairs = (Object[]) internalAnnotation.getValue(); + String diagnosticMessage; + Range annotationRange = null; + if (valuePairs.length == 0) { + annotationRange = PositionUtils.toNameRange(annotation, context.getUtils()); + diagnosticMessage = Messages.getMessage("ResourcesAnnotationMustDefineResourceAnnotation", + "@Resources", "@Resource"); + diagnostics.add(context.createDiagnostic(uri, diagnosticMessage, annotationRange, + Constants.DIAGNOSTIC_SOURCE, + ErrorCode.MissingResourceAnnotation, + DiagnosticSeverity.Error)); + } int objKind = internalAnnotation.getValueKind(); for (Object childAnnotationObj : valuePairs) { if (objKind == IMemberValuePair.K_ANNOTATION) { @@ -194,8 +205,8 @@ public List collectDiagnostics(JavaDiagnosticsContext context, IProg IType type = (IType) element; if (type.getElementType() == IJavaElement.TYPE && ((IType) type).isClass()) { - Range annotationRange = PositionUtils.toNameRange(childAnnotation, - context.getUtils()); + annotationRange = PositionUtils.toNameRange(childAnnotation, + context.getUtils()); Boolean nameEmpty = true; Boolean typeEmpty = true; for (IMemberValuePair pair : childAnnotation.getMemberValuePairs()) { @@ -206,7 +217,6 @@ public List collectDiagnostics(JavaDiagnosticsContext context, IProg typeEmpty = false; } } - String diagnosticMessage; if (nameEmpty) { diagnosticMessage = Messages.getMessage( "AnnotationMustDefineAttribute", diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/ErrorCode.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/ErrorCode.java index 9c8406b7..1ff5822c 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/ErrorCode.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/ErrorCode.java @@ -19,6 +19,7 @@ */ public enum ErrorCode implements IJavaErrorCode { InvalidDateFormat, + MissingResourceAnnotation, MissingResourceNameAttribute, MissingResourceTypeAttribute, PostConstructParams, diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/InsertDefaultResourceAnnotationToResourcesAnnotation.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/InsertDefaultResourceAnnotationToResourcesAnnotation.java new file mode 100644 index 00000000..69d0b437 --- /dev/null +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/java/org/eclipse/lsp4jakarta/jdt/internal/annotations/InsertDefaultResourceAnnotationToResourcesAnnotation.java @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright (c) 2021, 2024 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 API and implementation +*******************************************************************************/ +package org.eclipse.lsp4jakarta.jdt.internal.annotations; + +import org.eclipse.lsp4jakarta.commons.codeaction.ICodeActionId; +import org.eclipse.lsp4jakarta.commons.codeaction.JakartaCodeActionId; +import org.eclipse.lsp4jakarta.jdt.core.java.codeaction.InsertAnnotationAttributesQuickFix; + +/** + * Inserts the name attribute to the @Resource annotation to the active element. + */ +public class InsertDefaultResourceAnnotationToResourcesAnnotation extends InsertAnnotationAttributesQuickFix { + + /** + * Constructor. + */ + public InsertDefaultResourceAnnotationToResourcesAnnotation() { + super("jakarta.annotation.Resource", "name", "type"); + } + + /** + * {@inheritDoc} + */ + @Override + public String getParticipantId() { + return InsertDefaultResourceAnnotationToResourcesAnnotation.class.getName(); + } + + /** + * {@inheritDoc} + */ + @Override + protected ICodeActionId getCodeActionId() { + return JakartaCodeActionId.InsertDefaultResourceAnnotationToResourcesAnnotation; + } +} diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties index 788521fb..f7a6eb34 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/src/main/resources/org/eclipse/lsp4jakarta/jdt/core/messages/messages.properties @@ -18,6 +18,7 @@ MethodMustNotHaveParameters = A method with the {0} annotation must not have any MethodMustBeVoid = A method with the {0} annotation must be void. MethodMustNotBeStatic = A method with the {0} annotation must not be static. MethodMustNotThrow = A method with the {0} annotation must not throw checked exceptions. +ResourcesAnnotationMustDefineResourceAnnotation = The {0} annotation must define at least one sub-annotation ''{1}''. # HttpServletQuickFix LetClassExtend = Let ''{0}'' extend ''{1}'' diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/demo-servlet-no-diagnostics/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/demo-servlet-no-diagnostics/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java new file mode 100644 index 00000000..44bfc2ef --- /dev/null +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/demo-servlet-no-diagnostics/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java @@ -0,0 +1,15 @@ +package src.main.java.io.openliberty.sample.jakarta.annotations; + +import java.lang.Exception; + +public class MyException extends Exception { + + /** + * Constructs a new MyException with the specified detail message. + * + * @param message the detail message + */ + public MyException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java new file mode 100644 index 00000000..2dbdf4c5 --- /dev/null +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/MyException.java @@ -0,0 +1,13 @@ +package io.openliberty.sample.jakarta.annotations; + +public class MyException extends Exception { + + /** + * Constructs a new MyException with the specified detail message. + * + * @param message the detail message + */ + public MyException(String message) { + super(message); + } +} diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourceAnnotation.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourceAnnotation.java index 6af65d71..0f429e11 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourceAnnotation.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourceAnnotation.java @@ -3,7 +3,7 @@ import jakarta.annotation.Resource; import jakarta.annotation.Resources; -@Resources ({ @Resource(name = "aaa"), @Resource(type = Object.class) }) +@Resource(type = Object.class, name = "aa") public class ResourceAnnotation { private Integer studentId; @@ -15,7 +15,8 @@ public class ResourceAnnotation { private boolean isSad; private String emailAddress; - + + } diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourcesAnnotation.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourcesAnnotation.java new file mode 100644 index 00000000..42c4350f --- /dev/null +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/projects/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/ResourcesAnnotation.java @@ -0,0 +1,16 @@ +package io.openliberty.sample.jakarta.annotations; + +import jakarta.annotation.Resource; +import jakarta.annotation.Resources; + +@Resources ({ @Resource(name = "aaa"), @Resource(type = Object.class) }) +public class ResourcesAnnotation { +} + +@Resources ({}) +class ResourcesAnnotationEmpty { +} + +@Resource(name = "aa", type = Object.class) +class DoctoralStudent { +} \ No newline at end of file diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourceAnnotationTest.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourceAnnotationTest.java index 3127024d..0fd936be 100644 --- a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourceAnnotationTest.java +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourceAnnotationTest.java @@ -49,41 +49,24 @@ public void GeneratedAnnotation() throws Exception { diagnosticsParams.setUris(Arrays.asList(uri)); // expected annotations - Diagnostic d1 = d(21, 0, 22, "The @Resource annotation must define the attribute 'type'.", + Diagnostic d1 = d(22, 0, 22, "The @Resource annotation must define the attribute 'type'.", DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceTypeAttribute"); - Diagnostic d2 = d(38, 0, 30, "The @Resource annotation must define the attribute 'name'.", + Diagnostic d2 = d(39, 0, 30, "The @Resource annotation must define the attribute 'name'.", DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceNameAttribute"); - // expected annotations - Diagnostic d3 = d(5, 14, 37, "The @Resource annotation must define the attribute 'type'.", - DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceTypeAttribute"); - - Diagnostic d4 = d(5, 39, 69, "The @Resource annotation must define the attribute 'name'.", - DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceNameAttribute"); + assertJavaDiagnostics(diagnosticsParams, IJDT_UTILS, d1, d2); - assertJavaDiagnostics(diagnosticsParams, IJDT_UTILS, d1, d2, d3, d4); - - JakartaJavaCodeActionParams codeActionParams = createCodeActionParams(uri, d3); - TextEdit te = te(5, 0, 6, 0, "@Resources({ @Resource(name = \"aaa\", type = \"\"), @Resource(type = Object.class) })\n"); - CodeAction ca = ca(uri, "Insert 'type' attribute to @Resource", d3, te); + JakartaJavaCodeActionParams codeActionParams = createCodeActionParams(uri, d1); + TextEdit te = te(22, 0, 22, 22, "@Resource(name = \"aa\", type = \"\")"); + CodeAction ca = ca(uri, "Insert 'type' attribute to @Resource", d1, te); assertJavaCodeAction(codeActionParams, IJDT_UTILS, ca); - JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d4); - TextEdit te1 = te(5, 0, 6, 0, "@Resources({ @Resource(name = \"aaa\"), @Resource(type = Object.class, name = \"\") })\n"); - CodeAction ca1 = ca(uri, "Insert 'name' attribute to @Resource", d4, te1); + JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d2); + TextEdit te1 = te(39, 0, 39, 30, "@Resource(type = Object.class, name = \"\")"); + CodeAction ca1 = ca(uri, "Insert 'name' attribute to @Resource", d2, te1); assertJavaCodeAction(codeActionParams1, IJDT_UTILS, ca1); - JakartaJavaCodeActionParams codeActionParams2 = createCodeActionParams(uri, d1); - TextEdit te2 = te(21, 0, 21, 22, "@Resource(name = \"aa\", type = \"\")"); - CodeAction ca2 = ca(uri, "Insert 'type' attribute to @Resource", d1, te2); - assertJavaCodeAction(codeActionParams2, IJDT_UTILS, ca2); - - JakartaJavaCodeActionParams codeActionParams3 = createCodeActionParams(uri, d2); - TextEdit te3 = te(38, 0, 38, 30, "@Resource(type = Object.class, name = \"\")"); - CodeAction ca3 = ca(uri, "Insert 'name' attribute to @Resource", d2, te3); - assertJavaCodeAction(codeActionParams3, IJDT_UTILS, ca3); - } -} +} \ No newline at end of file diff --git a/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourcesAnnotationTest.java b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourcesAnnotationTest.java new file mode 100644 index 00000000..62e7cff9 --- /dev/null +++ b/jakarta.jdt/org.eclipse.lsp4jakarta.jdt.test/src/main/java/org/eclipse/lsp4jakarta/jdt/annotations/ResourcesAnnotationTest.java @@ -0,0 +1,78 @@ +/******************************************************************************* +* Copyright (c) 2021, 2022 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 API and implementation +*******************************************************************************/ +package org.eclipse.lsp4jakarta.jdt.annotations; + +import static org.eclipse.lsp4jakarta.jdt.core.JakartaForJavaAssert.assertJavaCodeAction; +import static org.eclipse.lsp4jakarta.jdt.core.JakartaForJavaAssert.assertJavaDiagnostics; +import static org.eclipse.lsp4jakarta.jdt.core.JakartaForJavaAssert.ca; +import static org.eclipse.lsp4jakarta.jdt.core.JakartaForJavaAssert.createCodeActionParams; +import static org.eclipse.lsp4jakarta.jdt.core.JakartaForJavaAssert.d; +import static org.eclipse.lsp4jakarta.jdt.core.JakartaForJavaAssert.te; + +import java.util.Arrays; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +import org.eclipse.lsp4j.TextEdit; +import org.eclipse.lsp4jakarta.commons.JakartaJavaCodeActionParams; +import org.eclipse.lsp4jakarta.commons.JakartaJavaDiagnosticsParams; +import org.eclipse.lsp4jakarta.jdt.core.BaseJakartaTest; +import org.eclipse.lsp4jakarta.jdt.core.utils.IJDTUtils; +import org.eclipse.lsp4jakarta.jdt.internal.core.ls.JDTUtilsLSImpl; +import org.junit.Test; + +public class ResourcesAnnotationTest extends BaseJakartaTest { + + protected static IJDTUtils IJDT_UTILS = JDTUtilsLSImpl.getInstance(); + + @Test + public void GeneratedAnnotation() throws Exception { + IJavaProject javaProject = loadJavaProject("jakarta-sample", ""); + IFile javaFile = javaProject.getProject().getFile(new Path("src/main/java/io/openliberty/sample/jakarta/annotations/ResourcesAnnotation.java")); + String uri = javaFile.getLocation().toFile().toURI().toString(); + + JakartaJavaDiagnosticsParams diagnosticsParams = new JakartaJavaDiagnosticsParams(); + diagnosticsParams.setUris(Arrays.asList(uri)); + + // expected annotations + Diagnostic d1 = d(5, 14, 37, "The @Resource annotation must define the attribute 'type'.", + DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceTypeAttribute"); + + Diagnostic d2 = d(5, 39, 69, "The @Resource annotation must define the attribute 'name'.", + DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceNameAttribute"); + + Diagnostic d3 = d(9, 0, 15, "The @Resources annotation must define at least one sub-annotation '@Resource'.", + DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceAnnotation"); + + assertJavaDiagnostics(diagnosticsParams, IJDT_UTILS, d1, d2, d3); + + JakartaJavaCodeActionParams codeActionParams = createCodeActionParams(uri, d1); + TextEdit te1 = te(5, 0, 6, 0, "@Resources({ @Resource(name = \"aaa\", type = \"\"), @Resource(type = Object.class) })\n"); + CodeAction ca1 = ca(uri, "Insert 'type' attribute to @Resource", d1, te1); + assertJavaCodeAction(codeActionParams, IJDT_UTILS, ca1); + + JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d2); + TextEdit te2 = te(5, 0, 6, 0, "@Resources({ @Resource(name = \"aaa\"), @Resource(type = Object.class, name = \"\") })\n"); + CodeAction ca2 = ca(uri, "Insert 'name' attribute to @Resource", d2, te2); + assertJavaCodeAction(codeActionParams1, IJDT_UTILS, ca2); + + JakartaJavaCodeActionParams codeActionParams2 = createCodeActionParams(uri, d3); + TextEdit te3 = te(9, 0, 9, 15, "@Resources({ @Resource(name = \"\", type = \"\") })"); + CodeAction ca3 = ca(uri, "Insert 'name,type' attributes to @Resource", d3, te3); + assertJavaCodeAction(codeActionParams2, IJDT_UTILS, ca3); + } +} diff --git a/jakarta.jdt/pom.xml b/jakarta.jdt/pom.xml index 6317ab39..e56f7c3c 100644 --- a/jakarta.jdt/pom.xml +++ b/jakarta.jdt/pom.xml @@ -140,7 +140,7 @@ -Xmx512m - 60 + 300