Skip to content

Commit 5d3a353

Browse files
committed
Arc - Do not validate static members in inner non-static classes for CDI annotations
1 parent f14cb40 commit 5d3a353

File tree

1 file changed

+53
-20
lines changed

1 file changed

+53
-20
lines changed

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/WrongAnnotationUsageProcessor.java

+53-20
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
import org.jboss.jandex.ClassInfo;
1414
import org.jboss.jandex.ClassInfo.NestingType;
1515
import org.jboss.jandex.DotName;
16+
import org.jboss.jandex.FieldInfo;
1617
import org.jboss.jandex.IndexView;
18+
import org.jboss.jandex.MethodInfo;
1719

1820
import io.quarkus.arc.deployment.ValidationPhaseBuildItem.ValidationErrorBuildItem;
1921
import io.quarkus.arc.processor.Annotations;
@@ -72,35 +74,66 @@ void detect(ArcConfig config, ApplicationIndexBuildItem applicationIndex, Custom
7274
NestingType nestingType = clazz.nestingType();
7375
if (NestingType.ANONYMOUS == nestingType || NestingType.LOCAL == nestingType
7476
|| (NestingType.INNER == nestingType && !Modifier.isStatic(clazz.flags()))) {
75-
// Annotations declared on the class, incl. the annotations added via transformers
76-
Collection<AnnotationInstance> classAnnotations = transformedAnnotations.getAnnotations(clazz);
77-
if (classAnnotations.isEmpty() && clazz.annotationsMap().isEmpty()) {
78-
continue;
79-
}
80-
if (scopeAnnotations.isScopeIn(classAnnotations)) {
77+
// Annotations declared on the class level, incl. the annotations added via transformers
78+
Collection<AnnotationInstance> classLevelAnnotations = transformedAnnotations.getAnnotations(clazz);
79+
if (scopeAnnotations.isScopeIn(classLevelAnnotations)) {
8180
validationErrors.produce(new ValidationErrorBuildItem(
8281
new IllegalStateException(String.format(
8382
"The %s class %s has a scope annotation but it must be ignored per the CDI rules",
8483
clazz.nestingType().toString(), clazz.name().toString()))));
85-
} else if (clazz.annotationsMap().containsKey(DotNames.OBSERVES)) {
86-
validationErrors.produce(new ValidationErrorBuildItem(
87-
new IllegalStateException(String.format(
88-
"The %s class %s declares an observer method but it must be ignored per the CDI rules",
89-
clazz.nestingType().toString(), clazz.name().toString()))));
90-
} else if (clazz.annotationsMap().containsKey(DotNames.PRODUCES)) {
91-
validationErrors.produce(new ValidationErrorBuildItem(
92-
new IllegalStateException(String.format(
93-
"The %s class %s declares a producer but it must be ignored per the CDI rules",
94-
clazz.nestingType().toString(), clazz.name().toString()))));
95-
} else if (Annotations.containsAny(classAnnotations, interceptorResolverBuildItem.getInterceptorBindings())
96-
|| Annotations.containsAny(clazz.annotations(),
97-
interceptorResolverBuildItem.getInterceptorBindings())) {
98-
// detect interceptor bindings on nested classes
84+
} else if (Annotations.containsAny(classLevelAnnotations,
85+
interceptorResolverBuildItem.getInterceptorBindings())) {
86+
// detect interceptor bindings declared at nested class level
9987
validationErrors.produce(new ValidationErrorBuildItem(
10088
new IllegalStateException(String.format(
10189
"The %s class %s declares an interceptor binding but it must be ignored per CDI rules",
10290
clazz.nestingType().toString(), clazz.name().toString()))));
10391
}
92+
93+
// iterate over methods and verify those
94+
// note that since JDK 16, you can have static method inside inner non-static class
95+
for (MethodInfo methodInfo : clazz.methods()) {
96+
// annotations declared on method level, incl. the annotations added via transformers
97+
Collection<AnnotationInstance> methodAnnotations = transformedAnnotations.getAnnotations(methodInfo);
98+
if (methodAnnotations.isEmpty()) {
99+
continue;
100+
}
101+
if (Annotations.contains(methodAnnotations, DotNames.OBSERVES)
102+
|| Annotations.contains(methodAnnotations, DotNames.OBSERVES_ASYNC)) {
103+
validationErrors.produce(new ValidationErrorBuildItem(
104+
new IllegalStateException(String.format(
105+
"The method %s in the %s class %s declares an observer method but it must be ignored per the CDI rules",
106+
methodInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
107+
} else if (Annotations.contains(methodAnnotations, DotNames.PRODUCES)) {
108+
validationErrors.produce(new ValidationErrorBuildItem(
109+
new IllegalStateException(String.format(
110+
"The method %s in the %s class %s declares a producer but it must be ignored per the CDI rules",
111+
methodInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
112+
} else if (!Modifier.isStatic(methodInfo.flags()) && Annotations.containsAny(methodAnnotations,
113+
interceptorResolverBuildItem.getInterceptorBindings())) {
114+
// detect interceptor bindings declared at nested class methods
115+
validationErrors.produce(new ValidationErrorBuildItem(
116+
new IllegalStateException(String.format(
117+
"The method %s in the %s class %s declares an interceptor binding but it must be ignored per CDI rules",
118+
methodInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
119+
}
120+
121+
}
122+
123+
// iterate over all fields, check for incorrect producer declarations
124+
for (FieldInfo fieldInfo : clazz.fields()) {
125+
// annotations declared on field level, incl. the annotations added via transformers
126+
Collection<AnnotationInstance> fieldAnnotations = transformedAnnotations.getAnnotations(fieldInfo);
127+
if (fieldAnnotations.isEmpty()) {
128+
continue;
129+
}
130+
if (Annotations.contains(fieldAnnotations, DotNames.PRODUCES)) {
131+
validationErrors.produce(new ValidationErrorBuildItem(
132+
new IllegalStateException(String.format(
133+
"The field %s in the %s class %s declares a producer but it must be ignored per the CDI rules",
134+
fieldInfo.name(), clazz.nestingType().toString(), clazz.name().toString()))));
135+
}
136+
}
104137
}
105138
}
106139
}

0 commit comments

Comments
 (0)