Skip to content

Commit e1d12d1

Browse files
committed
jooby-apt: kotlin: mvc: don't generate primitive types with generics type
- test: allow to generate kotlin source code from Java input, just for testing purpose - Add suppress unchecked warnings - fix #3490
1 parent 7cbc0a9 commit e1d12d1

10 files changed

Lines changed: 113 additions & 24 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static String string(ProcessingEnvironment environment, String option, String de
5858
}
5959
}
6060

61-
private MvcContext context;
61+
protected MvcContext context;
6262
private Consumer<String> output;
6363
private final Set<Object> processed = new HashSet<>();
6464

@@ -96,7 +96,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
9696
var routeMap = buildRouteRegistry(annotations, roundEnv);
9797
for (var router : routeMap.values()) {
9898
try {
99-
var sourceCode = router.toSourceCode();
99+
var sourceCode = router.toSourceCode(null);
100100
var sourceLocation = router.getGeneratedFilename();
101101
onGeneratedSource(toJavaFileObject(sourceLocation, sourceCode));
102102
context.debug("router %s: %s", router.getTargetType(), router.getGeneratedType());

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ public static String type(boolean kt, CharSequence value) {
4343
var result = value.toString().replace("java.lang.", "");
4444
if (kt) {
4545
return switch (result) {
46-
case "byte" -> "Byte";
47-
case "boolean" -> "Boolean";
46+
case "byte", "Byte" -> "Byte";
47+
case "boolean", "Boolean" -> "Boolean";
4848
case "char", "Character" -> "Char";
4949
case "int", "Integer" -> "Int";
50-
case "short" -> "Short";
51-
case "long" -> "Long";
52-
case "double" -> "Double";
53-
case "float" -> "Float";
50+
case "short", "Short" -> "Short";
51+
case "long", "Long" -> "Long";
52+
case "double", "Double" -> "Double";
53+
case "float", "Float" -> "Float";
5454
case "Object" -> "Any";
5555
default -> {
5656
var arg = result.indexOf('<');

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class MvcRoute {
2929
private final TypeDefinition returnType;
3030
private String generatedName;
3131
private final boolean suspendFun;
32+
private boolean uncheckedCast;
3233

3334
public MvcRoute(MvcContext context, MvcRouter router, ExecutableElement method) {
3435
this.context = context;
@@ -297,11 +298,19 @@ public List<String> generateHandlerCall(boolean kt) {
297298
kotlinNotEnoughTypeInformation,
298299
paramList.toString());
299300
if (!cast.isEmpty()) {
301+
setUncheckedCast(true);
300302
call = kt ? call + " as " + returnTypeString : "(" + returnTypeString + ") " + call;
301303
}
302304
buffer.add(statement(indent(2), "return ", call, semicolon(kt)));
303305
}
304306
buffer.add(statement("}", System.lineSeparator()));
307+
if (uncheckedCast) {
308+
if (kt) {
309+
buffer.add(0, statement("@Suppress(\"UNCHECKED_CAST\")"));
310+
} else {
311+
buffer.add(0, statement("@SuppressWarnings(\"unchecked\")"));
312+
}
313+
}
305314
return buffer;
306315
}
307316

@@ -452,4 +461,8 @@ private String javadocComment(boolean kt) {
452461
String.join(", ", getRawParameterTypes(true)),
453462
") */");
454463
}
464+
465+
public void setUncheckedCast(boolean value) {
466+
this.uncheckedCast = value;
467+
}
455468
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ public String getPackageName() {
107107
*
108108
* @return
109109
*/
110-
public String toSourceCode() throws IOException {
111-
var kt = isKt();
110+
public String toSourceCode(Boolean generateKotlin) throws IOException {
111+
var kt = generateKotlin == Boolean.TRUE || isKt();
112112
var generateTypeName = context.generateRouterName(getTargetType().getSimpleName().toString());
113113
try (var in = getClass().getResourceAsStream("Source" + (kt ? ".kt" : ".java"))) {
114114
Objects.requireNonNull(in);

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public String toSourceCode(
3131
boolean nullable) {
3232
if (type.is(Map.class)) {
3333
if (kt) {
34+
route.setUncheckedCast(true);
3435
return CodeBlock.of(
3536
"(ctx.attributes[",
3637
CodeBlock.string(name),
@@ -42,17 +43,13 @@ public String toSourceCode(
4243
")).orElseGet(() ->" + " ctx.getAttributes())");
4344
}
4445
} else {
45-
return kt
46-
? CodeBlock.of(
47-
"ctx.", method, "(", CodeBlock.string(name), ") as ", type.getRawType().toString())
48-
: CodeBlock.of(
49-
"(",
50-
type.getRawType().toString(),
51-
") ctx.",
52-
method,
53-
"(",
54-
CodeBlock.string(name),
55-
")");
46+
if (kt) {
47+
route.setUncheckedCast(true);
48+
return CodeBlock.of(
49+
"ctx.", method, "(", CodeBlock.string(name), ") as ", type.getRawType().toString());
50+
}
51+
return CodeBlock.of(
52+
"(", type.getRawType().toString(), ") ctx.", method, "(", CodeBlock.string(name), ")");
5653
}
5754
}
5855
},
@@ -234,6 +231,7 @@ public String toSourceCode(
234231
var prefix = "";
235232
var suffix = "";
236233
if (toValue.getValue().isParameterizedType()) {
234+
route.setUncheckedCast(true);
237235
prefix = "(";
238236
suffix = ") as " + CodeBlock.type(true, toValue.getValue().toString());
239237
}

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public TypeDefinition(Types types, TypeMirror type) {
3131
}
3232

3333
public String toSourceCode(boolean kt) {
34-
return toSourceCode(this, kt);
34+
return toSourceCode(this, kt, false);
3535
}
3636

3737
public String getArgumentsString(boolean kt, boolean convertTypeVar, Set<TypeKind> kinds) {
@@ -54,7 +54,7 @@ public String getArgumentsString(boolean kt, boolean convertTypeVar, Set<TypeKin
5454
.collect(Collectors.joining(", ", "<", "> "));
5555
}
5656

57-
private static String toSourceCode(TypeDefinition type, boolean kt) {
57+
private static String toSourceCode(TypeDefinition type, boolean kt, boolean generics) {
5858
if (type.isParameterizedType()) {
5959
var buffer = new StringBuilder();
6060
var methodName =
@@ -78,12 +78,16 @@ private static String toSourceCode(TypeDefinition type, boolean kt) {
7878
.append(", ");
7979
}
8080
for (TypeDefinition arg : type.getArguments()) {
81-
buffer.append(toSourceCode(arg, kt)).append(separator);
81+
// Generics are always wrapper
82+
buffer.append(toSourceCode(arg, kt, true)).append(separator);
8283
}
8384
buffer.setLength(buffer.length() - separator.length());
8485
buffer.append(").getType()");
8586
return buffer.toString();
8687
} else {
88+
if (generics && kt) {
89+
return type.getRawType().toString().replace("java.lang.", "") + clazz(kt);
90+
}
8791
return CodeBlock.type(kt, type.getRawType().toString()) + clazz(kt);
8892
}
8993
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.testing.compile.JavaFileObjects;
2626
import com.google.testing.compile.JavaSourcesSubjectFactory;
2727
import io.jooby.*;
28+
import io.jooby.internal.apt.MvcContext;
2829

2930
public class ProcessorRunner {
3031

@@ -71,6 +72,10 @@ public JavaFileObject getSource() {
7172
return source;
7273
}
7374

75+
public MvcContext getContext() {
76+
return context;
77+
}
78+
7479
@Override
7580
protected void onGeneratedSource(JavaFileObject source) {
7681
this.source = source;
@@ -117,6 +122,12 @@ public ProcessorRunner withSource(SneakyThrows.Consumer<JavaFileObject> consumer
117122
return this;
118123
}
119124

125+
public ProcessorRunner withSource(boolean kt, SneakyThrows.Consumer<String> consumer)
126+
throws IOException {
127+
consumer.accept(processor.getContext().getRouters().get(0).toSourceCode(kt));
128+
return this;
129+
}
130+
120131
private String[] sourceNames(Class input) {
121132
List<String> result = new ArrayList<>();
122133
while (input != Object.class) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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.i3490;
7+
8+
public class Box3490<T> {
9+
private T value;
10+
11+
public Box3490(T value) {}
12+
13+
public T getValue() {
14+
return value;
15+
}
16+
}
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.i3490;
7+
8+
import io.jooby.annotation.GET;
9+
import io.jooby.annotation.QueryParam;
10+
11+
public class C3490 {
12+
13+
@GET("/3490")
14+
public Box3490<Integer> get(@QueryParam int id) {
15+
return null;
16+
}
17+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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.i3490;
7+
8+
import static org.junit.jupiter.api.Assertions.assertTrue;
9+
10+
import java.io.IOException;
11+
12+
import org.junit.jupiter.api.Test;
13+
14+
import io.jooby.apt.ProcessorRunner;
15+
16+
public class Issue3490 {
17+
18+
@Test
19+
public void shouldNotGeneratePrimitiveOnKotlinGenerics() throws IOException {
20+
new ProcessorRunner(new C3490())
21+
.withSource(
22+
true,
23+
source -> {
24+
assertTrue(
25+
source.contains(
26+
".setReturnType(io.jooby.Reified.getParameterized(tests.i3490.Box3490::class.java,"
27+
+ " Integer::class.java).getType())"));
28+
});
29+
}
30+
}

0 commit comments

Comments
 (0)