Skip to content

Commit 9c0d7eb

Browse files
authored
[JExtract/JNI] Omit unsupported types instead of crashing (#313)
1 parent 94d5f34 commit 9c0d7eb

File tree

5 files changed

+54
-21
lines changed

5 files changed

+54
-21
lines changed

Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class MySwiftClass {
1616
let x: Int64
1717
let y: Int64
1818

19+
public let byte: UInt8 = 0
1920
public let constant: Int64 = 100
2021
public var mutable: Int64 = 0
2122
public var product: Int64 {

Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
public class MySwiftClass {
1616

17+
public let byte: UInt8 = 0
1718
public var len: Int
1819
public var cap: Int
1920

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ extension JNISwift2JavaGenerator {
176176
}
177177

178178
private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
179+
guard let _ = translatedDecl(for: decl) else {
180+
// Failed to translate. Skip.
181+
return
182+
}
183+
179184
if decl.isStatic || decl.isInitializer || !decl.hasParent {
180185
printStaticFunctionBinding(&printer, decl)
181186
} else {
@@ -196,7 +201,7 @@ extension JNISwift2JavaGenerator {
196201
/// and passes it down to another native function along with the arguments
197202
/// to call the Swift implementation.
198203
private func printMemberMethodBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
199-
let translatedDecl = translatedDecl(for: decl)
204+
let translatedDecl = translatedDecl(for: decl)! // We will only call this method if we can translate the decl.
200205

201206
printDeclDocumentation(&printer, decl)
202207
printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in
@@ -220,7 +225,10 @@ extension JNISwift2JavaGenerator {
220225
}
221226

222227
private func printInitializerBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc, type: ImportedNominalType) {
223-
let translatedDecl = translatedDecl(for: decl)
228+
guard let translatedDecl = translatedDecl(for: decl) else {
229+
// Failed to translate. Skip.
230+
return
231+
}
224232

225233
printDeclDocumentation(&printer, decl)
226234
printer.printBraceBlock("public static \(renderFunctionSignature(decl))") { printer in
@@ -275,7 +283,9 @@ extension JNISwift2JavaGenerator {
275283
/// `func method(x: Int, y: Int) -> Int` becomes
276284
/// `long method(long x, long y)`
277285
private func renderFunctionSignature(_ decl: ImportedFunc) -> String {
278-
let translatedDecl = translatedDecl(for: decl)
286+
guard let translatedDecl = translatedDecl(for: decl) else {
287+
fatalError("Unable to render function signature for a function that cannot be translated: \(decl)")
288+
}
279289
let resultType = translatedDecl.translatedFunctionSignature.resultType
280290
var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter)
281291

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,19 @@ import JavaTypes
1717
extension JNISwift2JavaGenerator {
1818
func translatedDecl(
1919
for decl: ImportedFunc
20-
) -> TranslatedFunctionDecl {
20+
) -> TranslatedFunctionDecl? {
2121
if let cached = translatedDecls[decl] {
2222
return cached
2323
}
2424

25-
let translation = JavaTranslation(swiftModuleName: self.swiftModuleName)
26-
let translated = translation.translate(decl)
25+
let translated: TranslatedFunctionDecl?
26+
do {
27+
let translation = JavaTranslation(swiftModuleName: swiftModuleName)
28+
translated = try translation.translate(decl)
29+
} catch {
30+
self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)")
31+
translated = nil
32+
}
2733

2834
translatedDecls[decl] = translated
2935
return translated
@@ -32,8 +38,8 @@ extension JNISwift2JavaGenerator {
3238
struct JavaTranslation {
3339
let swiftModuleName: String
3440

35-
func translate(_ decl: ImportedFunc) -> TranslatedFunctionDecl {
36-
let translatedFunctionSignature = translate(functionSignature: decl.functionSignature)
41+
func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl {
42+
let translatedFunctionSignature = try translate(functionSignature: decl.functionSignature)
3743
// Types with no parent will be outputted inside a "module" class.
3844
let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName
3945

@@ -51,31 +57,31 @@ extension JNISwift2JavaGenerator {
5157
)
5258
}
5359

54-
func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) -> TranslatedFunctionSignature {
55-
let parameters = functionSignature.parameters.enumerated().map { idx, param in
60+
func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) throws -> TranslatedFunctionSignature {
61+
let parameters = try functionSignature.parameters.enumerated().map { idx, param in
5662
let parameterName = param.parameterName ?? "arg\(idx))"
57-
return translate(swiftParam: param, parameterName: parameterName)
63+
return try translate(swiftParam: param, parameterName: parameterName)
5864
}
5965

60-
return TranslatedFunctionSignature(
66+
return try TranslatedFunctionSignature(
6167
parameters: parameters,
6268
resultType: translate(swiftType: functionSignature.result.type)
6369
)
6470
}
6571

66-
func translate(swiftParam: SwiftParameter, parameterName: String) -> JavaParameter {
67-
return JavaParameter(
72+
func translate(swiftParam: SwiftParameter, parameterName: String) throws -> JavaParameter {
73+
return try JavaParameter(
6874
name: parameterName,
6975
type: translate(swiftType: swiftParam.type)
7076
)
7177
}
7278

73-
func translate(swiftType: SwiftType) -> JavaType {
79+
func translate(swiftType: SwiftType) throws -> JavaType {
7480
switch swiftType {
7581
case .nominal(let nominalType):
7682
if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
7783
guard let javaType = translate(knownType: knownType) else {
78-
fatalError("unsupported known type: \(knownType)")
84+
throw JavaTranslationError.unsupportedSwiftType(swiftType)
7985
}
8086
return javaType
8187
}
@@ -86,7 +92,7 @@ extension JNISwift2JavaGenerator {
8692
return .void
8793

8894
case .metatype, .optional, .tuple, .function, .existential, .opaque:
89-
fatalError("unsupported type: \(self)")
95+
throw JavaTranslationError.unsupportedSwiftType(swiftType)
9096
}
9197
}
9298

@@ -127,4 +133,8 @@ extension JNISwift2JavaGenerator {
127133
let parameters: [JavaParameter]
128134
let resultType: JavaType
129135
}
136+
137+
enum JavaTranslationError: Error {
138+
case unsupportedSwiftType(SwiftType)
139+
}
130140
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ extension JNISwift2JavaGenerator {
116116
}
117117

118118
private func printInitializerThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
119-
let translatedDecl = translatedDecl(for: decl)
119+
guard let translatedDecl = translatedDecl(for: decl) else {
120+
// Failed to translate. Skip.
121+
return
122+
}
123+
120124
let typeName = translatedDecl.parentName
121125

122126
printCDecl(
@@ -146,6 +150,11 @@ extension JNISwift2JavaGenerator {
146150
_ printer: inout CodePrinter,
147151
_ decl: ImportedFunc
148152
) {
153+
guard let _ = translatedDecl(for: decl) else {
154+
// Failed to translate. Skip.
155+
return
156+
}
157+
149158
// Free functions does not have a parent
150159
if decl.isStatic || !decl.hasParent {
151160
self.printSwiftStaticFunctionThunk(&printer, decl)
@@ -155,7 +164,7 @@ extension JNISwift2JavaGenerator {
155164
}
156165

157166
private func printSwiftStaticFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
158-
let translatedDecl = self.translatedDecl(for: decl)
167+
let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if we can translate the decl.
159168

160169
printCDecl(
161170
&printer,
@@ -172,7 +181,7 @@ extension JNISwift2JavaGenerator {
172181
}
173182

174183
private func printSwiftMemberFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
175-
let translatedDecl = self.translatedDecl(for: decl)
184+
let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if can translate the decl.
176185
let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName
177186

178187
printCDecl(
@@ -199,7 +208,9 @@ extension JNISwift2JavaGenerator {
199208
_ decl: ImportedFunc,
200209
calleeName: String
201210
) {
202-
let translatedDecl = self.translatedDecl(for: decl)
211+
guard let translatedDecl = self.translatedDecl(for: decl) else {
212+
fatalError("Cannot print function downcall for a function that can't be translated: \(decl)")
213+
}
203214
let swiftReturnType = decl.functionSignature.result.type
204215

205216
let tryClause: String = decl.isThrowing ? "try " : ""

0 commit comments

Comments
 (0)