Skip to content

Commit 2477362

Browse files
authored
Merge pull request #31444 from Ladicek/arc-build-compatible-extensions
ArC: initial implementation of CDI Build Compatible Extensions
2 parents e000c18 + 50d4034 commit 2477362

File tree

98 files changed

+7285
-40
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+7285
-40
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ FeatureBuildItem feature() {
148148
return new FeatureBuildItem(Feature.CDI);
149149
}
150150

151+
@BuildStep
152+
BuildCompatibleExtensionsBuildItem buildCompatibleExtensions() {
153+
return new BuildCompatibleExtensionsBuildItem();
154+
}
155+
151156
@BuildStep
152157
AdditionalBeanBuildItem quarkusApplication(CombinedIndexBuildItem combinedIndex) {
153158
List<String> quarkusApplications = new ArrayList<>();
@@ -190,6 +195,7 @@ public ContextRegistrationPhaseBuildItem initialize(
190195
BeanArchiveIndexBuildItem beanArchiveIndex,
191196
CombinedIndexBuildItem combinedIndex,
192197
ApplicationIndexBuildItem applicationIndex,
198+
BuildCompatibleExtensionsBuildItem buildCompatibleExtensions,
193199
List<ExcludedTypeBuildItem> excludedTypes,
194200
List<AnnotationsTransformerBuildItem> annotationTransformers,
195201
List<InjectionPointTransformerBuildItem> injectionPointTransformers,
@@ -421,6 +427,8 @@ public Integer compute(AnnotationTarget target, Collection<StereotypeInfo> stere
421427
builder.addSuppressConditionGenerator(generator.getGenerator());
422428
}
423429

430+
builder.setBuildCompatibleExtensions(buildCompatibleExtensions.entrypoint);
431+
424432
BeanProcessor beanProcessor = builder.build();
425433
ContextRegistrar.RegistrationContext context = beanProcessor.registerCustomContexts();
426434
return new ContextRegistrationPhaseBuildItem(context, beanProcessor);

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public BeanArchiveIndexBuildItem build(ArcConfig config, ApplicationArchivesBuil
4949
List<AdditionalBeanBuildItem> additionalBeans, List<GeneratedBeanBuildItem> generatedBeans,
5050
LiveReloadBuildItem liveReloadBuildItem, BuildProducer<GeneratedClassBuildItem> generatedClass,
5151
CustomScopeAnnotationsBuildItem customScopes, List<ExcludeDependencyBuildItem> excludeDependencyBuildItems,
52-
List<BeanArchivePredicateBuildItem> beanArchivePredicates)
52+
List<BeanArchivePredicateBuildItem> beanArchivePredicates,
53+
BuildCompatibleExtensionsBuildItem buildCompatibleExtensions)
5354
throws Exception {
5455

5556
// First build an index from application archives
@@ -63,6 +64,10 @@ public BeanArchiveIndexBuildItem build(ArcConfig config, ApplicationArchivesBuil
6364
additionalBeanClasses.addAll(i.getBeanClasses());
6465
}
6566

67+
Set<String> additionalBeansFromExtensions = new HashSet<>();
68+
buildCompatibleExtensions.entrypoint.runDiscovery(applicationIndex, additionalBeansFromExtensions);
69+
additionalBeanClasses.addAll(additionalBeansFromExtensions);
70+
6671
// Build the index for additional beans and generated bean classes
6772
Set<DotName> additionalIndex = new HashSet<>();
6873
Set<DotName> knownMissingClasses = new HashSet<>();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.quarkus.arc.deployment;
2+
3+
import io.quarkus.arc.processor.bcextensions.ExtensionsEntryPoint;
4+
import io.quarkus.builder.item.SimpleBuildItem;
5+
6+
public final class BuildCompatibleExtensionsBuildItem extends SimpleBuildItem {
7+
public final ExtensionsEntryPoint entrypoint = new ExtensionsEntryPoint();
8+
}

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AssignabilityCheck.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import org.jboss.jandex.IndexView;
1414
import org.jboss.jandex.Type;
1515

16-
final class AssignabilityCheck {
16+
public final class AssignabilityCheck {
1717

1818
private final ConcurrentMap<DotName, Set<DotName>> cache;
1919
private final IndexView index;
@@ -23,7 +23,7 @@ public AssignabilityCheck(IndexView beanArchiveIndex, IndexView applicationIndex
2323
this.index = applicationIndex != null ? CompositeIndex.create(beanArchiveIndex, applicationIndex) : beanArchiveIndex;
2424
}
2525

26-
boolean isAssignableFrom(Type type1, Type type2) {
26+
public boolean isAssignableFrom(Type type1, Type type2) {
2727
// java.lang.Object is assignable from any type
2828
if (type1.name().equals(DotNames.OBJECT)) {
2929
return true;

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,22 @@ public THIS targetPackageName(String name) {
201201
return self();
202202
}
203203

204+
/**
205+
* @deprecated use {@link #alternative(boolean)} and {@link #priority(int)};
206+
* this method will be removed at some time after Quarkus 3.6
207+
*/
208+
@Deprecated(forRemoval = true, since = "3.0")
204209
public THIS alternativePriority(int value) {
205210
this.alternative = true;
206211
this.priority = value;
207212
return self();
208213
}
209214

215+
public THIS alternative(boolean alternative) {
216+
this.alternative = alternative;
217+
return self();
218+
}
219+
210220
public THIS priority(int value) {
211221
this.priority = value;
212222
return self();

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import io.quarkus.arc.processor.BeanRegistrar.RegistrationContext;
4949
import io.quarkus.arc.processor.BuildExtension.BuildContext;
5050
import io.quarkus.arc.processor.BuildExtension.Key;
51+
import io.quarkus.arc.processor.bcextensions.ExtensionsEntryPoint;
5152
import io.quarkus.gizmo.MethodCreator;
5253
import io.quarkus.gizmo.ResultHandle;
5354

@@ -119,8 +120,11 @@ public class BeanDeployment {
119120

120121
private final List<Predicate<ClassInfo>> excludeTypes;
121122

123+
private final ExtensionsEntryPoint buildCompatibleExtensions;
124+
122125
BeanDeployment(String name, BuildContextImpl buildContext, BeanProcessor.Builder builder) {
123126
this.name = name;
127+
this.buildCompatibleExtensions = builder.buildCompatibleExtensions;
124128
this.buildContext = buildContext;
125129
Map<DotName, BeanDefiningAnnotation> beanDefiningAnnotations = new HashMap<>();
126130
if (builder.additionalBeanDefiningAnnotations != null) {
@@ -269,6 +273,10 @@ BeanRegistrar.RegistrationContext registerBeans(List<BeanRegistrar> beanRegistra
269273
this.injectionPoints.addAll(injectionPoints);
270274
buildContextPut(Key.INJECTION_POINTS.asString(), Collections.unmodifiableList(this.injectionPoints));
271275

276+
if (buildCompatibleExtensions != null) {
277+
buildCompatibleExtensions.runRegistration(beanArchiveComputingIndex, beans, observers);
278+
}
279+
272280
return registerSyntheticBeans(beanRegistrars, buildContext);
273281
}
274282

@@ -524,6 +532,10 @@ public Collection<StereotypeInfo> getStereotypes() {
524532
return Collections.unmodifiableCollection(stereotypes.values());
525533
}
526534

535+
Map<DotName, StereotypeInfo> getStereotypesMap() {
536+
return Collections.unmodifiableMap(stereotypes);
537+
}
538+
527539
/**
528540
* Returns the index that was used during discovery and type-safe resolution.
529541
* <p>
@@ -1231,6 +1243,10 @@ private RegistrationContext registerSyntheticBeans(List<BeanRegistrar> beanRegis
12311243
for (BeanRegistrar registrar : beanRegistrars) {
12321244
registrar.register(context);
12331245
}
1246+
if (buildCompatibleExtensions != null) {
1247+
buildCompatibleExtensions.runSynthesis(beanArchiveComputingIndex);
1248+
buildCompatibleExtensions.registerSyntheticBeans(context);
1249+
}
12341250
this.injectionPoints.addAll(context.syntheticInjectionPoints);
12351251
return context;
12361252
}
@@ -1243,6 +1259,10 @@ io.quarkus.arc.processor.ObserverRegistrar.RegistrationContext registerSynthetic
12431259
registrar.register(context);
12441260
context.extension = null;
12451261
}
1262+
if (buildCompatibleExtensions != null) {
1263+
buildCompatibleExtensions.registerSyntheticObservers(context);
1264+
buildCompatibleExtensions.runRegistrationAgain(beanArchiveComputingIndex, beans, observers);
1265+
}
12461266
return context;
12471267
}
12481268

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,8 +987,13 @@ Builder disposer(DisposerInfo disposer) {
987987
return this;
988988
}
989989

990+
/**
991+
* @deprecated use {@link #alternative(boolean)} and {@link #priority(Integer)};
992+
* this method will be removed at some time after Quarkus 3.6
993+
*/
994+
@Deprecated(forRemoval = true, since = "3.0")
990995
Builder alternativePriority(Integer alternativePriority) {
991-
return alternative(true).priority(priority);
996+
return alternative(true).priority(alternativePriority);
992997
}
993998

994999
Builder alternative(boolean value) {

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import io.quarkus.arc.processor.BuildExtension.Key;
3838
import io.quarkus.arc.processor.ResourceOutput.Resource;
3939
import io.quarkus.arc.processor.ResourceOutput.Resource.SpecialType;
40+
import io.quarkus.arc.processor.bcextensions.ExtensionsEntryPoint;
4041
import io.quarkus.gizmo.BytecodeCreator;
4142

4243
/**
@@ -85,7 +86,15 @@ public static Builder builder() {
8586
// Such as java.lang.Deprecated
8687
protected final Predicate<DotName> injectionPointAnnotationsPredicate;
8788

89+
private final ExtensionsEntryPoint buildCompatibleExtensions;
90+
8891
private BeanProcessor(Builder builder) {
92+
this.buildCompatibleExtensions = builder.buildCompatibleExtensions;
93+
if (buildCompatibleExtensions != null) {
94+
buildCompatibleExtensions.registerMetaAnnotations(builder);
95+
buildCompatibleExtensions.runEnhancement(builder.beanArchiveComputingIndex, builder);
96+
}
97+
8998
this.reflectionRegistration = builder.reflectionRegistration;
9099
this.applicationClassPredicate = builder.applicationClassPredicate;
91100
this.name = builder.name;
@@ -153,7 +162,13 @@ public void initialize(Consumer<BytecodeTransformer> bytecodeTransformerConsumer
153162
* @return the validation context
154163
*/
155164
public BeanDeploymentValidator.ValidationContext validate(Consumer<BytecodeTransformer> bytecodeTransformerConsumer) {
156-
return beanDeployment.validate(beanDeploymentValidators, bytecodeTransformerConsumer);
165+
ValidationContext validationContext = beanDeployment.validate(beanDeploymentValidators, bytecodeTransformerConsumer);
166+
if (buildCompatibleExtensions != null) {
167+
buildCompatibleExtensions.runValidation(beanDeployment.getBeanArchiveIndex(),
168+
validationContext.get(Key.BEANS), validationContext.get(Key.OBSERVERS));
169+
buildCompatibleExtensions.registerValidationErrors(validationContext);
170+
}
171+
return validationContext;
157172
}
158173

159174
public void processValidationErrors(BeanDeploymentValidator.ValidationContext validationContext) {
@@ -477,6 +492,8 @@ public static class Builder {
477492
AlternativePriorities alternativePriorities;
478493
final List<Predicate<ClassInfo>> excludeTypes;
479494

495+
ExtensionsEntryPoint buildCompatibleExtensions;
496+
480497
Predicate<DotName> applicationClassPredicate;
481498

482499
public Builder() {
@@ -785,6 +802,11 @@ public Builder addSuppressConditionGenerator(Function<BeanInfo, Consumer<Bytecod
785802
return this;
786803
}
787804

805+
public Builder setBuildCompatibleExtensions(ExtensionsEntryPoint buildCompatibleExtensions) {
806+
this.buildCompatibleExtensions = buildCompatibleExtensions;
807+
return this;
808+
}
809+
788810
public BeanProcessor build() {
789811
return new BeanProcessor(this);
790812
}

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Beans.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.HashSet;
1212
import java.util.Iterator;
1313
import java.util.List;
14+
import java.util.Map;
1415
import java.util.Set;
1516
import java.util.function.BiFunction;
1617
import java.util.function.Consumer;
@@ -313,7 +314,7 @@ static ScopeInfo initStereotypeScope(List<StereotypeInfo> stereotypes, Annotatio
313314
}
314315

315316
Set<ScopeInfo> stereotypeScopes = new HashSet<>();
316-
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment)) {
317+
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment.getStereotypesMap())) {
317318
if (stereotype.getDefaultScope() != null) {
318319
stereotypeScopes.add(stereotype.getDefaultScope());
319320
}
@@ -334,7 +335,7 @@ static boolean initStereotypeAlternative(List<StereotypeInfo> stereotypes, BeanD
334335
return false;
335336
}
336337

337-
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment)) {
338+
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment.getStereotypesMap())) {
338339
if (stereotype.isAlternative()) {
339340
return true;
340341
}
@@ -352,7 +353,7 @@ static Integer initStereotypeAlternativePriority(List<StereotypeInfo> stereotype
352353
}
353354

354355
Set<Integer> priorities = new HashSet<>();
355-
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment)) {
356+
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment.getStereotypesMap())) {
356357
if (stereotype.getAlternativePriority() != null) {
357358
priorities.add(stereotype.getAlternativePriority());
358359
}
@@ -374,7 +375,7 @@ static String initStereotypeName(List<StereotypeInfo> stereotypes, AnnotationTar
374375
return null;
375376
}
376377

377-
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment)) {
378+
for (StereotypeInfo stereotype : stereotypesWithTransitive(stereotypes, beanDeployment.getStereotypesMap())) {
378379
if (stereotype.isNamed()) {
379380
switch (target.kind()) {
380381
case CLASS:
@@ -392,21 +393,21 @@ static String initStereotypeName(List<StereotypeInfo> stereotypes, AnnotationTar
392393
return null;
393394
}
394395

395-
private static List<StereotypeInfo> stereotypesWithTransitive(List<StereotypeInfo> stereotypes,
396-
BeanDeployment beanDeployment) {
396+
public static List<StereotypeInfo> stereotypesWithTransitive(List<StereotypeInfo> stereotypes,
397+
Map<DotName, StereotypeInfo> allStereotypes) {
397398
List<StereotypeInfo> result = new ArrayList<>();
398399
Set<DotName> alreadySeen = new HashSet<>(); // to guard against hypothetical stereotype cycle
399400
Deque<StereotypeInfo> workQueue = new ArrayDeque<>(stereotypes);
400401
while (!workQueue.isEmpty()) {
401402
StereotypeInfo stereotype = workQueue.poll();
403+
if (alreadySeen.contains(stereotype.getName())) {
404+
continue;
405+
}
402406
result.add(stereotype);
403407
alreadySeen.add(stereotype.getName());
404408

405409
for (AnnotationInstance parentStereotype : stereotype.getParentStereotypes()) {
406-
if (alreadySeen.contains(parentStereotype.name())) {
407-
continue;
408-
}
409-
StereotypeInfo parent = beanDeployment.getStereotype(parentStereotype.name());
410+
StereotypeInfo parent = allStereotypes.get(parentStereotype.name());
410411
if (parent != null) {
411412
workQueue.add(parent);
412413
}

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverConfigurator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public ObserverConfigurator(Consumer<ObserverConfigurator> consumer) {
4444
this.transactionPhase = TransactionPhase.IN_PROGRESS;
4545
}
4646

47+
@Override
48+
protected ObserverConfigurator self() {
49+
return this;
50+
}
51+
4752
/**
4853
* A unique identifier should be used for multiple synthetic observer methods with the same
4954
* attributes (including the bean class).

0 commit comments

Comments
 (0)