Repository: avaje/avaje-inject
Pull request #363 (2023-07-04 04:53:57)

Fix typeuse annotations not getting trimmed properly
It seems that our trim functions were not designed to handle type_use.

Use regex to trim annotations.
Use regex to sanitize imports.

SentryMan: actually hmmm
SentryMan: it seems we shall need to find a better regex
SentryMan: I'm good with this

Patch:
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/Util.java b/inject-generator/src/main/java/io/avaje/inject/generator/Util.java
index 82dcf50a..ca7d3673 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/Util.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/Util.java
@@ -1,15 +1,23 @@
 package io.avaje.inject.generator;
 
-import java.util.Optional;
 import static io.avaje.inject.generator.ProcessingContext.isImportedType;
 
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
 
 final class Util {
-
+  // whitespace not in quotes
+  private static final Pattern WHITE_SPACE_REGEX =
+      Pattern.compile("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
+  // comma not in quotes
+  private static final Pattern COMMA_PATTERN =
+      Pattern.compile(", (?=(?:[^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)");
   static final String ASPECT_PROVIDER_PREFIX = "io.avaje.inject.aop.AspectProvider<";
   static final String PROVIDER_PREFIX = "jakarta.inject.Provider<";
   private static final String OPTIONAL_PREFIX = "java.util.Optional<";
@@ -49,23 +57,38 @@ final class Util {
     return type.substring(0, i);
   }
 
-
   /** Trim off annotations from the raw type if present. */
-  public static String trimAnnotations(String type) {
-    final int pos = type.indexOf(".@");
+  public static String trimAnnotations(String input) {
+
+    input = COMMA_PATTERN.matcher(input).replaceAll(",");
+
+    return cutAnnotations(input);
+  }
+
+  private static String cutAnnotations(String input) {
+    final int pos = input.indexOf("@");
     if (pos == -1) {
-      return type;
+      return input;
     }
-    return type.substring(0, pos + 1) + type.substring(type.lastIndexOf(' ') + 1);
+
+    final Matcher matcher = WHITE_SPACE_REGEX.matcher(input);
+
+    int currentIndex = 0;
+    if (matcher.find()) {
+      currentIndex = matcher.start();
+    }
+    final var result = input.substring(0, pos) + input.substring(currentIndex + 1);
+
+    return cutAnnotations(result);
   }
 
   public static String sanitizeImports(String type) {
     final int pos = type.indexOf("@");
     if (pos == -1) {
-      return type.replace("[]", "");
+      return type.replaceAll("[^\\n\\r\\t $;\\w.]", "");
     }
     final var start = pos == 0 ? type.substring(0, pos) : "";
-    return start + type.substring(type.lastIndexOf(' ') + 1).replace("[]", "");
+    return start + type.substring(type.lastIndexOf(' ') + 1).replaceAll("[^\\n\\r\\t $;\\w.]", "");
   }
 
   static String nestedPackageOf(String cls) {


Test patch:
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/UtilTest.java b/inject-generator/src/test/java/io/avaje/inject/generator/UtilTest.java
index 34a3f074..033b4a4d 100644
--- a/inject-generator/src/test/java/io/avaje/inject/generator/UtilTest.java
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/UtilTest.java
@@ -120,6 +120,26 @@ class UtilTest {
     assertTrue(Util.validImportType("other.pack.Foo"));
   }
 
+  @Test
+  void trimmedAnnotation() {
+
+  assertEquals(
+        "java.util.Map<java.lang.String,java.lang.String>",
+        Util.trimAnnotations(
+            "java.util.@io.avaje.validation.constraints.NotEmpty(message=\"sus \", groups={io.avaje.validation.generator.models.valid.Ship.class}) Map<java.lang.@io.avaje.validation.constraints.NotEmpty(groups={io.avaje.validation.generator.models.valid.Ship.class}),@io.avaje.validation.constraints.NotBlank String,java.lang.@io.avaje.validation.constraints.NotBlank(groups={io.avaje.validation.generator.models.valid.Ship.class}),@io.avaje.validation.Valid String>"));
+
+    assertEquals(
+        "java.util.List<java.lang.String>",
+        Util.trimAnnotations(
+            "java.util.@jakarta.validation.constraints.NotEmpty(\"message(); ,\") List<java.lang.@jakarta.validation.constraints.NotNull String>"));
+    assertEquals("int", Util.trimAnnotations("@jakarta.validation.constraints.Positive int"));
+    assertEquals(
+        "java.util.Map<java.lang.String,java.lang.String>",
+        Util.trimAnnotations(
+            "java.util.Map<@jakarta.validation.constraints.Positive(message=\"sus \", groups=1) java.lang.String,java.lang.String>"));
+
+    }
+
   @Test
   void validImportType_not() {
     assertFalse(Util.validImportType("void"));
@@ -159,5 +179,6 @@ class UtilTest {
     assertEquals("my.Foo", Util.sanitizeImports("@annotationMcgee my.Foo"));
     assertEquals("my.Foo", Util.sanitizeImports("@org.bar.annotationMcgee my.Foo[]"));
     assertEquals("my.Foo", Util.sanitizeImports("@org.bar.annotationMcgee my.Foo"));
+    assertEquals("java.util.String", Util.sanitizeImports("java.util.String>"));
   }
 }
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/MethodTest.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/MethodTest.java
new file mode 100644
index 00000000..f75d4741
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/MethodTest.java
@@ -0,0 +1,13 @@
+package io.avaje.inject.generator.models.valid.aspect;
+
+import java.util.Map;
+
+import io.avaje.inject.Component;
+import io.avaje.inject.generator.models.valid.Timed;
+
+@Component
+public class MethodTest {
+
+  @Timed
+  void test(@Param Map<@TypeUse String, String> str, @Param int inty, String regular) {}
+}
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/Param.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/Param.java
new file mode 100644
index 00000000..c286f529
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/Param.java
@@ -0,0 +1,3 @@
+package io.avaje.inject.generator.models.valid.aspect;
+
+public @interface Param {}
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/TypeUse.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/TypeUse.java
new file mode 100644
index 00000000..d7aa1c41
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/aspect/TypeUse.java
@@ -0,0 +1,11 @@
+package io.avaje.inject.generator.models.valid.aspect;
+
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target(TYPE_USE)
+@Retention(RUNTIME)
+public @interface TypeUse {}