Repository: avaje/avaje-inject (java)

Issue:
Duplicate class names
There are two classes with the same name in different packages, causing the dependency injection module to malfunction.

```
/Users/yein/work/mahu/mahu-admin/mahu-admin-web/build/generated/sources/annotationProcessor/java/main/cool/houge/mahu/admin/MahuAdminModule.java:26: error: The single-type-import of DictController$DI has already defined a type with the same simple name
import cool.houge.mahu.admin.controller.system.DictController$DI;
^
/Users/yein/work/mahu/mahu-admin/mahu-admin-web/build/generated/sources/annotationProcessor/java/main/cool/houge/mahu/admin/MahuAdminModule.java:216: error: Reference to DictController$DI is ambiguous
    DictController$DI.build(builder);
    ^
  Both class cool.houge.mahu.admin.controller.DictController$DI from cool.houge.mahu.admin.controller and class cool.houge.mahu.admin.controller.system.DictController$DI from cool.houge.mahu.admin.controller.system match
/Users/yein/work/mahu/mahu-admin/mahu-admin-web/build/generated/sources/annotationProcessor/java/main/cool/houge/mahu/admin/MahuAdminModule.java:452: error: Reference to DictController$DI is ambiguous
    DictController$DI.build(builder);
```

This is a Java compilation error caused by having two inner classes named DictController$DI in different packages:
1. cool.houge.mahu.admin.controller.DictController$DI
2. cool.houge.mahu.admin.controller.system.DictController$DI

Pull request:
Fix duplicate short names in Module Generation
Now will fully qualify when a short name conflicts.

fixes #794 

Patch:
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/MetaData.java b/inject-generator/src/main/java/io/avaje/inject/generator/MetaData.java
index f2845fe2..26698f81 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/MetaData.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/MetaData.java
@@ -222,7 +222,7 @@ final class MetaData implements Comparable<MetaData> {
     }
   }
 
