Repository: avaje/avaje-inject
Pull request #302 (2023-02-28 01:27:40)

Component Import Annotaion
Adds an annotation to import types and generate DI classes for them.


Patch:
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/Processor.java b/inject-generator/src/main/java/io/avaje/inject/generator/Processor.java
index 79cdb982..949f8e81 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/Processor.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/Processor.java
@@ -23,7 +23,6 @@ import javax.lang.model.element.TypeElement;
 import javax.lang.model.util.Elements;
 import javax.tools.StandardLocation;
 
-
 @SupportedAnnotationTypes({
   Constants.INJECTMODULE,
   Constants.FACTORY,
@@ -33,6 +32,7 @@ import javax.tools.StandardLocation;
   Constants.SCOPE,
   Constants.TESTSCOPE,
   Constants.CONTROLLER,
+  ImportPrism.PRISM_TYPE
 })
 public final class Processor extends AbstractProcessor {
 
@@ -97,6 +97,19 @@ public final class Processor extends AbstractProcessor {
     }
     readChangedBeans(roundEnv.getElementsAnnotatedWith(context.element(Constants.COMPONENT)), false);
     readChangedBeans(roundEnv.getElementsAnnotatedWith(context.element(Constants.PROTOTYPE)), false);
+   
+    final var importedElements =
+        roundEnv.getElementsAnnotatedWith(context.element(ImportPrism.PRISM_TYPE)).stream()
+            .map(ImportPrism::getInstanceOn)
+            .flatMap(p -> p.value().stream())
+            .map(context::asElement)
+            .map(TypeElement.class::cast)
+            .collect(Collectors.toSet());
+
+    readChangedBeans(importedElements, false);
+
+    readChangedBeans(
+        roundEnv.getElementsAnnotatedWith(context.element(Constants.PROTOTYPE)), false);
     final var typeElement = elementUtils.getTypeElement(Constants.CONTROLLER);
     if (typeElement != null) {
       readChangedBeans(roundEnv.getElementsAnnotatedWith(typeElement), false);
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java b/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java
index 28b3bbc3..9e6cc2cc 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java
@@ -2,6 +2,7 @@
 @GeneratePrism(Factory.class)
 @GeneratePrism(Singleton.class)
 @GeneratePrism(Component.class)
+@GeneratePrism(Component.Import.class)
 @GeneratePrism(Prototype.class)
 @GeneratePrism(Scope.class)
 @GeneratePrism(Qualifier.class)
diff --git a/inject/src/main/java/io/avaje/inject/Component.java b/inject/src/main/java/io/avaje/inject/Component.java
index c29051f5..d5f50c7c 100644
--- a/inject/src/main/java/io/avaje/inject/Component.java
+++ b/inject/src/main/java/io/avaje/inject/Component.java
@@ -1,5 +1,7 @@
 package io.avaje.inject;
 
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -46,4 +48,26 @@ import java.lang.annotation.Target;
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Component {
+
+  /**
+   * Specify types to generate DI classes for.
+   *
+   * <p>These types are typically in an external project / dependency or otherwise types that we
+   * can't or don't want to explicitly annotate with {@code @Singleton}/{@code @Component}.
+   *
+   * <p>Typically, we put this annotation on a package.
+   *
+   * <pre>{@code
+   * Component.Import({Customer.class, Product.class, ...})
+   * package org.example.processor;
+   *
+   * }</pre>
+   */
+  @Retention(CLASS)
+  @Target({ElementType.TYPE, ElementType.PACKAGE})
+  @interface Import {
+
+    /** Specify types to generate DI classes for. */
+    Class<?>[] value();
+  }
 }


Test patch:
diff --git a/inject-test/src/test/java/org/example/autonamed/MyAutoB2.java b/inject-test/src/test/java/org/example/autonamed/MyAutoB2.java
index 9286d254..0d3eef01 100644
--- a/inject-test/src/test/java/org/example/autonamed/MyAutoB2.java
+++ b/inject-test/src/test/java/org/example/autonamed/MyAutoB2.java
@@ -1,8 +1,5 @@
 package org.example.autonamed;
 
-import jakarta.inject.Singleton;
-
-@Singleton
 public class MyAutoB2 {
 
   final AutoB2 one;
diff --git a/inject-test/src/test/java/org/example/autonamed/MyAutoB2Explicit.java b/inject-test/src/test/java/org/example/autonamed/MyAutoB2Explicit.java
index c5b87de6..0ec87c88 100644
--- a/inject-test/src/test/java/org/example/autonamed/MyAutoB2Explicit.java
+++ b/inject-test/src/test/java/org/example/autonamed/MyAutoB2Explicit.java
@@ -1,9 +1,11 @@
 package org.example.autonamed;
 
+import io.avaje.inject.Component;
 import jakarta.inject.Named;
 import jakarta.inject.Singleton;
 
 @Singleton
+@Component.Import(MyAutoB2.class)
 public class MyAutoB2Explicit {
 
   final AutoB2 one;