ttsc 0.18.4 → 0.19.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 +5 -6
- package/cmd/graphbench/main.go +1 -1
- package/cmd/platform/main.go +1 -48
- package/cmd/ttsc/build_branches_test.go +5 -1
- package/cmd/ttsc/main.go +0 -50
- package/cmd/ttsc/main_alias_branches_test.go +6 -12
- package/cmd/ttscgraph/dump.go +13 -3
- package/cmd/ttscserver/main.go +5 -3
- package/driver/lsp.go +13 -1
- package/driver/plugins.go +35 -0
- package/driver/program.go +7 -8
- package/driver/rewrite.go +381 -21
- package/go.mod +1 -0
- package/internal/graph/build.go +297 -3
- package/internal/graph/build_records_a_node_per_top_level_declaration_test.go +16 -2
- package/internal/graph/diagnostics.go +5 -4
- package/internal/graph/dump.go +60 -4
- package/internal/graph/dump_is_a_function_of_the_source_test.go +71 -0
- package/internal/graph/dump_serializes_the_full_graph_test.go +16 -4
- package/internal/graph/edges.go +122 -11
- package/internal/graph/exports.go +74 -17
- package/internal/graph/graph.go +33 -1
- package/internal/graph/node_identity_is_position_invariant_test.go +4 -2
- package/internal/graph/resolve.go +24 -0
- package/internal/graphsymbols/provider.go +50 -14
- package/internal/lspserver/lsp_native_plugin_source.go +77 -23
- package/internal/lspserver/lsp_plugin.go +19 -2
- package/internal/lspserver/lsp_proxy.go +244 -52
- package/internal/lspserver/lsp_server.go +35 -27
- package/internal/lspserver/lsp_symbols.go +25 -16
- package/lib/TtscCompiler.d.ts +10 -0
- package/lib/TtscCompiler.js +24 -6
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/TtscService.js +9 -7
- package/lib/TtscService.js.map +1 -1
- package/lib/compiler/internal/compileProjectInMemory.js +1 -0
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/project/createNativeProjectContextArgs.d.ts +3 -0
- package/lib/compiler/internal/project/createNativeProjectContextArgs.js +14 -0
- package/lib/compiler/internal/project/createNativeProjectContextArgs.js.map +1 -0
- package/lib/compiler/internal/project/readProjectConfig.js +53 -4
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/project/resolveProjectConfig.d.ts +9 -2
- package/lib/compiler/internal/project/resolveProjectConfig.js +45 -16
- package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
- package/lib/compiler/internal/residentTransformProcess.d.ts +16 -5
- package/lib/compiler/internal/residentTransformProcess.js +68 -20
- package/lib/compiler/internal/residentTransformProcess.js.map +1 -1
- package/lib/compiler/internal/runBuild.d.ts +11 -0
- package/lib/compiler/internal/runBuild.js +44 -8
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/runSingleFileEmit.js +7 -4
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +16 -0
- package/lib/compiler/internal/sharedHostHelpers.js +23 -0
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.js +18 -1
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +34 -8
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/flags/parser.d.ts +17 -0
- package/lib/flags/parser.js +11 -1
- package/lib/flags/parser.js.map +1 -1
- package/lib/flags/schema.js +7 -0
- package/lib/flags/schema.js.map +1 -1
- package/lib/launcher/internal/prepareExecution.js +21 -2
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +13 -53
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtscserver.js +11 -0
- package/lib/launcher/internal/runTtscserver.js.map +1 -1
- package/lib/launcher/internal/runTtsx.js +27 -11
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/launcher/internal/runtimeHooks.d.ts +81 -0
- package/lib/launcher/internal/runtimeHooks.js +632 -43
- package/lib/launcher/internal/runtimeHooks.js.map +1 -1
- package/lib/launcher/internal/servedSourceMap.d.ts +25 -0
- package/lib/launcher/internal/servedSourceMap.js +164 -0
- package/lib/launcher/internal/servedSourceMap.js.map +1 -0
- package/lib/plugin/internal/buildSourcePlugin.d.ts +146 -2
- package/lib/plugin/internal/buildSourcePlugin.js +651 -113
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.d.ts +7 -0
- package/lib/plugin/internal/loadProjectPlugins.js +33 -10
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerContext.d.ts +16 -2
- package/lib/structures/ITtscPluginCapabilities.d.ts +8 -0
- package/lib/structures/ITtscPluginFactoryContext.d.ts +14 -0
- package/lib/structures/internal/ITtscParsedProjectConfig.d.ts +3 -0
- package/lib/structures/internal/ITtscProjectIdentity.d.ts +17 -0
- package/lib/structures/internal/ITtscProjectIdentity.js +3 -0
- package/lib/structures/internal/ITtscProjectIdentity.js.map +1 -0
- package/lib/structures/internal/TtscCommonOptions.d.ts +8 -0
- package/package.json +11 -8
- package/shim/ast/lint.go +10 -0
- package/shim/ast/shim.go +44 -0
- package/shim/checker/enums_gen.go +19 -0
- package/shim/checker/shim.go +130 -0
- package/shim/diagnosticwriter/lint.go +30 -3
- package/shim/scanner/regexp.go +27 -0
- package/src/TtscCompiler.ts +25 -6
- package/src/TtscService.ts +15 -7
- package/src/compiler/internal/compileProjectInMemory.ts +1 -0
- package/src/compiler/internal/project/createNativeProjectContextArgs.ts +15 -0
- package/src/compiler/internal/project/readProjectConfig.ts +61 -5
- package/src/compiler/internal/project/resolveProjectConfig.ts +51 -21
- package/src/compiler/internal/residentTransformProcess.ts +95 -21
- package/src/compiler/internal/runBuild.ts +76 -9
- package/src/compiler/internal/runSingleFileEmit.ts +7 -4
- package/src/compiler/internal/sharedHostHelpers.ts +24 -0
- package/src/compiler/internal/startResidentTransform.ts +21 -1
- package/src/compiler/internal/transformProjectInMemory.ts +49 -6
- package/src/flags/parser.ts +28 -1
- package/src/flags/schema.ts +8 -0
- package/src/launcher/internal/prepareExecution.ts +22 -2
- package/src/launcher/internal/runTtsc.ts +13 -61
- package/src/launcher/internal/runTtscserver.ts +14 -0
- package/src/launcher/internal/runTtsx.ts +28 -13
- package/src/launcher/internal/runtimeHooks.ts +771 -53
- package/src/launcher/internal/servedSourceMap.ts +183 -0
- package/src/plugin/internal/buildSourcePlugin.ts +859 -122
- package/src/plugin/internal/loadProjectPlugins.ts +36 -6
- package/src/structures/ITtscCompilerContext.ts +17 -2
- package/src/structures/ITtscPluginCapabilities.ts +9 -0
- package/src/structures/ITtscPluginFactoryContext.ts +15 -0
- package/src/structures/internal/ITtscParsedProjectConfig.ts +3 -0
- package/src/structures/internal/ITtscProjectIdentity.ts +17 -0
- package/src/structures/internal/TtscCommonOptions.ts +8 -0
- package/tools/shim_audit/baseline.json +16 -7
- package/tools/shim_audit/main.go +777 -71
- package/tools/shim_audit/main_test.go +28 -1
- package/tools/shim_audit/producer_exemptions_require_rationale_test.go +42 -0
- package/tools/shim_audit/producer_surface_includes_exposed_methods_test.go +154 -0
- package/tools/shim_audit/producer_surface_rejects_unproducible_reference_test.go +142 -0
- package/utility/host.go +46 -20
- package/utility/serve.go +1 -1
- package/shim/checker/signature_api_completeness.go +0 -58
|
@@ -11,6 +11,7 @@ import type { ITtscParsedProjectConfig } from "../../structures/internal/ITtscPa
|
|
|
11
11
|
import type { TtscBuildResult } from "../../structures/internal/TtscBuildResult";
|
|
12
12
|
import { buildNativeCompiler } from "./buildNativeCompiler";
|
|
13
13
|
import { packageRootDir } from "./paths";
|
|
14
|
+
import { createNativeProjectContextArgs } from "./project/createNativeProjectContextArgs";
|
|
14
15
|
import { readProjectConfig } from "./project/readProjectConfig";
|
|
15
16
|
import { resolveBinary } from "./resolveBinary";
|
|
16
17
|
import { resolveTsgo } from "./resolveTsgo";
|
|
@@ -18,6 +19,7 @@ import { appendBuildOutput, normalizeBuildOutput } from "./runBuild";
|
|
|
18
19
|
import {
|
|
19
20
|
assertSharedHostCompatibility,
|
|
20
21
|
linkedTransformPlugins,
|
|
22
|
+
resolvePluginConfigDir,
|
|
21
23
|
selectSharedHostPlugin,
|
|
22
24
|
} from "./sharedHostHelpers";
|
|
23
25
|
import { outputText, spawnNative } from "./spawnNative";
|
|
@@ -126,6 +128,8 @@ function transformProjectWithPlugins(
|
|
|
126
128
|
cacheDir: options.cacheDir ?? options.env?.TTSC_CACHE_DIR,
|
|
127
129
|
cwd,
|
|
128
130
|
entries: options.plugins,
|
|
131
|
+
env: { ...process.env, ...options.env },
|
|
132
|
+
pluginConfigDir: options.pluginConfigDir,
|
|
129
133
|
projectRoot: options.projectRoot,
|
|
130
134
|
tsconfig: project.path,
|
|
131
135
|
});
|
|
@@ -167,7 +171,11 @@ function transformProjectWithPlugins(
|
|
|
167
171
|
const plugin = selectSharedHostPlugin(transformers);
|
|
168
172
|
const res = spawnNative(
|
|
169
173
|
plugin.binary,
|
|
170
|
-
createNativeTransformArgs(
|
|
174
|
+
createNativeTransformArgs(
|
|
175
|
+
project,
|
|
176
|
+
transformers,
|
|
177
|
+
resolvePluginConfigDir(options),
|
|
178
|
+
),
|
|
171
179
|
{
|
|
172
180
|
cwd: project.root,
|
|
173
181
|
env: nativePluginEnv(options, tsgoBinary, loaded.nativePlugins, plugin),
|
|
@@ -217,7 +225,12 @@ function runNativeChecks(
|
|
|
217
225
|
for (const plugin of checks) {
|
|
218
226
|
const res = spawnNative(
|
|
219
227
|
plugin.binary,
|
|
220
|
-
createNativeCheckArgs(
|
|
228
|
+
createNativeCheckArgs(
|
|
229
|
+
project,
|
|
230
|
+
nativePlugins,
|
|
231
|
+
plugin,
|
|
232
|
+
resolvePluginConfigDir(options),
|
|
233
|
+
),
|
|
221
234
|
{
|
|
222
235
|
cwd: project.root,
|
|
223
236
|
env: nativePluginEnv(options, tsgoBinary, nativePlugins, plugin),
|
|
@@ -250,26 +263,39 @@ function runNativeChecks(
|
|
|
250
263
|
function createNativeTransformArgs(
|
|
251
264
|
project: ITtscParsedProjectConfig,
|
|
252
265
|
plugins: readonly ITtscLoadedNativePlugin[],
|
|
266
|
+
pluginConfigOrigin?: string,
|
|
253
267
|
): string[] {
|
|
254
|
-
|
|
268
|
+
const args = [
|
|
255
269
|
"transform",
|
|
256
270
|
"--tsconfig=" + project.path,
|
|
257
271
|
"--plugins-json=" + serializeNativePlugins(plugins),
|
|
258
272
|
"--cwd=" + project.root,
|
|
259
273
|
];
|
|
274
|
+
if (
|
|
275
|
+
selectSharedHostPlugin(plugins).capabilities?.projectContextArgs === true
|
|
276
|
+
) {
|
|
277
|
+
args.push(...createNativeProjectContextArgs(project, pluginConfigOrigin));
|
|
278
|
+
}
|
|
279
|
+
return args;
|
|
260
280
|
}
|
|
261
281
|
|
|
262
282
|
/** Build the CLI argument list for the `check` subcommand. */
|
|
263
283
|
function createNativeCheckArgs(
|
|
264
284
|
project: ITtscParsedProjectConfig,
|
|
265
285
|
plugins: readonly ITtscLoadedNativePlugin[],
|
|
286
|
+
plugin: ITtscLoadedNativePlugin,
|
|
287
|
+
pluginConfigOrigin?: string,
|
|
266
288
|
): string[] {
|
|
267
|
-
|
|
289
|
+
const args = [
|
|
268
290
|
"check",
|
|
269
291
|
"--tsconfig=" + project.path,
|
|
270
292
|
"--plugins-json=" + serializeNativePlugins(plugins),
|
|
271
293
|
"--cwd=" + project.root,
|
|
272
294
|
];
|
|
295
|
+
if (plugin.capabilities?.projectContextArgs === true) {
|
|
296
|
+
args.push(...createNativeProjectContextArgs(project, pluginConfigOrigin));
|
|
297
|
+
}
|
|
298
|
+
return args;
|
|
273
299
|
}
|
|
274
300
|
|
|
275
301
|
/**
|
|
@@ -291,8 +317,11 @@ function serializeNativePlugins(
|
|
|
291
317
|
/**
|
|
292
318
|
* Build the environment for a native plugin spawn. Injects `TTSC_NODE_BINARY`,
|
|
293
319
|
* `TTSC_TSGO_BINARY`, and `TTSC_TTSX_BINARY` so the sidecar can re-invoke
|
|
294
|
-
* Node.js or tsgo without searching PATH
|
|
295
|
-
*
|
|
320
|
+
* Node.js or tsgo without searching PATH, plus `TTSC_PLUGIN_CONFIG_DIR` when
|
|
321
|
+
* the caller declared a plugin config anchor (an embedder compiling through a
|
|
322
|
+
* generated wrapper tsconfig) so config-file discovery walks the real project
|
|
323
|
+
* instead of the wrapper's temp-dir ancestry. For transform plugins, also
|
|
324
|
+
* passes `TTSC_LINKED_PLUGINS_JSON` when linked sources are present.
|
|
296
325
|
*/
|
|
297
326
|
function nativePluginEnv(
|
|
298
327
|
options: ITtscCompilerContext,
|
|
@@ -300,15 +329,29 @@ function nativePluginEnv(
|
|
|
300
329
|
nativePlugins?: readonly ITtscLoadedNativePlugin[],
|
|
301
330
|
plugin?: ITtscLoadedNativePlugin,
|
|
302
331
|
): NodeJS.ProcessEnv {
|
|
332
|
+
const pluginConfigDir = resolvePluginConfigDir(options);
|
|
303
333
|
const env: NodeJS.ProcessEnv = {
|
|
304
334
|
...process.env,
|
|
305
335
|
TTSC_NODE_BINARY: process.env.TTSC_NODE_BINARY ?? process.execPath,
|
|
336
|
+
...(pluginConfigDir === undefined
|
|
337
|
+
? {}
|
|
338
|
+
: { TTSC_PLUGIN_CONFIG_DIR: pluginConfigDir }),
|
|
306
339
|
TTSC_TSGO_BINARY: process.env.TTSC_TSGO_BINARY ?? tsgoBinary,
|
|
307
340
|
TTSC_TTSX_BINARY:
|
|
308
341
|
process.env.TTSC_TTSX_BINARY ??
|
|
309
342
|
path.join(__dirname, "..", "..", "launcher", "ttsx.js"),
|
|
310
343
|
...options.env,
|
|
311
344
|
};
|
|
345
|
+
// The anchor is per-invocation state owned by this host: when this run
|
|
346
|
+
// declared none (and the caller's env does not name one), drop any value
|
|
347
|
+
// inherited from an ancestor ttsc process so a nested build never
|
|
348
|
+
// mis-anchors its plugins at the outer project.
|
|
349
|
+
if (
|
|
350
|
+
pluginConfigDir === undefined &&
|
|
351
|
+
options.env?.TTSC_PLUGIN_CONFIG_DIR === undefined
|
|
352
|
+
) {
|
|
353
|
+
delete env.TTSC_PLUGIN_CONFIG_DIR;
|
|
354
|
+
}
|
|
312
355
|
if (plugin?.stage === "transform") {
|
|
313
356
|
const linked = linkedTransformPlugins(nativePlugins ?? []);
|
|
314
357
|
if (linked.length !== 0) {
|
package/src/flags/parser.ts
CHANGED
|
@@ -58,6 +58,23 @@ export interface ParseOptions {
|
|
|
58
58
|
* `--` is appended to `passthrough` as-is (ttsx already does this).
|
|
59
59
|
*/
|
|
60
60
|
readonly honorDoubleDashSeparator?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Classifies a bare (non-dash) token as a genuine positional argument (a
|
|
63
|
+
* source file, the ttsx entry, a project path) rather than the
|
|
64
|
+
* space-separated value of a preceding forwarded flag.
|
|
65
|
+
*
|
|
66
|
+
* When omitted, every bare token is a positional — the historical behaviour
|
|
67
|
+
* for project-shaped subcommands that never forward `--flag value` pairs.
|
|
68
|
+
*
|
|
69
|
+
* When provided, a bare token that fails the predicate is appended to
|
|
70
|
+
* `passthrough` in its original position instead of `positional`, so an
|
|
71
|
+
* unknown `--flag value` pair reaches tsgo with its adjacency and relative
|
|
72
|
+
* order intact. The parser deliberately does not guess a forwarded flag's
|
|
73
|
+
* arity from the flag itself (it has no schema for a truly unknown flag); the
|
|
74
|
+
* predicate is the only signal that separates a forwarded value from a real
|
|
75
|
+
* input file, and both callers key it on the TypeScript source extension.
|
|
76
|
+
*/
|
|
77
|
+
readonly isPositional?: (token: string) => boolean;
|
|
61
78
|
}
|
|
62
79
|
|
|
63
80
|
/**
|
|
@@ -153,7 +170,17 @@ export function parseFlags(opts: ParseOptions): ParseResult {
|
|
|
153
170
|
continue;
|
|
154
171
|
}
|
|
155
172
|
|
|
156
|
-
// Bare token: positional argument (file / entry / project
|
|
173
|
+
// Bare token: either a genuine positional argument (file / entry / project
|
|
174
|
+
// path) or the space-separated value of a preceding forwarded flag. When a
|
|
175
|
+
// caller forwards unknown flags it supplies `isPositional` to tell the two
|
|
176
|
+
// apart; a forwarded value is appended to `passthrough` in place so the
|
|
177
|
+
// `--flag value` pair reaches tsgo in its original order and adjacency,
|
|
178
|
+
// instead of being split into a separate bucket the caller later
|
|
179
|
+
// concatenates out of order.
|
|
180
|
+
if (opts.isPositional !== undefined && !opts.isPositional(current)) {
|
|
181
|
+
passthrough.push(current);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
157
184
|
positional.push(current);
|
|
158
185
|
if (opts.forwardAfterFirstPositional === true && positional.length === 1) {
|
|
159
186
|
forwardingTail = true;
|
package/src/flags/schema.ts
CHANGED
|
@@ -477,6 +477,14 @@ export const FLAG_SCHEMA: readonly FlagSpec[] = [
|
|
|
477
477
|
description:
|
|
478
478
|
"JSON-encoded ttsc plugin manifest (internal: emitted by runBuild).",
|
|
479
479
|
},
|
|
480
|
+
{
|
|
481
|
+
name: "--project-context-json",
|
|
482
|
+
kind: "value",
|
|
483
|
+
subcommands: ["build", "check", "fix", "format"],
|
|
484
|
+
consumedBy: ["lint"],
|
|
485
|
+
description:
|
|
486
|
+
"JSON-encoded lexical and physical project identity (internal: emitted by runBuild).",
|
|
487
|
+
},
|
|
480
488
|
{
|
|
481
489
|
name: "--manifest",
|
|
482
490
|
kind: "value",
|
|
@@ -71,8 +71,12 @@ function createProjectContext(
|
|
|
71
71
|
) {
|
|
72
72
|
const project = readProjectConfig(
|
|
73
73
|
options.project
|
|
74
|
-
? {
|
|
75
|
-
|
|
74
|
+
? {
|
|
75
|
+
cwd,
|
|
76
|
+
projectRoot: options.projectRoot,
|
|
77
|
+
tsconfig: path.resolve(cwd, options.project),
|
|
78
|
+
}
|
|
79
|
+
: { cwd, file: filename, projectRoot: options.projectRoot },
|
|
76
80
|
);
|
|
77
81
|
const tsconfig = project.path;
|
|
78
82
|
const root = project.root;
|
|
@@ -83,6 +87,7 @@ function createProjectContext(
|
|
|
83
87
|
const processDir = path.join(cacheDir, "project", PROCESS_CACHE_KEY);
|
|
84
88
|
const virtualRoot = path.join(processDir, "fs");
|
|
85
89
|
return {
|
|
90
|
+
project,
|
|
86
91
|
tsconfig,
|
|
87
92
|
root,
|
|
88
93
|
cacheDir,
|
|
@@ -102,6 +107,13 @@ function createProjectContext(
|
|
|
102
107
|
typeof project.compilerOptions.module === "string"
|
|
103
108
|
? project.compilerOptions.module
|
|
104
109
|
: undefined,
|
|
110
|
+
// Force a source map on the transient runtime emit only when the project
|
|
111
|
+
// configures none — when it already emits `sourceMap` or `inlineSourceMap`,
|
|
112
|
+
// the serve path inlines/absolutizes that map, so no override is needed
|
|
113
|
+
// (issue #353).
|
|
114
|
+
forceRuntimeSourceMap:
|
|
115
|
+
project.compilerOptions.sourceMap !== true &&
|
|
116
|
+
project.compilerOptions.inlineSourceMap !== true,
|
|
105
117
|
built: false,
|
|
106
118
|
emittedFiles: undefined as string[] | undefined,
|
|
107
119
|
};
|
|
@@ -139,8 +151,16 @@ function buildProject(
|
|
|
139
151
|
cacheDir: context.pluginCacheDir,
|
|
140
152
|
outDir: context.emitDir,
|
|
141
153
|
passthrough: options.passthrough,
|
|
154
|
+
// Emit a source map on the transient entry emit (a PID-isolated temp dir,
|
|
155
|
+
// never the consumer's `outDir`) so the serve path can inline it under the
|
|
156
|
+
// source URL. Routed as a dedicated build option, not a forwarded tsgo
|
|
157
|
+
// flag, so it never reaches a native plugin host's argument parser (issue
|
|
158
|
+
// #353).
|
|
159
|
+
forceRuntimeSourceMap: context.forceRuntimeSourceMap,
|
|
160
|
+
pluginConfigDir: options.pluginConfigDir,
|
|
142
161
|
plugins: options.plugins,
|
|
143
162
|
quiet: true,
|
|
163
|
+
resolvedProject: context.project,
|
|
144
164
|
singleThreaded: options.singleThreaded,
|
|
145
165
|
tsconfig: context.tsconfig,
|
|
146
166
|
});
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
1
|
import fs from "node:fs";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
|
|
5
4
|
import { TtscCompiler } from "../../TtscCompiler";
|
|
6
5
|
import { readProjectConfig } from "../../compiler/internal/project/readProjectConfig";
|
|
7
6
|
import { resolveProjectConfig } from "../../compiler/internal/project/resolveProjectConfig";
|
|
8
|
-
import { resolveBinary } from "../../compiler/internal/resolveBinary";
|
|
9
7
|
import { runBuild } from "../../compiler/internal/runBuild";
|
|
10
8
|
import { runSingleFileEmit } from "../../compiler/internal/runSingleFileEmit";
|
|
11
9
|
import {
|
|
@@ -68,8 +66,6 @@ export function runTtsc(
|
|
|
68
66
|
return runClean(rest);
|
|
69
67
|
case "prepare":
|
|
70
68
|
return runPrepare(rest);
|
|
71
|
-
case "demo":
|
|
72
|
-
return delegateToNative(argv);
|
|
73
69
|
case "-p":
|
|
74
70
|
case "--project":
|
|
75
71
|
return runCompatibleBuild(argv, "build");
|
|
@@ -391,54 +387,6 @@ function isOutsideRelativePath(relative: string): boolean {
|
|
|
391
387
|
);
|
|
392
388
|
}
|
|
393
389
|
|
|
394
|
-
function delegateToNative(argv: readonly string[]): number {
|
|
395
|
-
const bin = resolveBinary();
|
|
396
|
-
if (!bin) {
|
|
397
|
-
process.stderr.write(
|
|
398
|
-
[
|
|
399
|
-
`ttsc: platform-specific helper binary not found (@ttsc/${process.platform}-${process.arch}).`,
|
|
400
|
-
`Set TTSC_BINARY to an absolute helper path or reinstall with optional dependencies enabled.`,
|
|
401
|
-
].join("\n") + "\n",
|
|
402
|
-
);
|
|
403
|
-
return 1;
|
|
404
|
-
}
|
|
405
|
-
const viaNode = /\.(?:[cm]?js|ts)$/i.test(bin);
|
|
406
|
-
if (!viaNode) {
|
|
407
|
-
ensureExecutable(bin);
|
|
408
|
-
}
|
|
409
|
-
const result = spawnSync(
|
|
410
|
-
viaNode ? process.execPath : bin,
|
|
411
|
-
viaNode ? [bin, ...argv] : [...argv],
|
|
412
|
-
{
|
|
413
|
-
stdio: "inherit",
|
|
414
|
-
env: process.env,
|
|
415
|
-
windowsHide: true,
|
|
416
|
-
},
|
|
417
|
-
);
|
|
418
|
-
if (result.error) {
|
|
419
|
-
process.stderr.write(`${result.error.message}\n`);
|
|
420
|
-
return 1;
|
|
421
|
-
}
|
|
422
|
-
return result.status ?? 1;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
function ensureExecutable(binary: string): void {
|
|
426
|
-
if (process.platform === "win32") {
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
try {
|
|
430
|
-
fs.accessSync(binary, fs.constants.X_OK);
|
|
431
|
-
return;
|
|
432
|
-
} catch {
|
|
433
|
-
try {
|
|
434
|
-
const mode = fs.statSync(binary).mode & 0o777;
|
|
435
|
-
fs.chmodSync(binary, mode | 0o755);
|
|
436
|
-
} catch {
|
|
437
|
-
/* keep the original spawn error path */
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
390
|
function parseProjectArgs(argv: readonly string[]) {
|
|
443
391
|
// `prepare` and `clean` are project-shaped commands. They share the same
|
|
444
392
|
// schema as the build lane; the engine forwards unknown flags as well as
|
|
@@ -461,6 +409,12 @@ function parseBuildArgs(argv: readonly string[], checkOnly: boolean) {
|
|
|
461
409
|
const result = parseFlags({
|
|
462
410
|
argv,
|
|
463
411
|
errorPrefix: "ttsc:",
|
|
412
|
+
// A bare token is a single-file input only when it carries a TypeScript
|
|
413
|
+
// source extension; any other bare token is the space-separated value of a
|
|
414
|
+
// preceding forwarded flag (e.g. the `es2020` in `--target es2020`). The
|
|
415
|
+
// parser routes those values into `passthrough` in place, so the forwarded
|
|
416
|
+
// flag/value pairs reach tsgo in their original order.
|
|
417
|
+
isPositional: looksLikeInputFile,
|
|
464
418
|
subcommand: "build",
|
|
465
419
|
});
|
|
466
420
|
// Defaults: pinned by the previous hand-parser. `quiet` defaults true,
|
|
@@ -476,15 +430,13 @@ function parseBuildArgs(argv: readonly string[], checkOnly: boolean) {
|
|
|
476
430
|
else if (explicitNoEmit === true) emit = false;
|
|
477
431
|
if (emit === undefined && checkOnly) emit = false;
|
|
478
432
|
|
|
479
|
-
|
|
480
|
-
//
|
|
481
|
-
//
|
|
482
|
-
//
|
|
483
|
-
//
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
);
|
|
487
|
-
const passthrough = [...result.passthrough, ...trailingValues];
|
|
433
|
+
// `isPositional: looksLikeInputFile` guarantees every `result.positional`
|
|
434
|
+
// token is a TypeScript input file; forwarded flag values already live in
|
|
435
|
+
// `result.passthrough` in their original order, so no reconstruction is
|
|
436
|
+
// needed here (the previous `[...passthrough, ...trailingValues]` concat
|
|
437
|
+
// reordered every flag ahead of every value).
|
|
438
|
+
const files = [...result.positional];
|
|
439
|
+
const passthrough = [...result.passthrough];
|
|
488
440
|
|
|
489
441
|
return {
|
|
490
442
|
binary: getString(result, "--binary"),
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
loadProjectPlugins,
|
|
12
12
|
} from "../../plugin/internal/loadProjectPlugins";
|
|
13
13
|
import type { ITtscLoadedNativePlugin } from "../../structures/internal/ITtscLoadedNativePlugin";
|
|
14
|
+
import type { ITtscProjectIdentity } from "../../structures/internal/ITtscProjectIdentity";
|
|
14
15
|
import { resolveTtscserverBinary } from "./resolveTtscserverBinary";
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -107,9 +108,11 @@ function resolveTtscserverEnv(argv: readonly string[]): NodeJS.ProcessEnv {
|
|
|
107
108
|
if (lspPlugins.length > 0) {
|
|
108
109
|
env.TTSC_LSP_PLUGINS_JSON = JSON.stringify({
|
|
109
110
|
plugins: serializeNativePlugins(context.nativePlugins),
|
|
111
|
+
projectContext: context.projectContext,
|
|
110
112
|
lspPlugins: lspPlugins.map((plugin) => ({
|
|
111
113
|
binary: plugin.binary,
|
|
112
114
|
name: plugin.name,
|
|
115
|
+
projectContextArgs: plugin.capabilities?.projectContextArgs === true,
|
|
113
116
|
stage: plugin.stage,
|
|
114
117
|
})),
|
|
115
118
|
});
|
|
@@ -119,10 +122,16 @@ function resolveTtscserverEnv(argv: readonly string[]): NodeJS.ProcessEnv {
|
|
|
119
122
|
|
|
120
123
|
function resolveLspExecutionContext(argv: readonly string[]): {
|
|
121
124
|
nativePlugins: readonly ITtscLoadedNativePlugin[];
|
|
125
|
+
projectContext?: ITtscProjectIdentity;
|
|
122
126
|
tsgoBinary: string;
|
|
123
127
|
} {
|
|
124
128
|
const cwd = path.resolve(optionValue(argv, "--cwd") ?? process.cwd());
|
|
125
129
|
const tsconfig = optionValue(argv, "--tsconfig");
|
|
130
|
+
const pluginConfigOrigin =
|
|
131
|
+
process.env.TTSC_PLUGIN_CONFIG_DIR === undefined ||
|
|
132
|
+
process.env.TTSC_PLUGIN_CONFIG_DIR === ""
|
|
133
|
+
? undefined
|
|
134
|
+
: path.resolve(cwd, process.env.TTSC_PLUGIN_CONFIG_DIR);
|
|
126
135
|
let project: ReturnType<typeof readProjectConfig>;
|
|
127
136
|
try {
|
|
128
137
|
project = readProjectConfig({ cwd, tsconfig });
|
|
@@ -149,12 +158,17 @@ function resolveLspExecutionContext(argv: readonly string[]): {
|
|
|
149
158
|
? loadProjectPlugins({
|
|
150
159
|
binary: resolveBinary() ?? "",
|
|
151
160
|
cwd,
|
|
161
|
+
pluginConfigDir: pluginConfigOrigin,
|
|
152
162
|
projectRoot: project.root,
|
|
153
163
|
tsconfig: project.path,
|
|
154
164
|
})
|
|
155
165
|
: { nativePlugins: [] };
|
|
156
166
|
return {
|
|
157
167
|
nativePlugins: loaded.nativePlugins,
|
|
168
|
+
projectContext: {
|
|
169
|
+
...project.identity,
|
|
170
|
+
...(pluginConfigOrigin === undefined ? {} : { pluginConfigOrigin }),
|
|
171
|
+
},
|
|
158
172
|
tsgoBinary: tsgo.binary,
|
|
159
173
|
};
|
|
160
174
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { getCompilerVersionText } from "./getCompilerVersionText";
|
|
13
13
|
import { prepareExecution } from "./prepareExecution";
|
|
14
14
|
import { resolveCacheDir } from "./resolveCacheDir";
|
|
15
|
+
import { checkNodeRuntimeSupport } from "./runtimeHooks";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* CLI entry point for `ttsx`. Type-checks the owning project via tsgo, emits
|
|
@@ -45,6 +46,17 @@ function run(argv: readonly string[]): number {
|
|
|
45
46
|
return 0;
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
// Refuse an unsupported Node.js before type-checking and spawning the child:
|
|
50
|
+
// the child inherits this process's Node version, so an early diagnostic here
|
|
51
|
+
// pre-empts both the Node 18 `--disable-warning` rejection and the Node 20
|
|
52
|
+
// missing-`registerHooks` TypeError with one actionable message. `--help` and
|
|
53
|
+
// `--version` are handled above so they still print on any Node.
|
|
54
|
+
const nodeSupport = checkNodeRuntimeSupport(process.versions.node);
|
|
55
|
+
if (nodeSupport !== null) {
|
|
56
|
+
process.stderr.write(`ttsx: ${nodeSupport}\n`);
|
|
57
|
+
return 2;
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
const cwd = path.resolve(parsed.cwd ?? process.cwd());
|
|
49
61
|
const entry = path.resolve(cwd, parsed.entry);
|
|
50
62
|
if (!fs.existsSync(entry)) {
|
|
@@ -109,6 +121,14 @@ function parseCLI(argv: readonly string[]) {
|
|
|
109
121
|
errorPrefix: "ttsx:",
|
|
110
122
|
forwardAfterFirstPositional: true,
|
|
111
123
|
honorDoubleDashSeparator: true,
|
|
124
|
+
// Only a TypeScript-extensioned bare token is the entry; every other bare
|
|
125
|
+
// token before it (e.g. the `es2020` in `--target es2020 entry.ts`) is a
|
|
126
|
+
// forwarded flag value. Classifying values via the predicate keeps them in
|
|
127
|
+
// `passthrough` in order AND stops a pre-entry value from being mistaken for
|
|
128
|
+
// the first positional sentinel — which previously flipped the parser into
|
|
129
|
+
// tail mode and pushed the real entry into `tail`, failing with
|
|
130
|
+
// "entry file is required".
|
|
131
|
+
isPositional: looksLikeEntryFile,
|
|
112
132
|
subcommand: "ttsx",
|
|
113
133
|
});
|
|
114
134
|
|
|
@@ -116,18 +136,13 @@ function parseCLI(argv: readonly string[]) {
|
|
|
116
136
|
if (entry === undefined) {
|
|
117
137
|
throw new Error("ttsx: entry file is required");
|
|
118
138
|
}
|
|
119
|
-
// With `forwardAfterFirstPositional: true`
|
|
120
|
-
// `result.positional` as just the
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
// --input src/input`
|
|
125
|
-
//
|
|
126
|
-
// that the parser stored positionally; forward those to tsgo with the
|
|
127
|
-
// rest of `passthrough`.
|
|
128
|
-
const preEntryValues: string[] = result.positional.filter(
|
|
129
|
-
(token) => token !== entry && !looksLikeEntryFile(token),
|
|
130
|
-
);
|
|
139
|
+
// With `forwardAfterFirstPositional: true` and `isPositional:
|
|
140
|
+
// looksLikeEntryFile`, the parser reports `result.positional` as just the
|
|
141
|
+
// entry, `result.passthrough` as the tsgo-forwarded flags (and their
|
|
142
|
+
// in-order space values) arriving BEFORE the entry, and `result.tail` as
|
|
143
|
+
// every token AFTER the entry — the user program's argv (e.g. the `generate
|
|
144
|
+
// --input src/input` tail of `ttsx typia.ts generate --input src/input`),
|
|
145
|
+
// which MUST NOT reach tsgo.
|
|
131
146
|
const postEntryArgs: string[] = [...result.tail];
|
|
132
147
|
|
|
133
148
|
const preload: string[] = [];
|
|
@@ -170,7 +185,7 @@ function parseCLI(argv: readonly string[]) {
|
|
|
170
185
|
preload,
|
|
171
186
|
project: getString(result, "--tsconfig"),
|
|
172
187
|
singleThreaded: getBoolean(result, "--singleThreaded") === true,
|
|
173
|
-
tsgoFlags: [...result.passthrough
|
|
188
|
+
tsgoFlags: [...result.passthrough],
|
|
174
189
|
};
|
|
175
190
|
}
|
|
176
191
|
|