Repository: avaje/avaje-inject
Pull request #198 (2022-04-27 05:51:30)

#197 - Bug isAddBeanFor() generated code includes package protected class and interface


Patch:
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java
index fa16441e..02d97120 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java
@@ -1,6 +1,7 @@
 package io.avaje.inject.generator;
 
 import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 import java.util.ArrayList;
@@ -117,8 +118,10 @@ class TypeExtendsReader {
     if (!fullName.equals(JAVA_LANG_OBJECT)) {
       String type = Util.unwrapProvider(fullName);
       if (!GenericType.isGeneric(type)) {
-        extendsTypes.add(type);
-        extendsInjection.read(element);
+        if (isPublic(element)) {
+          extendsTypes.add(type);
+          extendsInjection.read(element);
+        }
         addSuperType(superOf(element));
       }
     }
@@ -130,26 +133,33 @@ class TypeExtendsReader {
 
   private void readInterfaces(TypeElement type) {
     for (TypeMirror anInterface : type.getInterfaces()) {
-      String rawType = Util.unwrapProvider(anInterface.toString());
-      if (rawType.indexOf('.') == -1) {
-        context.logWarn("skip when no package on interface " + rawType);
-      } else if (Constants.AUTO_CLOSEABLE.equals(rawType) || Constants.IO_CLOSEABLE.equals(rawType)) {
-        closeable = true;
-      } else {
-        rawType = GenericType.removeParameter(rawType);
-        if (qualifierName == null) {
-          final String iShortName = Util.shortName(rawType);
-          if (beanSimpleName.endsWith(iShortName)) {
-            // derived qualifier name based on prefix to interface short name
-            qualifierName = beanSimpleName.substring(0, beanSimpleName.length() - iShortName.length()).toLowerCase();
+      Element element = context.asElement(anInterface);
+      if (isPublic(element)) {
+        String rawType = Util.unwrapProvider(anInterface.toString());
+        if (rawType.indexOf('.') == -1) {
+          context.logWarn("skip when no package on interface " + rawType);
+        } else if (Constants.AUTO_CLOSEABLE.equals(rawType) || Constants.IO_CLOSEABLE.equals(rawType)) {
+          closeable = true;
+        } else {
+          rawType = GenericType.removeParameter(rawType);
+          if (qualifierName == null) {
+            final String iShortName = Util.shortName(rawType);
+            if (beanSimpleName.endsWith(iShortName)) {
+              // derived qualifier name based on prefix to interface short name
+              qualifierName = beanSimpleName.substring(0, beanSimpleName.length() - iShortName.length()).toLowerCase();
+            }
           }
+          interfaceTypes.add(rawType);
+          readExtendedInterfaces(rawType);
         }
-        interfaceTypes.add(rawType);
-        readExtendedInterfaces(rawType);
       }
     }
   }
 
+  private boolean isPublic(Element element) {
+    return element != null && element.getModifiers().contains(Modifier.PUBLIC);
+  }
+
   private void readExtendedInterfaces(String type) {
     GenericType genericType = GenericType.parse(type);
     final TypeElement element = context.element(genericType.topType());


Test patch:
diff --git a/inject-test/src/test/java/org/example/inherit/InhPub.java b/inject-test/src/test/java/org/example/inherit/InhPub.java
new file mode 100644
index 00000000..cfe7d819
--- /dev/null
+++ b/inject-test/src/test/java/org/example/inherit/InhPub.java
@@ -0,0 +1,14 @@
+package org.example.inherit;
+
+import io.avaje.inject.Bean;
+import io.avaje.inject.Factory;
+import org.example.inherit.notpublic.PubExposed;
+
+@Factory
+public class InhPub  {
+
+  @Bean
+  PubExposed exposed() {
+    return new PubExposed();
+  }
+}
diff --git a/inject-test/src/test/java/org/example/inherit/InhPubTest.java b/inject-test/src/test/java/org/example/inherit/InhPubTest.java
new file mode 100644
index 00000000..ab1a1e07
--- /dev/null
+++ b/inject-test/src/test/java/org/example/inherit/InhPubTest.java
@@ -0,0 +1,20 @@
+package org.example.inherit;
+
+import io.avaje.inject.xtra.ApplicationScope;
+import org.example.inherit.notpublic.PubExposed;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class InhPubTest {
+
+  @Test
+  void test() {
+    final InhPub one = ApplicationScope.get(InhPub.class);
+    PubExposed exposed = one.exposed();
+
+    assertThat(exposed).isNotNull();
+    assertThat(exposed.hello()).isEqualTo("hello");
+    assertThat(exposed.ifaceMethod()).isEqualTo("ifaceMethod");
+  }
+}
diff --git a/inject-test/src/test/java/org/example/inherit/notpublic/NonPubBase.java b/inject-test/src/test/java/org/example/inherit/notpublic/NonPubBase.java
new file mode 100644
index 00000000..c34fc084
--- /dev/null
+++ b/inject-test/src/test/java/org/example/inherit/notpublic/NonPubBase.java
@@ -0,0 +1,11 @@
+package org.example.inherit.notpublic;
+
+/**
+ * Package protected (NOT public)
+ */
+class NonPubBase {
+
+  public String hello() {
+    return "hello";
+  }
+}
diff --git a/inject-test/src/test/java/org/example/inherit/notpublic/NonPubIface.java b/inject-test/src/test/java/org/example/inherit/notpublic/NonPubIface.java
new file mode 100644
index 00000000..8c215336
--- /dev/null
+++ b/inject-test/src/test/java/org/example/inherit/notpublic/NonPubIface.java
@@ -0,0 +1,6 @@
+package org.example.inherit.notpublic;
+
+interface NonPubIface {
+
+  String ifaceMethod();
+}
diff --git a/inject-test/src/test/java/org/example/inherit/notpublic/PubExposed.java b/inject-test/src/test/java/org/example/inherit/notpublic/PubExposed.java
new file mode 100644
index 00000000..7276895a
--- /dev/null
+++ b/inject-test/src/test/java/org/example/inherit/notpublic/PubExposed.java
@@ -0,0 +1,15 @@
+package org.example.inherit.notpublic;
+
+/**
+ * Extends a package protected class, implements package protected interface.
+ * <p>
+ * Neither should be including in the generated isAddBeanFor().
+ */
+public class PubExposed extends NonPubBase implements NonPubIface {
+
+  @Override
+  public String ifaceMethod() {
+    return "ifaceMethod";
+  }
+
+}