Skip to content

Commit 7b820db

Browse files
committed
- build: more fixes on refactor/generator split
1 parent dd8ea41 commit 7b820db

3 files changed

Lines changed: 81 additions & 64 deletions

File tree

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

Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,14 @@ public List<String> generateHandlerCall(boolean kt) {
213213
handlerTypeString = Types.PROJECTED + "<" + returnTypeString + ">";
214214
}
215215

216-
boolean nullable =
217-
methodCallHeader(
218-
kt,
219-
"ctx",
220-
methodName,
221-
buffer,
222-
handlerTypeGenerics,
223-
handlerTypeString,
224-
!method.getThrownTypes().isEmpty());
216+
methodCallHeader(
217+
kt,
218+
"ctx",
219+
methodName,
220+
buffer,
221+
handlerTypeGenerics,
222+
handlerTypeString,
223+
!method.getThrownTypes().isEmpty());
225224

226225
int controllerIndent = 2;
227226

@@ -248,49 +247,27 @@ public List<String> generateHandlerCall(boolean kt) {
248247
statusCode,
249248
")",
250249
semicolon(kt)));
251-
buffer.add(
252-
statement(
253-
indent(controllerIndent),
254-
"c.",
255-
this.method.getSimpleName(),
256-
paramList.toString(),
257-
semicolon(kt)));
250+
251+
String call = buildMethodCall(kt, paramList.toString(), false, false);
252+
253+
buffer.add(statement(indent(controllerIndent), call, semicolon(kt)));
258254
buffer.add(
259255
statement(indent(controllerIndent), "return ctx.getResponseCode()", semicolon(kt)));
260256
} else if (returnType.is("io.jooby.StatusCode")) {
257+
String call = buildMethodCall(kt, paramList.toString(), false, false);
258+
261259
buffer.add(
262260
statement(
263-
indent(controllerIndent),
264-
kt ? "val" : "var",
265-
" statusCode = c.",
266-
this.method.getSimpleName(),
267-
paramList.toString(),
268-
semicolon(kt)));
261+
indent(controllerIndent), kt ? "val" : "var", " statusCode = ", call, semicolon(kt)));
269262
buffer.add(
270263
statement(indent(controllerIndent), "ctx.setResponseCode(statusCode)", semicolon(kt)));
271264
buffer.add(statement(indent(controllerIndent), "return statusCode", semicolon(kt)));
272265
} else {
273-
var castStr =
274-
isProjectedReturnType
275-
? ""
276-
: customReturnType.getArgumentsString(kt, false, Set.of(TypeKind.TYPEVAR));
277-
278-
// Force cast only if the return type contains Type Variables (like <E>)
279-
var needsCast = !castStr.isEmpty();
280-
var kotlinNotEnoughTypeInformation = !castStr.isEmpty() && kt ? "<Any>" : "";
281-
282-
var call =
283-
of(
284-
"c.",
285-
this.method.getSimpleName(),
286-
kotlinNotEnoughTypeInformation,
287-
paramList.toString());
288-
289-
if (needsCast) {
290-
setUncheckedCast(true);
291-
// Use the RAW return type string for the cast, not the modified handler type
292-
call = kt ? call + " as " + returnTypeString : "(" + returnTypeString + ") " + call;
293-
}
266+
267+
// Leverage shared WebRoute logic for casting and type erasure!
268+
String call =
269+
buildMethodCall(kt, paramList.toString(), isProjectedReturnType, isProjectedReturnType);
270+
boolean nullable = kt && isNullableKotlinReturn();
294271

295272
// 3. ONLY wrap the call if it's a NON-projected type with a projection string
296273
if (projection != null && !isProjectedReturnType) {
@@ -300,16 +277,12 @@ public List<String> generateHandlerCall(boolean kt) {
300277
indent(controllerIndent),
301278
"return ",
302279
projected,
303-
kt && nullable ? "!!" : "",
280+
nullable ? "!!" : "",
304281
semicolon(kt)));
305282
} else {
306283
buffer.add(
307284
statement(
308-
indent(controllerIndent),
309-
"return ",
310-
call,
311-
kt && nullable ? "!!" : "",
312-
semicolon(kt)));
285+
indent(controllerIndent), "return ", call, nullable ? "!!" : "", semicolon(kt)));
313286
}
314287
}
315288

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

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,10 @@ public List<String> generateHandlerCall(boolean kt) {
517517

518518
buffer.add(
519519
statement(indent(controllerIndent), var(kt), "c = this.factory.apply(ctx)", semicolon(kt)));
520-
var call = CodeBlock.of("c.", this.method.getSimpleName(), paramList.toString());
520+
521+
// Leverage shared WebRoute logic for casting and type erasure!
522+
String call = buildMethodCall(kt, paramList.toString(), false, true);
523+
boolean nullable = kt && isNullableKotlinReturn();
521524

522525
if (returnType.isVoid()) {
523526
buffer.add(statement(indent(controllerIndent), call, semicolon(kt)));
@@ -532,26 +535,20 @@ public List<String> generateHandlerCall(boolean kt) {
532535
indent(controllerIndent),
533536
"return io.jooby.rpc.trpc.TrpcResponse.of(",
534537
call,
538+
nullable ? "!!" : "", // Shared nullability check
535539
")",
536540
semicolon(kt)));
537541
}
538542

