Skip to content

Commit b4f5067

Browse files
committed
jooby-apt: should NOT generate metadata for defaults annotation attributes
- ref #3525 - fix #3526
1 parent 0811e9b commit b4f5067

13 files changed

Lines changed: 87 additions & 25 deletions

File tree

modules/jooby-apt/src/main/java/io/jooby/apt/JoobyProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
108108
verifyBeanValidationDependency(routeMap.values());
109109
for (var router : routeMap.values()) {
110110
try {
111+
context.add(router);
111112
var sourceCode = router.toSourceCode(null);
112113
var sourceLocation = router.getGeneratedFilename();
113114
onGeneratedSource(toJavaFileObject(sourceLocation, sourceCode));
114115
context.debug("router %s: %s", router.getTargetType(), router.getGeneratedType());
115116
router.getRoutes().forEach(it -> context.debug(" %s", it));
116117
writeSource(router, sourceLocation, sourceCode);
117-
context.add(router);
118118
} catch (IOException cause) {
119119
throw new RuntimeException("Unable to generate: " + router.getTargetType(), cause);
120120
}

modules/jooby-apt/src/main/java/io/jooby/internal/apt/RouteAttributesGenerator.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,13 @@ public Optional<String> toSourceCode(boolean kt, MvcRoute route, int indent) {
6060
if (attributes.isEmpty()) {
6161
return Optional.empty();
6262
} else {
63-
return Optional.of(toSourceCode(kt, annotationMap(route.getMethod()), indent + 6));
63+
return Optional.of(
64+
toSourceCode(kt, annotationMap(route.getMethod()), indent + 6, new HashMap<>()));
6465
}
6566
}
6667

67-
private String toSourceCode(boolean kt, Map<String, Object> attributes, int indent) {
68+
private String toSourceCode(
69+
boolean kt, Map<String, Object> attributes, int indent, Map<String, Object> defaults) {
6870
var buffer = new StringBuilder();
6971
var separator = ",\n";
7072
var pairPrefix = "";
@@ -82,23 +84,24 @@ private String toSourceCode(boolean kt, Map<String, Object> attributes, int inde
8284
buffer.append(indent(indent + 4));
8385
buffer.append(pairPrefix);
8486
buffer.append(CodeBlock.string(e.getKey())).append(", ");
85-
buffer.append(valueToSourceCode(kt, e.getValue(), indent + 4));
87+
buffer.append(valueToSourceCode(kt, e.getValue(), indent + 4, defaults));
8688
buffer.append(pairSuffix).append(separator);
8789
}
8890
buffer.setLength(buffer.length() - separator.length());
8991
buffer.append(")");
9092
return buffer.toString();
9193
}
9294

93-
private Object valueToSourceCode(boolean kt, Object value, int indent) {
95+
private Object valueToSourceCode(
96+
boolean kt, Object value, int indent, Map<String, Object> defaults) {
9497
if (value instanceof String) {
9598
return CodeBlock.string((String) value);
9699
} else if (value instanceof Character) {
97100
return "'" + value + "'";
98101
} else if (value instanceof Map attributeMap) {
99-
return "\n " + indent(indent) + toSourceCode(kt, attributeMap, indent + 1);
102+
return "\n " + indent(indent) + toSourceCode(kt, attributeMap, indent + 1, defaults);
100103
} else if (value instanceof List list) {
101-
return valueToSourceCode(kt, list, indent);
104+
return valueToSourceCode(kt, list, indent, defaults);
102105
} else if (value instanceof EnumValue enumValue) {
103106
return enumValue.type + "." + enumValue.value;
104107
} else if (value instanceof TypeMirror) {
@@ -118,12 +121,13 @@ private Object valueToSourceCode(boolean kt, Object value, int indent) {
118121
}
119122
}
120123

121-
private String valueToSourceCode(boolean kt, List values, int indent) {
124+
private String valueToSourceCode(
125+
boolean kt, List values, int indent, Map<String, Object> defaults) {
122126
var buffer = new StringBuilder();
123127
buffer.append("java.util.List.of(");
124128
var separator = ", ";
125129
for (Object value : values) {
126-
buffer.append(valueToSourceCode(kt, value, indent)).append(separator);
130+
buffer.append(valueToSourceCode(kt, value, indent, defaults)).append(separator);
127131
}
128132
buffer.setLength(buffer.length() - separator.length());
129133
buffer.append(")");
@@ -158,7 +162,8 @@ private Map<String, Object> annotationMap(List<? extends AnnotationMirror> annot
158162
String prefix = elem.getSimpleName().toString();
159163
// Set all values and then override with present values (fix for JDK 11+)
160164
result.putAll(toMap(annotation.getElementValues(), prefix));
161-
toMap(elements.getElementValuesWithDefaults(annotation), prefix).forEach(result::putIfAbsent);
165+
// toMap(elements.getElementValuesWithDefaults(annotation),
166+
// prefix).forEach(result::putIfAbsent);
162167
}
163168
return result;
164169
}

modules/jooby-apt/src/test/java/io/jooby/apt/ProcessorRunner.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {
5858

5959
private static class HookJoobyProcessor extends JoobyProcessor {
6060
private JavaFileObject source;
61+
private String kotlinSource;
6162

6263
public HookJoobyProcessor(Consumer<String> console) {
6364
super((kind, message) -> console.accept(message));
@@ -72,13 +73,23 @@ public JavaFileObject getSource() {
7273
return source;
7374
}
7475

76+
public String getKotlinSource() {
77+
return kotlinSource;
78+
}
79+
7580
public MvcContext getContext() {
7681
return context;
7782
}
7883

7984
@Override
8085
protected void onGeneratedSource(JavaFileObject source) {
8186
this.source = source;
87+
try {
88+
// Generate kotlin source code inside the compiler scope... avoid false positive errors
89+
this.kotlinSource = context.getRouters().get(0).toSourceCode(true);
90+
} catch (IOException e) {
91+
SneakyThrows.propagate(e);
92+
}
8293
}
8394
}
8495

@@ -117,14 +128,17 @@ public ProcessorRunner withRouter(SneakyThrows.Consumer2<Jooby, JavaFileObject>
117128
return this;
118129
}
119130

120-
public ProcessorRunner withSource(SneakyThrows.Consumer<JavaFileObject> consumer) {
131+
public ProcessorRunner withJavaObject(SneakyThrows.Consumer<JavaFileObject> consumer) {
121132
consumer.accept(processor.getSource());
122133
return this;
123134
}
124135

125-
public ProcessorRunner withSource(boolean kt, SneakyThrows.Consumer<String> consumer)
126-
throws IOException {
127-
consumer.accept(processor.getContext().getRouters().get(0).toSourceCode(kt));
136+
public ProcessorRunner withSourceCode(SneakyThrows.Consumer<String> consumer) {
137+
return withSourceCode(false, consumer);
138+
}
139+
140+
public ProcessorRunner withSourceCode(boolean kt, SneakyThrows.Consumer<String> consumer) {
141+
consumer.accept(kt ? processor.kotlinSource : processor.getSource().toString());
128142
return this;
129143
}
130144

modules/jooby-apt/src/test/java/tests/Issue1525.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ public void routeClassAttributes() throws Exception {
2020
.withRouter(
2121
app -> {
2222
Route route0 = app.getRoutes().get(0);
23-
assertEquals(2, route0.getAttributes().size(), route0.getAttributes().toString());
23+
assertEquals(1, route0.getAttributes().size(), route0.getAttributes().toString());
2424
assertEquals("Admin", route0.attribute("roleAnnotation"));
2525

2626
Route route1 = app.getRoutes().get(1);
27-
assertEquals(2, route1.getAttributes().size(), route1.getAttributes().toString());
27+
assertEquals(1, route1.getAttributes().size(), route1.getAttributes().toString());
2828
assertEquals("User", route1.attribute("roleAnnotation"));
2929
});
3030
}

modules/jooby-apt/src/test/java/tests/ModuleCompilerTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ public void routeAttributes() throws Exception {
277277
.withRouter(
278278
app -> {
279279
Route route = app.getRoutes().get(0);
280-
assertEquals(13, route.getAttributes().size(), route.getAttributes().toString());
280+
assertEquals(12, route.getAttributes().size(), route.getAttributes().toString());
281281
assertEquals("string", route.attribute("someAnnotation"));
282282
assertEquals(Integer.valueOf(5), route.attribute("someAnnotation.i"));
283283
assertEquals(Long.valueOf(200), route.attribute("someAnnotation.l"));
@@ -289,7 +289,6 @@ public void routeAttributes() throws Exception {
289289
assertEquals(Short.MIN_VALUE, (short) route.attribute("someAnnotation.s"));
290290
assertEquals(Arrays.asList("a", "b"), route.attribute("someAnnotation.values"));
291291
assertEquals("User", route.attribute("roleAnnotation"));
292-
assertEquals("one", route.attribute("roleAnnotation.level"));
293292
Map<String, Object> link = route.attribute("someAnnotation.annotation");
294293
assertNotNull(link);
295294
assertEquals("link", link.get("LinkAnnotation"));

modules/jooby-apt/src/test/java/tests/i3469/Issue3469.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class Issue3469 {
1919
@Test
2020
public void shouldGenerateConstructors() throws Exception {
2121
new ProcessorRunner(new C3469(new Foo3469(), List.of(new Bar3469())))
22-
.withSource(
22+
.withJavaObject(
2323
source -> {
2424
assertTrue(
2525
source
@@ -35,7 +35,7 @@ public void shouldGenerateConstructors() throws Exception {
3535
@Test
3636
public void shouldGenerateFieldInjectWithDefaultConstructor() throws Exception {
3737
new ProcessorRunner(new C3469FieldInject())
38-
.withSource(
38+
.withJavaObject(
3939
source -> {
4040
assertTrue(source.toString().contains("this(C3469FieldInject.class);"));
4141
});

modules/jooby-apt/src/test/java/tests/i3476/Issue3476.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class Issue3476 {
1616
@Test
1717
public void shouldGenerateGenerics() throws Exception {
1818
new ProcessorRunner(new C3476())
19-
.withSource(
19+
.withJavaObject(
2020
source -> {
2121
assertTrue(source.toString().contains("public <T> java.util.List<T> get("));
2222
assertTrue(source.toString().contains("return (java.util.List<T>) c.get("));

modules/jooby-apt/src/test/java/tests/i3490/Issue3490.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class Issue3490 {
1818
@Test
1919
public void shouldNotGeneratePrimitiveOnKotlinGenerics() throws IOException {
2020
new ProcessorRunner(new C3490())
21-
.withSource(
21+
.withSourceCode(
2222
true,
2323
source -> {
2424
assertTrue(

modules/jooby-apt/src/test/java/tests/i3507/Issue3507.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class Issue3507 {
1818
@Test
1919
public void shouldGenerateNullSafeKtReturnType() throws IOException {
2020
new ProcessorRunner(new C3507())
21-
.withSource(
21+
.withSourceCode(
2222
true,
2323
source -> {
2424
assertTrue(source.contains("return c.get(ctx.query(\"query\").value())!!"));
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package tests.i3525;
7+
8+
import io.jooby.annotation.GET;
9+
import io.jooby.annotation.QueryParam;
10+
import io.swagger.v3.oas.annotations.Parameter;
11+
12+
public class C3525 {
13+
@GET("/3525")
14+
@Parameter(name = "paramA", description = "paramA")
15+
@Parameter(name = "paramB", description = "paramB")
16+
public void repeatable(@QueryParam String paramA, @QueryParam String paramB) {}
17+
}

0 commit comments

Comments
 (0)