-  void buildMethod(Append append) {
+  void buildMethod(Append append, boolean fullyQualify) {
     if (generateProxy) {
       return;
     }
@@ -273,7 +273,7 @@ final class MetaData implements Comparable<MetaData> {
     if (hasMethod()) {
       append.append("    ").append(Util.shortMethod(method)).append("(builder");
     } else {
-      append.append("    ").append(shortType).append(Constants.DI).append(".build(builder");
+      append.append("    ").append(fullyQualify ? type : shortType).append(Constants.DI).append(".build(builder");
     }
     append.append(");").append(NEWLINE);
     append.append("  }").append(NEWLINE);
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java
index 4811f455..73bee4a8 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java
@@ -3,14 +3,17 @@ package io.avaje.inject.generator;
 import static io.avaje.inject.generator.APContext.logError;
 import static io.avaje.inject.generator.APContext.typeElement;
 import static io.avaje.inject.generator.ProcessingContext.createMetaInfWriterFor;
+import static java.util.stream.Collectors.toSet;
 
 import java.io.IOException;
 import java.io.Writer;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.stream.Stream;
 
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.TypeElement;
@@ -52,6 +55,7 @@ final class SimpleModuleWriter {
   private final String fullName;
   private final ScopeInfo scopeInfo;
   private final MetaDataOrdering ordering;
+  private final Set<String> duplicateTypes;
 
   private Append writer;
 
@@ -61,6 +65,13 @@ final class SimpleModuleWriter {
     this.modulePackage = scopeInfo.modulePackage();
     this.shortName = scopeInfo.moduleShortName();
     this.fullName = scopeInfo.moduleFullName();
+    final Set<String> seen = new HashSet<>();
+    this.duplicateTypes =
+      ordering.ordered().stream()
+        .map(MetaData::type)
+        .filter(t -> !seen.add(ProcessorUtils.shortType(t)))
+        .flatMap(t -> Stream.of(t, t + "$DI"))
+        .collect(toSet());
   }
 
   void write(ScopeInfo.Type scopeType) throws IOException {
@@ -183,7 +194,7 @@ final class SimpleModuleWriter {
 
   private void writeBuildMethods() {
     for (MetaData metaData : ordering.ordered()) {
-      metaData.buildMethod(writer);
+      metaData.buildMethod(writer, duplicateTypes.contains(metaData.type()));
     }
   }
 
@@ -192,8 +203,9 @@ final class SimpleModuleWriter {
     for (String type : factoryImportTypes()) {
       writer.append("import %s;", type).eol();
     }
+
     for (String type : scopeInfo.initModuleDependencies(ordering.importTypes())) {
-      if (Util.validImportType(type, modulePackage)) {
+      if (!duplicateTypes.contains(type) && Util.validImportType(type, modulePackage)) {
         writer.append("import %s;", type).eol();
       }
     }


Test patch:
diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/duplicate/SameType.java b/blackbox-test-inject/src/main/java/org/example/myapp/duplicate/SameType.java
new file mode 100644
index 00000000..7a2c4867
--- /dev/null
+++ b/blackbox-test-inject/src/main/java/org/example/myapp/duplicate/SameType.java
@@ -0,0 +1,9 @@
+package org.example.myapp.duplicate;
+
+import jakarta.inject.Singleton;
+
+@Singleton
+public class SameType {
+  @Singleton
+  public static class Inner {}
+}
diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/duplicate/two/SameType.java b/blackbox-test-inject/src/main/java/org/example/myapp/duplicate/two/SameType.java
new file mode 100644
index 00000000..6b0f176b
--- /dev/null
+++ b/blackbox-test-inject/src/main/java/org/example/myapp/duplicate/two/SameType.java
@@ -0,0 +1,9 @@
+package org.example.myapp.duplicate.two;
+
+import jakarta.inject.Singleton;
+
+@Singleton
+public class SameType {
+  @Singleton
+  public static class Inner {}
+}
diff --git a/blackbox-test-inject/src/test/java/org/example/myapp/duplicate/SameTypeTest.java b/blackbox-test-inject/src/test/java/org/example/myapp/duplicate/SameTypeTest.java
new file mode 100644
index 00000000..2710f4a0
--- /dev/null
+++ b/blackbox-test-inject/src/test/java/org/example/myapp/duplicate/SameTypeTest.java
@@ -0,0 +1,26 @@
+package org.example.myapp.duplicate;
+
+import io.avaje.inject.BeanScope;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+class SameTypeTest {
+
+  @Test
+  void testDuplicateShortName() {
+    try (BeanScope testScope = BeanScope.builder().build()) {
+
+      var sameType = testScope.get(SameType.class);
+      var sameTypeInner = testScope.get(SameType.Inner.class);
+      var sameType2 = testScope.get(org.example.myapp.duplicate.two.SameType.class);
+      var sameType2Inner = testScope.get(org.example.myapp.duplicate.two.SameType.Inner.class);
+
+      assertThat(sameType).isNotNull();
+      assertThat(sameTypeInner).isNotNull();
+      assertThat(sameType2).isNotNull();
+      assertThat(sameType2Inner).isNotNull();
+    }
+  }
+}
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/duplicate/SameType.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/duplicate/SameType.java
new file mode 100644
index 00000000..d155644b
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/duplicate/SameType.java
@@ -0,0 +1,9 @@
+package io.avaje.inject.generator.models.valid.duplicate;
+
+import jakarta.inject.Singleton;
+
+@Singleton
+public class SameType {
+  @Singleton
+  public static class Inner {}
+}
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/duplicate/two/SameType.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/duplicate/two/SameType.java
new file mode 100644
index 00000000..994cc543
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/duplicate/two/SameType.java
@@ -0,0 +1,9 @@
+package io.avaje.inject.generator.models.valid.duplicate.two;
+
+import jakarta.inject.Singleton;
+
+@Singleton
+public class SameType {
+  @Singleton
+  public static class Inner {}
+}