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..6d712b72 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
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2021, 2023 IBM Corporation and others.
+* Copyright (c) 2021, 2023, 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
@@ -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..f35dc602 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
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2023 IBM Corporation and others.
+* Copyright (c) 2023, 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
@@ -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..f7a1eb5e
--- /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) 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/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..3aaf2c5a
--- /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,28 @@
+/*******************************************************************************
+* Copyright (c) 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 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..33a39f90 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
@@ -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
@@ -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..44552a88
--- /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(17, 14, 37, "The @Resource annotation must define the attribute 'type'.",
+ DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceTypeAttribute");
+
+ Diagnostic d2 = d(17, 39, 69, "The @Resource annotation must define the attribute 'name'.",
+ DiagnosticSeverity.Error, "jakarta-annotations", "MissingResourceNameAttribute");
+
+ Diagnostic d3 = d(21, 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(17, 0, 18, 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(17, 0, 18, 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(21, 0, 21, 15, "@Resources({ @Resource(name = \"\", type = \"\") })");
+ CodeAction ca3 = ca(uri, "Insert 'name,type' attributes to @Resource", d3, te3);
+ assertJavaCodeAction(codeActionParams2, IJDT_UTILS, ca3);
+ }
+}