ttsc 0.20.1 → 0.22.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.
Files changed (95) hide show
  1. package/cmd/ttscserver/main.go +79 -3
  2. package/cmd/ttscserver/run_lsp_uses_native_plugin_manifest_source_test.go +96 -16
  3. package/driver/lsp.go +4 -0
  4. package/internal/lspserver/lsp_document_diagnostics_omits_cached_project_when_current_result_has_none_test.go +48 -0
  5. package/internal/lspserver/lsp_executable_project_input_change_requests_launcher_restart_test.go +98 -0
  6. package/internal/lspserver/lsp_external_watched_change_retains_program_test.go +53 -0
  7. package/internal/lspserver/lsp_hints_refresh_scheduled_by_editor_events_test.go +9 -0
  8. package/internal/lspserver/lsp_native_plugin_source.go +171 -55
  9. package/internal/lspserver/lsp_native_resident.go +110 -9
  10. package/internal/lspserver/lsp_plugin.go +6 -0
  11. package/internal/lspserver/lsp_project_context_transport_identity_test.go +43 -0
  12. package/internal/lspserver/lsp_project_diagnostics.go +235 -0
  13. package/internal/lspserver/lsp_project_diagnostics_capability_is_independent_test.go +67 -0
  14. package/internal/lspserver/lsp_project_diagnostics_program_input_overlap_refreshes_all_producers_test.go +78 -0
  15. package/internal/lspserver/lsp_project_diagnostics_refresh_accumulates_owner_freshness_test.go +65 -0
  16. package/internal/lspserver/lsp_project_diagnostics_refresh_keeps_each_producer_last_good_test.go +90 -0
  17. package/internal/lspserver/lsp_project_diagnostics_refreshes_only_input_owners_test.go +62 -0
  18. package/internal/lspserver/lsp_project_diagnostics_resident_unsupported_falls_back_test.go +123 -0
  19. package/internal/lspserver/lsp_project_diagnostics_resume_preserves_generation_test.go +52 -0
  20. package/internal/lspserver/lsp_project_diagnostics_translates_relative_client_project_test.go +90 -0
  21. package/internal/lspserver/lsp_project_input_ownership_resolves_declared_spellings_test.go +95 -0
  22. package/internal/lspserver/lsp_project_input_registration.go +504 -0
  23. package/internal/lspserver/lsp_project_input_registration_rechecks_selection_baseline_test.go +71 -0
  24. package/internal/lspserver/lsp_project_input_registration_reconciles_rejected_pending_request_test.go +268 -0
  25. package/internal/lspserver/lsp_project_input_registration_shapes_patterns_test.go +94 -0
  26. package/internal/lspserver/lsp_project_input_watchers_anchor_missing_paths_test.go +48 -0
  27. package/internal/lspserver/lsp_project_inputs.go +944 -0
  28. package/internal/lspserver/lsp_project_inputs_match_missing_exact_and_glob_test.go +129 -0
  29. package/internal/lspserver/lsp_project_inputs_reject_invalid_and_foreign_snapshots_test.go +110 -0
  30. package/internal/lspserver/lsp_proxy.go +591 -28
  31. package/internal/lspserver/lsp_reload_directories_compare_immediate_topology_test.go +188 -0
  32. package/internal/lspserver/lsp_reload_file_fingerprint_preserves_raw_symlink_target_test.go +47 -0
  33. package/internal/lspserver/lsp_resident_falls_back_when_serve_unsupported_test.go +1 -1
  34. package/internal/lspserver/lsp_resident_invalidation_broadcasts_program_input_overlap_test.go +60 -0
  35. package/internal/lspserver/lsp_resident_invalidation_targets_project_input_owners_test.go +51 -0
  36. package/internal/lspserver/lsp_same_transport_entries_are_deduplicated_test.go +66 -0
  37. package/lib/compiler/internal/project/readProjectConfig.d.ts +5 -3
  38. package/lib/compiler/internal/project/readProjectConfig.js +46 -14
  39. package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
  40. package/lib/compiler/internal/residentCheckProcess.d.ts +46 -0
  41. package/lib/compiler/internal/residentCheckProcess.js +227 -0
  42. package/lib/compiler/internal/residentCheckProcess.js.map +1 -0
  43. package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +2 -1
  44. package/lib/compiler/internal/resolveEmittedJavaScript.js +35 -18
  45. package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
  46. package/lib/compiler/internal/runBuild.d.ts +64 -1
  47. package/lib/compiler/internal/runBuild.js +484 -7
  48. package/lib/compiler/internal/runBuild.js.map +1 -1
  49. package/lib/compiler/internal/runSingleFileEmit.js +1 -0
  50. package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
  51. package/lib/flags/parser.js +13 -17
  52. package/lib/flags/parser.js.map +1 -1
  53. package/lib/flags/schema.d.ts +10 -3
  54. package/lib/flags/schema.js +99 -0
  55. package/lib/flags/schema.js.map +1 -1
  56. package/lib/internal/projectInputPathIdentity.d.ts +23 -0
  57. package/lib/internal/projectInputPathIdentity.js +222 -0
  58. package/lib/internal/projectInputPathIdentity.js.map +1 -0
  59. package/lib/launcher/internal/runTtsc.d.ts +17 -0
  60. package/lib/launcher/internal/runTtsc.js +121 -88
  61. package/lib/launcher/internal/runTtsc.js.map +1 -1
  62. package/lib/launcher/internal/runTtscserver.d.ts +13 -1
  63. package/lib/launcher/internal/runTtscserver.js +415 -45
  64. package/lib/launcher/internal/runTtscserver.js.map +1 -1
  65. package/lib/launcher/internal/singleFileOutput.d.ts +16 -0
  66. package/lib/launcher/internal/singleFileOutput.js +103 -0
  67. package/lib/launcher/internal/singleFileOutput.js.map +1 -0
  68. package/lib/launcher/internal/watchTopology.d.ts +214 -2
  69. package/lib/launcher/internal/watchTopology.js +1560 -41
  70. package/lib/launcher/internal/watchTopology.js.map +1 -1
  71. package/lib/plugin/internal/loadProjectPlugins.d.ts +1 -0
  72. package/lib/plugin/internal/loadProjectPlugins.js +5 -0
  73. package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
  74. package/lib/structures/ITtscPluginCapabilities.d.ts +31 -0
  75. package/lib/structures/internal/ITtscProjectInputSnapshot.d.ts +29 -0
  76. package/lib/structures/internal/ITtscProjectInputSnapshot.js +3 -0
  77. package/lib/structures/internal/ITtscProjectInputSnapshot.js.map +1 -0
  78. package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +5 -0
  79. package/package.json +8 -8
  80. package/src/compiler/internal/project/readProjectConfig.ts +62 -8
  81. package/src/compiler/internal/residentCheckProcess.ts +279 -0
  82. package/src/compiler/internal/resolveEmittedJavaScript.ts +43 -21
  83. package/src/compiler/internal/runBuild.ts +728 -12
  84. package/src/compiler/internal/runSingleFileEmit.ts +1 -0
  85. package/src/flags/parser.ts +17 -17
  86. package/src/flags/schema.ts +111 -3
  87. package/src/internal/projectInputPathIdentity.ts +273 -0
  88. package/src/launcher/internal/runTtsc.ts +141 -117
  89. package/src/launcher/internal/runTtscserver.ts +561 -54
  90. package/src/launcher/internal/singleFileOutput.ts +133 -0
  91. package/src/launcher/internal/watchTopology.ts +2008 -59
  92. package/src/plugin/internal/loadProjectPlugins.ts +8 -0
  93. package/src/structures/ITtscPluginCapabilities.ts +34 -0
  94. package/src/structures/internal/ITtscProjectInputSnapshot.ts +29 -0
  95. package/src/structures/internal/TtscSingleFileEmitOptions.ts +5 -0
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveSingleFileOutput = resolveSingleFileOutput;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const readProjectConfig_1 = require("../../compiler/internal/project/readProjectConfig");
9
+ const schema_1 = require("../../flags/schema");
10
+ /**
11
+ * Resolves the only file that positional `ttsc <source>` can materialize in the
12
+ * user's tree.
13
+ *
14
+ * The compiler itself emits into a private temporary directory. The launcher
15
+ * then copies one transformed JavaScript file to this path, so project-mode
16
+ * declaration, map, build-info, outFile, and broad outDir products are not
17
+ * positional outputs.
18
+ */
19
+ function resolveSingleFileOutput(options) {
20
+ const project = readProjectSettings(options);
21
+ const extension = singleFileJavaScriptExtension(options.file, passthroughStringOption(options.passthrough, "--jsx") ?? project?.jsx);
22
+ const jsBasename = node_path_1.default.basename(options.file).replace(/\.(?:[cm]?tsx?|jsx)$/i, "") +
23
+ extension;
24
+ if (options.cliOutDir) {
25
+ const relative = node_path_1.default.relative(options.cwd, options.file);
26
+ const jsRelative = relative.slice(0, relative.length - node_path_1.default.extname(relative).length) +
27
+ extension;
28
+ return node_path_1.default.resolve(options.cwd, options.cliOutDir, jsRelative);
29
+ }
30
+ if (project?.outDir !== undefined) {
31
+ const fromRoot = node_path_1.default.relative(project.rootDir, options.file);
32
+ if (fromRoot !== "" && !isOutsideSingleFileLayout(fromRoot)) {
33
+ const jsRelative = fromRoot.slice(0, fromRoot.length - node_path_1.default.extname(fromRoot).length) +
34
+ extension;
35
+ return node_path_1.default.resolve(project.outDir, jsRelative);
36
+ }
37
+ return node_path_1.default.resolve(project.outDir, jsBasename);
38
+ }
39
+ return options.file.replace(/\.(?:[cm]?tsx?|jsx)$/i, extension);
40
+ }
41
+ function readProjectSettings(options) {
42
+ try {
43
+ const project = (0, readProjectConfig_1.readProjectConfig)({
44
+ cwd: options.cwd,
45
+ file: options.file,
46
+ tsconfig: options.tsconfig,
47
+ });
48
+ const outDir = project.compilerOptions.outDir;
49
+ const rawRoot = project.compilerOptions.rootDir;
50
+ const rootDir = typeof rawRoot === "string" && rawRoot.length !== 0
51
+ ? node_path_1.default.isAbsolute(rawRoot)
52
+ ? rawRoot
53
+ : node_path_1.default.resolve(project.root, rawRoot)
54
+ : project.root;
55
+ const rawJsx = project.compilerOptions.jsx;
56
+ return {
57
+ jsx: typeof rawJsx === "string" && rawJsx.length !== 0
58
+ ? rawJsx.toLowerCase()
59
+ : undefined,
60
+ outDir: typeof outDir === "string" && outDir.length !== 0 ? outDir : undefined,
61
+ rootDir,
62
+ };
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ function isOutsideSingleFileLayout(relative) {
69
+ return (relative === ".." ||
70
+ relative.startsWith(`..${node_path_1.default.sep}`) ||
71
+ node_path_1.default.isAbsolute(relative));
72
+ }
73
+ function singleFileJavaScriptExtension(file, jsx) {
74
+ switch (node_path_1.default.extname(file).toLowerCase()) {
75
+ case ".mts":
76
+ return ".mjs";
77
+ case ".cts":
78
+ return ".cjs";
79
+ case ".tsx":
80
+ case ".jsx":
81
+ return jsx === "preserve" ? ".jsx" : ".js";
82
+ default:
83
+ return ".js";
84
+ }
85
+ }
86
+ function passthroughStringOption(tokens, name) {
87
+ let value;
88
+ for (let index = 0; index < (tokens?.length ?? 0); index++) {
89
+ const token = tokens?.[index];
90
+ if (token === undefined ||
91
+ token.includes("=") ||
92
+ (0, schema_1.resolveFlagSpec)(token)?.name !== (0, schema_1.resolveFlagSpec)(name)?.name) {
93
+ continue;
94
+ }
95
+ const next = tokens?.[index + 1];
96
+ if (next !== undefined) {
97
+ value = next.toLowerCase();
98
+ index++;
99
+ }
100
+ }
101
+ return value;
102
+ }
103
+ //# sourceMappingURL=singleFileOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"singleFileOutput.js","sourceRoot":"","sources":["../../../src/launcher/internal/singleFileOutput.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,27 @@
1
+ import { type ProjectInputPathIdentityContext } from "../../internal/projectInputPathIdentity";
2
+ import type { ITtscProjectInputSnapshot } from "../../structures/internal/ITtscProjectInputSnapshot";
1
3
  import type { TtscBuildOptions } from "../../structures/internal/TtscBuildOptions";
2
- type WatchTopologyOptions = Pick<TtscBuildOptions, "binary" | "env" | "outDir" | "passthrough" | "projectRoot" | "tsconfig"> & {
4
+ type WatchTopologyOptions = Pick<TtscBuildOptions, "binary" | "emit" | "env" | "outDir" | "passthrough" | "projectRoot" | "tsconfig"> & {
3
5
  cwd: string;
4
6
  files: readonly string[];
5
7
  };
6
8
  type WatchTopologyCallbacks = {
7
9
  onError(location: string, error: unknown): void;
8
- onInputChange(): void;
10
+ onInputChange(change: WatchInputChange): void;
11
+ onProjectInputWatchRoots?(roots: readonly string[]): void;
9
12
  onTopologyChange(): void;
10
13
  };
14
+ export type WatchInputChange = {
15
+ /** Keep the resident process but cold-load its compiler Program. */
16
+ invalidate?: boolean;
17
+ kind: "compiler" | "config" | "plugin" | "project";
18
+ path?: string;
19
+ };
20
+ export type CompilerDirectoryWatchEventPlan = {
21
+ changes: string[];
22
+ rearm: string[];
23
+ refresh: boolean;
24
+ };
11
25
  /**
12
26
  * Keeps the launcher watch set aligned with the compiler's current program.
13
27
  *
@@ -19,25 +33,223 @@ type WatchTopologyCallbacks = {
19
33
  export declare class WatchTopology {
20
34
  private readonly options;
21
35
  private readonly callbacks;
36
+ private analysisOnly;
37
+ private closed;
22
38
  private directories;
23
39
  private directoryWatchers;
24
40
  private extraInputs;
25
41
  private extraWatchers;
42
+ private compilerFileStamps;
26
43
  private files;
27
44
  private fileWatchers;
28
45
  private observedDirectories;
46
+ private outputFiles;
29
47
  private outputs;
48
+ private projectInputFingerprints;
49
+ private projectInputMatches;
50
+ private projectInputs;
51
+ private declaredProjectInputs;
52
+ private projectInputRejectedWatchRoots;
53
+ private projectInputWatchRoots;
54
+ private projectInputWatchers;
55
+ private projectInputLinkWatchers;
56
+ private reloadFiles;
30
57
  constructor(options: WatchTopologyOptions, callbacks: WatchTopologyCallbacks);
31
58
  /** Re-resolve compiler inputs and notify only when their membership changed. */
32
59
  refresh(notify: boolean): void;
33
60
  /** Add Go plugin source trees discovered by the real build lane. */
34
61
  setExtraInputs(inputs: readonly string[]): void;
62
+ /**
63
+ * Reconcile project-rule dependencies, retaining absent files and empty glob
64
+ * populations as live topology.
65
+ */
66
+ setProjectInputs(inputs: ITtscProjectInputSnapshot): void;
35
67
  /** Close every watcher so SIGINT/SIGTERM can drain the event loop. */
36
68
  close(): void;
37
69
  private syncFileWatchers;
70
+ /** Whether a tracked file's bytes differ from the last stamp taken. */
71
+ private compilerFileMoved;
38
72
  private syncDirectoryWatchers;
73
+ /**
74
+ * Narrow a plan's changes to the tracked files that actually moved.
75
+ *
76
+ * A backend that cannot name what changed forces the plan to nominate every
77
+ * tracked file under the watched directory, which is the only safe answer it
78
+ * can give from an event carrying no filename. macOS delivers such events for
79
+ * ordinary activity elsewhere in the project, so the compiler lane would wake
80
+ * for sources nobody touched. Only a content notification passes through: it
81
+ * is the one event that claims the bytes moved. A rename claims the directory
82
+ * entry was rewritten and an unnamed event claims nothing, so both are
83
+ * decided from the bytes, which is the question neither of them answered.
84
+ */
85
+ private compilerChangesToReport;
86
+ private recordCompilerFileStamp;
87
+ private rearmFileWatchers;
39
88
  private syncExtraWatchers;
89
+ private syncProjectInputWatchers;
90
+ /**
91
+ * Watch the directory that holds a declaration which is itself a link.
92
+ *
93
+ * A recursive watcher cannot report the link being replaced. The backend that
94
+ * keys its handles by path skips an entry it already knows, and the handle it
95
+ * put on the entry followed the link to the target's inode, which unlinking
96
+ * and recreating the link never touches. A plain directory watch has neither
97
+ * property: it reports the entry by name the moment it moves. These are kept
98
+ * apart from the recursive roots because they are not roots — they observe
99
+ * one directory, they are never reported as watch roots, and an ancestor
100
+ * covering them does not make them redundant.
101
+ */
102
+ private syncProjectInputLinkWatchers;
103
+ /** Drop the watcher that just reported a directory replacement. */
104
+ private retireProjectInputWatcher;
105
+ private retainProjectInputWatchRoot;
106
+ /**
107
+ * One snapshot holding every spelling of every declaration.
108
+ *
109
+ * Consumers that decide from a population rather than from a single path have
110
+ * to see both, or half of them answer from the file a link pointed at when
111
+ * the snapshot was published while the event they are judging resolved to the
112
+ * file it points at now.
113
+ */
114
+ private projectInputPopulation;
115
+ /**
116
+ * Every spelling of one declaration that has to be anchored separately.
117
+ *
118
+ * The retained snapshot is normalized to physical identities, which is what
119
+ * every comparison needs but not what every watcher needs: a declaration
120
+ * reached through a symlink resolves to its target's directory, so anchoring
121
+ * the normalized form alone watches the bytes and never the link. Retargeting
122
+ * or replacing the link then goes unobserved, even though it is exactly what
123
+ * decides which bytes the declaration names next. Both spellings are planned
124
+ * through the same root selection, so the project-root hoist and the
125
+ * nearest-existing-ancestor boundary still bound each of them, and the active
126
+ * set drops one again whenever they coincide or share an ancestor.
127
+ */
128
+ private projectInputDeclarations;
129
+ private projectInputWatchRoot;
130
+ private refreshProjectInputs;
131
+ private collectProjectInputMatches;
40
132
  private refreshFromDirectory;
41
133
  private isCompilerOutputDirectory;
134
+ private isCompilerOutput;
135
+ private isProjectInputCompilerOutputDirectory;
136
+ private isProjectInputCompilerOutput;
137
+ private isProjectInputDirectory;
138
+ private classifyCompilerInput;
139
+ private isPluginInput;
42
140
  }
141
+ export declare function reloadInputsForFailedTopologyRefresh(reloadFiles: Iterable<string>, changed?: string): string[];
142
+ type SynchronizedWatcher = {
143
+ close(): void;
144
+ on(event: "error", listener: (error: Error) => void): unknown;
145
+ };
146
+ export declare function syncWatchers<T extends SynchronizedWatcher>(watchers: Map<string, T>, desired: ReadonlyMap<string, string>, create: (location: string, key: string) => T, onError: (location: string, error: unknown) => void): boolean;
147
+ export declare function literalGlobRoot(pattern: string): string;
148
+ /**
149
+ * Chooses the one stable recursive watcher root owned by a project-input
150
+ * declaration.
151
+ *
152
+ * Inputs inside the project share its physical root so directory replacement
153
+ * cannot strand a child handle. External inputs use the nearest existing
154
+ * ancestor of their declared parent, which is the explicit boundary for
155
+ * observing a currently missing external tree without polling every file --
156
+ * except that the boundary never rises to a directory holding the project,
157
+ * since such a root outranks the project's own in the active merge and leaves
158
+ * one handle over a shared system directory to carry everything. An external
159
+ * declaration that can only be owned that way falls back to its own tree, and
160
+ * is left unwatched when even that would contain the project.
161
+ */
162
+ export declare function projectInputWatchDirectories(target: string, projectRoot: string): string[];
163
+ /**
164
+ * Removes recursive roots already covered by an ancestor without rewriting the
165
+ * declaration-specific roots retained by WatchTopology.
166
+ */
167
+ export declare function projectInputActiveWatchDirectories(directories: Iterable<string>, identities?: ProjectInputPathIdentityContext): string[];
168
+ export declare function projectInputAvailableWatchDirectory(location: string, rejected: ReadonlySet<string>, identities?: ProjectInputPathIdentityContext, projectRoot?: string): string | undefined;
169
+ /**
170
+ * Whether a replacement at this path leaves a recursive watcher bound to the
171
+ * object that was replaced.
172
+ *
173
+ * Only one backend needs the answer. Node routes a recursive watch to its own
174
+ * per-directory implementation when the platform is neither macOS nor Windows,
175
+ * and that implementation keys its handles by path: the handle for a directory
176
+ * renamed away stays bound to the object that left, and any child whose name
177
+ * survives the swap is skipped as already known. The native subtree backends
178
+ * both other platforms use follow the path, so retiring their watcher would buy
179
+ * nothing and would open a window in which no events are delivered.
180
+ *
181
+ * The answer is deliberately narrower than the rescan rule, because
182
+ * reinstalling a root costs one watch descriptor per entry beneath it, which an
183
+ * install storm would pay thousands of times. A directory appearing inside a
184
+ * glob root deserves a rescan but replaces nothing a root stands on, and a
185
+ * reload directory anchors the directory that contains it rather than itself,
186
+ * since its fingerprint is a digest of its own immediate entries and nothing
187
+ * below it can reach the declared corpus.
188
+ */
189
+ export declare function projectInputReplacementStrandsWatchers(snapshot: ITtscProjectInputSnapshot, location: string, identities?: ProjectInputPathIdentityContext, platform?: NodeJS.Platform): boolean;
190
+ /**
191
+ * Decide whether an event that named no declared input can still have moved
192
+ * one.
193
+ *
194
+ * The admitted set is the only bound on how often a watch session re-reads and
195
+ * re-hashes its declared corpus, and both directions cost: too narrow drops an
196
+ * atomic replacement, too wide re-fingerprints on every entry an install
197
+ * creates. Exported so that boundary is pinned directly instead of being
198
+ * inferred from a rebuild that a silent rescan and a skipped rescan produce
199
+ * identically.
200
+ */
201
+ export declare function projectInputTopologyMayAffect(snapshot: ITtscProjectInputSnapshot, location: string, previous: ReadonlyMap<string, string>, identities?: ProjectInputPathIdentityContext): boolean;
202
+ export declare function projectInputEventShouldNotify(input: {
203
+ contentChanged: boolean;
204
+ directlyMatched: boolean;
205
+ membershipChanged: boolean;
206
+ }): boolean;
207
+ /**
208
+ * Classify an exact execution-selection input ahead of ordinary project data.
209
+ *
210
+ * `changedInputs` carries fingerprint or membership deltas, so a filename-less
211
+ * event can still select the cold lane. A named exact event selects the cold
212
+ * lane only after the surrounding change detector admits the event; unchanged
213
+ * bytes remain quiet before this classifier is observed.
214
+ */
215
+ export declare function projectInputReloadEventShouldNotify(input: {
216
+ changed?: string;
217
+ changedInputs: readonly string[];
218
+ reloadDirectories?: readonly string[];
219
+ reloadFiles: readonly string[];
220
+ globs?: readonly string[];
221
+ }): boolean;
222
+ /**
223
+ * Return whether a project-input population transition can reshape a Program.
224
+ *
225
+ * JSON is data to a ProjectRule but may simultaneously be a `resolveJsonModule`
226
+ * source. TypeScript and JavaScript paths can likewise overlap a project-input
227
+ * declaration. Their creation or deletion therefore requires a cold Program
228
+ * inside the existing resident process. A filename-less event cannot identify
229
+ * the changed member and is conservatively invalidating whenever the population
230
+ * moved.
231
+ */
232
+ export declare function projectInputMembershipInvalidatesProgram(input: {
233
+ changed?: string;
234
+ changedInputs?: readonly string[];
235
+ contentChanged?: boolean;
236
+ next: ReadonlyMap<string, string>;
237
+ previous: ReadonlyMap<string, string>;
238
+ }): boolean;
239
+ /**
240
+ * Plan one compiler-directory event without relying on backend timing.
241
+ *
242
+ * POSIX file watchers own ordinary content changes. A named rename re-arms the
243
+ * replaced file; an unnamed event conservatively re-arms and reports every
244
+ * surviving tracked input below the watch root. Windows has no per-file
245
+ * watchers here, so both named and unnamed directory events report inputs.
246
+ */
247
+ export declare function planCompilerDirectoryWatchEvent(input: {
248
+ changed?: string;
249
+ event: string;
250
+ exists(location: string): boolean;
251
+ location: string;
252
+ platform: NodeJS.Platform;
253
+ trackedFiles: ReadonlyMap<string, string>;
254
+ }): CompilerDirectoryWatchEventPlan;
43
255
  export {};