@@ -168,14 +168,26 @@ extension JNISwift2JavaGenerator {
168168 let nominalTypeName = nominalType. nominalTypeDecl. name
169169
170170 if let knownType = nominalType. nominalTypeDecl. knownTypeKind {
171- guard let javaType = JNISwift2JavaGenerator . translate ( knownType: knownType) else {
172- throw JavaTranslationError . unsupportedSwiftType ( swiftType)
171+ switch knownType {
172+ case . optional:
173+ guard let genericArgs = nominalType. genericArguments, genericArgs. count == 1 else {
174+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
175+ }
176+ return try translateOptionalParameter (
177+ wrappedType: genericArgs [ 0 ] ,
178+ parameterName: parameterName
179+ )
180+
181+ default :
182+ guard let javaType = JNISwift2JavaGenerator . translate ( knownType: knownType) else {
183+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
184+ }
185+
186+ return TranslatedParameter (
187+ parameter: JavaParameter ( name: parameterName, type: javaType) ,
188+ conversion: . placeholder
189+ )
173190 }
174-
175- return TranslatedParameter (
176- parameter: JavaParameter ( name: parameterName, type: javaType) ,
177- conversion: . placeholder
178- )
179191 }
180192
181193 if nominalType. isJavaKitWrapper {
@@ -216,7 +228,73 @@ extension JNISwift2JavaGenerator {
216228 conversion: . placeholder
217229 )
218230
219- case . metatype, . optional, . tuple, . existential, . opaque:
231+ case . optional( let wrapped) :
232+ return try translateOptionalParameter (
233+ wrappedType: wrapped,
234+ parameterName: parameterName
235+ )
236+
237+ case . metatype, . tuple, . existential, . opaque:
238+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
239+ }
240+ }
241+
242+ func translateOptionalParameter(
243+ wrappedType swiftType: SwiftType ,
244+ parameterName: String
245+ ) throws -> TranslatedParameter {
246+ switch swiftType {
247+ case . nominal( let nominalType) :
248+ let nominalTypeName = nominalType. nominalTypeDecl. name
249+
250+ if let knownType = nominalType. nominalTypeDecl. knownTypeKind {
251+ guard let javaType = JNISwift2JavaGenerator . translate ( knownType: knownType) else {
252+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
253+ }
254+
255+ let ( translatedClass, orElseValue) = switch javaType {
256+ case . boolean: ( " Optional<Boolean> " , " false " )
257+ case . byte: ( " Optional<Byte> " , " 0 " )
258+ case . char: ( " Optional<Character> " , " 0 " )
259+ case . short: ( " Optional<Short> " , " 0 " )
260+ case . int: ( " OptionalInt " , " 0 " )
261+ case . long: ( " OptionalLong " , " 0 " )
262+ case . float: ( " Optional<Float> " , " 0 " )
263+ case . double: ( " OptionalDouble " , " 0 " )
264+ case . javaLangString: ( " Optional<String> " , #""""# )
265+ default :
266+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
267+ }
268+
269+ return TranslatedParameter (
270+ parameter: JavaParameter (
271+ name: parameterName,
272+ type: JavaType ( className: translatedClass)
273+ ) ,
274+ conversion: . commaSeparated( [
275+ . isOptionalPresent,
276+ . method( . placeholder, function: " orElse " , arguments: [ . constant( orElseValue) ] )
277+ ] )
278+ )
279+ }
280+
281+ guard !nominalType. isJavaKitWrapper else {
282+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
283+ }
284+
285+ // Assume JExtract imported class
286+ return TranslatedParameter (
287+ parameter: JavaParameter (
288+ name: parameterName,
289+ type: . class( package : nil , name: " Optional< \( nominalTypeName) > " )
290+ ) ,
291+ conversion: . method(
292+ . method( . placeholder, function: " map " , arguments: [ . constant( " \( nominalType) ::$memoryAddress " ) ] ) ,
293+ function: " orElse " ,
294+ arguments: [ . constant( " 0L " ) ]
295+ )
296+ )
297+ default :
220298 throw JavaTranslationError . unsupportedSwiftType ( swiftType)
221299 }
222300 }
@@ -337,41 +415,77 @@ extension JNISwift2JavaGenerator {
337415 /// The value being converted
338416 case placeholder
339417
418+ case constant( String )
419+
420+ // The input exploded into components.
421+ case explodedName( component: String )
422+
423+ // Convert the results of the inner steps to a comma separated list.
424+ indirect case commaSeparated( [ JavaNativeConversionStep ] )
425+
340426 /// `value.$memoryAddress()`
341427 indirect case valueMemoryAddress( JavaNativeConversionStep )
342428
343429 /// Call `new \(Type)(\(placeholder), swiftArena$)`
344430 indirect case constructSwiftValue( JavaNativeConversionStep , JavaType )
345431
432+ indirect case method( JavaNativeConversionStep , function: String , arguments: [ JavaNativeConversionStep ] )
433+
434+ case isOptionalPresent
435+
346436 /// Returns the conversion string applied to the placeholder.
347437 func render( _ printer: inout CodePrinter , _ placeholder: String ) -> String {
348438 // NOTE: 'printer' is used if the conversion wants to cause side-effects.
349439 // E.g. storing a temporary values into a variable.
350440 switch self {
351441 case . placeholder:
352442 return placeholder
353-
443+
444+ case . constant( let value) :
445+ return value
446+
447+ case . explodedName( let component) :
448+ return " \( placeholder) _ \( component) "
449+
450+ case . commaSeparated( let list) :
451+ return list. map ( { $0. render ( & printer, placeholder) } ) . joined ( separator: " , " )
452+
354453 case . valueMemoryAddress:
355454 return " \( placeholder) .$memoryAddress() "
356-
455+
357456 case . constructSwiftValue( let inner, let javaType) :
358457 let inner = inner. render ( & printer, placeholder)
359458 return " new \( javaType. className!) ( \( inner) , swiftArena$) "
360-
459+
460+ case . isOptionalPresent:
461+ return " (byte) ( \( placeholder) .isPresent() ? 1 : 0) "
462+
463+ case . method( let inner, let methodName, let arguments) :
464+ let inner = inner. render ( & printer, placeholder)
465+ let args = arguments. map { $0. render ( & printer, placeholder) }
466+ let argsStr = args. joined ( separator: " , " )
467+ return " \( inner) . \( methodName) ( \( argsStr) ) "
468+
361469 }
362470 }
363471
364472 /// Whether the conversion uses SwiftArena.
365473 var requiresSwiftArena : Bool {
366474 switch self {
367- case . placeholder:
475+ case . placeholder, . constant , . explodedName , . isOptionalPresent :
368476 return false
369477
370478 case . constructSwiftValue:
371479 return true
372480
373481 case . valueMemoryAddress( let inner) :
374482 return inner. requiresSwiftArena
483+
484+ case . commaSeparated( let list) :
485+ return list. contains ( where: { $0. requiresSwiftArena } )
486+
487+ case . method( let inner, _, _) :
488+ return inner. requiresSwiftArena
375489 }
376490 }
377491 }
0 commit comments