Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ extension SwiftKnownTypeDeclKind {
.qualified(const: true, volatile: false, type: .void)
)
case .void: .void
case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data, .dataProtocol, .optional:
case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
.unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data, .dataProtocol, .essentialsData,
.essentialsDataProtocol, .optional:
nil
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ struct CdeclLowering {
)
}

case .data:
case .data, .essentialsData:
break

default:
Expand Down Expand Up @@ -375,7 +375,7 @@ struct CdeclLowering {
case .nominal(let nominal):
if let knownType = nominal.nominalTypeDecl.knownTypeKind {
switch knownType {
case .data:
case .data, .essentialsData:
break
case .unsafeRawPointer, .unsafeMutableRawPointer:
throw LoweringError.unhandledType(.optional(wrappedType))
Expand All @@ -387,7 +387,7 @@ struct CdeclLowering {
throw LoweringError.unhandledType(.optional(wrappedType))
case .void, .string:
throw LoweringError.unhandledType(.optional(wrappedType))
case .dataProtocol:
case .dataProtocol, .essentialsDataProtocol:
throw LoweringError.unhandledType(.optional(wrappedType))
default:
// Unreachable? Should be handled by `CType(cdeclType:)` lowering above.
Expand Down Expand Up @@ -505,7 +505,7 @@ struct CdeclLowering {
])
)

case .data:
case .data, .essentialsData:
break

default:
Expand Down Expand Up @@ -606,7 +606,7 @@ struct CdeclLowering {
case .void:
return LoweredResult(cdeclResultType: .void, cdeclOutParameters: [], conversion: .placeholder)

case .data:
case .data, .essentialsData:
break

case .string, .optional:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ extension FFMSwift2JavaGenerator {
conversion: .call(.placeholder, function: "SwiftRuntime.toCString", withArena: true)
)

case .data:
case .data, .essentialsData:
break

default:
Expand Down Expand Up @@ -515,7 +515,7 @@ extension FFMSwift2JavaGenerator {
case .nominal(let nominal):
if let knownType = nominal.nominalTypeDecl.knownTypeKind {
switch knownType {
case .data, .dataProtocol:
case .data, .dataProtocol, .essentialsData, .essentialsDataProtocol:
break
default:
throw JavaTranslationError.unhandledType(.optional(swiftType))
Expand Down Expand Up @@ -658,7 +658,7 @@ extension FFMSwift2JavaGenerator {
)
)

case .data:
case .data, .essentialsData:
break

case .unsafePointer, .unsafeMutablePointer:
Expand Down
2 changes: 1 addition & 1 deletion Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ enum JNIJavaTypeTranslator {
.unsafePointer, .unsafeMutablePointer,
.unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
.unsafeBufferPointer, .unsafeMutableBufferPointer,
.optional, .data, .dataProtocol:
.optional, .data, .dataProtocol, .essentialsData, .essentialsDataProtocol:
return nil
}
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ extension Swift2JavaTranslator {
visitor.visit(sourceFile: input.syntax)
}

// If any API uses 'Foundation.Data', import 'Data' as if it's declared in
// this module.
if let dataDecl = self.symbolTable[.data] {
let dataProtocolDecl = self.symbolTable[.dataProtocol]!
// If any API uses 'Foundation.Data' or 'FoundationEssentials.Data',
// import 'Data' as if it's declared in this module.
if let dataDecl = self.symbolTable[.data] ?? self.symbolTable[.essentialsData] {
let dataProtocolDecl = (self.symbolTable[.dataProtocol] ?? self.symbolTable[.essentialsDataProtocol])!
if self.isUsing(where: { $0 == dataDecl || $0 == dataProtocolDecl }) {
visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil)
}
Expand Down
19 changes: 17 additions & 2 deletions Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import SwiftSyntaxBuilder
enum SwiftKnownModule: String {
case swift = "Swift"
case foundation = "Foundation"
case foundationEssentials = "FoundationEssentials"

var name: String {
return self.rawValue
Expand All @@ -27,13 +28,15 @@ enum SwiftKnownModule: String {
return switch self {
case .swift: swiftSymbolTable
case .foundation: foundationSymbolTable
case .foundationEssentials: foundationEssentialsSymbolTable
}
}

var sourceFile: SourceFileSyntax {
return switch self {
case .swift: swiftSourceFile
case .foundation: foundationSourceFile
case .foundation: foundationEssentialsSourceFile
case .foundationEssentials: foundationEssentialsSourceFile
}
}
}
Expand All @@ -44,6 +47,12 @@ private var swiftSymbolTable: SwiftModuleSymbolTable {
return builder.finalize()
}

private var foundationEssentialsSymbolTable: SwiftModuleSymbolTable {
var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "FoundationEssentials", importedModules: ["Swift": swiftSymbolTable])
builder.handle(sourceFile: foundationEssentialsSourceFile)
return builder.finalize()
}

private var foundationSymbolTable: SwiftModuleSymbolTable {
var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Foundation", importedModules: ["Swift": swiftSymbolTable])
builder.handle(sourceFile: foundationSourceFile)
Expand Down Expand Up @@ -87,7 +96,7 @@ private let swiftSourceFile: SourceFileSyntax = """
}
"""

private let foundationSourceFile: SourceFileSyntax = """
private let foundationEssentialsSourceFile: SourceFileSyntax = """
public protocol DataProtocol {}

public struct Data: DataProtocol {
Expand All @@ -96,3 +105,9 @@ private let foundationSourceFile: SourceFileSyntax = """
public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
}
"""

private var foundationSourceFile: SourceFileSyntax {
// On platforms other than Darwin, imports such as FoundationEssentials, FoundationNetworking, etc. are used,
// so this file should be created by combining the files of the aforementioned modules.
foundationEssentialsSourceFile
}
4 changes: 4 additions & 0 deletions Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import SwiftSyntax

enum SwiftKnownTypeDeclKind: String, Hashable {
// MARK: -Std
case bool = "Swift.Bool"
case int = "Swift.Int"
case uint = "Swift.UInt"
Expand All @@ -40,8 +41,11 @@ enum SwiftKnownTypeDeclKind: String, Hashable {
case void = "Swift.Void"
case string = "Swift.String"

// MARK: -Foundation
case dataProtocol = "Foundation.DataProtocol"
case essentialsDataProtocol = "FoundationEssentials.DataProtocol"
case data = "Foundation.Data"
case essentialsData = "FoundationEssentials.Data"

var moduleAndName: (module: String, name: String) {
let qualified = self.rawValue
Expand Down
3 changes: 3 additions & 0 deletions Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct SwiftKnownTypes {

var dataProtocol: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.dataProtocol])) }
var data: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.data])) }
var essentialsDataProtocol: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsDataProtocol])) }
var essentialsData: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsData])) }

