diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java
index 0bee6f858918c..91b10940263cf 100644
--- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java
+++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java
@@ -32,6 +32,9 @@
public final class SyntheticBeanBuildItem extends MultiBuildItem {
/**
+ * Returns a configurator object allowing for further customization of the synthetic bean.
+ *
+ * The implementation class is automatically registered as a resulting bean type.
*
* @param implClazz
* @return a new configurator instance
@@ -42,6 +45,9 @@ public static ExtendedBeanConfigurator configure(Class> implClazz) {
}
/**
+ * Returns a configurator object allowing for further customization of the synthetic bean.
+ *
+ * The implementation class is automatically registered as a resulting bean type.
*
* @param implClazz
* @return a new configurator instance
@@ -51,6 +57,32 @@ public static ExtendedBeanConfigurator configure(DotName implClazz) {
return new ExtendedBeanConfigurator(implClazz).addType(implClazz);
}
+ /**
+ * Returns a configurator object allowing for further customization of the synthetic bean.
+ *
+ * Unlike {@link #configure(Class)}, the implementation class is not registered as a resulting bean type.
+ *
+ * @param implClazz
+ * @return a new configurator instance
+ * @see ExtendedBeanConfigurator#done()
+ */
+ public static ExtendedBeanConfigurator create(Class> implClazz) {
+ return create(DotName.createSimple(implClazz.getName()));
+ }
+
+ /**
+ * Returns a configurator object allowing for further customization of the synthetic bean.
+ *
+ * Unlike {@link #configure(DotName)}, the implementation class is not registered as a resulting bean type.
+ *
+ * @param implClazz
+ * @return a new configurator instance
+ * @see ExtendedBeanConfigurator#done()
+ */
+ public static ExtendedBeanConfigurator create(DotName implClazz) {
+ return new ExtendedBeanConfigurator(implClazz);
+ }
+
private final ExtendedBeanConfigurator configurator;
SyntheticBeanBuildItem(ExtendedBeanConfigurator configurator) {
diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/create/SyntheticBeanBuildItemCreateTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/create/SyntheticBeanBuildItemCreateTest.java
new file mode 100644
index 0000000000000..9dbcf9e929612
--- /dev/null
+++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/create/SyntheticBeanBuildItemCreateTest.java
@@ -0,0 +1,77 @@
+package io.quarkus.arc.test.synthetic.create;
+
+import java.util.function.Consumer;
+
+import jakarta.enterprise.inject.Vetoed;
+
+import org.jboss.jandex.DotName;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.ArcContainer;
+import io.quarkus.arc.BeanCreator;
+import io.quarkus.arc.SyntheticCreationalContext;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.arc.processor.BuiltinScope;
+import io.quarkus.builder.BuildChainBuilder;
+import io.quarkus.builder.BuildContext;
+import io.quarkus.builder.BuildStep;
+import io.quarkus.test.QuarkusUnitTest;
+
+/**
+ * Tests that {@link SyntheticBeanBuildItem#create(DotName)} does not add automatically register the param type as bean type
+ */
+public class SyntheticBeanBuildItemCreateTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClasses(SyntheticBeanBuildItemCreateTest.class, FooCreator.class, FooInterface.class, Foo.class))
+ .addBuildChainCustomizer(buildCustomizer());
+
+ static Consumer buildCustomizer() {
+ return new Consumer() {
+
+ @Override
+ public void accept(BuildChainBuilder builder) {
+ builder.addBuildStep(new BuildStep() {
+
+ @Override
+ public void execute(BuildContext context) {
+ context.produce(SyntheticBeanBuildItem.create(Foo.class)
+ .addType(FooInterface.class)
+ .scope(BuiltinScope.SINGLETON.getInfo())
+ .unremovable()
+ .creator(FooCreator.class)
+ .done());
+ }
+ }).produces(SyntheticBeanBuildItem.class).build();
+ }
+ };
+ }
+
+ @Test
+ public void testBeanTypes() {
+ ArcContainer container = Arc.container();
+ Assertions.assertFalse(container.select(Foo.class).isResolvable());
+ Assertions.assertTrue(container.select(FooInterface.class).isResolvable());
+ }
+
+ @Vetoed
+ public static class Foo implements FooInterface {
+ }
+
+ interface FooInterface {
+ }
+
+ public static class FooCreator implements BeanCreator {
+
+ @Override
+ public Foo create(SyntheticCreationalContext context) {
+ return new Foo();
+ }
+
+ }
+}
diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/removeTypes/SyntheticBeanBuildItemRemoveTypesTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/removeTypes/SyntheticBeanBuildItemRemoveTypesTest.java
new file mode 100644
index 0000000000000..cbe724fbfc236
--- /dev/null
+++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/removeTypes/SyntheticBeanBuildItemRemoveTypesTest.java
@@ -0,0 +1,103 @@
+package io.quarkus.arc.test.synthetic.removeTypes;
+
+import java.util.function.Consumer;
+
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.Type;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.ArcContainer;
+import io.quarkus.arc.BeanCreator;
+import io.quarkus.arc.SyntheticCreationalContext;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.arc.processor.BuiltinScope;
+import io.quarkus.builder.BuildChainBuilder;
+import io.quarkus.builder.BuildContext;
+import io.quarkus.builder.BuildStep;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class SyntheticBeanBuildItemRemoveTypesTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClasses(SyntheticBeanBuildItemRemoveTypesTest.class, FooCreator.class, FooInterface.class, Foo.class,
+ FooSubclass.class, Charlie.class, CharlieSubclass.class, CharlieInterface.class, BarInterface.class,
+ BazInterface.class))
+ .addBuildChainCustomizer(buildCustomizer());
+
+ static Consumer buildCustomizer() {
+ return new Consumer() {
+
+ @Override
+ public void accept(BuildChainBuilder builder) {
+ builder.addBuildStep(new BuildStep() {
+
+ @Override
+ public void execute(BuildContext context) {
+ context.produce(SyntheticBeanBuildItem.create(FooSubclass.class)
+ .addTypeClosure(FooSubclass.class)
+ .removeTypes(DotName.createSimple(CharlieSubclass.class))
+ .removeTypes(DotName.createSimple(FooSubclass.class))
+ .removeTypes(Type.create(BazInterface.class))
+ .scope(BuiltinScope.SINGLETON.getInfo())
+ .unremovable()
+ .creator(FooCreator.class)
+ .done());
+ }
+ }).produces(SyntheticBeanBuildItem.class).build();
+ }
+ };
+ }
+
+ @Test
+ public void testRemovingBeanTypes() {
+ ArcContainer container = Arc.container();
+ Assertions.assertTrue(container.select(Foo.class).isResolvable());
+ Assertions.assertTrue(container.select(FooInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(BarInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(Charlie.class).isResolvable());
+ Assertions.assertTrue(container.select(CharlieInterface.class).isResolvable());
+
+ // CharlieSubclass, FooSubclass and BazInterface should not be registered as bean types
+ Assertions.assertFalse(container.select(CharlieSubclass.class).isResolvable());
+ Assertions.assertFalse(container.select(FooSubclass.class).isResolvable());
+ Assertions.assertFalse(container.select(BazInterface.class).isResolvable());
+ }
+
+ public static class FooSubclass extends Foo implements FooInterface {
+ }
+
+ public static class Foo extends Charlie implements BazInterface {
+ }
+
+ public static class CharlieSubclass extends Charlie {
+ }
+
+ public static class Charlie implements CharlieInterface {
+ }
+
+ interface CharlieInterface {
+ }
+
+ interface FooInterface extends BarInterface {
+ }
+
+ interface BarInterface {
+ }
+
+ interface BazInterface {
+ }
+
+ public static class FooCreator implements BeanCreator {
+
+ @Override
+ public FooSubclass create(SyntheticCreationalContext context) {
+ return new FooSubclass();
+ }
+
+ }
+}
diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/typeClosure/SyntheticBeanBuildItemAddTypeClosureGenericsTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/typeClosure/SyntheticBeanBuildItemAddTypeClosureGenericsTest.java
new file mode 100644
index 0000000000000..779aeff0de853
--- /dev/null
+++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/typeClosure/SyntheticBeanBuildItemAddTypeClosureGenericsTest.java
@@ -0,0 +1,129 @@
+package io.quarkus.arc.test.synthetic.typeClosure;
+
+import java.util.function.Consumer;
+
+import jakarta.enterprise.util.TypeLiteral;
+
+import org.jboss.jandex.ParameterizedType;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.ArcContainer;
+import io.quarkus.arc.BeanCreator;
+import io.quarkus.arc.SyntheticCreationalContext;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.arc.processor.BuiltinScope;
+import io.quarkus.builder.BuildChainBuilder;
+import io.quarkus.builder.BuildContext;
+import io.quarkus.builder.BuildStep;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class SyntheticBeanBuildItemAddTypeClosureGenericsTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClasses(SyntheticBeanBuildItemAddTypeClosureGenericsTest.class, FooCreator.class, FooInterface.class,
+ Foo.class,
+ FooSubclass.class, Charlie.class, CharlieSubclass.class, CharlieInterface.class, BarInterface.class,
+ BazInterface.class, Alpha.class, Beta.class))
+ .addBuildChainCustomizer(buildCustomizer());
+
+ static Consumer buildCustomizer() {
+ return new Consumer() {
+
+ @Override
+ public void accept(BuildChainBuilder builder) {
+ builder.addBuildStep(new BuildStep() {
+
+ @Override
+ public void execute(BuildContext context) {
+ context.produce(SyntheticBeanBuildItem.create(FooSubclass.class)
+ .addTypeClosure(ParameterizedType.builder(FooSubclass.class).addArgument(Beta.class).build())
+ .scope(BuiltinScope.SINGLETON.getInfo())
+ .unremovable()
+ .creator(FooCreator.class)
+ .done());
+ }
+ }).produces(SyntheticBeanBuildItem.class).build();
+ }
+ };
+ }
+
+ @Test
+ public void testBeanTypesDiscovered() {
+ ArcContainer container = Arc.container();
+
+ // Foo/Bar/Baz interfaces should work normally, no generics there
+ Assertions.assertTrue(container.select(FooInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(BarInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(BazInterface.class).isResolvable());
+
+ // FooSubclass is resolvable only as correct parameterized type
+ Assertions.assertTrue(container.select(new TypeLiteral>() {
+ }).isResolvable());
+ Assertions.assertFalse(container.select(new TypeLiteral>() {
+ }).isResolvable());
+ Assertions.assertFalse(container.select(FooSubclass.class).isResolvable());
+
+ // Foo type should work only parameterized
+ Assertions.assertTrue(container.select(new TypeLiteral>() {
+ }).isResolvable());
+ Assertions.assertFalse(container.select(Foo.class).isResolvable());
+
+ // Foo extends Charlie raw type
+ // we should be able to perform resolution for raw type but not for a parameterized type
+ Assertions.assertTrue(container.select(Charlie.class).isResolvable());
+ Assertions.assertTrue(container.select(CharlieInterface.class).isResolvable());
+ Assertions.assertFalse(container.select(new TypeLiteral>() {
+ }).isResolvable());
+ Assertions.assertFalse(container.select(new TypeLiteral>() {
+ }).isResolvable());
+
+ // CharlieSubclass should not be discovered as bean type
+ Assertions.assertFalse(container.select(CharlieSubclass.class).isResolvable());
+ }
+
+ public static class Alpha {
+
+ }
+
+ public static class Beta {
+
+ }
+
+ public static class FooSubclass extends Foo implements FooInterface {
+ }
+
+ public static class Foo extends Charlie implements BazInterface {
+ }
+
+ public static class CharlieSubclass extends Charlie {
+ }
+
+ public static class Charlie implements CharlieInterface {
+ }
+
+ interface CharlieInterface {
+ }
+
+ interface FooInterface extends BarInterface {
+ }
+
+ interface BarInterface {
+ }
+
+ interface BazInterface {
+ }
+
+ public static class FooCreator implements BeanCreator> {
+
+ @Override
+ public FooSubclass create(SyntheticCreationalContext> context) {
+ return new FooSubclass();
+ }
+
+ }
+}
diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/typeClosure/SyntheticBeanBuildItemAddTypeClosureTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/typeClosure/SyntheticBeanBuildItemAddTypeClosureTest.java
new file mode 100644
index 0000000000000..3801726f44eb7
--- /dev/null
+++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/synthetic/typeClosure/SyntheticBeanBuildItemAddTypeClosureTest.java
@@ -0,0 +1,100 @@
+package io.quarkus.arc.test.synthetic.typeClosure;
+
+import java.util.function.Consumer;
+
+import org.jboss.jandex.DotName;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.ArcContainer;
+import io.quarkus.arc.BeanCreator;
+import io.quarkus.arc.SyntheticCreationalContext;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.arc.processor.BuiltinScope;
+import io.quarkus.builder.BuildChainBuilder;
+import io.quarkus.builder.BuildContext;
+import io.quarkus.builder.BuildStep;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class SyntheticBeanBuildItemAddTypeClosureTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClasses(SyntheticBeanBuildItemAddTypeClosureTest.class, FooCreator.class, FooInterface.class, Foo.class,
+ FooSubclass.class, Charlie.class, CharlieSubclass.class, CharlieInterface.class, BarInterface.class,
+ BazInterface.class))
+ .addBuildChainCustomizer(buildCustomizer());
+
+ static Consumer buildCustomizer() {
+ return new Consumer() {
+
+ @Override
+ public void accept(BuildChainBuilder builder) {
+ builder.addBuildStep(new BuildStep() {
+
+ @Override
+ public void execute(BuildContext context) {
+ context.produce(SyntheticBeanBuildItem.create(FooSubclass.class)
+ .addTypeClosure(FooInterface.class)
+ .addTypeClosure(DotName.createSimple(Foo.class))
+ .scope(BuiltinScope.SINGLETON.getInfo())
+ .unremovable()
+ .creator(FooCreator.class)
+ .done());
+ }
+ }).produces(SyntheticBeanBuildItem.class).build();
+ }
+ };
+ }
+
+ @Test
+ public void testBeanTypesDiscovered() {
+ ArcContainer container = Arc.container();
+ Assertions.assertTrue(container.select(Foo.class).isResolvable());
+ Assertions.assertTrue(container.select(FooInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(BarInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(Charlie.class).isResolvable());
+ Assertions.assertTrue(container.select(CharlieInterface.class).isResolvable());
+ Assertions.assertTrue(container.select(BazInterface.class).isResolvable());
+
+ // Charlie and Foo subclasses should not be registered as bean types
+ Assertions.assertFalse(container.select(CharlieSubclass.class).isResolvable());
+ Assertions.assertFalse(container.select(FooSubclass.class).isResolvable());
+ }
+
+ public static class FooSubclass extends Foo implements FooInterface {
+ }
+
+ public static class Foo extends Charlie implements BazInterface {
+ }
+
+ public static class CharlieSubclass extends Charlie {
+ }
+
+ public static class Charlie implements CharlieInterface {
+ }
+
+ interface CharlieInterface {
+ }
+
+ interface FooInterface extends BarInterface {
+ }
+
+ interface BarInterface {
+ }
+
+ interface BazInterface {
+ }
+
+ public static class FooCreator implements BeanCreator {
+
+ @Override
+ public FooSubclass create(SyntheticCreationalContext context) {
+ return new FooSubclass();
+ }
+
+ }
+}
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java
index 156df45341604..80f7b6add09fd 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java
@@ -85,6 +85,14 @@ public void done() {
.build());
}
+ // perform type discovery for registered types
+ for (Type jandexType : registeredTypeClosures) {
+ this.types.addAll(Types.getTypeClosureFromJandexType(jandexType, beanDeployment).unrestrictedTypes());
+ }
+
+ // restrict resulting bean types if needed
+ this.types.removeAll(typesToRemove);
+
BeanInfo.Builder builder = new BeanInfo.Builder()
.implClazz(implClass)
.identifier(identifier)
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
index 84644292fd52a..f2992031c8ba4 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
@@ -45,6 +45,8 @@ public abstract class BeanConfiguratorBase types;
+ protected final Set registeredTypeClosures;
+ protected final Set typesToRemove;
protected final Set qualifiers;
protected ScopeInfo scope;
protected Boolean alternative;
@@ -66,6 +68,8 @@ public abstract class BeanConfiguratorBase();
+ this.registeredTypeClosures = new HashSet<>();
+ this.typesToRemove = new HashSet<>();
this.qualifiers = new HashSet<>();
this.stereotypes = new ArrayList<>();
this.removable = true;
@@ -83,6 +87,10 @@ public THIS read(BeanConfiguratorBase, ?> base) {
identifier = base.identifier;
types.clear();
types.addAll(base.types);
+ registeredTypeClosures.clear();
+ registeredTypeClosures.addAll(base.registeredTypeClosures);
+ typesToRemove.clear();
+ typesToRemove.addAll(base.typesToRemove);
qualifiers.clear();
qualifiers.addAll(base.qualifiers);
scope = base.scope;
@@ -134,6 +142,74 @@ public THIS addType(Class> type) {
return addType(DotName.createSimple(type.getName()));
}
+ /**
+ * Adds an unrestricted set of bean types for the given type as if it represented a bean class of a managed bean.
+ *
+ * @param typeName {@link DotName} representation of a class that should be scanned for types
+ * @return self
+ */
+ public THIS addTypeClosure(DotName typeName) {
+ return addTypeClosure(Type.create(typeName, Kind.CLASS));
+ }
+
+ /**
+ * Adds an unrestricted set of bean types for the given type as if it represented a bean class of a managed bean.
+ *
+ * @param type a class that should be scanned for types
+ * @return self
+ */
+ public THIS addTypeClosure(Class> type) {
+ return addTypeClosure(Type.create(type));
+ }
+
+ /**
+ * Adds an unrestricted set of bean types for the given type as if it represented a bean class of a managed bean.
+ *
+ * @param type {@link Type} representation of a class that should be scanned for types
+ * @return self
+ */
+ public THIS addTypeClosure(Type type) {
+ this.registeredTypeClosures.add(type);
+ return self();
+ }
+
+ /**
+ * Removes listed types from the resulting types of the synthetic bean.
+ *
+ * @param types types that should be removed from the resulting set of bean types
+ * @return self
+ */
+ public THIS removeTypes(Class>... types) {
+ for (Class> classType : types) {
+ removeTypes(Type.create(classType));
+ }
+ return self();
+ }
+
+ /**
+ * Removes listed types from the resulting types of the synthetic bean.
+ *
+ * @param types types that should be removed from the resulting set of bean types
+ * @return self
+ */
+ public THIS removeTypes(DotName... types) {
+ for (DotName name : types) {
+ removeTypes(Type.create(name, Kind.CLASS));
+ }
+ return self();
+ }
+
+ /**
+ * Removes listed types from the resulting types of the synthetic bean.
+ *
+ * @param types types that should be removed from the resulting set of bean types
+ * @return self
+ */
+ public THIS removeTypes(Type... types) {
+ Collections.addAll(this.typesToRemove, types);
+ return self();
+ }
+
public THIS addQualifier(Class extends Annotation> annotationClass) {
return addQualifier(DotName.createSimple(annotationClass.getName()));
}
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java
index fb21183066102..c1307f808b520 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java
@@ -25,7 +25,7 @@ interface RegistrationContext extends BuildContext {
* Configure a new synthetic bean. The bean is not added to the deployment unless the {@link BeanConfigurator#done()}
* method is called.
*
- * @param beanClass
+ * @param beanClassName
* @return a new synthetic bean configurator
*/
BeanConfigurator configure(DotName beanClassName);
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java
index a2018013dc4c4..e085ef67e1516 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java
@@ -522,6 +522,38 @@ record TypeClosure(Set types, Set unrestrictedTypes) {
}
}
+ static TypeClosure getTypeClosureFromJandexType(Type jandexType, BeanDeployment beanDeployment) {
+ Set types;
+ Set unrestrictedBeanTypes = new HashSet<>();
+ if (jandexType.kind() == Kind.TYPE_VARIABLE) {
+ throw new IllegalStateException("A type variable is not a legal bean type");
+ }
+ if (jandexType.kind() == Kind.PRIMITIVE || jandexType.kind() == Kind.ARRAY) {
+ types = new HashSet<>();
+ types.add(jandexType);
+ types.add(OBJECT_TYPE);
+ return new TypeClosure(types);
+ } else {
+ ClassInfo jandexTypeClassInfo = getClassByName(beanDeployment.getBeanArchiveIndex(), jandexType);
+ if (jandexTypeClassInfo == null) {
+ throw new IllegalArgumentException(
+ "Provided Jandex type not found in index: " + jandexType.name());
+ }
+ if (Kind.CLASS.equals(jandexType.kind())) {
+ types = getTypeClosure(jandexTypeClassInfo, null, Collections.emptyMap(), beanDeployment, null,
+ unrestrictedBeanTypes);
+ } else if (Kind.PARAMETERIZED_TYPE.equals(jandexType.kind())) {
+ types = getTypeClosure(jandexTypeClassInfo, null,
+ buildResolvedMap(jandexType.asParameterizedType().arguments(), jandexTypeClassInfo.typeParameters(),
+ Collections.emptyMap(), beanDeployment.getBeanArchiveIndex()),
+ beanDeployment, null, unrestrictedBeanTypes);
+ } else {
+ throw new IllegalArgumentException("Unsupported return type");
+ }
+ }
+ return new TypeClosure(types, unrestrictedBeanTypes);
+ }
+
static Set getClassUnrestrictedTypeClosure(ClassInfo classInfo, BeanDeployment beanDeployment) {
Set types;
Set unrestrictedBeanTypes = new HashSet<>();