Skip to content

Commit 46c64db

Browse files
committed
BridgeJS: Namespace enum implementation, refactor to parse enums using default SwiftSyntax methods
1 parent d03e74c commit 46c64db

File tree

16 files changed

+1353
-560
lines changed

16 files changed

+1353
-560
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 289 additions & 209 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 377 additions & 164 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@
22

33
// MARK: - Types
44

5-
public enum Constants {
6-
public static let supportedRawTypes = [
7-
"String", "Bool", "Int", "Int32", "Int64", "UInt", "UInt32", "UInt64", "Float", "Double",
8-
]
9-
}
10-
115
public enum BridgeType: Codable, Equatable {
126
case int, float, double, string, bool, jsObject(String?), swiftHeapObject(String), void
137
case caseEnum(String)
14-
case rawValueEnum(String, String)
8+
case rawValueEnum(String, SwiftEnumRawType)
159
case associatedValueEnum(String)
1610
case namespaceEnum(String)
1711
}
@@ -20,6 +14,39 @@ public enum WasmCoreType: String, Codable {
2014
case i32, i64, f32, f64, pointer
2115
}
2216

17+
/// Represents supported Swift enum raw types with their WASM ABI properties
18+
public enum SwiftEnumRawType: String, CaseIterable, Codable {
19+
case string = "String"
20+
case bool = "Bool"
21+
case int = "Int"
22+
case int32 = "Int32"
23+
case int64 = "Int64"
24+
case uint = "UInt"
25+
case uint32 = "UInt32"
26+
case uint64 = "UInt64"
27+
case float = "Float"
28+
case double = "Double"
29+
30+
public var wasmCoreType: WasmCoreType? {
31+
switch self {
32+
case .string:
33+
return nil // String has special handling with UTF-8 bytes and length
34+
case .bool, .int, .int32, .uint, .uint32:
35+
return .i32
36+
case .int64, .uint64:
37+
return .i64
38+
case .float:
39+
return .f32
40+
case .double:
41+
return .f64
42+
}
43+
}
44+
45+
public static func from(_ rawTypeString: String) -> SwiftEnumRawType? {
46+
return Self.allCases.first { $0.rawValue == rawTypeString }
47+
}
48+
}
49+
2350
public struct Parameter: Codable {
2451
public let label: String?
2552
public let name: String
@@ -72,11 +99,10 @@ public struct EnumCase: Codable, Equatable {
7299

73100
public struct ExportedEnum: Codable, Equatable {
74101
public let name: String
102+
public let swiftCallName: String
75103
public let cases: [EnumCase]
76104
public let rawType: String?
77105
public let namespace: [String]?
78-
public let nestedTypes: [String]
79-
80106
public var enumType: EnumType {
81107
if cases.isEmpty {
82108
return .namespace
@@ -87,12 +113,18 @@ public struct ExportedEnum: Codable, Equatable {
87113
}
88114
}
89115

90-
public init(name: String, cases: [EnumCase], rawType: String?, namespace: [String]?, nestedTypes: [String]) {
116+
public init(
117+
name: String,
118+
swiftCallName: String,
119+
cases: [EnumCase],
120+
rawType: String?,
121+
namespace: [String]?
122+
) {
91123
self.name = name
124+
self.swiftCallName = swiftCallName
92125
self.cases = cases
93126
self.rawType = rawType
94127
self.namespace = namespace
95-
self.nestedTypes = nestedTypes
96128
}
97129
}
98130

@@ -132,17 +164,20 @@ public struct ExportedFunction: Codable {
132164

133165
public struct ExportedClass: Codable {
134166
public var name: String
167+
public var swiftCallName: String
135168
public var constructor: ExportedConstructor?
136169
public var methods: [ExportedFunction]
137170
public var namespace: [String]?
138171

139172
public init(
140173
name: String,
174+
swiftCallName: String,
141175
constructor: ExportedConstructor? = nil,
142176
methods: [ExportedFunction],
143177
namespace: [String]? = nil
144178
) {
145179
self.name = name
180+
self.swiftCallName = swiftCallName
146181
self.constructor = constructor
147182
self.methods = methods
148183
self.namespace = namespace
@@ -254,58 +289,11 @@ extension BridgeType {
254289
case .caseEnum:
255290
return .i32
256291
case .rawValueEnum(_, let rawType):
257-
switch rawType {
258-
case "String":
259-
return nil // String uses special handling
260-
case "Bool", "Int", "Int32", "UInt", "UInt32":
261-
return .i32
262-
case "Int64", "UInt64":
263-
return .i64
264-
case "Float":
265-
return .f32
266-
case "Double":
267-
return .f64
268-
default:
269-
return nil
270-
}
292+
return rawType.wasmCoreType
271293
case .associatedValueEnum:
272294
return nil
273295
case .namespaceEnum:
274296
return nil
275297
}
276298
}
277-
278-
/// Returns the Swift type name for this bridge type
279-
var swiftTypeName: String {
280-
switch self {
281-
case .void: return "Void"
282-
case .bool: return "Bool"
283-
case .int: return "Int"
284-
case .float: return "Float"
285-
case .double: return "Double"
286-
case .string: return "String"
287-
case .jsObject(let name): return name ?? "JSObject"
288-
case .swiftHeapObject(let name): return name
289-
case .caseEnum(let name): return name
290-
case .rawValueEnum(let name, _): return name
291-
case .associatedValueEnum(let name): return name
292-
case .namespaceEnum(let name): return name
293-
}
294-
}
295-
296-
/// Returns the TypeScript type name for this bridge type
297-
var tsTypeName: String {
298-
switch self {
299-
case .void: return "void"
300-
case .bool: return "boolean"
301-
case .int, .float, .double: return "number"
302-
case .string: return "string"
303-
case .jsObject(let name): return name ?? "any"
304-
case .swiftHeapObject(let name): return name
305-
case .caseEnum(let name): return name
306-
case .rawValueEnum(let name, _): return name
307-
case .associatedValueEnum(let name): return name
308-
case .namespaceEnum(let name): return name
309-
}
310-
}
311299
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumNamespace.swift

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// Empty enum to act as namespace wrapper for classes
1+
// Empty enums to act as namespace wrappers for nested elements
2+
23
@JS enum Utils {
34
@JS class Converter {
45
@JS init() {}
@@ -9,14 +10,19 @@
910
}
1011
}
1112

12-
// TODO: Add namespace enum with static functions when supported
13-
1413
@JS enum Networking {
15-
@JS enum Method {
16-
case get
17-
case post
18-
case put
19-
case delete
14+
@JS enum API {
15+
@JS enum Method {
16+
case get
17+
case post
18+
case put
19+
case delete
20+
}
21+
// Invalid to declare @JS(namespace) here as it would be conflicting with nesting
22+
@JS class HTTPServer {
23+
@JS init() {}
24+
@JS func call(_ method: Method)
25+
}
2026
}
2127
}
2228

@@ -34,3 +40,17 @@
3440
case development = 3000
3541
}
3642
}
43+
44+
@JS(namespace: "Networking.APIV2")
45+
enum Internal {
46+
@JS enum SupportedMethod {
47+
case get
48+
case post
49+
}
50+
@JS class TestServer {
51+
@JS init() {}
52+
@JS func call(_ method: SupportedMethod)
53+
}
54+
}
55+
56+
// TODO: Add namespace enum with static functions when supported

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumRawType.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,6 @@
6161
case pi = 3.14159
6262
}
6363

64-
@JS enum FeatureFlag: Bool {
65-
case enabled = true
66-
case disabled = false
67-
}
68-
6964
@JS func setTheme(_ theme: Theme)
7065
@JS func getTheme() -> Theme
7166

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.d.ts

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,86 @@
44
// To update this file, just rebuild your project or run
55
// `swift package bridge-js`.
66

7-
// TODO: Implement namespace enum: Utils
8-
// TODO: Implement namespace enum: Networking
9-
// TODO: Implement namespace enum: Configuration
7+
export {};
8+
9+
declare global {
10+
namespace Configuration {
11+
const LogLevel: {
12+
readonly Debug: "debug";
13+
readonly Info: "info";
14+
readonly Warning: "warning";
15+
readonly Error: "error";
16+
};
17+
type LogLevel = typeof LogLevel[keyof typeof LogLevel];
18+
const Port: {
19+
readonly Http: 80;
20+
readonly Https: 443;
21+
readonly Development: 3000;
22+
};
23+
type Port = typeof Port[keyof typeof Port];
24+
}
25+
namespace Networking {
26+
namespace API {
27+
class HTTPServer {
28+
constructor();
29+
call(method: Networking.API.Method): void;
30+
}
31+
const Method: {
32+
readonly Get: 0;
33+
readonly Post: 1;
34+
readonly Put: 2;
35+
readonly Delete: 3;
36+
};
37+
type Method = typeof Method[keyof typeof Method];
38+
}
39+
namespace APIV2 {
40+
namespace Internal {
41+
class TestServer {
42+
constructor();
43+
call(method: Internal.SupportedMethod): void;
44+
}
45+
const SupportedMethod: {
46+
readonly Get: 0;
47+
readonly Post: 1;
48+
};
49+
type SupportedMethod = typeof SupportedMethod[keyof typeof SupportedMethod];
50+
}
51+
}
52+
}
53+
namespace Utils {
54+
class Converter {
55+
constructor();
56+
toString(value: number): string;
57+
}
58+
}
59+
}
60+
61+
/// Represents a Swift heap object like a class instance or an actor instance.
62+
export interface SwiftHeapObject {
63+
/// Release the heap object.
64+
///
65+
/// Note: Calling this method will release the heap object and it will no longer be accessible.
66+
release(): void;
67+
}
68+
export interface Converter extends SwiftHeapObject {
69+
toString(value: number): string;
70+
}
71+
export interface HTTPServer extends SwiftHeapObject {
72+
call(method: Networking.API.Method): void;
73+
}
74+
export interface TestServer extends SwiftHeapObject {
75+
call(method: Internal.SupportedMethod): void;
76+
}
1077
export type Exports = {
78+
Converter: {
79+
new(): Converter;
80+
}
81+
HTTPServer: {
82+
new(): HTTPServer;
83+
}
84+
TestServer: {
85+
new(): TestServer;
86+
}
1187
}
1288
export type Imports = {
1389
}

0 commit comments

Comments
 (0)