ttsc 0.11.0 → 0.12.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 +25 -6
- package/cmd/ttsc/api_compile.go +101 -106
- package/cmd/ttsc/api_compile_branches_test.go +81 -0
- package/cmd/ttsc/api_transform.go +49 -54
- package/cmd/ttsc/api_transform_branches_test.go +41 -0
- package/cmd/ttsc/build.go +108 -109
- package/cmd/ttsc/build_branches_test.go +130 -0
- package/cmd/ttsc/helpers_test.go +47 -0
- package/cmd/ttsc/main.go +104 -103
- package/cmd/ttsc/main_alias_branches_test.go +29 -0
- package/cmd/ttscserver/main.go +104 -96
- package/cmd/ttscserver/run_lsp_prefers_tsgo_flag_test.go +42 -0
- package/cmd/ttscserver/run_lsp_reports_server_error_test.go +23 -25
- package/cmd/ttscserver/run_lsp_uses_tsgo_environment_test.go +44 -0
- package/cmd/utility-host/main.go +42 -0
- package/driver/lsp.go +60 -0
- package/driver/plugins.go +122 -0
- package/driver/program.go +346 -356
- package/driver/rewrite.go +336 -339
- package/{driver → internal/lspserver}/lsp_envelope.go +70 -64
- package/{driver → internal/lspserver}/lsp_frame.go +62 -62
- package/{driver → internal/lspserver}/lsp_plugin.go +58 -58
- package/internal/lspserver/lsp_proxy.go +391 -0
- package/internal/lspserver/lsp_server.go +231 -0
- package/lib/TtscCompiler.d.ts +3 -3
- package/lib/TtscCompiler.js +20 -6
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/compiler/internal/resolveTsgo.d.ts +1 -0
- package/lib/compiler/internal/resolveTsgo.js +15 -4
- package/lib/compiler/internal/resolveTsgo.js.map +1 -1
- package/lib/compiler/internal/runBuild.js +12 -4
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +12 -33
- package/lib/compiler/internal/sharedHostHelpers.js +27 -70
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +12 -5
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +9 -4
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtscserver.d.ts +1 -0
- package/lib/launcher/internal/runTtscserver.js +38 -1
- package/lib/launcher/internal/runTtscserver.js.map +1 -1
- package/lib/plugin/internal/buildSourcePlugin.d.ts +3 -0
- package/lib/plugin/internal/buildSourcePlugin.js +444 -41
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.js +153 -34
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerContext.d.ts +2 -1
- package/lib/structures/ITtscPlugin.d.ts +8 -13
- package/lib/structures/ITtscPluginFactoryContext.d.ts +4 -5
- package/lib/structures/ITtscProjectPluginConfig.d.ts +2 -2
- package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +4 -2
- package/package.json +8 -8
- package/shim/lsp/shim.go +11 -17
- package/src/TtscCompiler.ts +20 -7
- package/src/compiler/internal/resolveTsgo.ts +18 -5
- package/src/compiler/internal/runBuild.ts +17 -4
- package/src/compiler/internal/sharedHostHelpers.ts +34 -67
- package/src/compiler/internal/transformProjectInMemory.ts +18 -5
- package/src/index.ts +0 -1
- package/src/launcher/internal/runTtsc.ts +9 -4
- package/src/launcher/internal/runTtscserver.ts +43 -1
- package/src/plugin/internal/buildSourcePlugin.ts +475 -41
- package/src/plugin/internal/loadProjectPlugins.ts +199 -39
- package/src/structures/ITtscCompilerContext.ts +2 -1
- package/src/structures/ITtscPlugin.ts +9 -13
- package/src/structures/ITtscPluginFactoryContext.ts +4 -5
- package/src/structures/ITtscProjectPluginConfig.ts +2 -2
- package/src/structures/internal/ITtscLoadedNativePlugin.ts +4 -2
- package/utility/host.go +267 -1296
- package/driver/lsp_proxy.go +0 -394
- package/driver/lsp_server.go +0 -197
- package/lib/defineTtscPlugin.d.ts +0 -18
- package/lib/defineTtscPlugin.js +0 -7
- package/lib/defineTtscPlugin.js.map +0 -1
- package/src/defineTtscPlugin.ts +0 -26
package/shim/lsp/shim.go
CHANGED
|
@@ -1,34 +1,28 @@
|
|
|
1
1
|
// gen_shims:hand-maintained
|
|
2
2
|
//
|
|
3
3
|
// Minimal shim of tsgo's internal/lsp package. Hand-written instead of
|
|
4
|
-
// generated so the surface stays narrow
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// the first line tells gen_shims to skip this file.
|
|
4
|
+
// generated so the surface stays narrow for custom in-process host
|
|
5
|
+
// experiments. The shipped ttscserver wraps `tsgo --lsp --stdio` as an
|
|
6
|
+
// external process and does not import this package. The marker on the
|
|
7
|
+
// first line tells gen_shims to skip this file.
|
|
9
8
|
package lsp
|
|
10
9
|
|
|
11
10
|
import (
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"io"
|
|
12
|
+
_ "unsafe"
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
innerlsp "github.com/microsoft/typescript-go/internal/lsp"
|
|
16
15
|
)
|
|
17
16
|
|
|
18
|
-
// Server is the opaque LSP server type from tsgo.
|
|
19
|
-
// its internals; it only calls Run and (via wrapped Writer) observes the
|
|
20
|
-
// traffic the server emits.
|
|
17
|
+
// Server is the opaque LSP server type from tsgo.
|
|
21
18
|
type Server = innerlsp.Server
|
|
22
19
|
|
|
23
20
|
// ServerOptions mirrors the upstream construction parameters. Fields with
|
|
24
|
-
// internal-package types (e.g. ParseCache *project.ParseCache)
|
|
25
|
-
// unset by
|
|
26
|
-
// optional pointer the upstream constructor accepts as nil.
|
|
21
|
+
// internal-package types (e.g. ParseCache *project.ParseCache) can be left
|
|
22
|
+
// unset by callers when upstream accepts nil.
|
|
27
23
|
type ServerOptions = innerlsp.ServerOptions
|
|
28
24
|
|
|
29
|
-
// Reader / Writer carry framed lsproto.Message values.
|
|
30
|
-
// the server through io.Pipe shims of these so it can splice its own
|
|
31
|
-
// JSON-RPC traffic into the same stream the editor speaks.
|
|
25
|
+
// Reader / Writer carry framed lsproto.Message values.
|
|
32
26
|
type Reader = innerlsp.Reader
|
|
33
27
|
type Writer = innerlsp.Writer
|
|
34
28
|
|
package/src/TtscCompiler.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { compileProjectInMemory } from "./compiler/internal/compileProjectInMemo
|
|
|
5
5
|
import { resolveProjectConfig } from "./compiler/internal/project/resolveProjectConfig";
|
|
6
6
|
import { resolveBinary } from "./compiler/internal/resolveBinary";
|
|
7
7
|
import { transformProjectInMemory } from "./compiler/internal/transformProjectInMemory";
|
|
8
|
+
import { defaultPluginCacheCleanTargets } from "./plugin/internal/buildSourcePlugin";
|
|
8
9
|
import { loadProjectPlugins } from "./plugin/internal/loadProjectPlugins";
|
|
9
10
|
import type { ITtscCompilerContext } from "./structures/ITtscCompilerContext";
|
|
10
11
|
import type { ITtscCompilerDiagnostic } from "./structures/ITtscCompilerDiagnostic";
|
|
@@ -75,9 +76,9 @@ export class TtscCompiler {
|
|
|
75
76
|
* Remove compiled cache artifacts for this compiler instance.
|
|
76
77
|
*
|
|
77
78
|
* When the constructor received `cacheDir`, this method removes exactly that
|
|
78
|
-
* directory.
|
|
79
|
-
*
|
|
80
|
-
*
|
|
79
|
+
* directory. When `TTSC_CACHE_DIR` is active, it removes that override's
|
|
80
|
+
* plugin cache plus legacy project-local caches. Otherwise it removes the
|
|
81
|
+
* default global plugin cache plus legacy project-local caches.
|
|
81
82
|
*
|
|
82
83
|
* The cache target comes from the constructor context. Create another
|
|
83
84
|
* `TtscCompiler` instance to clean another project or another cache root.
|
|
@@ -90,13 +91,25 @@ export class TtscCompiler {
|
|
|
90
91
|
return removeExistingDirectories([cacheDir]);
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
const envCacheDir =
|
|
94
|
-
this.context.env?.TTSC_CACHE_DIR ?? process.env.TTSC_CACHE_DIR;
|
|
95
94
|
const projectRoot = this.resolveCleanProjectRoot();
|
|
96
|
-
|
|
97
|
-
...(envCacheDir ? [path.resolve(envCacheDir, "plugins")] : []),
|
|
95
|
+
const legacyTargets = [
|
|
98
96
|
path.join(projectRoot, "node_modules", ".ttsc"),
|
|
99
97
|
path.join(projectRoot, ".ttsc"),
|
|
98
|
+
];
|
|
99
|
+
if (this.context.env?.TTSC_CACHE_DIR) {
|
|
100
|
+
return removeExistingDirectories([
|
|
101
|
+
path.resolve(projectRoot, this.context.env.TTSC_CACHE_DIR, "plugins"),
|
|
102
|
+
...legacyTargets,
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
if (process.env.TTSC_CACHE_DIR) {
|
|
106
|
+
return removeExistingDirectories([
|
|
107
|
+
path.resolve(process.env.TTSC_CACHE_DIR, "plugins"),
|
|
108
|
+
...legacyTargets,
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
return removeExistingDirectories([
|
|
112
|
+
...defaultPluginCacheCleanTargets(projectRoot),
|
|
100
113
|
]);
|
|
101
114
|
}
|
|
102
115
|
|
|
@@ -8,6 +8,7 @@ export function resolveTsgo(
|
|
|
8
8
|
binary?: string;
|
|
9
9
|
cwd?: string;
|
|
10
10
|
env?: NodeJS.ProcessEnv;
|
|
11
|
+
resolveFrom?: string;
|
|
11
12
|
} = {},
|
|
12
13
|
) {
|
|
13
14
|
const env = opts.env ?? process.env;
|
|
@@ -28,11 +29,13 @@ export function resolveTsgo(
|
|
|
28
29
|
|
|
29
30
|
const cwd = path.resolve(opts.cwd ?? process.cwd());
|
|
30
31
|
let packageJson: string;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
packageJson =
|
|
33
|
+
resolveNativePreviewPackageJson(path.join(cwd, "package.json")) ??
|
|
34
|
+
(opts.resolveFrom
|
|
35
|
+
? resolveNativePreviewPackageJson(opts.resolveFrom)
|
|
36
|
+
: undefined) ??
|
|
37
|
+
"";
|
|
38
|
+
if (!packageJson) {
|
|
36
39
|
throw new Error(
|
|
37
40
|
[
|
|
38
41
|
"ttsc: @typescript/native-preview is required.",
|
|
@@ -81,6 +84,16 @@ export function resolveTsgo(
|
|
|
81
84
|
};
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
function resolveNativePreviewPackageJson(from: string): string | undefined {
|
|
88
|
+
try {
|
|
89
|
+
return createRequire(from).resolve(
|
|
90
|
+
"@typescript/native-preview/package.json",
|
|
91
|
+
);
|
|
92
|
+
} catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
84
97
|
function readPackageJson(file: string): Record<string, unknown> {
|
|
85
98
|
return JSON.parse(fs.readFileSync(file, "utf8")) as Record<string, unknown>;
|
|
86
99
|
}
|
|
@@ -12,7 +12,11 @@ import type { TtscCommonOptions } from "../../structures/internal/TtscCommonOpti
|
|
|
12
12
|
import { resolveProjectConfig } from "./project/resolveProjectConfig";
|
|
13
13
|
import { resolveBinary } from "./resolveBinary";
|
|
14
14
|
import { resolveTsgo } from "./resolveTsgo";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
assertSharedHostCompatibility,
|
|
17
|
+
linkedTransformPlugins,
|
|
18
|
+
selectSharedHostPlugin,
|
|
19
|
+
} from "./sharedHostHelpers";
|
|
16
20
|
|
|
17
21
|
/** Merge spawn env without clobbering unrelated vars. */
|
|
18
22
|
function mergeEnv(extra?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
@@ -27,14 +31,22 @@ function mergeEnv(extra?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
|
27
31
|
function nativePluginEnv(
|
|
28
32
|
extra: NodeJS.ProcessEnv | undefined,
|
|
29
33
|
execution: ReturnType<typeof resolveExecutionContext>,
|
|
34
|
+
plugin?: ITtscLoadedNativePlugin,
|
|
30
35
|
): NodeJS.ProcessEnv {
|
|
31
|
-
|
|
36
|
+
const env = mergeEnv({
|
|
32
37
|
TTSC_TSGO_BINARY: process.env.TTSC_TSGO_BINARY ?? execution.tsgo.binary,
|
|
33
38
|
TTSC_TTSX_BINARY:
|
|
34
39
|
process.env.TTSC_TTSX_BINARY ??
|
|
35
40
|
path.join(__dirname, "..", "..", "launcher", "ttsx.js"),
|
|
36
41
|
...extra,
|
|
37
42
|
});
|
|
43
|
+
if (plugin?.stage === "transform") {
|
|
44
|
+
const linked = linkedTransformPlugins(execution.nativePlugins);
|
|
45
|
+
if (linked.length !== 0) {
|
|
46
|
+
env.TTSC_LINKED_PLUGINS_JSON = serializeNativePlugins(linked);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return env;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
function spawnBinary(
|
|
@@ -192,8 +204,9 @@ function buildWithNativeCompilerPlugins(
|
|
|
192
204
|
execution: ReturnType<typeof resolveExecutionContext>,
|
|
193
205
|
plugins: readonly ITtscLoadedNativePlugin[],
|
|
194
206
|
): TtscBuildResult {
|
|
207
|
+
const host = selectSharedHostPlugin(plugins);
|
|
195
208
|
return runNativePluginCommand(
|
|
196
|
-
|
|
209
|
+
host,
|
|
197
210
|
createNativeBuildArgs(execution, options, plugins),
|
|
198
211
|
options,
|
|
199
212
|
execution,
|
|
@@ -405,7 +418,7 @@ function runNativePluginCommand(
|
|
|
405
418
|
): TtscBuildResult {
|
|
406
419
|
const res = spawnBinary(plugin.binary, args, {
|
|
407
420
|
cwd: execution.projectRoot,
|
|
408
|
-
env: nativePluginEnv(options.env, execution),
|
|
421
|
+
env: nativePluginEnv(options.env, execution, plugin),
|
|
409
422
|
encoding: "utf8",
|
|
410
423
|
});
|
|
411
424
|
if (res.error) {
|
|
@@ -1,79 +1,19 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
1
|
import type { ITtscLoadedNativePlugin } from "../../structures/internal/ITtscLoadedNativePlugin";
|
|
5
2
|
|
|
6
3
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* binaries differ. Each entry must be both name-pinned and manifest-pinned: the
|
|
10
|
-
* plugin must declare itself with one of these names AND its source path must
|
|
11
|
-
* resolve to a `package.json` whose `name` field matches.
|
|
12
|
-
*
|
|
13
|
-
* This whitelist exists because `@ttsc/banner`, `@ttsc/paths`, and
|
|
14
|
-
* `@ttsc/strip` are AST-only mutators that operate on the same
|
|
15
|
-
* `*shimast.SourceFile` graph and do not own emit. They are composed through
|
|
16
|
-
* `packages/ttsc/utility/host.go`, so any one of their binaries can host the
|
|
17
|
-
* shared run. Third-party plugins cannot participate in this fast path; they
|
|
18
|
-
* must opt into composition through the explicit `ITtscPlugin.composes` field.
|
|
19
|
-
*/
|
|
20
|
-
export const FIRST_PARTY_UTILITY_PLUGIN_NAMES: ReadonlySet<string> = new Set([
|
|
21
|
-
"@ttsc/banner",
|
|
22
|
-
"@ttsc/paths",
|
|
23
|
-
"@ttsc/strip",
|
|
24
|
-
]);
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Reports whether the given plugin is a first-party utility transform plugin
|
|
28
|
-
* that may participate in the shared compiler host alongside other first-party
|
|
29
|
-
* utility transforms. Returns `false` for `check`-stage plugins, for unknown
|
|
30
|
-
* names, and for plugins whose `source` does not resolve to a matching
|
|
31
|
-
* `package.json`.
|
|
4
|
+
* Reports whether the given transform source is linked into another compiler
|
|
5
|
+
* host instead of owning the process itself.
|
|
32
6
|
*/
|
|
33
|
-
export function
|
|
7
|
+
export function isLinkedTransform(
|
|
34
8
|
plugin: ITtscLoadedNativePlugin,
|
|
35
9
|
): boolean {
|
|
36
|
-
|
|
37
|
-
if (!FIRST_PARTY_UTILITY_PLUGIN_NAMES.has(plugin.name)) return false;
|
|
38
|
-
const manifest = readNearestPackageManifest(plugin.source);
|
|
39
|
-
return manifest?.name === plugin.name;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Walks upward from `source` (a directory or file path) up to four parent
|
|
44
|
-
* levels searching for the nearest `package.json`. Returns the parsed manifest
|
|
45
|
-
* object on success, or `undefined` when no manifest is found or parsing fails.
|
|
46
|
-
* The depth bound mirrors the pre-existing inline implementations in
|
|
47
|
-
* `runBuild.ts` and `transformProjectInMemory.ts`.
|
|
48
|
-
*/
|
|
49
|
-
export function readNearestPackageManifest(
|
|
50
|
-
source: string,
|
|
51
|
-
): { name?: unknown } | undefined {
|
|
52
|
-
try {
|
|
53
|
-
let current = fs.statSync(source).isDirectory()
|
|
54
|
-
? source
|
|
55
|
-
: path.dirname(source);
|
|
56
|
-
for (let i = 0; i < 4; i += 1) {
|
|
57
|
-
const manifest = path.join(current, "package.json");
|
|
58
|
-
if (fs.existsSync(manifest)) {
|
|
59
|
-
return JSON.parse(fs.readFileSync(manifest, "utf8")) as {
|
|
60
|
-
name?: unknown;
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
const parent = path.dirname(current);
|
|
64
|
-
if (parent === current) break;
|
|
65
|
-
current = parent;
|
|
66
|
-
}
|
|
67
|
-
} catch {
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
70
|
-
return undefined;
|
|
10
|
+
return plugin.stage === "transform" && plugin.kind === "linked";
|
|
71
11
|
}
|
|
72
12
|
|
|
73
13
|
/**
|
|
74
14
|
* Verifies that all transform plugins in `plugins` either resolve to the same
|
|
75
|
-
* native binary (the common case)
|
|
76
|
-
*
|
|
15
|
+
* native binary (the common case) after linked sources are removed from the
|
|
16
|
+
* compiler-owner set.
|
|
77
17
|
*
|
|
78
18
|
* Two callers exist with subtly different error wording: the build path
|
|
79
19
|
* (`runBuild.ts`) reports "multiple compiler native backends cannot share one
|
|
@@ -90,7 +30,14 @@ export function assertSharedHostCompatibility(
|
|
|
90
30
|
if (binaries.length <= 1) {
|
|
91
31
|
return;
|
|
92
32
|
}
|
|
93
|
-
|
|
33
|
+
const ownerBinaries = [
|
|
34
|
+
...new Set(
|
|
35
|
+
plugins
|
|
36
|
+
.filter((plugin) => !isLinkedTransform(plugin))
|
|
37
|
+
.map((plugin) => plugin.binary),
|
|
38
|
+
),
|
|
39
|
+
];
|
|
40
|
+
if (ownerBinaries.length <= 1) {
|
|
94
41
|
return;
|
|
95
42
|
}
|
|
96
43
|
const phrase =
|
|
@@ -103,3 +50,23 @@ export function assertSharedHostCompatibility(
|
|
|
103
50
|
"; compose transform libraries through one aggregate native host",
|
|
104
51
|
);
|
|
105
52
|
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Picks the native binary that must own the compiler pass. Linked transform
|
|
56
|
+
* sources ride inside a host that uses driver.LoadProgram, so an executable
|
|
57
|
+
* transform wins when one is present.
|
|
58
|
+
*/
|
|
59
|
+
export function selectSharedHostPlugin(
|
|
60
|
+
plugins: readonly ITtscLoadedNativePlugin[],
|
|
61
|
+
): ITtscLoadedNativePlugin {
|
|
62
|
+
return (
|
|
63
|
+
plugins.find((plugin) => !isLinkedTransform(plugin)) ??
|
|
64
|
+
plugins[0]!
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function linkedTransformPlugins(
|
|
69
|
+
plugins: readonly ITtscLoadedNativePlugin[],
|
|
70
|
+
): ITtscLoadedNativePlugin[] {
|
|
71
|
+
return plugins.filter(isLinkedTransform);
|
|
72
|
+
}
|
|
@@ -16,7 +16,11 @@ import { readProjectConfig } from "./project/readProjectConfig";
|
|
|
16
16
|
import { resolveBinary } from "./resolveBinary";
|
|
17
17
|
import { resolveTsgo } from "./resolveTsgo";
|
|
18
18
|
import { appendBuildOutput, normalizeBuildOutput } from "./runBuild";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
assertSharedHostCompatibility,
|
|
21
|
+
linkedTransformPlugins,
|
|
22
|
+
selectSharedHostPlugin,
|
|
23
|
+
} from "./sharedHostHelpers";
|
|
20
24
|
|
|
21
25
|
/** Transform a project and capture TypeScript source output in memory. */
|
|
22
26
|
export function transformProjectInMemory(options: ITtscCompilerContext): {
|
|
@@ -126,13 +130,13 @@ function transformProjectWithPlugins(
|
|
|
126
130
|
}
|
|
127
131
|
assertSharedHostCompatibility(transformers, "source-to-source");
|
|
128
132
|
|
|
129
|
-
const plugin = transformers
|
|
133
|
+
const plugin = selectSharedHostPlugin(transformers);
|
|
130
134
|
const res = spawnNative(
|
|
131
135
|
plugin.binary,
|
|
132
136
|
createNativeTransformArgs(project, transformers),
|
|
133
137
|
{
|
|
134
138
|
cwd: project.root,
|
|
135
|
-
env: nativePluginEnv(options, project.root),
|
|
139
|
+
env: nativePluginEnv(options, project.root, loaded.nativePlugins, plugin),
|
|
136
140
|
},
|
|
137
141
|
);
|
|
138
142
|
if (res.error) {
|
|
@@ -174,7 +178,7 @@ function runNativeChecks(
|
|
|
174
178
|
createNativeCheckArgs(project, nativePlugins),
|
|
175
179
|
{
|
|
176
180
|
cwd: project.root,
|
|
177
|
-
env: nativePluginEnv(options, project.root),
|
|
181
|
+
env: nativePluginEnv(options, project.root, nativePlugins, plugin),
|
|
178
182
|
},
|
|
179
183
|
);
|
|
180
184
|
if (res.error) {
|
|
@@ -239,9 +243,11 @@ function serializeNativePlugins(
|
|
|
239
243
|
function nativePluginEnv(
|
|
240
244
|
options: ITtscCompilerContext,
|
|
241
245
|
projectRoot: string,
|
|
246
|
+
nativePlugins?: readonly ITtscLoadedNativePlugin[],
|
|
247
|
+
plugin?: ITtscLoadedNativePlugin,
|
|
242
248
|
): NodeJS.ProcessEnv {
|
|
243
249
|
const tsgo = resolveTsgo({ ...options, cwd: projectRoot });
|
|
244
|
-
|
|
250
|
+
const env: NodeJS.ProcessEnv = {
|
|
245
251
|
...process.env,
|
|
246
252
|
TTSC_NODE_BINARY: process.env.TTSC_NODE_BINARY ?? process.execPath,
|
|
247
253
|
TTSC_TSGO_BINARY: process.env.TTSC_TSGO_BINARY ?? tsgo.binary,
|
|
@@ -250,6 +256,13 @@ function nativePluginEnv(
|
|
|
250
256
|
path.join(__dirname, "..", "..", "launcher", "ttsx.js"),
|
|
251
257
|
...options.env,
|
|
252
258
|
};
|
|
259
|
+
if (plugin?.stage === "transform") {
|
|
260
|
+
const linked = linkedTransformPlugins(nativePlugins ?? []);
|
|
261
|
+
if (linked.length !== 0) {
|
|
262
|
+
env.TTSC_LINKED_PLUGINS_JSON = serializeNativePlugins(linked);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return env;
|
|
253
266
|
}
|
|
254
267
|
|
|
255
268
|
function spawnNative(
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { resolveProjectConfig } from "../../compiler/internal/project/resolvePro
|
|
|
7
7
|
import { resolveBinary } from "../../compiler/internal/resolveBinary";
|
|
8
8
|
import { runBuild } from "../../compiler/internal/runBuild";
|
|
9
9
|
import { runSingleFileEmit } from "../../compiler/internal/runSingleFileEmit";
|
|
10
|
+
import { defaultPluginCacheCleanTargets } from "../../plugin/internal/buildSourcePlugin";
|
|
10
11
|
import type { TtscBuildOptions } from "../../structures/internal/TtscBuildOptions";
|
|
11
12
|
import { getCompilerVersionText } from "./getCompilerVersionText";
|
|
12
13
|
|
|
@@ -161,13 +162,17 @@ function runClean(argv: readonly string[]): number {
|
|
|
161
162
|
const options = parseProjectArgs(argv);
|
|
162
163
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
163
164
|
const projectRoot = resolveCleanProjectRoot(cwd, options.tsconfig);
|
|
164
|
-
const
|
|
165
|
+
const legacyTargets = [
|
|
165
166
|
path.join(projectRoot, "node_modules", ".ttsc"),
|
|
166
167
|
path.join(projectRoot, ".ttsc"),
|
|
168
|
+
];
|
|
169
|
+
const targets = [
|
|
167
170
|
...(options.cacheDir ? [path.resolve(cwd, options.cacheDir)] : []),
|
|
168
171
|
...(process.env.TTSC_CACHE_DIR
|
|
169
|
-
? [path.resolve(process.env.TTSC_CACHE_DIR, "plugins")]
|
|
170
|
-
:
|
|
172
|
+
? [path.resolve(process.env.TTSC_CACHE_DIR, "plugins"), ...legacyTargets]
|
|
173
|
+
: options.cacheDir
|
|
174
|
+
? legacyTargets
|
|
175
|
+
: defaultPluginCacheCleanTargets(projectRoot)),
|
|
171
176
|
];
|
|
172
177
|
const removed: string[] = [];
|
|
173
178
|
for (const target of targets) {
|
|
@@ -436,7 +441,7 @@ function printHelp(): void {
|
|
|
436
441
|
" ttsc fix [options] Apply check-plugin lint + format edits, then run `ttsc check`.",
|
|
437
442
|
" ttsc format [options] Apply check-plugin format-class edits only (write-only, no type check).",
|
|
438
443
|
" ttsc prepare [options] Build configured source-plugin binaries into cache.",
|
|
439
|
-
" ttsc clean [options] Delete
|
|
444
|
+
" ttsc clean [options] Delete source-plugin cache directories.",
|
|
440
445
|
].join("\n"),
|
|
441
446
|
);
|
|
442
447
|
process.stdout.write("\n");
|
|
@@ -2,6 +2,7 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
|
|
5
|
+
import { resolveTsgo } from "../../compiler/internal/resolveTsgo";
|
|
5
6
|
import { resolveTtscserverBinary } from "./resolveTtscserverBinary";
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -11,6 +12,7 @@ import { resolveTtscserverBinary } from "./resolveTtscserverBinary";
|
|
|
11
12
|
* performs only:
|
|
12
13
|
*
|
|
13
14
|
* - Resolve the platform binary,
|
|
15
|
+
* - Resolve the project TypeScript-Go binary for the native wrapper,
|
|
14
16
|
* - Inject `--stdio` when the first arg is not a meta-command,
|
|
15
17
|
* - Delegate to the binary with inherited stdio so OS-level signals reach the
|
|
16
18
|
* child via the parent's process group.
|
|
@@ -31,9 +33,18 @@ export function runTtscserver(
|
|
|
31
33
|
ensureExecutable(binary);
|
|
32
34
|
|
|
33
35
|
const args = needsStdio(argv) ? ["--stdio", ...argv] : [...argv];
|
|
36
|
+
let env: NodeJS.ProcessEnv;
|
|
37
|
+
try {
|
|
38
|
+
env = resolveTtscserverEnv(args);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
process.stderr.write(
|
|
41
|
+
`ttscserver: ${stripTtscPrefix(formatError(error))}\n`,
|
|
42
|
+
);
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
34
45
|
const result = spawnSync(binary, args, {
|
|
35
46
|
stdio: "inherit",
|
|
36
|
-
env
|
|
47
|
+
env,
|
|
37
48
|
windowsHide: true,
|
|
38
49
|
});
|
|
39
50
|
if (result.error) {
|
|
@@ -55,6 +66,37 @@ export function runTtscserver(
|
|
|
55
66
|
return result.status ?? 1;
|
|
56
67
|
}
|
|
57
68
|
|
|
69
|
+
function resolveTtscserverEnv(argv: readonly string[]): NodeJS.ProcessEnv {
|
|
70
|
+
if (!argv.includes("--stdio")) {
|
|
71
|
+
return process.env;
|
|
72
|
+
}
|
|
73
|
+
if (process.env.TTSC_TSGO_BINARY || hasTsgoOption(argv)) {
|
|
74
|
+
return process.env;
|
|
75
|
+
}
|
|
76
|
+
const tsgo = resolveTsgo({
|
|
77
|
+
cwd: process.cwd(),
|
|
78
|
+
resolveFrom: __filename,
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
...process.env,
|
|
82
|
+
TTSC_TSGO_BINARY: tsgo.binary,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function hasTsgoOption(argv: readonly string[]): boolean {
|
|
87
|
+
return argv.some((arg) => arg === "--tsgo" || arg.startsWith("--tsgo="));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function formatError(error: unknown): string {
|
|
91
|
+
return error instanceof Error ? error.message : String(error);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function stripTtscPrefix(message: string): string {
|
|
95
|
+
return message.startsWith("ttsc: ")
|
|
96
|
+
? message.slice("ttsc: ".length)
|
|
97
|
+
: message;
|
|
98
|
+
}
|
|
99
|
+
|
|
58
100
|
/**
|
|
59
101
|
* `--stdio` is the only transport the native host accepts today. The launcher
|
|
60
102
|
* injects it only when the first argv token looks like a forwarded option;
|