func unsafePointer(_ pointeeType: SwiftType) -> SwiftType {
.nominal(
Expand Down Expand Up @@ -79,6 +81,7 @@ struct SwiftKnownTypes {
func representativeType(of knownProtocol: SwiftKnownTypeDeclKind) -> SwiftType? {
switch knownProtocol {
case .dataProtocol: return self.data
case .essentialsDataProtocol: return self.essentialsData
default: return nil
}
}
Expand Down
86 changes: 86 additions & 0 deletions Tests/JExtractSwiftTests/DataImportTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ final class DataImportTests {
public func receiveDataProtocol<T: DataProtocol>(dat: some DataProtocol, dat2: T?)
"""

let essentials_data_interfaceFile =
"""
import FoundationEssentials

public func receiveData(dat: Data)
public func returnData() -> Data
"""

let essentials_dataProtocol_interfaceFile =
"""
import FoundationEssentials

public func receiveDataProtocol<T: DataProtocol>(dat: some DataProtocol, dat2: T?)
"""


@Test("Import Data: Swift thunks")
func data_swiftThunk() throws {
Expand Down Expand Up @@ -85,6 +100,57 @@ final class DataImportTests {
""",
]
)

try assertOutput(
input: essentials_data_interfaceFile, .ffm, .swift,
expectedChunks: [
"""
import FoundationEssentials
""",
"""
@_cdecl("swiftjava_SwiftModule_receiveData_dat")
public func swiftjava_SwiftModule_receiveData_dat(_ dat: UnsafeRawPointer) {
receiveData(dat: dat.assumingMemoryBound(to: Data.self).pointee)
}
""",
"""
@_cdecl("swiftjava_SwiftModule_returnData")
public func swiftjava_SwiftModule_returnData(_ _result: UnsafeMutableRawPointer) {
_result.assumingMemoryBound(to: Data.self).initialize(to: returnData())
}
""",

"""
@_cdecl("swiftjava_getType_SwiftModule_Data")
public func swiftjava_getType_SwiftModule_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
}
""",

"""
@_cdecl("swiftjava_SwiftModule_Data_init_bytes_count")
public func swiftjava_SwiftModule_Data_init_bytes_count(_ bytes: UnsafeRawPointer, _ count: Int, _ _result: UnsafeMutableRawPointer) {
_result.assumingMemoryBound(to: Data.self).initialize(to: Data(bytes: bytes, count: count))
}
""",

"""
@_cdecl("swiftjava_SwiftModule_Data_count$get")
public func swiftjava_SwiftModule_Data_count$get(_ self: UnsafeRawPointer) -> Int {
return self.assumingMemoryBound(to: Data.self).pointee.count
}
""",

"""
@_cdecl("swiftjava_SwiftModule_Data_withUnsafeBytes__")
public func swiftjava_SwiftModule_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
return body(_0.baseAddress, _0.count)
})
}
""",
]
)
}

@Test("Import Data: JavaBindings")
Expand Down Expand Up @@ -354,6 +420,26 @@ final class DataImportTests {
"""
]
)

try assertOutput(
input: essentials_dataProtocol_interfaceFile, .ffm, .swift,
expectedChunks: [
"""
import FoundationEssentials
""",
"""
@_cdecl("swiftjava_SwiftModule_receiveDataProtocol_dat_dat2")
public func swiftjava_SwiftModule_receiveDataProtocol_dat_dat2(_ dat: UnsafeRawPointer, _ dat2: UnsafeRawPointer?) {
receiveDataProtocol(dat: dat.assumingMemoryBound(to: Data.self).pointee, dat2: dat2?.assumingMemoryBound(to: Data.self).pointee)
}
""",

// Just to make sure 'Data' is imported.
"""
@_cdecl("swiftjava_getType_SwiftModule_Data")
"""
]
)
}

@Test("Import DataProtocol: JavaBindings")
Expand Down
Loading