diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/GenericType.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/GenericType.swift index d4597327..0968489e 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/GenericType.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/GenericType.swift @@ -22,20 +22,50 @@ public struct MyID { } } -public func makeIntID(_ value: Int) -> MyID { - MyID(value) -} +public enum MyIDs { + public static func makeIntID(_ value: Int) -> MyID { + MyID(value) + } -public func makeStringID(_ value: String) -> MyID { - MyID(value) -} + public static func takeIntValue(from value: MyID) -> Int { + value.rawValue + } -public func takeIntValue(from value: MyID) -> Int { - value.rawValue -} + public static func makeStringID(_ value: String) -> MyID { + MyID(value) + } -public func takeStringValue(from value: MyID) -> String { - value.rawValue + public static func takeStringValue(from value: MyID) -> String { + value.rawValue + } + + public static func makeIDs(_ stringValue: String, _ intValue: Int) -> (MyID, MyID) { + (MyID(stringValue), MyID(intValue)) + } + + public static func takeValuesFromTuple(_ tuple: (MyID, MyID)) -> (String, Int) { + (tuple.0.rawValue, tuple.1.rawValue) + } + + public static func makeDoubleIDOptional(_ value: Double) -> MyID? { + MyID(value) + } + + public static func takeDoubleValueOptional(from id: MyID?) -> Double? { + id?.rawValue + } + + public static func takeDoubleValue(from value: MyID) -> Double { + value.rawValue + } + + public static func makeOptionalStringID(_ value: String?) -> MyID { + MyID(value) + } + + public static func takeOptionalStringValue(from id: MyID) -> String? { + id.rawValue + } } public struct MyEntity { diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/GenericTypeTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/GenericTypeTest.java index bedf0eca..18e60b59 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/GenericTypeTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/GenericTypeTest.java @@ -14,8 +14,11 @@ package com.example.swift; +import java.util.Optional; +import java.util.OptionalLong; import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.SwiftArena; +import org.swift.swiftkit.core.tuple.Tuple2; import static org.junit.jupiter.api.Assertions.*; @@ -23,20 +26,35 @@ public class GenericTypeTest { @Test void genericTypeValueRoundtrip() { try (var arena = SwiftArena.ofConfined()) { - MyID stringId = MySwiftLibrary.makeStringID("Java", arena); + MyID stringId = MyIDs.makeStringID("Java", arena); assertEquals("Java", stringId.getDescription()); - assertEquals("Java", MySwiftLibrary.takeStringValue(stringId)); + assertEquals("Java", MyIDs.takeStringValue(stringId)); - MyID intId = MySwiftLibrary.makeIntID(42, arena); + MyID intId = MyIDs.makeIntID(42, arena); assertEquals("42", intId.getDescription()); - assertEquals(42, MySwiftLibrary.takeIntValue(intId)); + assertEquals(42, MyIDs.takeIntValue(intId)); + + Tuple2, MyID> ids = MyIDs.makeIDs("Java", 42, arena); + assertEquals("Java", ids.$0.getDescription()); + assertEquals("42", ids.$1.getDescription()); + assertEquals("Java", MyIDs.takeValuesFromTuple(ids).$0); + assertEquals(42, MyIDs.takeValuesFromTuple(ids).$1); + + Optional> doubleIdOptional = MyIDs.makeDoubleIDOptional(42.195, arena); + assertTrue(doubleIdOptional.isPresent()); + assertEquals(42.195, MyIDs.takeDoubleValueOptional(doubleIdOptional).getAsDouble()); + assertEquals(42.195, MyIDs.takeDoubleValue(doubleIdOptional.get())); // ensure wrapped value is alive + + MyID> optionalStringId = MyIDs.makeOptionalStringID(Optional.of("Java"), arena); + assertEquals("Optional(\"Java\")", optionalStringId.getDescription()); + assertEquals("Java", MyIDs.takeOptionalStringValue(optionalStringId).get()); } } @Test void genericTypeProperty() { try (var arena = SwiftArena.ofConfined()) { - MyID intId = MySwiftLibrary.makeIntID(42, arena); + MyID intId = MyIDs.makeIntID(42, arena); MyEntity entity = MyEntity.init(intId, "name", arena); assertEquals("42", entity.getId(arena).getDescription()); } diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift index fd7f6dc5..68059eed 100644 --- a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -164,18 +164,31 @@ extension JavaType { /// The boxed class name for this type, suitable for use as a generic type argument. var boxedName: String { switch self { - case .boolean: "Boolean" - case .byte: "Byte" - case .char: "Character" - case .short: "Short" - case .int: "Integer" - case .long: "Long" - case .float: "Float" - case .double: "Double" - case .void: "Void" - case .javaLangString: "String" - case .class(_, let name, _): name - case .array: description + case .boolean: return "Boolean" + case .byte: return "Byte" + case .char: return "Character" + case .short: return "Short" + case .int: return "Integer" + case .long: return "Long" + case .float: return "Float" + case .double: return "Double" + case .void: return "Void" + case .javaLangString: return "String" + case .class(let package, let name, let typeParameters): + let packagePart: String = + if let package { + "\(package)." + } else { + "" + } + let genericClause: String = + if !typeParameters.isEmpty { + "<\(typeParameters.map(\.boxedName).joined(separator: ", "))>" + } else { + "" + } + return "\(packagePart)\(name)\(genericClause)" + case .array: return description } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 6c99d3de..b21c7372 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -732,7 +732,13 @@ extension JNISwift2JavaGenerator { if translatedFunctionSignature.resultType.javaType.isVoid { printer.print("\(downcall);") } else { - let result = translatedFunctionSignature.resultType.conversion.render(&printer, downcall) + let result: String + if translatedDecl.nativeFunctionSignature.result.javaType.isVoid { + printer.print("\(downcall);") + result = translatedFunctionSignature.resultType.conversion.render(&printer, "") + } else { + result = translatedFunctionSignature.resultType.conversion.render(&printer, downcall) + } printer.print("return \(result);") } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 38e891f2..41a4fbae 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -698,20 +698,14 @@ extension JNISwift2JavaGenerator { javaType: translatedFutureType, annotations: result.annotations, outParameters: result.outParameters + [futureOutParameter], - conversion: .aggregate( - variable: nil, - [ - .print(.placeholder), // Make the downcall - .method( - .constant("future$"), - function: "thenApply", - arguments: [ - .lambda( - args: ["futureResult$"], - body: .replacingPlaceholder(result.conversion, placeholder: "futureResult$") - ) - ] - ), + conversion: .method( + .constant("future$"), + function: "thenApply", + arguments: [ + .lambda( + args: ["futureResult$"], + body: .replacingPlaceholder(result.conversion, placeholder: "futureResult$") + ) ] ) ) @@ -984,19 +978,13 @@ extension JNISwift2JavaGenerator { return TranslatedResult( javaType: javaType, annotations: resultAnnotations, - outParameters: [.init(name: "instance", type: ._OutSwiftGenericInstance, allocation: .new)], - conversion: .aggregate( - variable: nil, - [ - .print(.placeholder), - .wrapMemoryAddressUnsafe( - .commaSeparated([ - .member(.constant("instance"), field: "selfPointer"), - .member(.constant("instance"), field: "selfTypePointer"), - ]), - javaType - ), - ] + outParameters: [.init(name: resultName, type: ._OutSwiftGenericInstance, allocation: .new)], + conversion: .wrapMemoryAddressUnsafe( + .commaSeparated([ + .member(.constant(resultName), field: "selfPointer"), + .member(.constant(resultName), field: "selfTypePointer"), + ]), + javaType ) ) } else { @@ -1158,19 +1146,27 @@ extension JNISwift2JavaGenerator { let outParamName = "\(resultName)_\(idx)$" // Determine the Java type for this element - let (javaType, elementConversion) = try translateTupleElementResult( - type: element.type, + let elementResult = try translate( + swiftResult: .init(convention: .indirect, type: element.type), + resultName: outParamName, genericParameters: genericParameters, genericRequirements: genericRequirements ) - let arrayType: JavaType = .array(javaType) - outParameters.append( - OutParameter(name: outParamName, type: arrayType, allocation: .newArray(javaType, size: 1)) - ) elementOutParamNames.append(outParamName) - elementConversions.append(elementConversion) - elementJavaTypes.append(javaType) + // FIXME: More accurate determination of whether the result is direct or indirect + if elementResult.outParameters.isEmpty { + // Convert direct result to indirect result + let arrayType: JavaType = .array(elementResult.javaType) + outParameters.append( + OutParameter(name: outParamName, type: arrayType, allocation: .newArray(elementResult.javaType, size: 1)) + ) + elementConversions.append(elementResult.conversion) + } else { + outParameters.append(contentsOf: elementResult.outParameters) + elementConversions.append(.placeToVar(elementResult.conversion, name: "\(resultName)_\(idx)")) + } + elementJavaTypes.append(elementResult.javaType) } let javaResultType: JavaType = .tuple(elementTypes: elementJavaTypes) @@ -1183,48 +1179,15 @@ extension JNISwift2JavaGenerator { javaType: javaResultType, outParameters: outParameters, conversion: .tupleFromOutParams( - tupleClassName: "new \(fullTupleClassName)<>", + tupleClassName: fullTupleClassName, elements: tupleElements ) ) } - /// Translate a single element type for tuple results on the Java side. - private func translateTupleElementResult( - type: SwiftType, - genericParameters: [SwiftGenericParameterDeclaration], - genericRequirements: [SwiftGenericRequirement] - ) throws -> (JavaType, JavaNativeConversionStep) { - switch type { - case .nominal(let nominalType): - if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { - throw JavaTranslationError.unsupportedSwiftType(type) - } - // Primitives: just read from array - return (javaType, .placeholder) - } - - guard !nominalType.isSwiftJavaWrapper else { - throw JavaTranslationError.unsupportedSwiftType(type) - } - - let javaType = try translateGenericTypeParameter( - type, - genericParameters: genericParameters, - genericRequirements: genericRequirements - ) - // JExtract class: wrap memory address - return (.long, .constructSwiftValue(.placeholder, javaType)) - - default: - throw JavaTranslationError.unsupportedSwiftType(type) - } - } - func translateOptionalResult( wrappedType swiftType: SwiftType, - resultName: String = "result", + resultName: String, genericParameters: [SwiftGenericParameterDeclaration], genericRequirements: [SwiftGenericRequirement] ) throws -> TranslatedResult { @@ -1279,9 +1242,9 @@ extension JNISwift2JavaGenerator { OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1)) ], conversion: .toOptionalFromIndirectReturn( - discriminatorName: .combinedName(component: "discriminator$"), + discriminatorName: .constant(discriminatorName), optionalClass: optionalClass, - javaType: javaType, + nativeResultJavaType: javaType, toValue: .placeholder, resultName: resultName ) @@ -1300,18 +1263,34 @@ extension JNISwift2JavaGenerator { genericParameters: genericParameters, genericRequirements: genericRequirements ) + + let wrappedValueResult = try translate( + swiftResult: SwiftResult(convention: .direct, type: swiftType), + resultName: resultName + "Wrapped$", + genericParameters: genericParameters, + genericRequirements: genericRequirements, + ) + + // FIXME: More accurate JavaType using NativeJavaTranslation results directly + let nativeResultJavaType: JavaType = + if wrappedValueResult.outParameters.isEmpty { + .long + } else { + .void + } + let returnType = JavaType.class(package: nil, name: "Optional", typeParameters: [javaType]) return TranslatedResult( javaType: returnType, annotations: parameterAnnotations, outParameters: [ OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1)) - ], + ] + wrappedValueResult.outParameters, conversion: .toOptionalFromIndirectReturn( - discriminatorName: .combinedName(component: "discriminator$"), + discriminatorName: .constant(discriminatorName), optionalClass: "Optional", - javaType: .long, - toValue: .wrapMemoryAddressUnsafe(.placeholder, javaType), + nativeResultJavaType: nativeResultJavaType, + toValue: wrappedValueResult.conversion, resultName: resultName ) ) @@ -1422,7 +1401,7 @@ extension JNISwift2JavaGenerator { ] ), function: "toArray", - arguments: [.constant("\(javaType)[]::new")] + arguments: [.constant("\(javaType.className!)[]::new")] ) ) @@ -1736,12 +1715,12 @@ extension JNISwift2JavaGenerator { static func toOptionalFromIndirectReturn( discriminatorName: JavaNativeConversionStep, optionalClass: String, - javaType: JavaType, + nativeResultJavaType: JavaType, toValue valueConversion: JavaNativeConversionStep, resultName: String ) -> JavaNativeConversionStep { .aggregate( - variable: (name: "\(resultName)$", type: javaType), + variable: nativeResultJavaType.isVoid ? nil : (name: "\(resultName)$", type: nativeResultJavaType), [ .ternary( .equals( @@ -1779,6 +1758,8 @@ extension JNISwift2JavaGenerator { /// E.g. `new Tuple2<>(result_0$[0], result_1$[0])` case tupleFromOutParams(tupleClassName: String, elements: [(outParamName: String, elementConversion: JavaNativeConversionStep)]) + indirect case placeToVar(JavaNativeConversionStep, name: String) + /// `Arrays.stream(args)` static func arraysStream(_ argument: JavaNativeConversionStep) -> JavaNativeConversionStep { .method(.constant("Arrays"), function: "stream", arguments: [argument]) @@ -1810,15 +1791,24 @@ extension JNISwift2JavaGenerator { case .constructSwiftValue(let inner, let javaType): let inner = inner.render(&printer, placeholder) - return "new \(javaType.className!)(\(inner), swiftArena)" + return "new \(javaType)(\(inner), swiftArena)" case .wrapMemoryAddressUnsafe(let inner, let javaType): let inner = inner.render(&printer, placeholder) - return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena)" + guard case .class(_, let className, let typeParameters) = javaType else { + fatalError("\(javaType) is not class.") + } + let genericClause = + if !typeParameters.isEmpty { + "<\(typeParameters.map(\.description).joined(separator: ", "))>" + } else { + "" + } + return "\(className).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)" case .constructJavaClass(let inner, let javaType): let inner = inner.render(&printer, placeholder) - return "new \(javaType.className!)(\(inner))" + return "new \(javaType)(\(inner))" case .call(let inner, let function): let inner = inner.render(&printer, placeholder) @@ -1931,14 +1921,17 @@ extension JNISwift2JavaGenerator { return #"Objects.requireNonNull(\#(inner), "\#(message)")"# case .tupleFromOutParams(let tupleClassName, let elements): - // Execute the native call first (the placeholder is the downcall expression) - printer.print("\(placeholder);") var args: [String] = [] for element in elements { let converted = element.elementConversion.render(&printer, "\(element.outParamName)[0]") args.append(converted) } - return "\(tupleClassName)(\(args.joined(separator: ", ")))" + return "new \(tupleClassName)<>(\(args.joined(separator: ", ")))" + + case .placeToVar(let inner, let name): + let inner = inner.render(&printer, placeholder) + printer.print("var \(name) = \(inner);") + return name } } @@ -2004,6 +1997,9 @@ extension JNISwift2JavaGenerator { case .tupleFromOutParams(_, let elements): return elements.contains(where: { $0.elementConversion.requiresSwiftArena }) + + case .placeToVar(let inner, _): + return inner.requiresSwiftArena } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 48875f8f..6b010794 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -577,18 +577,26 @@ extension JNISwift2JavaGenerator { throw JavaTranslationError.unsupportedSwiftType(swiftType) } + let wrappedValueResult = try translate( + swiftResult: .init( + convention: .direct, + type: swiftType + ), + resultName: resultName + "Wrapped" + ) + // Assume JExtract imported class return NativeResult( - javaType: .long, + javaType: wrappedValueResult.javaType, conversion: .optionalRaisingIndirectReturn( - .getJNIValue(.allocateSwiftValue(.placeholder, name: "_result", swiftType: swiftType)), - returnType: .long, + wrappedValueResult.conversion, + returnType: wrappedValueResult.javaType, discriminatorParameterName: discriminatorName, placeholderValue: .constant("0") ), outParameters: [ JavaParameter(name: discriminatorName, type: .array(.byte)) - ] + ] + wrappedValueResult.outParameters ) default: @@ -746,9 +754,9 @@ extension JNISwift2JavaGenerator { conversion: .genericValueIndirectReturn( .getJNIValue(.allocateSwiftValue(.placeholder, name: resultName, swiftType: swiftResult.type)), swiftFunctionResultType: swiftResult.type, - outArgumentName: "out" + outArgumentName: resultName + "Out" ), - outParameters: [.init(name: "out", type: ._OutSwiftGenericInstance)] + outParameters: [.init(name: resultName + "Out", type: ._OutSwiftGenericInstance)] ) } else { return NativeResult( @@ -784,12 +792,21 @@ extension JNISwift2JavaGenerator { let outParamName = "\(resultName)_\(idx)$" // Get the JNI type for this element - let elementResult = try translateElementResult(type: element.type) - - outParameters.append( - JavaParameter(name: outParamName, type: .array(elementResult.javaType)) + let elementResult = try translate( + swiftResult: .init(convention: .indirect, type: element.type), + resultName: outParamName ) + // FIXME: More accurate determination of whether the result is direct or indirect + if elementResult.outParameters.isEmpty { + // Convert direct result to indirect result + outParameters.append( + JavaParameter(name: outParamName, type: .array(elementResult.javaType)) + ) + } else { + outParameters.append(contentsOf: elementResult.outParameters) + } + destructureElements.append( ( index: idx, @@ -808,31 +825,6 @@ extension JNISwift2JavaGenerator { ) } - /// Translate a single element type for use in tuple result destructuring. - private func translateElementResult(type: SwiftType) throws -> (javaType: JavaType, conversion: NativeSwiftConversionStep) { - switch type { - case .nominal(let nominalType): - if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), - javaType.implementsJavaValue - else { - throw JavaTranslationError.unsupportedSwiftType(type) - } - return (javaType: javaType, conversion: .getJNIValue(.placeholder)) - } - - guard !nominalType.isSwiftJavaWrapper else { - throw JavaTranslationError.unsupportedSwiftType(type) - } - - // JExtract class: allocate and return pointer - return (javaType: .long, conversion: .getJNIValue(.allocateSwiftValue(.placeholder, name: "element", swiftType: type))) - - default: - throw JavaTranslationError.unsupportedSwiftType(type) - } - } - func translateArrayResult( elementType: SwiftType, resultName: String @@ -1490,12 +1482,16 @@ extension JNISwift2JavaGenerator { let discriminatorParameterName, let placeholderValue ): - printer.print("let result$: \(returnType.jniTypeName)") + if !returnType.isVoid { + printer.print("let result$: \(returnType.jniTypeName)") + } printer.printBraceBlock("if let innerResult$ = \(placeholder)") { printer in let inner = inner.render(&printer, "innerResult$") + if !returnType.isVoid { + printer.print("result$ = \(inner)") + } printer.print( """ - result$ = \(inner) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, \(discriminatorParameterName), 0, 1, &flag$) """ @@ -1503,27 +1499,34 @@ extension JNISwift2JavaGenerator { } printer.printBraceBlock("else") { printer in let placeholderValue = placeholderValue.render(&printer, placeholder) + if !returnType.isVoid { + printer.print("result$ = \(placeholderValue)") + } printer.print( """ - result$ = \(placeholderValue) var flag$ = Int8(0) environment.interface.SetByteArrayRegion(environment, \(discriminatorParameterName), 0, 1, &flag$) """ ) } - - return "result$" + if !returnType.isVoid { + return "result$" + } else { + return "" + } case .genericValueIndirectReturn(let inner, let swiftFunctionResultType, let outArgumentName): let inner = inner.render(&printer, placeholder) - printer.print( - """ - environment.interface.SetLongField(environment, \(outArgumentName), _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, \(inner)) - let metadataPointer = unsafeBitCast(\(swiftFunctionResultType).self, to: UnsafeRawPointer.self) - let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) - environment.interface.SetLongField(environment, \(outArgumentName), _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) - """ - ) + printer.printBraceBlock("do") { printer in + printer.print( + """ + environment.interface.SetLongField(environment, \(outArgumentName), _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, \(inner)) + let metadataPointer = unsafeBitCast(\(swiftFunctionResultType).self, to: UnsafeRawPointer.self) + let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) + environment.interface.SetLongField(environment, \(outArgumentName), _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) + """ + ) + } return "" case .method(let inner, let methodName, let arguments): @@ -1727,13 +1730,15 @@ extension JNISwift2JavaGenerator { for element in elements { let accessor = element.label ?? "\(element.index)" let converted = element.conversion.render(&printer, "\(tupleVar).\(accessor)") - if element.javaType.isPrimitive { + switch element.javaType { + case .void: break + case .boolean, .byte, .char, .short, .int, .long, .float, .double: let setMethodName = element.javaType.jniSetArrayRegionMethodName printer.print("var element_\(element.index)_jni$ = \(converted)") printer.print( "environment.interface.\(setMethodName)(environment, \(element.outParamName), 0, 1, &element_\(element.index)_jni$)" ) - } else { + case .class, .array: printer.print("let element_\(element.index)_jni$ = \(converted)") printer.print( "environment.interface.SetObjectArrayElement(environment, \(element.outParamName), 0, element_\(element.index)_jni$)" diff --git a/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift b/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift index c09bbaaa..0690ee01 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift @@ -28,7 +28,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """, """ @@ -104,7 +104,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena); } """, """ @@ -142,7 +142,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena); } """, """ @@ -183,7 +183,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -200,7 +200,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -217,7 +217,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -234,7 +234,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -295,7 +295,7 @@ struct JNIDictionaryTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, java.lang.String key, long value, SwiftArena swiftArena) { - return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress(), key, value), swiftArena); + return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress(), key, value), swiftArena); } """, """ diff --git a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift new file mode 100644 index 00000000..897a2103 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift @@ -0,0 +1,286 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIGenericCombinationTests { + static let myIDDecl = + #""" + public struct MyID { + public var rawValue: T + public init(_ rawValue: T) { + self.rawValue = rawValue + } + public var description: String { + "\(rawValue)" + } + } + """# + + @Suite struct WithOptional { + let returnFuncFile = """ + \(myIDDecl) + + public func makeStringIDOptional(_ value: String) -> MyID? { + return MyID(value) + } + """ + + let argumentFuncFile = """ + \(myIDDecl) + + public func takeStringIDOptional(_ value: MyID?) { + } + """ + + @Test + func returnFuncJava() throws { + try assertOutput( + input: returnFuncFile, + .jni, + .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + public static Optional> makeStringIDOptional(java.lang.String value, SwiftArena swiftArena) { + byte[] result$_discriminator$ = new byte[1]; + org.swift.swiftkit.core._OutSwiftGenericInstance resultWrapped$ = new org.swift.swiftkit.core._OutSwiftGenericInstance(); + SwiftModule.$makeStringIDOptional(value, result$_discriminator$, resultWrapped$); + return (result$_discriminator$[0] == 1) ? Optional.of(MyID.wrapMemoryAddressUnsafe(resultWrapped$.selfPointer, resultWrapped$.selfTypePointer, swiftArena)) : Optional.empty(); + } + """, + """ + private static native void $makeStringIDOptional(java.lang.String value, byte[] result_discriminator$, org.swift.swiftkit.core._OutSwiftGenericInstance resultWrappedOut); + """, + ] + ) + } + + @Test + func returnFuncSwift() throws { + try assertOutput( + input: returnFuncFile, + .jni, + .swift, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024makeStringIDOptional__Ljava_lang_String_2_3BLorg_swift_swiftkit_core__1OutSwiftGenericInstance_2") + public func Java_com_example_swift_SwiftModule__00024makeStringIDOptional__Ljava_lang_String_2_3BLorg_swift_swiftkit_core__1OutSwiftGenericInstance_2(environment: UnsafeMutablePointer!, thisClass: jclass, value: jstring?, result_discriminator$: jbyteArray?, resultWrappedOut: jobject?) { + if let innerResult$ = SwiftModule.makeStringIDOptional(String(fromJNI: value, in: environment)) { + let resultWrapped$ = UnsafeMutablePointer>.allocate(capacity: 1) + resultWrapped$.initialize(to: innerResult$) + let resultWrappedBits$ = Int64(Int(bitPattern: resultWrapped$)) + do { + environment.interface.SetLongField(environment, resultWrappedOut, _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, resultWrappedBits$.getJNIValue(in: environment)) + let metadataPointer = unsafeBitCast(MyID.self, to: UnsafeRawPointer.self) + let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) + environment.interface.SetLongField(environment, resultWrappedOut, _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) + } + var flag$ = Int8(1) + environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) + } + else { + var flag$ = Int8(0) + environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) + } + return + } + """ + ] + ) + } + + @Test + func argumentFuncJava() throws { + try assertOutput( + input: argumentFuncFile, + .jni, + .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + public static void takeStringIDOptional(Optional> value) { + SwiftModule.$takeStringIDOptional(value.map(MyID::$memoryAddress).orElse(0L)); + } + """, + """ + private static native void $takeStringIDOptional(long value); + """, + ] + ) + } + + @Test + func argumentFuncSwift() throws { + try assertOutput( + input: argumentFuncFile, + .jni, + .swift, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeStringIDOptional__J") + public func Java_com_example_swift_SwiftModule__00024takeStringIDOptional__J(environment: UnsafeMutablePointer!, thisClass: jclass, value: jlong) { + let valueBits$ = Int(Int64(fromJNI: value, in: environment)) + let value$ = UnsafeMutablePointer>(bitPattern: valueBits$) + SwiftModule.takeStringIDOptional(value$?.pointee) + } + """ + ] + ) + } + } + + @Suite struct WithTuple { + let returnFuncFile = """ + \(myIDDecl) + + public static func makeIDs(_ stringValue: String, _ intValue: Int64) -> (MyID, MyID) { + (MyID(stringValue), MyID(intValue)) + } + """ + + let argumentFuncFile = """ + \(myIDDecl) + + public static func takeValues(from tuple: (MyID, MyID)) -> (String, Int64) { + (tuple.0.rawValue, tuple.1.rawValue) + } + """ + + @Test + func returnFuncJava() throws { + try assertOutput( + input: returnFuncFile, + .jni, + .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + public static org.swift.swiftkit.core.tuple.Tuple2, MyID> makeIDs(java.lang.String stringValue, long intValue, SwiftArena swiftArena) { + org.swift.swiftkit.core._OutSwiftGenericInstance result_0$ = new org.swift.swiftkit.core._OutSwiftGenericInstance(); + org.swift.swiftkit.core._OutSwiftGenericInstance result_1$ = new org.swift.swiftkit.core._OutSwiftGenericInstance(); + SwiftModule.$makeIDs(stringValue, intValue, result_0$, result_1$); + var result_0 = MyID.wrapMemoryAddressUnsafe(result_0$.selfPointer, result_0$.selfTypePointer, swiftArena); + var result_1 = MyID.wrapMemoryAddressUnsafe(result_1$.selfPointer, result_1$.selfTypePointer, swiftArena); + return new org.swift.swiftkit.core.tuple.Tuple2<>(result_0, result_1); + } + """, + """ + private static native void $makeIDs(java.lang.String stringValue, long intValue, org.swift.swiftkit.core._OutSwiftGenericInstance result_0$Out, org.swift.swiftkit.core._OutSwiftGenericInstance result_1$Out); + """, + ] + ) + } + + @Test + func returnFuncSwift() throws { + try assertOutput( + input: returnFuncFile, + .jni, + .swift, + detectChunkByInitialLines: 4, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024makeIDs__Ljava_lang_String_2JLorg_swift_swiftkit_core__1OutSwiftGenericInstance_2Lorg_swift_swiftkit_core__1OutSwiftGenericInstance_2") + public func Java_com_example_swift_SwiftModule__00024makeIDs__Ljava_lang_String_2JLorg_swift_swiftkit_core__1OutSwiftGenericInstance_2Lorg_swift_swiftkit_core__1OutSwiftGenericInstance_2(environment: UnsafeMutablePointer!, thisClass: jclass, stringValue: jstring?, intValue: jlong, result_0$Out: jobject?, result_1$Out: jobject?) { + let tupleResult$ = SwiftModule.makeIDs(String(fromJNI: stringValue, in: environment), Int64(fromJNI: intValue, in: environment)) + let result_0$$ = UnsafeMutablePointer>.allocate(capacity: 1) + result_0$$.initialize(to: tupleResult$.0) + let result_0$Bits$ = Int64(Int(bitPattern: result_0$$)) + do { + environment.interface.SetLongField(environment, result_0$Out, _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, result_0$Bits$.getJNIValue(in: environment)) + let metadataPointer = unsafeBitCast(MyID.self, to: UnsafeRawPointer.self) + let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) + environment.interface.SetLongField(environment, result_0$Out, _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) + } + let result_1$$ = UnsafeMutablePointer>.allocate(capacity: 1) + result_1$$.initialize(to: tupleResult$.1) + let result_1$Bits$ = Int64(Int(bitPattern: result_1$$)) + do { + environment.interface.SetLongField(environment, result_1$Out, _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, result_1$Bits$.getJNIValue(in: environment)) + let metadataPointer = unsafeBitCast(MyID.self, to: UnsafeRawPointer.self) + let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) + environment.interface.SetLongField(environment, result_1$Out, _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) + } + return + } + """ + ] + ) + } + + @Test + func argumentFuncJava() throws { + try assertOutput( + input: argumentFuncFile, + .jni, + .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + public static org.swift.swiftkit.core.tuple.Tuple2 takeValues(org.swift.swiftkit.core.tuple.Tuple2, MyID> tuple) { + java.lang.String[] result_0$ = new java.lang.String[1]; + long[] result_1$ = new long[1]; + SwiftModule.$takeValues(tuple.$0.$memoryAddress(), tuple.$1.$memoryAddress(), result_0$, result_1$); + return new org.swift.swiftkit.core.tuple.Tuple2<>(result_0$[0], result_1$[0]); + } + """, + """ + private static native void $takeValues(long tuple_0, long tuple_1, java.lang.String[] result_0$, long[] result_1$); + """, + ] + ) + } + + @Test + func argumentFuncSwift() throws { + try assertOutput( + input: argumentFuncFile, + .jni, + .swift, + detectChunkByInitialLines: 2, + expectedChunks: [ + #""" + @_cdecl("Java_com_example_swift_SwiftModule__00024takeValues__JJ_3Ljava_lang_String_2_3J") + public func Java_com_example_swift_SwiftModule__00024takeValues__JJ_3Ljava_lang_String_2_3J(environment: UnsafeMutablePointer!, thisClass: jclass, tuple_0: jlong, tuple_1: jlong, result_0$: jobjectArray?, result_1$: jlongArray?) { + assert(tuple_0 != 0, "tuple_0 memory address was null") + let tuple_0Bits$ = Int(Int64(fromJNI: tuple_0, in: environment)) + let tuple_0$ = UnsafeMutablePointer>(bitPattern: tuple_0Bits$) + guard let tuple_0$ else { + fatalError("tuple_0 memory address was null in call to \(#function)!") + } + assert(tuple_1 != 0, "tuple_1 memory address was null") + let tuple_1Bits$ = Int(Int64(fromJNI: tuple_1, in: environment)) + let tuple_1$ = UnsafeMutablePointer>(bitPattern: tuple_1Bits$) + guard let tuple_1$ else { + fatalError("tuple_1 memory address was null in call to \(#function)!") + } + let tupleResult$ = SwiftModule.takeValues(from: (tuple_0$.pointee, tuple_1$.pointee)) + let element_0_jni$ = tupleResult$.0.getJNILocalRefValue(in: environment) + environment.interface.SetObjectArrayElement(environment, result_0$, 0, element_0_jni$) + var element_1_jni$ = tupleResult$.1.getJNILocalRefValue(in: environment) + environment.interface.SetLongArrayRegion(environment, result_1$, 0, 1, &element_1_jni$) + return + } + """# + ] + ) + } + } + +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIGenericTypeTests.swift b/Tests/JExtractSwiftTests/JNI/JNIGenericTypeTests.swift index cf5beded..7c97ad39 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIGenericTypeTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIGenericTypeTests.swift @@ -155,13 +155,13 @@ struct JNIGenericTypeTests { expectedChunks: [ """ public static MyID makeStringID(java.lang.String value, SwiftArena swiftArena) { - org.swift.swiftkit.core._OutSwiftGenericInstance instance = new org.swift.swiftkit.core._OutSwiftGenericInstance(); - SwiftModule.$makeStringID(value, instance); - return MyID.wrapMemoryAddressUnsafe(instance.selfPointer, instance.selfTypePointer, swiftArena); + org.swift.swiftkit.core._OutSwiftGenericInstance result = new org.swift.swiftkit.core._OutSwiftGenericInstance(); + SwiftModule.$makeStringID(value, result); + return MyID.wrapMemoryAddressUnsafe(result.selfPointer, result.selfTypePointer, swiftArena); } """, """ - private static native void $makeStringID(java.lang.String value, org.swift.swiftkit.core._OutSwiftGenericInstance out); + private static native void $makeStringID(java.lang.String value, org.swift.swiftkit.core._OutSwiftGenericInstance resultOut); """, """ public static long takeIntID(MyID value) { @@ -185,14 +185,16 @@ struct JNIGenericTypeTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_SwiftModule__00024makeStringID__Ljava_lang_String_2Lorg_swift_swiftkit_core__1OutSwiftGenericInstance_2") - public func Java_com_example_swift_SwiftModule__00024makeStringID__Ljava_lang_String_2Lorg_swift_swiftkit_core__1OutSwiftGenericInstance_2(environment: UnsafeMutablePointer!, thisClass: jclass, value: jstring?, out: jobject?) { + public func Java_com_example_swift_SwiftModule__00024makeStringID__Ljava_lang_String_2Lorg_swift_swiftkit_core__1OutSwiftGenericInstance_2(environment: UnsafeMutablePointer!, thisClass: jclass, value: jstring?, resultOut: jobject?) { let result$ = UnsafeMutablePointer>.allocate(capacity: 1) result$.initialize(to: SwiftModule.makeStringID(String(fromJNI: value, in: environment))) let resultBits$ = Int64(Int(bitPattern: result$)) - environment.interface.SetLongField(environment, out, _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, resultBits$.getJNIValue(in: environment)) - let metadataPointer = unsafeBitCast(MyID.self, to: UnsafeRawPointer.self) - let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) - environment.interface.SetLongField(environment, out, _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) + do { + environment.interface.SetLongField(environment, resultOut, _JNIMethodIDCache._OutSwiftGenericInstance.selfPointer, resultBits$.getJNIValue(in: environment)) + let metadataPointer = unsafeBitCast(MyID.self, to: UnsafeRawPointer.self) + let metadataPointerBits$ = Int64(Int(bitPattern: metadataPointer)) + environment.interface.SetLongField(environment, resultOut, _JNIMethodIDCache._OutSwiftGenericInstance.selfTypePointer, metadataPointerBits$.getJNIValue(in: environment)) + } return } """, diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift index 90702944..728165bf 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -184,10 +184,10 @@ struct JNIOptionalTests { let arg$ = UnsafeMutablePointer(bitPattern: argBits$) let result$: jlong if let innerResult$ = SwiftModule.optionalClass(arg$?.pointee) { - let _result$ = UnsafeMutablePointer.allocate(capacity: 1) - _result$.initialize(to: innerResult$) - let _resultBits$ = Int64(Int(bitPattern: _result$)) - result$ = _resultBits$.getJNIValue(in: environment) + let resultWrapped$ = UnsafeMutablePointer.allocate(capacity: 1) + resultWrapped$.initialize(to: innerResult$) + let resultWrappedBits$ = Int64(Int(bitPattern: resultWrapped$)) + result$ = resultWrappedBits$.getJNILocalRefValue(in: environment) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) } diff --git a/Tests/JExtractSwiftTests/JNI/JNISetTest.swift b/Tests/JExtractSwiftTests/JNI/JNISetTest.swift index 4a70fdcd..e654344d 100644 --- a/Tests/JExtractSwiftTests/JNI/JNISetTest.swift +++ b/Tests/JExtractSwiftTests/JNI/JNISetTest.swift @@ -28,7 +28,7 @@ struct JNISetTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) { - return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """, """ @@ -104,7 +104,7 @@ struct JNISetTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftSet f(org.swift.swiftkit.core.collections.SwiftSet set, SwiftArena swiftArena) { - return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress()), swiftArena); + return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress()), swiftArena); } """, """ @@ -145,7 +145,7 @@ struct JNISetTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) { - return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -162,7 +162,7 @@ struct JNISetTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) { - return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -179,7 +179,7 @@ struct JNISetTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) { - return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); + return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena); } """ ] @@ -240,7 +240,7 @@ struct JNISetTest { expectedChunks: [ """ public static org.swift.swiftkit.core.collections.SwiftSet f(org.swift.swiftkit.core.collections.SwiftSet set, java.lang.String element, SwiftArena swiftArena) { - return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress(), element), swiftArena); + return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress(), element), swiftArena); } """, """ diff --git a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift index 328fa33d..1a92fa99 100644 --- a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift @@ -56,9 +56,9 @@ struct JNITupleTests { expectedChunks: [ """ let tupleResult$ = SwiftModule.returnPair() - var element_0_jni$ = tupleResult$.0.getJNIValue(in: environment) + var element_0_jni$ = tupleResult$.0.getJNILocalRefValue(in: environment) environment.interface.SetLongArrayRegion(environment, result_0$, 0, 1, &element_0_jni$) - let element_1_jni$ = tupleResult$.1.getJNIValue(in: environment) + let element_1_jni$ = tupleResult$.1.getJNILocalRefValue(in: environment) environment.interface.SetObjectArrayElement(environment, result_1$, 0, element_1_jni$) """ ] @@ -127,9 +127,9 @@ struct JNITupleTests { expectedChunks: [ """ let tupleResult$ = SwiftModule.labeledTuple() - var element_0_jni$ = tupleResult$.x.getJNIValue(in: environment) + var element_0_jni$ = tupleResult$.x.getJNILocalRefValue(in: environment) environment.interface.SetIntArrayRegion(environment, result_0$, 0, 1, &element_0_jni$) - var element_1_jni$ = tupleResult$.y.getJNIValue(in: environment) + var element_1_jni$ = tupleResult$.y.getJNILocalRefValue(in: environment) environment.interface.SetIntArrayRegion(environment, result_1$, 0, 1, &element_1_jni$) """ ]