Skip to content

Commit

Permalink
Arc - Do not validate static members in inner non-static classes for …
Browse files Browse the repository at this point in the history
…CDI annotations
  • Loading branch information
manovotn committed Mar 3, 2023
1 parent f14cb40 commit 6b2f04b
Showing 1 changed file with 60 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.ClassInfo.NestingType;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;

import io.quarkus.arc.deployment.ValidationPhaseBuildItem.ValidationErrorBuildItem;
import io.quarkus.arc.processor.Annotations;
Expand Down Expand Up @@ -72,35 +75,72 @@ void detect(ArcConfig config, ApplicationIndexBuildItem applicationIndex, Custom
NestingType nestingType = clazz.nestingType();
if (NestingType.ANONYMOUS == nestingType || NestingType.LOCAL == nestingType
|| (NestingType.INNER == nestingType && !Modifier.isStatic(clazz.flags()))) {
// Annotations declared on the class, incl. the annotations added via transformers
Collection<AnnotationInstance> classAnnotations = transformedAnnotations.getAnnotations(clazz);
if (classAnnotations.isEmpty() && clazz.annotationsMap().isEmpty()) {
continue;
}
if (scopeAnnotations.isScopeIn(classAnnotations)) {
// Annotations declared on the class level, incl. the annotations added via transformers
List<AnnotationInstance> classLevelAnnotations = transformedAnnotations.getAnnotations(clazz).stream()
.filter(a -> a.target().kind() == AnnotationTarget.Kind.CLASS).collect(Collectors.toList());
if (scopeAnnotations.isScopeIn(classLevelAnnotations)) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The %s class %s has a scope annotation but it must be ignored per the CDI rules",
clazz.nestingType().toString(), clazz.name().toString()))));
} else if (clazz.annotationsMap().containsKey(DotNames.OBSERVES)) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The %s class %s declares an observer method but it must be ignored per the CDI rules",
clazz.nestingType().toString(), clazz.name().toString()))));
} else if (clazz.annotationsMap().containsKey(DotNames.PRODUCES)) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The %s class %s declares a producer but it must be ignored per the CDI rules",
clazz.nestingType().toString(), clazz.name().toString()))));
} else if (Annotations.containsAny(classAnnotations, interceptorResolverBuildItem.getInterceptorBindings())
|| Annotations.containsAny(clazz.annotations(),
interceptorResolverBuildItem.getInterceptorBindings())) {
// detect interceptor bindings on nested classes
} else if (Annotations.containsAny(classLevelAnnotations,
interceptorResolverBuildItem.getInterceptorBindings())) {
// detect interceptor bindings declared at nested class level
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The %s class %s declares an interceptor binding but it must be ignored per CDI rules",
clazz.nestingType().toString(), clazz.name().toString()))));
}

// iterate over methods and verify those
// since JDK 16, you can have static method inside inner non-static class - skip those
for (MethodInfo methodInfo : clazz.methods()) {
if (Modifier.isStatic(methodInfo.flags())) {
continue;
}
// annotations declared on method level, incl. the annotations added via transformers
Collection<AnnotationInstance> methodAnnotations = transformedAnnotations.getAnnotations(methodInfo);
if (methodAnnotations.isEmpty()) {
continue;
}
if (Annotations.contains(methodAnnotations, DotNames.OBSERVES)) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The method %s in the %s class %s declares an observer method but it must be ignored per the CDI rules",
methodInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
} else if (Annotations.contains(methodAnnotations, DotNames.PRODUCES)) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The method %s in the %s class %s declares a producer but it must be ignored per the CDI rules",
methodInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
} else if (Annotations.containsAny(methodAnnotations,
interceptorResolverBuildItem.getInterceptorBindings())) {
// detect interceptor bindings declared at nested class methods
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The method %s in the %s class %s declares an interceptor binding but it must be ignored per CDI rules",
methodInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
}

}

// iterate over all fields, check for incorrect producer declarations
for (FieldInfo fieldInfo : clazz.fields()) {
if (Modifier.isStatic(fieldInfo.flags())) {
continue;
}
// annotations declared on field level, incl. the annotations added via transformers
Collection<AnnotationInstance> fieldAnnotations = transformedAnnotations.getAnnotations(fieldInfo);
if (fieldAnnotations.isEmpty()) {
continue;
}
if (Annotations.contains(fieldAnnotations, DotNames.PRODUCES)) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException(String.format(
"The field %s in the %s class %s declares a producer but it must be ignored per the CDI rules",
fieldInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
}
}
}
}
}
Expand Down

0 comments on commit 6b2f04b

Please sign in to comment.