diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 386a7227..fd0ce488 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -16,6 +16,7 @@ public class MySwiftClass { let x: Int64 let y: Int64 + public let byte: UInt8 = 0 public let constant: Int64 = 100 public var mutable: Int64 = 0 public var product: Int64 { diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 97f5149e..30661045 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -14,6 +14,7 @@ public class MySwiftClass { + public let byte: UInt8 = 0 public var len: Int public var cap: Int diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index ec0fa9c4..80b47760 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -176,6 +176,11 @@ extension JNISwift2JavaGenerator { } private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + guard let _ = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } + if decl.isStatic || decl.isInitializer || !decl.hasParent { printStaticFunctionBinding(&printer, decl) } else { @@ -196,7 +201,7 @@ extension JNISwift2JavaGenerator { /// and passes it down to another native function along with the arguments /// to call the Swift implementation. private func printMemberMethodBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = translatedDecl(for: decl) + let translatedDecl = translatedDecl(for: decl)! // We will only call this method if we can translate the decl. printDeclDocumentation(&printer, decl) printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in @@ -220,7 +225,10 @@ extension JNISwift2JavaGenerator { } private func printInitializerBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc, type: ImportedNominalType) { - let translatedDecl = translatedDecl(for: decl) + guard let translatedDecl = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } printDeclDocumentation(&printer, decl) printer.printBraceBlock("public static \(renderFunctionSignature(decl))") { printer in @@ -275,7 +283,9 @@ extension JNISwift2JavaGenerator { /// `func method(x: Int, y: Int) -> Int` becomes /// `long method(long x, long y)` private func renderFunctionSignature(_ decl: ImportedFunc) -> String { - let translatedDecl = translatedDecl(for: decl) + guard let translatedDecl = translatedDecl(for: decl) else { + fatalError("Unable to render function signature for a function that cannot be translated: \(decl)") + } let resultType = translatedDecl.translatedFunctionSignature.resultType var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 179991df..9dc433d4 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -17,13 +17,19 @@ import JavaTypes extension JNISwift2JavaGenerator { func translatedDecl( for decl: ImportedFunc - ) -> TranslatedFunctionDecl { + ) -> TranslatedFunctionDecl? { if let cached = translatedDecls[decl] { return cached } - let translation = JavaTranslation(swiftModuleName: self.swiftModuleName) - let translated = translation.translate(decl) + let translated: TranslatedFunctionDecl? + do { + let translation = JavaTranslation(swiftModuleName: swiftModuleName) + translated = try translation.translate(decl) + } catch { + self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") + translated = nil + } translatedDecls[decl] = translated return translated @@ -32,8 +38,8 @@ extension JNISwift2JavaGenerator { struct JavaTranslation { let swiftModuleName: String - func translate(_ decl: ImportedFunc) -> TranslatedFunctionDecl { - let translatedFunctionSignature = translate(functionSignature: decl.functionSignature) + func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { + let translatedFunctionSignature = try translate(functionSignature: decl.functionSignature) // Types with no parent will be outputted inside a "module" class. let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName @@ -51,31 +57,31 @@ extension JNISwift2JavaGenerator { ) } - func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) -> TranslatedFunctionSignature { - let parameters = functionSignature.parameters.enumerated().map { idx, param in + func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) throws -> TranslatedFunctionSignature { + let parameters = try functionSignature.parameters.enumerated().map { idx, param in let parameterName = param.parameterName ?? "arg\(idx))" - return translate(swiftParam: param, parameterName: parameterName) + return try translate(swiftParam: param, parameterName: parameterName) } - return TranslatedFunctionSignature( + return try TranslatedFunctionSignature( parameters: parameters, resultType: translate(swiftType: functionSignature.result.type) ) } - func translate(swiftParam: SwiftParameter, parameterName: String) -> JavaParameter { - return JavaParameter( + func translate(swiftParam: SwiftParameter, parameterName: String) throws -> JavaParameter { + return try JavaParameter( name: parameterName, type: translate(swiftType: swiftParam.type) ) } - func translate(swiftType: SwiftType) -> JavaType { + func translate(swiftType: SwiftType) throws -> JavaType { switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { guard let javaType = translate(knownType: knownType) else { - fatalError("unsupported known type: \(knownType)") + throw JavaTranslationError.unsupportedSwiftType(swiftType) } return javaType } @@ -86,7 +92,7 @@ extension JNISwift2JavaGenerator { return .void case .metatype, .optional, .tuple, .function, .existential, .opaque: - fatalError("unsupported type: \(self)") + throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -127,4 +133,8 @@ extension JNISwift2JavaGenerator { let parameters: [JavaParameter] let resultType: JavaType } + + enum JavaTranslationError: Error { + case unsupportedSwiftType(SwiftType) + } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index c32e0e27..30db69d1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -116,7 +116,11 @@ extension JNISwift2JavaGenerator { } private func printInitializerThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = translatedDecl(for: decl) + guard let translatedDecl = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } + let typeName = translatedDecl.parentName printCDecl( @@ -146,6 +150,11 @@ extension JNISwift2JavaGenerator { _ printer: inout CodePrinter, _ decl: ImportedFunc ) { + guard let _ = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } + // Free functions does not have a parent if decl.isStatic || !decl.hasParent { self.printSwiftStaticFunctionThunk(&printer, decl) @@ -155,7 +164,7 @@ extension JNISwift2JavaGenerator { } private func printSwiftStaticFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = self.translatedDecl(for: decl) + let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if we can translate the decl. printCDecl( &printer, @@ -172,7 +181,7 @@ extension JNISwift2JavaGenerator { } private func printSwiftMemberFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = self.translatedDecl(for: decl) + let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if can translate the decl. let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName printCDecl( @@ -199,7 +208,9 @@ extension JNISwift2JavaGenerator { _ decl: ImportedFunc, calleeName: String ) { - let translatedDecl = self.translatedDecl(for: decl) + guard let translatedDecl = self.translatedDecl(for: decl) else { + fatalError("Cannot print function downcall for a function that can't be translated: \(decl)") + } let swiftReturnType = decl.functionSignature.result.type let tryClause: String = decl.isThrowing ? "try " : ""