|
230 | 230 | import org.jooby.apitool.RouteParameter; |
231 | 231 | import org.jooby.apitool.RouteResponse; |
232 | 232 | import org.jooby.funzy.Try; |
| 233 | + |
233 | 234 | import static org.jooby.funzy.When.when; |
| 235 | + |
234 | 236 | import org.jooby.internal.RouteMetadata; |
| 237 | + |
235 | 238 | import static org.jooby.internal.apitool.Filters.access; |
236 | 239 | import static org.jooby.internal.apitool.Filters.and; |
237 | | -import static org.jooby.internal.apitool.Filters.call; |
238 | 240 | import static org.jooby.internal.apitool.Filters.file; |
239 | 241 | import static org.jooby.internal.apitool.Filters.getOrCreateKotlinClass; |
240 | 242 | import static org.jooby.internal.apitool.Filters.is; |
|
249 | 251 | import static org.jooby.internal.apitool.Filters.param; |
250 | 252 | import static org.jooby.internal.apitool.Filters.path; |
251 | 253 | import static org.jooby.internal.apitool.Filters.scriptRoute; |
| 254 | +import static org.jooby.internal.apitool.Filters.sendObject; |
252 | 255 | import static org.jooby.internal.apitool.Filters.use; |
| 256 | + |
253 | 257 | import org.jooby.internal.mvc.MvcRoutes; |
254 | 258 | import org.jooby.mvc.Body; |
255 | 259 | import org.jooby.mvc.Flash; |
|
259 | 263 | import org.objectweb.asm.ClassReader; |
260 | 264 | import org.objectweb.asm.Handle; |
261 | 265 | import org.objectweb.asm.Opcodes; |
| 266 | + |
262 | 267 | import static org.objectweb.asm.Opcodes.GETSTATIC; |
263 | 268 | import static org.objectweb.asm.Opcodes.INVOKESPECIAL; |
| 269 | + |
264 | 270 | import org.objectweb.asm.Type; |
265 | 271 | import org.objectweb.asm.tree.AbstractInsnNode; |
266 | 272 | import org.objectweb.asm.tree.ClassNode; |
@@ -408,7 +414,7 @@ public List<RouteMethod> parse(String classname) throws Exception { |
408 | 414 |
|
409 | 415 | java.lang.reflect.Type returnType; |
410 | 416 | if (method.desc.endsWith("V")) { |
411 | | - returnType = void.class; |
| 417 | + returnType = sendReturnType(loader, method); |
412 | 418 | } else if (method.desc.endsWith(RETURN_OBJ)) { |
413 | 419 | returnType = returnType(loader, method); |
414 | 420 | } else { |
@@ -1055,36 +1061,53 @@ private java.lang.reflect.Type returnType(final ClassLoader loader, |
1055 | 1061 | .filter(and(is(InsnNode.class), opcode(Opcodes.ARETURN))) |
1056 | 1062 | .findFirst() |
1057 | 1063 | .map(AbstractInsnNode::getPrevious) |
1058 | | - .map(previous -> { |
1059 | | - /** return 1; return true; return new Foo(); */ |
1060 | | - if (previous instanceof MethodInsnNode) { |
1061 | | - MethodInsnNode minnsn = ((MethodInsnNode) previous); |
1062 | | - if (minnsn.name.equals("<init>")) { |
1063 | | - return loadType(loader, minnsn.owner); |
1064 | | - } |
1065 | | - String desc = minnsn.desc; |
1066 | | - java.lang.reflect.Type type = TypeDescriptorParser.parse(loader, desc); |
1067 | | - if (type.getTypeName().equals(Result.class.getName())) { |
1068 | | - return new TypeWithStatus(type, statusCodeFor(minnsn)); |
1069 | | - } |
1070 | | - return type; |
1071 | | - } |
1072 | | - /** return "String" | int | double */ |
1073 | | - if (previous instanceof LdcInsnNode) { |
1074 | | - Object cst = ((LdcInsnNode) previous).cst; |
1075 | | - if (cst instanceof Type) { |
1076 | | - return TypeDescriptorParser.parse(loader, ((Type) cst).getDescriptor()); |
1077 | | - } |
1078 | | - return cst.getClass(); |
1079 | | - } |
1080 | | - /** return variable */ |
1081 | | - if (previous instanceof VarInsnNode) { |
1082 | | - VarInsnNode varInsn = (VarInsnNode) previous; |
1083 | | - return localVariable(loader, m, varInsn); |
1084 | | - } |
| 1064 | + .map(previous -> handleReturnType(loader, m, previous)) |
| 1065 | + .orElseGet(() -> sendReturnType(loader, m)); |
| 1066 | + } |
1085 | 1067 |
|
1086 | | - return Object.class; |
1087 | | - }).orElse(Object.class); |
| 1068 | + private java.lang.reflect.Type handleReturnType(ClassLoader loader, MethodNode m, |
| 1069 | + AbstractInsnNode previous) { |
| 1070 | + /** return 1; return true; return new Foo(); */ |
| 1071 | + if (previous instanceof MethodInsnNode) { |
| 1072 | + MethodInsnNode minnsn = ((MethodInsnNode) previous); |
| 1073 | + if (minnsn.name.equals("<init>")) { |
| 1074 | + return loadType(loader, minnsn.owner); |
| 1075 | + } |
| 1076 | + String desc = minnsn.desc; |
| 1077 | + java.lang.reflect.Type type = TypeDescriptorParser.parse(loader, desc); |
| 1078 | + if (type.getTypeName().equals(Result.class.getName())) { |
| 1079 | + return new TypeWithStatus(type, statusCodeFor(minnsn)); |
| 1080 | + } |
| 1081 | + return type; |
| 1082 | + } |
| 1083 | + /** return "String" | int | double */ |
| 1084 | + if (previous instanceof LdcInsnNode) { |
| 1085 | + Object cst = ((LdcInsnNode) previous).cst; |
| 1086 | + if (cst instanceof Type) { |
| 1087 | + return TypeDescriptorParser.parse(loader, ((Type) cst).getDescriptor()); |
| 1088 | + } |
| 1089 | + return cst.getClass(); |
| 1090 | + } |
| 1091 | + /** return variable */ |
| 1092 | + if (previous instanceof VarInsnNode) { |
| 1093 | + VarInsnNode varInsn = (VarInsnNode) previous; |
| 1094 | + return localVariable(loader, m, varInsn); |
| 1095 | + } |
| 1096 | + |
| 1097 | + return Object.class; |
| 1098 | + } |
| 1099 | + |
| 1100 | + private java.lang.reflect.Type sendReturnType(ClassLoader loader, MethodNode m) { |
| 1101 | + return new Insns(m) |
| 1102 | + .last() |
| 1103 | + .prev() |
| 1104 | + .filter(MethodInsnNode.class::isInstance) |
| 1105 | + .map(MethodInsnNode.class::cast) |
| 1106 | + .filter(sendObject()) |
| 1107 | + .findFirst() |
| 1108 | + .map(AbstractInsnNode::getPrevious) |
| 1109 | + .map(node -> handleReturnType(loader, m, node)) |
| 1110 | + .orElse(void.class); |
1088 | 1111 | } |
1089 | 1112 |
|
1090 | 1113 | private Integer statusCodeFor(MethodInsnNode node) { |
|
0 commit comments