Skip to content

Commit c50fec3

Browse files
committed
BridgeJS: Static functions / properties improvements for access via Exports
1 parent e252510 commit c50fec3

File tree

9 files changed

+185
-139
lines changed

9 files changed

+185
-139
lines changed

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 101 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,6 @@ struct BridgeJSLink {
146146

147147
// Process functions
148148
for function in skeleton.functions {
149-
if function.effects.isStatic,
150-
case .enumName(_) = function.staticContext
151-
{
152-
continue
153-
}
154-
155149
var (js, dts) = try renderExportedFunction(function: function)
156150

157151
if function.effects.isStatic,
@@ -195,17 +189,110 @@ struct BridgeJSLink {
195189
}
196190

197191
for enumDefinition in skeleton.enums where enumDefinition.enumType != .namespace {
192+
// Process enum static methods to add to Exports type
193+
let enumExportPrinter = CodeFragmentPrinter()
194+
let enumDtsPrinter = CodeFragmentPrinter()
195+
198196
for function in enumDefinition.staticMethods {
199-
let assignmentJs = try renderEnumStaticFunctionAssignment(
200-
function: function,
201-
enumName: enumDefinition.name
197+
let thunkBuilder = ExportedThunkBuilder(effects: function.effects)
198+
for param in function.parameters {
199+
try thunkBuilder.lowerParameter(param: param)
200+
}
201+
let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType)
202+
203+
let methodPrinter = CodeFragmentPrinter()
204+
methodPrinter.write("\(function.name): function(\(function.parameters.map { $0.name }.joined(separator: ", "))) {")
205+
methodPrinter.indent {
206+
methodPrinter.write(contentsOf: thunkBuilder.body)
207+
methodPrinter.write(contentsOf: thunkBuilder.cleanupCode)
208+
methodPrinter.write(lines: thunkBuilder.checkExceptionLines())
209+
if let returnExpr = returnExpr {
210+
methodPrinter.write("return \(returnExpr);")
211+
}
212+
}
213+
methodPrinter.write("},")
214+
215+
enumExportPrinter.write(lines: methodPrinter.lines)
216+
enumDtsPrinter.write("\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));")
217+
}
218+
219+
let enumExportLines = enumExportPrinter.lines
220+
let enumDtsLines = enumDtsPrinter.lines
221+
222+
let enumPropertyPrinter = CodeFragmentPrinter()
223+
let enumPropertyDtsPrinter = CodeFragmentPrinter()
224+
225+
for property in enumDefinition.staticProperties {
226+
let readonly = property.isReadonly ? "readonly " : ""
227+
enumPropertyDtsPrinter.write("\(readonly)\(property.name): \(property.type.tsType);")
228+
229+
let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
230+
let getterReturnExpr = try getterThunkBuilder.call(
231+
abiName: property.getterAbiName(),
232+
returnType: property.type
202233
)
203-
data.enumStaticAssignments.append(contentsOf: assignmentJs)
234+
235+
enumPropertyPrinter.write("get \(property.name)() {")
236+
enumPropertyPrinter.indent {
237+
enumPropertyPrinter.write(contentsOf: getterThunkBuilder.body)
238+
enumPropertyPrinter.write(contentsOf: getterThunkBuilder.cleanupCode)
239+
enumPropertyPrinter.write(lines: getterThunkBuilder.checkExceptionLines())
240+
if let returnExpr = getterReturnExpr {
241+
enumPropertyPrinter.write("return \(returnExpr);")
242+
}
243+
}
244+
enumPropertyPrinter.write("},")
245+
246+
if !property.isReadonly {
247+
let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
248+
try setterThunkBuilder.lowerParameter(
249+
param: Parameter(label: "value", name: "value", type: property.type)
250+
)
251+
_ = try setterThunkBuilder.call(
252+
abiName: property.setterAbiName(),
253+
returnType: .void
254+
)
255+
256+
enumPropertyPrinter.write("set \(property.name)(value) {")
257+
enumPropertyPrinter.indent {
258+
enumPropertyPrinter.write(contentsOf: setterThunkBuilder.body)
259+
enumPropertyPrinter.write(contentsOf: setterThunkBuilder.cleanupCode)
260+
enumPropertyPrinter.write(lines: setterThunkBuilder.checkExceptionLines())
261+
}
262+
enumPropertyPrinter.write("},")
263+
}
204264
}
205-
for property in enumDefinition.staticProperties {
206-
let (propJs, _) = try renderEnumStaticProperty(property: property, enumName: enumDefinition.name)
207-
data.enumStaticAssignments.append(contentsOf: propJs)
265+
266+
let enumPropertyLines = enumPropertyPrinter.lines
267+
let enumPropertyDtsLines = enumPropertyDtsPrinter.lines
268+
269+
if !enumExportLines.isEmpty || !enumPropertyLines.isEmpty {
270+
let exportsPrinter = CodeFragmentPrinter()
271+
let dtsExportsPrinter = CodeFragmentPrinter()
272+
273+
exportsPrinter.write("\(enumDefinition.name): {")
274+
exportsPrinter.indent {
275+
// Combine all lines and handle trailing comma removal
276+
var allLines = enumExportLines + enumPropertyLines
277+
if let lastLineIndex = allLines.indices.last, allLines[lastLineIndex].hasSuffix(",") {
278+
allLines[lastLineIndex] = String(allLines[lastLineIndex].dropLast())
279+
}
280+
exportsPrinter.write(lines: allLines)
281+
}
282+
exportsPrinter.write("},")
283+
284+
dtsExportsPrinter.write("\(enumDefinition.name): {")
285+
dtsExportsPrinter.indent {
286+
dtsExportsPrinter.write(lines: enumDtsLines)
287+
dtsExportsPrinter.write(lines: enumPropertyDtsLines)
288+
}
289+
dtsExportsPrinter.write("}")
290+
291+
data.exportsLines.append(contentsOf: exportsPrinter.lines)
292+
data.dtsExportLines.append(contentsOf: dtsExportsPrinter.lines)
208293
}
294+
295+
// Static properties are now handled in Exports type - no global assignments needed
209296
}
210297

211298
}
@@ -994,8 +1081,6 @@ struct BridgeJSLink {
9941081
private func generateDeclarations(enumDefinition: ExportedEnum) -> [String] {
9951082
let printer = CodeFragmentPrinter()
9961083

997-
let enumStaticFunctions = enumDefinition.staticMethods
998-
9991084
switch enumDefinition.emitStyle {
10001085
case .tsEnum:
10011086
switch enumDefinition.enumType {
@@ -1035,22 +1120,10 @@ struct BridgeJSLink {
10351120
printer.write("readonly \(caseName): \(value);")
10361121
}
10371122

1038-
for function in enumStaticFunctions {
1039-
let signature = renderTSSignature(
1040-
parameters: function.parameters,
1041-
returnType: function.returnType,
1042-
effects: function.effects
1043-
)
1044-
printer.write("\(function.name)\(signature);")
1045-
}
1046-
for property in enumDefinition.staticProperties {
1047-
let readonly = property.isReadonly ? "readonly " : ""
1048-
printer.write("\(readonly)\(property.name): \(property.type.tsType);")
1049-
}
10501123
}
10511124
printer.write("};")
10521125
printer.write(
1053-
"export type \(enumDefinition.name) = typeof \(enumDefinition.name)[keyof typeof \(enumDefinition.name)];"
1126+
"export type \(enumDefinition.name)Tag = typeof \(enumDefinition.name)[keyof typeof \(enumDefinition.name)];"
10541127
)
10551128
printer.nextLine()
10561129
case .associatedValue:
@@ -1064,18 +1137,6 @@ struct BridgeJSLink {
10641137
}
10651138
printer.write("};")
10661139

1067-
for function in enumStaticFunctions {
1068-
let signature = renderTSSignature(
1069-
parameters: function.parameters,
1070-
returnType: function.returnType,
1071-
effects: function.effects
1072-
)
1073-
printer.write("\(function.name)\(signature);")
1074-
}
1075-
for property in enumDefinition.staticProperties {
1076-
let readonly = property.isReadonly ? "readonly " : ""
1077-
printer.write("\(readonly)\(property.name): \(property.type.tsType);")
1078-
}
10791140
}
10801141
printer.write("};")
10811142
printer.nextLine()

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -537,14 +537,6 @@ struct IntrinsicJSFragment: Sendable {
537537
}
538538
}
539539
printer.write("},")
540-
541-
for function in enumDefinition.staticMethods {
542-
printer.write("\(function.name): null,")
543-
}
544-
545-
for property in enumDefinition.staticProperties {
546-
printer.write("\(property.name): null,")
547-
}
548540
}
549541
printer.write("};")
550542
printer.nextLine()
@@ -633,14 +625,6 @@ struct IntrinsicJSFragment: Sendable {
633625
let caseName = enumCase.name.capitalizedFirstLetter
634626
printer.write("\(caseName): \(index),")
635627
}
636-
637-
for function in enumDefinition.staticMethods {
638-
printer.write("\(function.name): null,")
639-
}
640-
641-
for property in enumDefinition.staticProperties {
642-
printer.write("\(property.name): null,")
643-
}
644628
}
645629
printer.write("};")
646630
printer.nextLine()
@@ -667,14 +651,6 @@ struct IntrinsicJSFragment: Sendable {
667651

668652
printer.write("\(caseName): \(formattedValue),")
669653
}
670-
671-
for function in enumDefinition.staticMethods {
672-
printer.write("\(function.name): null,")
673-
}
674-
675-
for property in enumDefinition.staticProperties {
676-
printer.write("\(property.name): null,")
677-
}
678654
}
679655
printer.write("};")
680656
printer.nextLine()

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ export const Direction: {
1010
readonly East: 2;
1111
readonly West: 3;
1212
};
13-
export type Direction = typeof Direction[keyof typeof Direction];
13+
export type DirectionTag = typeof Direction[keyof typeof Direction];
1414

