@@ -47,18 +47,41 @@ extension JavaMethodMacro: BodyMacro {
4747 }
4848
4949 guard let funcDecl = declaration. as ( FunctionDeclSyntax . self) else {
50- fatalError ( " not a function " )
50+ fatalError ( " not a function: \( declaration ) " )
5151 }
5252
5353 let isStatic = node. attributeName. trimmedDescription == " JavaStaticMethod "
5454 let funcName = funcDecl. name. text
5555 let params = funcDecl. signature. parameterClause. parameters
56- let resultType : String =
57- funcDecl. signature. returnClause. map { result in
58- " , resultType: \( result. type. typeReferenceString) .self "
59- } ?? " "
6056 let paramNames = params. map { param in param. parameterName? . text ?? " " } . joined ( separator: " , " )
6157
58+ let genericResultType : String ? =
59+ if case let . argumentList( arguments) = node. arguments,
60+ let firstElement = arguments. first,
61+ let stringLiteral = firstElement. expression
62+ . as ( StringLiteralExprSyntax . self) ,
63+ stringLiteral. segments. count == 1 ,
64+ case let . stringSegment( wrapperName) ? = stringLiteral. segments. first {
65+ " \( wrapperName) "
66+ } else {
67+ nil
68+ }
69+
70+ // Determine the result type
71+ let resultType : String =
72+ if let returnClause = funcDecl. signature. returnClause {
73+ if let genericResultType {
74+ // we need to type-erase the signature, because on JVM level generics are erased and we'd otherwise
75+ // form a signature with the "concrete" type, which would not match the real byte-code level signature
76+ // of the method we're trying to call -- which would result in a MethodNotFound exception.
77+ " , resultType: /*type-erased: \( genericResultType) */JavaObject?.self "
78+ } else {
79+ " , resultType: \( returnClause. type. typeReferenceString) .self "
80+ }
81+ } else {
82+ " "
83+ }
84+
6285 let parametersAsArgs : String
6386 if paramNames. isEmpty {
6487 parametersAsArgs = " "
@@ -70,8 +93,25 @@ extension JavaMethodMacro: BodyMacro {
7093 funcDecl. signature. effectSpecifiers? . throwsClause != nil
7194 ? " try " : " try! "
7295
96+ let resultSyntax : CodeBlockItemSyntax =
97+ " \( raw: tryKeyword) dynamicJava \( raw: isStatic ? " Static " : " " ) MethodCall(methodName: \( literal: funcName) \( raw: parametersAsArgs) \( raw: resultType) ) "
98+
99+ if let genericResultType {
100+ return [
101+ """
102+ /* convert erased return value to \(raw: genericResultType) */
103+ if let result$ = \( resultSyntax) {
104+ return \( raw: genericResultType) (javaThis: result$.javaThis, environment: try! JavaVirtualMachine.shared().environment())
105+ } else {
106+ return nil
107+ }
108+ """
109+ ]
110+ }
111+
112+ // no return type conversions
73113 return [
74- " return \( raw : tryKeyword ) dynamicJava \( raw : isStatic ? " Static " : " " ) MethodCall(methodName: \( literal : funcName ) \( raw : parametersAsArgs ) \( raw : resultType ) ) "
114+ " return \( resultSyntax ) "
75115 ]
76116 }
77117
0 commit comments