Skip to content

Commit b33a8ef

Browse files
BridgeJS: Re-organize snapshot test structure
1 parent 4af1984 commit b33a8ef

File tree

316 files changed

+15234
-17911
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

316 files changed

+15234
-17911
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ xcuserdata/
1010
Examples/*/Bundle
1111
Examples/*/package-lock.json
1212
Package.resolved
13-
Plugins/BridgeJS/Sources/JavaScript/package-lock.json
13+
Plugins/BridgeJS/Sources/TS2Swift/JavaScript/package-lock.json
1414
Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/**/*.actual
1515
bridge-js.config.local.json
1616
_site/

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,24 @@ Tests for `BridgeJS` plugin:
6060
swift test --package-path ./Plugins/BridgeJS
6161
```
6262

63+
This runs both the TS2Swift Vitest suite (TypeScript `.d.ts` -> Swift macro output) and the Swift codegen/link tests. For fast iteration on the ts2swift tool only, run Vitest directly:
64+
65+
```bash
66+
cd Plugins/BridgeJS/Sources/TS2Swift/JavaScript && npm test
67+
```
68+
6369
To update snapshot test files when expected output changes:
6470

6571
```bash
6672
UPDATE_SNAPSHOTS=1 swift test --package-path ./Plugins/BridgeJS
6773
```
6874

75+
When you change ts2swift behavior, update Vitest snapshots (e.g. `npx vitest run --update` in `Sources/TS2Swift/JavaScript`) and regenerate the macro Swift fixtures used by Swift tests (writes `Tests/BridgeJSToolTests/Inputs/MacroSwift/` from `Inputs/TypeScript/*.d.ts`):
76+
77+
```bash
78+
cd Plugins/BridgeJS/Sources/TS2Swift/JavaScript && npm run generate-macro-fixtures
79+
```
80+
6981
### Editing `./Runtime` directory
7082

7183
The `./Runtime` directory contains the JavaScript runtime that interacts with the JavaScript environment and Swift code.

Plugins/BridgeJS/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let package = Package(
5959
"BridgeJSLink",
6060
"TS2Swift",
6161
],
62-
exclude: ["__Snapshots__", "Inputs", "MultifileInputs", "ImportMacroInputs"]
62+
exclude: ["__Snapshots__", "Inputs"]
6363
),
6464
.macro(
6565
name: "BridgeJSMacros",

Plugins/BridgeJS/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ graph LR
100100
| `Foundation.URL` | `string` | - | [#496](https://github.com/swiftwasm/JavaScriptKit/issues/496) |
101101
| Generics | - | - | [#398](https://github.com/swiftwasm/JavaScriptKit/issues/398) |
102102

103-
### Import-specific (TypeScript Swift)
103+
### Import-specific (TypeScript -> Swift)
104104

105105
| TypeScript Type | Swift Type | Status |
106106
|:----------------|:-----------|:-------|
@@ -163,6 +163,12 @@ Return values use direct Wasm returns for primitives, and imported intrinsic fun
163163

164164
For detailed semantics, see the [How It Works sections](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-class#How-It-Works) in the user documentation.
165165

166+
## Testing
167+
168+
- **Full BridgeJS tests** (Swift + TS2Swift Vitest): `swift test --package-path ./Plugins/BridgeJS`
169+
- **TS2Swift only** (fast iteration on `.d.ts` -> Swift): `npm -C Sources/TS2Swift/JavaScript test`
170+
- **Regenerate snapshot artifacts**: `UPDATE_SNAPSHOTS=1 swift test --package-path ./Plugins/BridgeJS`
171+
166172
## Debug utilities
167173

168174
`BridgeJSToolInternal` exposes pipeline stages for debugging:

Plugins/BridgeJS/Sources/TS2Swift/JavaScript/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
"dependencies": {
44
"typescript": "5.8.2"
55
},
6+
"devDependencies": {
7+
"vitest": "^2.0.0"
8+
},
69
"bin": {
710
"ts2swift": "./bin/ts2swift.js"
11+
},
12+
"scripts": {
13+
"test": "vitest run"
814
}
915
}

Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js

Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,80 @@ function printUsage() {
7676
console.error('Usage: ts2swift <d.ts file path> -p <tsconfig.json path> [--global <d.ts>]... [-o output.swift]');
7777
}
7878

79+
/**
80+
* Run ts2swift for a single input file (programmatic API, no process I/O).
81+
* @param {string} filePath - Path to the .d.ts file
82+
* @param {{ tsconfigPath: string, logLevel?: string, globalFiles?: string[] }} options
83+
* @returns {string} Generated Swift source
84+
* @throws {Error} on parse/type-check errors (diagnostics are included in the message)
85+
*/
86+
export function run(filePath, options) {
87+
const { tsconfigPath, logLevel = 'info', globalFiles: globalFilesOpt = [] } = options;
88+
const globalFiles = Array.isArray(globalFilesOpt) ? globalFilesOpt : (globalFilesOpt ? [globalFilesOpt] : []);
89+
90+
const diagnosticEngine = new DiagnosticEngine(logLevel);
91+
92+
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
93+
const configParseResult = ts.parseJsonConfigFileContent(
94+
configFile.config,
95+
ts.sys,
96+
path.dirname(path.resolve(tsconfigPath))
97+
);
98+
99+
if (configParseResult.errors.length > 0) {
100+
const message = ts.formatDiagnosticsWithColorAndContext(configParseResult.errors, {
101+
getCanonicalFileName: (fileName) => fileName,
102+
getNewLine: () => ts.sys.newLine,
103+
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
104+
});
105+
throw new Error(`TypeScript config/parse errors:\n${message}`);
106+
}
107+
108+
const program = TypeProcessor.createProgram([filePath, ...globalFiles], configParseResult.options);
109+
const diagnostics = program.getSemanticDiagnostics();
110+
if (diagnostics.length > 0) {
111+
const message = ts.formatDiagnosticsWithColorAndContext(diagnostics, {
112+
getCanonicalFileName: (fileName) => fileName,
113+
getNewLine: () => ts.sys.newLine,
114+
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
115+
});
116+
throw new Error(`TypeScript semantic errors:\n${message}`);
117+
}
118+
119+
const prelude = [
120+
"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,",
121+
"// DO NOT EDIT.",
122+
"//",
123+
"// To update this file, just rebuild your project or run",
124+
"// `swift package bridge-js`.",
125+
"",
126+
"@_spi(Experimental) import JavaScriptKit",
127+
"",
128+
"",
129+
].join("\n");
130+
131+
/** @type {string[]} */
132+
const bodies = [];
133+
const globalFileSet = new Set(globalFiles);
134+
for (const inputPath of [filePath, ...globalFiles]) {
135+
const processor = new TypeProcessor(program.getTypeChecker(), diagnosticEngine, {
136+
defaultImportFromGlobal: globalFileSet.has(inputPath),
137+
});
138+
const result = processor.processTypeDeclarations(program, inputPath);
139+
const body = result.content.trim();
140+
if (body.length > 0) bodies.push(body);
141+
}
142+
143+
const hasAny = bodies.length > 0;
144+
return hasAny ? prelude + bodies.join("\n\n") + "\n" : "";
145+
}
146+
79147
/**
80148
* Main function to run the CLI
81149
* @param {string[]} args - Command-line arguments
82150
* @returns {void}
83151
*/
84152
export function main(args) {
85-
// Parse command line arguments
86153
const options = parseArgs({
87154
args,
88155
options: {
@@ -118,64 +185,25 @@ export function main(args) {
118185
}
119186

120187
const filePath = options.positionals[0];
121-
const diagnosticEngine = new DiagnosticEngine(options.values["log-level"] || "info");
122-
123-
diagnosticEngine.print("verbose", `Processing ${filePath}...`);
124-
125-
// Create TypeScript program and process declarations
126-
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
127-
const configParseResult = ts.parseJsonConfigFileContent(
128-
configFile.config,
129-
ts.sys,
130-
path.dirname(path.resolve(tsconfigPath))
131-
);
132-
133-
if (configParseResult.errors.length > 0) {
134-
diagnosticEngine.tsDiagnose(configParseResult.errors);
135-
process.exit(1);
136-
}
137-
188+
const logLevel = options.values["log-level"] || "info";
138189
/** @type {string[]} */
139190
const globalFiles = Array.isArray(options.values.global)
140191
? options.values.global
141192
: (options.values.global ? [options.values.global] : []);
142193

143-
const program = TypeProcessor.createProgram([filePath, ...globalFiles], configParseResult.options);
144-
const diagnostics = program.getSemanticDiagnostics();
145-
if (diagnostics.length > 0) {
146-
diagnosticEngine.tsDiagnose(diagnostics);
147-
process.exit(1);
148-
}
149-
150-
const prelude = [
151-
"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,",
152-
"// DO NOT EDIT.",
153-
"//",
154-
"// To update this file, just rebuild your project or run",
155-
"// `swift package bridge-js`.",
156-
"",
157-
"@_spi(Experimental) import JavaScriptKit",
158-
"",
159-
"",
160-
].join("\n");
194+
const diagnosticEngine = new DiagnosticEngine(logLevel);
195+
diagnosticEngine.print("verbose", `Processing ${filePath}...`);
161196

162-
/** @type {string[]} */
163-
const bodies = [];
164-
const globalFileSet = new Set(globalFiles);
165-
for (const inputPath of [filePath, ...globalFiles]) {
166-
const processor = new TypeProcessor(program.getTypeChecker(), diagnosticEngine, {
167-
defaultImportFromGlobal: globalFileSet.has(inputPath),
168-
});
169-
const result = processor.processTypeDeclarations(program, inputPath);
170-
const body = result.content.trim();
171-
if (body.length > 0) bodies.push(body);
197+
let swiftOutput;
198+
try {
199+
swiftOutput = run(filePath, { tsconfigPath, logLevel, globalFiles });
200+
} catch (err) {
201+
console.error(err.message);
202+
process.exit(1);
172203
}
173204

174-
const hasAny = bodies.length > 0;
175-
const swiftOutput = hasAny ? prelude + bodies.join("\n\n") + "\n" : "";
176-
177205
if (options.values.output) {
178-
if (hasAny) {
206+
if (swiftOutput.length > 0) {
179207
fs.mkdirSync(path.dirname(options.values.output), { recursive: true });
180208
fs.writeFileSync(options.values.output, swiftOutput);
181209
}

0 commit comments

Comments
 (0)