Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add quickfix fn to handle composite annotations #513

Merged
merged 2 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion jakarta.jdt/org.eclipse.lsp4jakarta.jdt.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
<!-- Annotations -->
<extension point="org.eclipse.lsp4jakarta.jdt.core.javaFeatureParticipants">
<diagnostics class="org.eclipse.lsp4jakarta.jdt.internal.annotations.AnnotationDiagnosticsParticipant" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-annotations#MissingResourceAnnotation"
class="org.eclipse.lsp4jakarta.jdt.internal.annotations.InsertDefaultResourceAnnotationToResourcesAnnotation" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-annotations#MissingResourceNameAttribute"
class="org.eclipse.lsp4jakarta.jdt.internal.annotations.InsertNameAttributeToResourceAnnotationQuickFix" />
Expand All @@ -84,7 +87,7 @@
class="org.eclipse.lsp4jakarta.jdt.internal.annotations.RemovePreDestroyAnnotationQuickFix" />
<codeAction kind="quickfix"
targetDiagnostic="jakarta-annotations#PreDestroyParams"
class="org.eclipse.lsp4jakarta.jdt.internal.annotations.RemoveAllMethodParametersQuickFix" />
class="org.eclipse.lsp4jakarta.jdt.internal.annotations.RemoveAllMethodParametersQuickFix" />
</extension>

<!-- Bean Validation -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
* Copyright (c) 2023, 2024 Red Hat Inc. 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
Expand Down Expand Up @@ -28,6 +28,7 @@ public enum JakartaCodeActionId implements ICodeActionId {
ChangeReturnTypeToVoid,
InsertResourceAnnotationTypeAttribute,
InsertResourceAnnotationNameAttribute,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update Copyright year to 2024

InsertDefaultResourceAnnotationToResourcesAnnotation,
RemoveAllParameters,
RemoveAnnotationPreDestroy,
RemoveAnnotationPostConstruct,
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -65,7 +65,8 @@ public List<Diagnostic> collectDiagnostics(JavaDiagnosticsContext context, IProg
ArrayList<Tuple.Two<IAnnotation, IAnnotatable>> annotatables = new ArrayList<Two<IAnnotation, IAnnotatable>>();
String[] validAnnotations = { Constants.GENERATED_FQ_NAME };
String[] validTypeAnnotations = { Constants.GENERATED_FQ_NAME,
Constants.RESOURCE_FQ_NAME };
Constants.RESOURCE_FQ_NAME,
Constants.RESOURCES_FQ_NAME };
String[] validMethodAnnotations = { Constants.GENERATED_FQ_NAME,
Constants.POST_CONSTRUCT_FQ_NAME, Constants.PRE_DESTROY_FQ_NAME,
Constants.RESOURCE_FQ_NAME };
Expand Down Expand Up @@ -120,6 +121,7 @@ public List<Diagnostic> collectDiagnostics(JavaDiagnosticsContext context, IProg
IAnnotation annotation = annotatable.getFirst();
IAnnotatable element = annotatable.getSecond();

// process Types? (class declarations)
if (DiagnosticUtils.isMatchedAnnotation(unit, annotation, Constants.GENERATED_FQ_NAME)) {
for (IMemberValuePair pair : annotation.getMemberValuePairs()) {
// If date element exists and is non-empty, it must follow ISO 8601 format.
Expand Down Expand Up @@ -178,7 +180,74 @@ public List<Diagnostic> collectDiagnostics(JavaDiagnosticsContext context, IProg
}
}
}
} else if (DiagnosticUtils.isMatchedAnnotation(unit, annotation, Constants.RESOURCES_FQ_NAME)) {
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) {
IAnnotation childAnnotation = (IAnnotation) childAnnotationObj;
if (DiagnosticUtils.isMatchedAnnotation(unit, childAnnotation,
Constants.RESOURCE_FQ_NAME)) {
if (element instanceof IType) {
IType type = (IType) element;
if (type.getElementType() == IJavaElement.TYPE
&& ((IType) type).isClass()) {
annotationRange = PositionUtils.toNameRange(childAnnotation,
context.getUtils());
Boolean nameEmpty = true;
Boolean typeEmpty = true;
for (IMemberValuePair pair : childAnnotation.getMemberValuePairs()) {
if (pair.getMemberName().equals("name")) {
nameEmpty = false;
}
if (pair.getMemberName().equals("type")) {
typeEmpty = false;
}
}
if (nameEmpty) {
diagnosticMessage = Messages.getMessage(
"AnnotationMustDefineAttribute",
"@Resource", "name");
diagnostics.add(context.createDiagnostic(uri, diagnosticMessage,
annotationRange,
Constants.DIAGNOSTIC_SOURCE,
ErrorCode.MissingResourceNameAttribute,
DiagnosticSeverity.Error));
}

if (typeEmpty) {
diagnosticMessage = Messages.getMessage(
"AnnotationMustDefineAttribute",
"@Resource", "type");
diagnostics.add(context.createDiagnostic(uri, diagnosticMessage,
annotationRange,
Constants.DIAGNOSTIC_SOURCE,
ErrorCode.MissingResourceTypeAttribute,
DiagnosticSeverity.Error));
}
}
}
}
}
}
}
}
}

// process methods now?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove: // process methods now?

if (DiagnosticUtils.isMatchedAnnotation(unit, annotation, Constants.POST_CONSTRUCT_FQ_NAME)) {
if (element instanceof IMethod) {
IMethod method = (IMethod) element;
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -30,6 +30,10 @@ public class Constants {
public static final String RESOURCE = "Resource";
public static final String RESOURCE_FQ_NAME = "jakarta.annotation.Resource";

/* @Resources */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update Copyright year to 2024

public static final String RESOURCES = "Resources";
public static final String RESOURCES_FQ_NAME = "jakarta.annotation.Resources";

/* @PostConstruct */
public static final String POST_CONSTRUCT = "PostConstruct";
public static final String POST_CONSTRUCT_FQ_NAME = "jakarta.annotation.PostConstruct";
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -19,6 +19,7 @@
*/
public enum ErrorCode implements IJavaErrorCode {
InvalidDateFormat,
MissingResourceAnnotation,
MissingResourceNameAttribute,
MissingResourceTypeAttribute,
PostConstructParams,
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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}''.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update Copyright year to 2024


# HttpServletQuickFix
LetClassExtend = Let ''{0}'' extend ''{1}''
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package io.openliberty.sample.jakarta.annotations;

import jakarta.annotation.Resource;
import jakarta.annotation.Resources;

@Resource(type = Object.class, name = "aa")
public class ResourceAnnotation {

private Integer studentId;


@Resource(shareable = true)
private boolean isHappy;

@Resource(name = "test")
private boolean isSad;


private String emailAddress;





}

@Resource(name = "aa")
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -63,10 +63,10 @@ public void GeneratedAnnotation() throws Exception {
assertJavaCodeAction(codeActionParams, IJDT_UTILS, ca);

JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d2);
TextEdit te1 = te(39, 0, 39, 30, "@Resource(type = \"\", name = \"\")");
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);

}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*******************************************************************************
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a new file the first like should be:
Copyright (c) 2024 IBM Corporation and others.

* 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.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);
}
}
Loading