1515
export const Status: {
1616
readonly Loading: 0;
1717
readonly Success: 1;
1818
readonly Error: 2;
1919
};
20-
export type Status = typeof Status[keyof typeof Status];
20+
export type StatusTag = typeof Status[keyof typeof Status];
2121

2222
export enum TSDirection {
2323
North = 0,
@@ -29,7 +29,7 @@ export enum TSDirection {
2929
export const PublicStatus: {
3030
readonly Success: 0;
3131
};
32-
export type PublicStatus = typeof PublicStatus[keyof typeof PublicStatus];
32+
export type PublicStatusTag = typeof PublicStatus[keyof typeof PublicStatus];
3333

3434
export type Exports = {
3535
setDirection(direction: Direction): void;

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const Theme: {
99
readonly Dark: "dark";
1010
readonly Auto: "auto";
1111
};
12-
export type Theme = typeof Theme[keyof typeof Theme];
12+
export type ThemeTag = typeof Theme[keyof typeof Theme];
1313

1414
export enum TSTheme {
1515
Light = "light",
@@ -21,14 +21,14 @@ export const FeatureFlag: {
2121
readonly Enabled: true;
2222
readonly Disabled: false;
2323
};
24-
export type FeatureFlag = typeof FeatureFlag[keyof typeof FeatureFlag];
24+
export type FeatureFlagTag = typeof FeatureFlag[keyof typeof FeatureFlag];
2525

2626
export const HttpStatus: {
2727
readonly Ok: 200;
2828
readonly NotFound: 404;
2929
readonly ServerError: 500;
3030
};
31-
export type HttpStatus = typeof HttpStatus[keyof typeof HttpStatus];
31+
export type HttpStatusTag = typeof HttpStatus[keyof typeof HttpStatus];
3232

3333
export enum TSHttpStatus {
3434
Ok = 200,
@@ -43,51 +43,51 @@ export const Priority: {
4343
readonly High: 4;
4444
readonly Highest: 5;
4545
};
46-
export type Priority = typeof Priority[keyof typeof Priority];
46+
export type PriorityTag = typeof Priority[keyof typeof Priority];
4747

4848
export const FileSize: {
4949
readonly Tiny: 1024;
5050
readonly Small: 10240;
5151
readonly Medium: 102400;
5252
readonly Large: 1048576;
5353
};
54-
export type FileSize = typeof FileSize[keyof typeof FileSize];
54+
export type FileSizeTag = typeof FileSize[keyof typeof FileSize];
5555

5656
export const UserId: {
5757
readonly Guest: 0;
5858
readonly User: 1000;
5959
readonly Admin: 9999;
6060
};
61-
export type UserId = typeof UserId[keyof typeof UserId];
61+
export type UserIdTag = typeof UserId[keyof typeof UserId];
6262

6363
export const TokenId: {
6464
readonly Invalid: 0;
6565
readonly Session: 12345;
6666
readonly Refresh: 67890;
6767
};
68-
export type TokenId = typeof TokenId[keyof typeof TokenId];
68+
export type TokenIdTag = typeof TokenId[keyof typeof TokenId];
6969

7070
export const SessionId: {
7171
readonly None: 0;
7272
readonly Active: 9876543210;
7373
readonly Expired: 1234567890;
7474
};
75-
export type SessionId = typeof SessionId[keyof typeof SessionId];
75+
export type SessionIdTag = typeof SessionId[keyof typeof SessionId];
7676

7777
export const Precision: {
7878
readonly Rough: 0.1;
7979
readonly Normal: 0.01;
8080
readonly Fine: 0.001;
8181
};
82-
export type Precision = typeof Precision[keyof typeof Precision];
82+
export type PrecisionTag = typeof Precision[keyof typeof Precision];
8383

8484
export const Ratio: {
8585
readonly Quarter: 0.25;
8686
readonly Half: 0.5;
8787
readonly Golden: 1.618;
8888
readonly Pi: 3.14159;
8989
};
90-
export type Ratio = typeof Ratio[keyof typeof Ratio];
90+
export type RatioTag = typeof Ratio[keyof typeof Ratio];
9191

9292
export type Exports = {
9393
setTheme(theme: Theme): void;

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@
77
export const Calculator: {
88
readonly Scientific: 0;
99
readonly Basic: 1;
10-
square(value: number): number;
1110
};
12-
export type Calculator = typeof Calculator[keyof typeof Calculator];
11+
export type CalculatorTag = typeof Calculator[keyof typeof Calculator];
1312

1413
export const APIResult: {
1514
readonly Tag: {
1615
readonly Success: 0;
1716
readonly Failure: 1;
1817
};
19-
roundtrip(value: APIResult): APIResult;
2018
};
2119

2220
export type APIResult =
@@ -48,6 +46,12 @@ export type Exports = {
4846
subtract(a: number, b: number): number;
4947
add(a: number, b: number): number;
5048
}
49+
Calculator: {
50+
square(value: number): number;
51+
}
52+
APIResult: {
53+
roundtrip(value: APIResult): APIResult;
54+
}
5155
}
5256
export type Imports = {
5357
}

0 commit comments

Comments
 (0)