Skip to content

Commit

Permalink
feat: Mark observer methods as implicitly used
Browse files Browse the repository at this point in the history
Signed-off-by: Fred Bricon <[email protected]>
  • Loading branch information
fbricon committed Sep 1, 2023
1 parent 20306d5 commit e18ed69
Showing 1 changed file with 48 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,70 @@
package com.redhat.devtools.intellij.lsp4mp4ij.psi.core;

import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.*;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.jaxrs.JaxRsConstants;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.AnnotationUtils;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.restclient.MicroProfileRestClientConstants;
import org.jetbrains.annotations.NotNull;

/**
* Automatically declares as used, methods annotated with jakarta.ws.rs.* or javax.ws.rs.* HTTP annotations,
* or {@link org.eclipse.microprofile.rest.client.inject.RestClient}
* Automatically declares the following as used:
* <ul>
* <li>methods annotated with jakarta.ws.rs.* or javax.ws.rs.* HTTP annotations, or {@link org.eclipse.microprofile.rest.client.inject.RestClient}</li>
* <li>non-abstract public observer methods, i.e. with a parameter annotated with <code>@jakarta.enterprise.event.Observes</code> or <code>@javax.enterprise.event.Observes</code></li>
* </ul>
*/
public class JavaEEImplicitUsageProvider implements ImplicitUsageProvider {

private static final String JAKARTA_OBSERVES = "jakarta.enterprise.event.Observes";
private static final String JAVAX_OBSERVES = "javax.enterprise.event.Observes";


@Override
public boolean isImplicitUsage(@NotNull PsiElement element) {
return isImplicitRead(element) || isImplicitWrite(element);
}

@Override
public boolean isImplicitRead(@NotNull PsiElement element) {
return isHttpOrRestClient(element) || isObserverMethod(element);
}

private boolean isObserverMethod(@NotNull PsiElement element) {
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod) element;
return isPublicNonAbstract(method) && observesOneParameter(method);
}
return false;
}

private boolean observesOneParameter(PsiMethod method) {
//XXX ideally we might want to check if the parent class is a managed bean class or session bean class (or of an extension)
//But that might prove a bit complex, so let's skip this part for now.

PsiParameter[] parameters = method.getParameterList().getParameters();

int observesAnnotationCount = 0;

for (PsiParameter parameter : parameters) {
if (AnnotationUtils.hasAnyAnnotation(parameter, JAKARTA_OBSERVES, JAVAX_OBSERVES)) {
observesAnnotationCount++;
if (observesAnnotationCount > 1) {
return false;
}
}
}

return observesAnnotationCount == 1;
}

private boolean isPublicNonAbstract(@NotNull PsiMethod method) {
return !method.isConstructor() &&
method.hasModifierProperty(PsiModifier.PUBLIC) &&
!method.hasModifierProperty(PsiModifier.ABSTRACT);
}

private boolean isHttpOrRestClient(@NotNull PsiElement element) {
return AnnotationUtils.hasAnyAnnotation(element, JaxRsConstants.HTTP_METHOD_ANNOTATIONS) ||
AnnotationUtils.hasAnnotation(element, MicroProfileRestClientConstants.REST_CLIENT_ANNOTATION);
}
Expand Down

0 comments on commit e18ed69

Please sign in to comment.