539543
if (!parameters.isEmpty()) buffer.add(statement(indent(2), "}"));
540544
buffer.add(statement("}", System.lineSeparator()));
541-
return buffer;
542-
}
543545

544-
private String box(String type) {
545-
return switch (type) {
546-
case "int" -> "Integer";
547-
case "long" -> "Long";
548-
case "double" -> "Double";
549-
case "float" -> "Float";
550-
case "boolean" -> "Boolean";
551-
case "byte" -> "Byte";
552-
case "short" -> "Short";
553-
case "char" -> "Character";
554-
default -> type;
555-
};
546+
// Shared Unchecked Cast suppression
547+
if (isUncheckedCast()) {
548+
if (kt) buffer.addFirst(statement("@Suppress(\"UNCHECKED_CAST\")"));
549+
else buffer.addFirst(statement("@SuppressWarnings(\"unchecked\")"));
550+
}
551+
552+
return buffer;
556553
}
557554
}

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010

1111
import java.util.List;
1212
import java.util.Objects;
13+
import java.util.Set;
1314
import java.util.stream.Stream;
1415

1516
import javax.lang.model.element.ExecutableElement;
17+
import javax.lang.model.type.TypeKind;
1618
import javax.lang.model.type.TypeMirror;
1719
import javax.lang.model.type.WildcardType;
1820

@@ -136,4 +138,49 @@ public List<String> getJavaMethodSignature(boolean kt) {
136138
.map(it -> it + clazz(kt))
137139
.toList();
138140
}
141+
142+
public boolean isNullableKotlinReturn() {
143+
return method.getAnnotationMirrors().stream()
144+
.map(javax.lang.model.element.AnnotationMirror::getAnnotationType)
145+
.map(java.util.Objects::toString)
146+
.anyMatch(AnnotationSupport.NULLABLE);
147+
}
148+
149+
protected String buildMethodCall(
150+
boolean kt, String paramList, boolean preventCast, boolean isRpcWrapper) {
151+
var customReturnType = getReturnType();
152+
var castStr =
153+
preventCast ? "" : customReturnType.getArgumentsString(kt, false, Set.of(TypeKind.TYPEVAR));
154+
155+
// Force cast ONLY if there's a Type Variable (<E> -> <Any>)
156+
// OR if it's an RPC wrapper where strict Java generics conflict with Kotlin's nullable generics
157+
var needsCast =
158+
!castStr.isEmpty()
159+
|| (kt && !preventCast && isRpcWrapper && !customReturnType.getArguments().isEmpty());
160+
161+
var kotlinNotEnoughTypeInformation = !castStr.isEmpty() && kt ? "<Any>" : "";
162+
163+
var call = "c." + this.method.getSimpleName() + kotlinNotEnoughTypeInformation + paramList;
164+
165+
if (needsCast) {
166+
setUncheckedCast(true);
167+
var returnTypeString = CodeBlock.type(kt, customReturnType.toString());
168+
call = kt ? call + " as " + returnTypeString : "(" + returnTypeString + ") " + call;
169+
}
170+
return call;
171+
}
172+
173+
protected String box(String type) {
174+
return switch (type) {
175+
case "int" -> "Integer";
176+
case "long" -> "Long";
177+
case "double" -> "Double";
178+
case "float" -> "Float";
179+
case "boolean" -> "Boolean";
180+
case "byte" -> "Byte";
181+
case "short" -> "Short";
182+
case "char" -> "Character";
183+
default -> type;
184+
};
185+
}
139186
}

0 commit comments

Comments
 (0)