ttsc 0.8.0-dev.20260505 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/cmd/ttsc/main.go +1 -1
- package/driver/program.go +56 -3
- package/driver/rewrite.go +2 -23
- package/lib/compiler/internal/runBuild.js +1 -2
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +1 -2
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +1 -1
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.js +5 -52
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscPlugin.d.ts +0 -15
- package/lib/structures/ITtscPlugin.js.map +1 -1
- package/lib/structures/TtscPluginStage.d.ts +1 -3
- package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +0 -3
- package/package.json +8 -8
- package/shim/ast/shim.go +6 -4
- package/src/compiler/internal/runBuild.ts +1 -2
- package/src/compiler/internal/transformProjectInMemory.ts +1 -2
- package/src/launcher/internal/runTtsc.ts +1 -1
- package/src/plugin/internal/loadProjectPlugins.ts +8 -76
- package/src/structures/ITtscPlugin.ts +0 -18
- package/src/structures/TtscPluginStage.ts +1 -3
- package/src/structures/internal/ITtscLoadedNativePlugin.ts +0 -3
- package/test/compiler.test.ts +3 -3
- package/utility/host.go +74 -46
- package/shim/compiler/emit_hooks.go +0 -494
package/shim/ast/shim.go
CHANGED
|
@@ -92,6 +92,8 @@ type ParameterDeclaration = innerast.ParameterDeclaration
|
|
|
92
92
|
type ParenthesizedTypeNode = innerast.ParenthesizedTypeNode
|
|
93
93
|
|
|
94
94
|
const (
|
|
95
|
+
KindEndOfFile = innerast.KindEndOfFile
|
|
96
|
+
KindSingleLineCommentTrivia = innerast.KindSingleLineCommentTrivia
|
|
95
97
|
KindCallExpression = innerast.KindCallExpression
|
|
96
98
|
KindIdentifier = innerast.KindIdentifier
|
|
97
99
|
KindMultiLineCommentTrivia = innerast.KindMultiLineCommentTrivia
|
|
@@ -167,12 +169,12 @@ const (
|
|
|
167
169
|
ModifierFlagsReadonly = innerast.ModifierFlagsReadonly
|
|
168
170
|
)
|
|
169
171
|
|
|
170
|
-
func NewNodeFactory(
|
|
171
|
-
return innerast.NewNodeFactory(
|
|
172
|
+
func NewNodeFactory(options NodeFactoryHooks) *NodeFactory {
|
|
173
|
+
return innerast.NewNodeFactory(options)
|
|
172
174
|
}
|
|
173
175
|
|
|
174
|
-
func NewNodeVisitor(visit func(node *Node) *Node, factory *NodeFactory,
|
|
175
|
-
return innerast.NewNodeVisitor(visit, factory,
|
|
176
|
+
func NewNodeVisitor(visit func(node *Node) *Node, factory *NodeFactory, options NodeVisitorHooks) *NodeVisitor {
|
|
177
|
+
return innerast.NewNodeVisitor(visit, factory, options)
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
func IsFunctionLike(node *Node) bool {
|
|
@@ -323,7 +323,6 @@ function serializeNativePlugins(
|
|
|
323
323
|
return JSON.stringify(
|
|
324
324
|
plugins.map((plugin) => ({
|
|
325
325
|
config: plugin.config,
|
|
326
|
-
hooks: plugin.hooks,
|
|
327
326
|
name: plugin.name,
|
|
328
327
|
stage: plugin.stage,
|
|
329
328
|
})),
|
|
@@ -411,7 +410,7 @@ function assertCompilerHostCompatibility(
|
|
|
411
410
|
}
|
|
412
411
|
throw new Error(
|
|
413
412
|
"ttsc: multiple compiler native backends cannot share one emit pass; " +
|
|
414
|
-
"compose transform
|
|
413
|
+
"compose transform libraries through one aggregate native host",
|
|
415
414
|
);
|
|
416
415
|
}
|
|
417
416
|
|
|
@@ -218,7 +218,6 @@ function serializeNativePlugins(
|
|
|
218
218
|
return JSON.stringify(
|
|
219
219
|
plugins.map((plugin) => ({
|
|
220
220
|
config: plugin.config,
|
|
221
|
-
hooks: plugin.hooks,
|
|
222
221
|
name: plugin.name,
|
|
223
222
|
stage: plugin.stage,
|
|
224
223
|
})),
|
|
@@ -237,7 +236,7 @@ function assertTransformHostCompatibility(
|
|
|
237
236
|
}
|
|
238
237
|
throw new Error(
|
|
239
238
|
"ttsc: multiple transform native backends cannot share one source-to-source pass; " +
|
|
240
|
-
"compose transform
|
|
239
|
+
"compose transform libraries through one aggregate native host",
|
|
241
240
|
);
|
|
242
241
|
}
|
|
243
242
|
|
|
@@ -369,7 +369,7 @@ function printHelp(): void {
|
|
|
369
369
|
"Plugin contract:",
|
|
370
370
|
" ttsc reads compilerOptions.plugins from tsconfig.json.",
|
|
371
371
|
" Plugin modules are descriptors for ordered native transformer backends.",
|
|
372
|
-
" JS transformOutput/transformSource
|
|
372
|
+
" JS transformOutput/transformSource functions are not part of the public contract.",
|
|
373
373
|
"",
|
|
374
374
|
"Compatibility aliases:",
|
|
375
375
|
" ttsc build [options] Same project build lane as `ttsc [options]`.",
|
|
@@ -60,7 +60,6 @@ export function loadProjectPlugins(options: {
|
|
|
60
60
|
plugins.forEach((plugin, index) => {
|
|
61
61
|
const stage = resolvePluginStage(plugin);
|
|
62
62
|
validatePluginSource(plugin);
|
|
63
|
-
validatePluginHooks(plugin, stage);
|
|
64
63
|
const binary = buildSourcePlugin({
|
|
65
64
|
baseDir: context.projectRoot,
|
|
66
65
|
cacheDir: options.cacheDir,
|
|
@@ -72,7 +71,6 @@ export function loadProjectPlugins(options: {
|
|
|
72
71
|
nativePlugins.push({
|
|
73
72
|
binary,
|
|
74
73
|
config: entries[index]!,
|
|
75
|
-
hooks: plugin.hooks,
|
|
76
74
|
name: plugin.name,
|
|
77
75
|
source: plugin.source,
|
|
78
76
|
stage,
|
|
@@ -92,7 +90,6 @@ function loadPluginEntry(
|
|
|
92
90
|
if (typeof specifier !== "string" || specifier.length === 0) {
|
|
93
91
|
throw new Error(`ttsc: plugin entry is missing a string "transform" field`);
|
|
94
92
|
}
|
|
95
|
-
rejectUserPhaseOptions(specifier, entry);
|
|
96
93
|
|
|
97
94
|
const request = resolvePluginRequest(specifier, context.projectRoot);
|
|
98
95
|
const mod = require(request) as {
|
|
@@ -111,11 +108,11 @@ function loadPluginEntry(
|
|
|
111
108
|
`ttsc: plugin "${specifier}" does not export a valid ttsc plugin`,
|
|
112
109
|
);
|
|
113
110
|
}
|
|
114
|
-
|
|
111
|
+
rejectJsTransformFunctions(specifier, plugin);
|
|
115
112
|
return plugin;
|
|
116
113
|
}
|
|
117
114
|
if (isTtscPlugin(candidate)) {
|
|
118
|
-
|
|
115
|
+
rejectJsTransformFunctions(specifier, candidate);
|
|
119
116
|
return candidate;
|
|
120
117
|
}
|
|
121
118
|
throw new Error(
|
|
@@ -131,35 +128,18 @@ function isTtscPlugin(value: unknown): value is ITtscPlugin {
|
|
|
131
128
|
);
|
|
132
129
|
}
|
|
133
130
|
|
|
134
|
-
function
|
|
131
|
+
function rejectJsTransformFunctions(
|
|
132
|
+
specifier: string,
|
|
133
|
+
candidate: object,
|
|
134
|
+
): void {
|
|
135
135
|
if ("transformSource" in candidate || "transformOutput" in candidate) {
|
|
136
136
|
throw new Error(
|
|
137
|
-
`ttsc: plugin "${specifier}" declares unsupported JS transform
|
|
137
|
+
`ttsc: plugin "${specifier}" declares unsupported JS transform functions; ` +
|
|
138
138
|
"declare a native backend instead",
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
function rejectUserPhaseOptions(
|
|
144
|
-
specifier: string,
|
|
145
|
-
entry: ITtscProjectPluginConfig,
|
|
146
|
-
): void {
|
|
147
|
-
for (const key of [
|
|
148
|
-
"after",
|
|
149
|
-
"afterDeclarations",
|
|
150
|
-
"before",
|
|
151
|
-
"phase",
|
|
152
|
-
"source:after",
|
|
153
|
-
]) {
|
|
154
|
-
if (key in entry) {
|
|
155
|
-
throw new Error(
|
|
156
|
-
`ttsc: plugin entry for "${specifier}" uses unsupported ts-patch option ${JSON.stringify(key)}; ` +
|
|
157
|
-
"ttsc plugins declare source/declaration hooks in the package descriptor, not in user tsconfig",
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
143
|
function resolvePluginStage(plugin: ITtscPlugin): TtscPluginStage {
|
|
164
144
|
if (plugin.stage === undefined) {
|
|
165
145
|
return "transform";
|
|
@@ -168,7 +148,7 @@ function resolvePluginStage(plugin: ITtscPlugin): TtscPluginStage {
|
|
|
168
148
|
if (plugin.stage === "output") {
|
|
169
149
|
throw new Error(
|
|
170
150
|
`ttsc: plugin "${plugin.name}" requested removed stage "output"; ` +
|
|
171
|
-
"upgrade the plugin to a transform
|
|
151
|
+
"upgrade the plugin to a transform-stage descriptor compatible with this ttsc version",
|
|
172
152
|
);
|
|
173
153
|
}
|
|
174
154
|
throw new Error(
|
|
@@ -184,54 +164,6 @@ function validatePluginSource(plugin: ITtscPlugin): void {
|
|
|
184
164
|
}
|
|
185
165
|
}
|
|
186
166
|
|
|
187
|
-
function validatePluginHooks(
|
|
188
|
-
plugin: ITtscPlugin,
|
|
189
|
-
stage: TtscPluginStage,
|
|
190
|
-
): void {
|
|
191
|
-
const hooks = plugin.hooks;
|
|
192
|
-
if (hooks !== undefined && typeof hooks !== "object") {
|
|
193
|
-
throw new Error(`ttsc: plugin "${plugin.name}" hooks must be an object`);
|
|
194
|
-
}
|
|
195
|
-
if (stage === "check") {
|
|
196
|
-
if (hooks !== undefined && Object.keys(hooks).length !== 0) {
|
|
197
|
-
throw new Error(
|
|
198
|
-
`ttsc: check plugin "${plugin.name}" must not declare transform hooks`,
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (hooks === undefined) {
|
|
204
|
-
throw new Error(
|
|
205
|
-
`ttsc: transform plugin "${plugin.name}" must declare source/declaration hooks in its package descriptor`,
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
for (const key of Object.keys(hooks)) {
|
|
209
|
-
if (key !== "source" && key !== "declaration") {
|
|
210
|
-
throw new Error(
|
|
211
|
-
`ttsc: plugin "${plugin.name}" requested unsupported hook ${JSON.stringify(key)}`,
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (hooks.source !== undefined && typeof hooks.source !== "boolean") {
|
|
216
|
-
throw new Error(
|
|
217
|
-
`ttsc: plugin "${plugin.name}" hooks.source must be boolean`,
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
if (
|
|
221
|
-
hooks.declaration !== undefined &&
|
|
222
|
-
typeof hooks.declaration !== "boolean"
|
|
223
|
-
) {
|
|
224
|
-
throw new Error(
|
|
225
|
-
`ttsc: plugin "${plugin.name}" hooks.declaration must be boolean`,
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
if (hooks.source !== true && hooks.declaration !== true) {
|
|
229
|
-
throw new Error(
|
|
230
|
-
`ttsc: transform plugin "${plugin.name}" must enable at least one source/declaration hook`,
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
167
|
function isPluginStage(value: string): value is TtscPluginStage {
|
|
236
168
|
return value === "transform" || value === "check";
|
|
237
169
|
}
|
|
@@ -1,20 +1,5 @@
|
|
|
1
1
|
import type { TtscPluginStage } from "./TtscPluginStage";
|
|
2
2
|
|
|
3
|
-
export interface ITtscPluginHooks {
|
|
4
|
-
/**
|
|
5
|
-
* Runs against TypeScript SourceFile AST before TypeScript-Go's built-in emit
|
|
6
|
-
* transforms. The Program/checker are created from the original source before
|
|
7
|
-
* this hook participates in emit.
|
|
8
|
-
*/
|
|
9
|
-
source?: boolean;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Runs against declaration AST before declaration printing. This is a
|
|
13
|
-
* plugin-package capability, never a user-facing tsconfig phase option.
|
|
14
|
-
*/
|
|
15
|
-
declaration?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
3
|
/**
|
|
19
4
|
* Runtime descriptor returned by a ttsc plugin module.
|
|
20
5
|
*
|
|
@@ -69,9 +54,6 @@ export interface ITtscPlugin {
|
|
|
69
54
|
* @default "transform"
|
|
70
55
|
*/
|
|
71
56
|
stage?: TtscPluginStage;
|
|
72
|
-
|
|
73
|
-
/** Native transform hook capabilities implemented by the plugin package. */
|
|
74
|
-
hooks?: ITtscPluginHooks;
|
|
75
57
|
}
|
|
76
58
|
|
|
77
59
|
export function defineTtscPlugin<T extends ITtscPlugin>(plugin: T): T;
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
* Pipeline stage where a plugin's lazily built Go sidecar participates.
|
|
3
3
|
*
|
|
4
4
|
* - `"transform"`: participates in the TypeScript-Go transform path. Transform
|
|
5
|
-
* plugins
|
|
6
|
-
* package descriptor and do not receive emitted JavaScript or emitted file
|
|
7
|
-
* text.
|
|
5
|
+
* plugins do not receive emitted JavaScript or emitted file text.
|
|
8
6
|
* - `"check"`: runs before emit and reports diagnostics only. Use this for
|
|
9
7
|
* lint or validation plugins that should fail the compile before JavaScript
|
|
10
8
|
* or declaration output is generated.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ITtscProjectPluginConfig } from "../ITtscProjectPluginConfig";
|
|
2
|
-
import type { ITtscPluginHooks } from "../ITtscPlugin";
|
|
3
2
|
import type { TtscPluginStage } from "../TtscPluginStage";
|
|
4
3
|
|
|
5
4
|
/** Native sidecar selected and built from one plugin descriptor. */
|
|
@@ -14,6 +13,4 @@ export interface ITtscLoadedNativePlugin {
|
|
|
14
13
|
source: string;
|
|
15
14
|
/** Pipeline stage where the sidecar participates. */
|
|
16
15
|
stage: TtscPluginStage;
|
|
17
|
-
/** Native transform hook capabilities declared by the plugin package. */
|
|
18
|
-
hooks?: ITtscPluginHooks;
|
|
19
16
|
}
|
package/test/compiler.test.ts
CHANGED
|
@@ -274,7 +274,7 @@ function createProject(options = {}) {
|
|
|
274
274
|
function writeSourcePlugin(root) {
|
|
275
275
|
fs.writeFileSync(
|
|
276
276
|
path.join(root, "plugin.cjs"),
|
|
277
|
-
'module.exports = { name: "prepare-fixture", source: "./plugin-go"
|
|
277
|
+
'module.exports = { name: "prepare-fixture", source: "./plugin-go" };\n',
|
|
278
278
|
"utf8",
|
|
279
279
|
);
|
|
280
280
|
fs.mkdirSync(path.join(root, "plugin-go"), { recursive: true });
|
|
@@ -293,7 +293,7 @@ function writeSourcePlugin(root) {
|
|
|
293
293
|
function writeBrokenTransformPlugin(root) {
|
|
294
294
|
fs.writeFileSync(
|
|
295
295
|
path.join(root, "plugin.cjs"),
|
|
296
|
-
'module.exports = { name: "broken-transform-fixture", source: "./plugin-go"
|
|
296
|
+
'module.exports = { name: "broken-transform-fixture", source: "./plugin-go" };\n',
|
|
297
297
|
"utf8",
|
|
298
298
|
);
|
|
299
299
|
fs.mkdirSync(path.join(root, "plugin-go"), { recursive: true });
|
|
@@ -327,7 +327,7 @@ function writeBrokenTransformPlugin(root) {
|
|
|
327
327
|
function writeCompilerPlugin(root) {
|
|
328
328
|
fs.writeFileSync(
|
|
329
329
|
path.join(root, "plugin.cjs"),
|
|
330
|
-
'module.exports = { name: "compile-fixture", source: "./plugin-go"
|
|
330
|
+
'module.exports = { name: "compile-fixture", source: "./plugin-go" };\n',
|
|
331
331
|
"utf8",
|
|
332
332
|
);
|
|
333
333
|
fs.mkdirSync(path.join(root, "plugin-go"), { recursive: true });
|
package/utility/host.go
CHANGED
|
@@ -18,7 +18,6 @@ import (
|
|
|
18
18
|
|
|
19
19
|
type pluginEntry struct {
|
|
20
20
|
Config map[string]any `json:"config"`
|
|
21
|
-
Hooks map[string]any `json:"hooks"`
|
|
22
21
|
Name string `json:"name"`
|
|
23
22
|
Stage string `json:"stage"`
|
|
24
23
|
}
|
|
@@ -35,9 +34,8 @@ type hostOptions struct {
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
type transformState struct {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
strip *stripRewriter
|
|
37
|
+
paths *pathsRewriter
|
|
38
|
+
strip *stripRewriter
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
type transformResult struct {
|
|
@@ -51,7 +49,7 @@ func RunBuild(args []string) int {
|
|
|
51
49
|
if !ok {
|
|
52
50
|
return 2
|
|
53
51
|
}
|
|
54
|
-
prog, entries,
|
|
52
|
+
prog, entries, _, sourcePreamble, ok := loadUtilityProgram(opts)
|
|
55
53
|
if !ok {
|
|
56
54
|
return 2
|
|
57
55
|
}
|
|
@@ -70,19 +68,7 @@ func RunBuild(args []string) int {
|
|
|
70
68
|
eDiags []driver.Diagnostic
|
|
71
69
|
err error
|
|
72
70
|
)
|
|
73
|
-
|
|
74
|
-
hooks := shimcompiler.EmitHooks{
|
|
75
|
-
BeforePrintJS: func(context *shimcompiler.EmitContext, file *shimast.SourceFile) *shimast.SourceFile {
|
|
76
|
-
return applyBannerJSDoc(context, file, state.banner)
|
|
77
|
-
},
|
|
78
|
-
BeforePrintDeclaration: func(context *shimcompiler.EmitContext, file *shimast.SourceFile) *shimast.SourceFile {
|
|
79
|
-
return applyBannerJSDoc(context, file, state.banner)
|
|
80
|
-
},
|
|
81
|
-
}
|
|
82
|
-
res, eDiags, err = prog.EmitAllRawWithHooks(nil, hooks)
|
|
83
|
-
} else {
|
|
84
|
-
res, eDiags, err = prog.EmitAllRaw(nil)
|
|
85
|
-
}
|
|
71
|
+
res, eDiags, err = prog.EmitAllRaw(makeSourcePreambleWriteFile(prog, sourcePreamble))
|
|
86
72
|
if err != nil {
|
|
87
73
|
fmt.Fprintf(os.Stderr, "ttsc utility: emit failed: %v\n", err)
|
|
88
74
|
return 3
|
|
@@ -96,13 +82,13 @@ func RunBuild(args []string) int {
|
|
|
96
82
|
return 0
|
|
97
83
|
}
|
|
98
84
|
|
|
99
|
-
// RunTransform returns the project TypeScript text after source
|
|
85
|
+
// RunTransform returns the project TypeScript text after source mutations.
|
|
100
86
|
func RunTransform(args []string) int {
|
|
101
87
|
opts, ok := parseHostOptions("transform", args)
|
|
102
88
|
if !ok {
|
|
103
89
|
return 2
|
|
104
90
|
}
|
|
105
|
-
prog, _, _, ok := loadUtilityProgram(opts)
|
|
91
|
+
prog, _, _, _, ok := loadUtilityProgram(opts)
|
|
106
92
|
if !ok {
|
|
107
93
|
return 2
|
|
108
94
|
}
|
|
@@ -163,39 +149,45 @@ func parseHostOptions(command string, args []string) (hostOptions, bool) {
|
|
|
163
149
|
}, true
|
|
164
150
|
}
|
|
165
151
|
|
|
166
|
-
func loadUtilityProgram(opts hostOptions) (*driver.Program, []pluginEntry, transformState, bool) {
|
|
152
|
+
func loadUtilityProgram(opts hostOptions) (*driver.Program, []pluginEntry, transformState, string, bool) {
|
|
167
153
|
entries, err := parsePluginEntries(opts.pluginsJSON)
|
|
168
154
|
if err != nil {
|
|
169
155
|
fmt.Fprintln(os.Stderr, err)
|
|
170
|
-
return nil, nil, transformState{}, false
|
|
156
|
+
return nil, nil, transformState{}, "", false
|
|
157
|
+
}
|
|
158
|
+
sourcePreamble, err := prepareSourcePreamble(entries)
|
|
159
|
+
if err != nil {
|
|
160
|
+
fmt.Fprintln(os.Stderr, err)
|
|
161
|
+
return nil, nil, transformState{}, "", false
|
|
171
162
|
}
|
|
172
163
|
prog, diags, err := driver.LoadProgram(opts.cwd, opts.tsconfig, driver.LoadProgramOptions{
|
|
173
|
-
ForceEmit:
|
|
174
|
-
ForceNoEmit:
|
|
175
|
-
OutDir:
|
|
164
|
+
ForceEmit: opts.emit,
|
|
165
|
+
ForceNoEmit: opts.noEmit,
|
|
166
|
+
OutDir: opts.outDir,
|
|
167
|
+
SourcePreamble: sourcePreamble,
|
|
176
168
|
})
|
|
177
169
|
if err != nil {
|
|
178
170
|
fmt.Fprintf(os.Stderr, "ttsc utility: %v\n", err)
|
|
179
|
-
return nil, nil, transformState{}, false
|
|
171
|
+
return nil, nil, transformState{}, "", false
|
|
180
172
|
}
|
|
181
173
|
if len(diags) > 0 {
|
|
182
174
|
driver.WritePrettyDiagnostics(os.Stderr, diags, opts.cwd)
|
|
183
|
-
return nil, nil, transformState{}, false
|
|
175
|
+
return nil, nil, transformState{}, "", false
|
|
184
176
|
}
|
|
185
177
|
if diags := prog.Diagnostics(); len(diags) > 0 {
|
|
186
178
|
driver.WritePrettyDiagnostics(os.Stderr, diags, opts.cwd)
|
|
187
|
-
return nil, nil, transformState{}, false
|
|
179
|
+
return nil, nil, transformState{}, "", false
|
|
188
180
|
}
|
|
189
181
|
state, err := prepareTransforms(prog, entries)
|
|
190
182
|
if err != nil {
|
|
191
183
|
fmt.Fprintln(os.Stderr, err)
|
|
192
|
-
return nil, nil, transformState{}, false
|
|
184
|
+
return nil, nil, transformState{}, "", false
|
|
193
185
|
}
|
|
194
186
|
if err := applySourceTransforms(prog, state); err != nil {
|
|
195
187
|
fmt.Fprintln(os.Stderr, err)
|
|
196
|
-
return nil, nil, transformState{}, false
|
|
188
|
+
return nil, nil, transformState{}, "", false
|
|
197
189
|
}
|
|
198
|
-
return prog, entries, state, true
|
|
190
|
+
return prog, entries, state, sourcePreamble, true
|
|
199
191
|
}
|
|
200
192
|
|
|
201
193
|
func parsePluginEntries(input string) ([]pluginEntry, error) {
|
|
@@ -213,12 +205,6 @@ func prepareTransforms(prog *driver.Program, entries []pluginEntry) (transformSt
|
|
|
213
205
|
state := transformState{}
|
|
214
206
|
for _, entry := range entries {
|
|
215
207
|
switch entry.Name {
|
|
216
|
-
case "@ttsc/banner":
|
|
217
|
-
banner, err := parseBanner(entry.Config)
|
|
218
|
-
if err != nil {
|
|
219
|
-
return state, err
|
|
220
|
-
}
|
|
221
|
-
state.banner = banner
|
|
222
208
|
case "@ttsc/paths":
|
|
223
209
|
state.paths = newPathsRewriter(prog)
|
|
224
210
|
case "@ttsc/strip":
|
|
@@ -232,6 +218,54 @@ func prepareTransforms(prog *driver.Program, entries []pluginEntry) (transformSt
|
|
|
232
218
|
return state, nil
|
|
233
219
|
}
|
|
234
220
|
|
|
221
|
+
func prepareSourcePreamble(entries []pluginEntry) (string, error) {
|
|
222
|
+
var preamble strings.Builder
|
|
223
|
+
for _, entry := range entries {
|
|
224
|
+
if entry.Name != "@ttsc/banner" {
|
|
225
|
+
continue
|
|
226
|
+
}
|
|
227
|
+
banner, err := parseBanner(entry.Config)
|
|
228
|
+
if err != nil {
|
|
229
|
+
return "", err
|
|
230
|
+
}
|
|
231
|
+
preamble.WriteString(banner)
|
|
232
|
+
}
|
|
233
|
+
return preamble.String(), nil
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
func makeSourcePreambleWriteFile(prog *driver.Program, sourcePreamble string) shimcompiler.WriteFile {
|
|
237
|
+
if sourcePreamble == "" || shouldRemoveComments(prog) {
|
|
238
|
+
return nil
|
|
239
|
+
}
|
|
240
|
+
return func(fileName, text string, _ *shimcompiler.WriteFileData) error {
|
|
241
|
+
if shouldEnsureSourcePreamble(fileName, text, sourcePreamble) {
|
|
242
|
+
text = sourcePreamble + text
|
|
243
|
+
}
|
|
244
|
+
return driver.DefaultWriteFile(fileName, text)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
func shouldRemoveComments(prog *driver.Program) bool {
|
|
249
|
+
if prog == nil || prog.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig.CompilerOptions == nil {
|
|
250
|
+
return false
|
|
251
|
+
}
|
|
252
|
+
return prog.ParsedConfig.ParsedConfig.CompilerOptions.RemoveComments.IsTrue()
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
func shouldEnsureSourcePreamble(fileName, text, sourcePreamble string) bool {
|
|
256
|
+
return isSourcePreambleOutputTarget(fileName) && !strings.Contains(text, sourcePreamble)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
func isSourcePreambleOutputTarget(fileName string) bool {
|
|
260
|
+
lower := strings.ToLower(filepath.ToSlash(fileName))
|
|
261
|
+
for _, suffix := range []string{".d.ts", ".d.mts", ".d.cts", ".js", ".jsx", ".mjs", ".cjs"} {
|
|
262
|
+
if strings.HasSuffix(lower, suffix) {
|
|
263
|
+
return true
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return false
|
|
267
|
+
}
|
|
268
|
+
|
|
235
269
|
func applySourceTransforms(prog *driver.Program, state transformState) error {
|
|
236
270
|
for _, file := range prog.SourceFiles() {
|
|
237
271
|
if state.paths != nil {
|
|
@@ -267,7 +301,8 @@ func parseBanner(config map[string]any) (string, error) {
|
|
|
267
301
|
}
|
|
268
302
|
var b strings.Builder
|
|
269
303
|
sep := strings.Repeat("-", 64)
|
|
270
|
-
b.WriteString("
|
|
304
|
+
b.WriteString("/**\n")
|
|
305
|
+
b.WriteString(" * ")
|
|
271
306
|
b.WriteString(sep)
|
|
272
307
|
b.WriteByte('\n')
|
|
273
308
|
for _, line := range lines {
|
|
@@ -277,6 +312,7 @@ func parseBanner(config map[string]any) (string, error) {
|
|
|
277
312
|
}
|
|
278
313
|
b.WriteString(" *\n")
|
|
279
314
|
b.WriteString(" * @packageDocumentation\n ")
|
|
315
|
+
b.WriteString("*/\n")
|
|
280
316
|
return b.String(), nil
|
|
281
317
|
}
|
|
282
318
|
|
|
@@ -284,14 +320,6 @@ func sanitizeJSDocLine(line string) string {
|
|
|
284
320
|
return strings.ReplaceAll(line, "*/", "* /")
|
|
285
321
|
}
|
|
286
322
|
|
|
287
|
-
func applyBannerJSDoc(context *shimcompiler.EmitContext, file *shimast.SourceFile, banner string) *shimast.SourceFile {
|
|
288
|
-
if context == nil || file == nil || banner == "" || file.Statements == nil || len(file.Statements.Nodes) == 0 {
|
|
289
|
-
return file
|
|
290
|
-
}
|
|
291
|
-
context.AddSyntheticLeadingComment(file.Statements.Nodes[0], shimast.KindMultiLineCommentTrivia, banner, true)
|
|
292
|
-
return file
|
|
293
|
-
}
|
|
294
|
-
|
|
295
323
|
type pathsRewriter struct {
|
|
296
324
|
basePath string
|
|
297
325
|
outDir string
|