tsifdef 1.1.8

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 (71) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/CHANGELOG.zh-CN.md +22 -0
  3. package/CONTRIBUTING.md +52 -0
  4. package/INTEGRATION.md +166 -0
  5. package/INTEGRATION.zh-CN.md +159 -0
  6. package/LICENSE +210 -0
  7. package/README.md +150 -0
  8. package/README.zh-CN.md +141 -0
  9. package/SECURITY.md +15 -0
  10. package/assets/icon-mono.svg +15 -0
  11. package/assets/icon.png +0 -0
  12. package/assets/icon.svg +16 -0
  13. package/dist/cli/build.d.ts +70 -0
  14. package/dist/cli/build.js +298 -0
  15. package/dist/cli/config.d.ts +30 -0
  16. package/dist/cli/config.js +135 -0
  17. package/dist/cli/diagnostics.d.ts +3 -0
  18. package/dist/cli/diagnostics.js +31 -0
  19. package/dist/cli/index.d.ts +6 -0
  20. package/dist/cli/index.js +35 -0
  21. package/dist/cli/main.d.ts +9 -0
  22. package/dist/cli/main.js +165 -0
  23. package/dist/cli/precompile.d.ts +38 -0
  24. package/dist/cli/precompile.js +192 -0
  25. package/dist/cli/source-files.d.ts +10 -0
  26. package/dist/cli/source-files.js +75 -0
  27. package/dist/cli/watch.d.ts +34 -0
  28. package/dist/cli/watch.js +183 -0
  29. package/dist/core/conditional.d.ts +18 -0
  30. package/dist/core/conditional.js +126 -0
  31. package/dist/core/expression.d.ts +44 -0
  32. package/dist/core/expression.js +224 -0
  33. package/dist/core/index.d.ts +7 -0
  34. package/dist/core/index.js +37 -0
  35. package/dist/core/projection.d.ts +15 -0
  36. package/dist/core/projection.js +99 -0
  37. package/dist/core/scanner.d.ts +33 -0
  38. package/dist/core/scanner.js +344 -0
  39. package/dist/eslint/package.d.ts +10 -0
  40. package/dist/eslint/package.js +55 -0
  41. package/dist/eslint/parser.d.ts +35 -0
  42. package/dist/eslint/parser.js +59 -0
  43. package/dist/eslint/plugin.d.ts +78 -0
  44. package/dist/eslint/plugin.js +229 -0
  45. package/dist/eslint/projection.d.ts +11 -0
  46. package/dist/eslint/projection.js +116 -0
  47. package/dist/tsserver/host-projection.d.ts +45 -0
  48. package/dist/tsserver/host-projection.js +160 -0
  49. package/dist/tsserver/index.d.ts +3 -0
  50. package/dist/tsserver/index.js +32 -0
  51. package/dist/tsserver/plugin.d.ts +15 -0
  52. package/dist/tsserver/plugin.js +129 -0
  53. package/dist/tsserver/project-controller.d.ts +37 -0
  54. package/dist/tsserver/project-controller.js +60 -0
  55. package/dist/version.d.ts +3 -0
  56. package/dist/version.js +20 -0
  57. package/dist/vscode/document-analysis.d.ts +62 -0
  58. package/dist/vscode/document-analysis.js +111 -0
  59. package/dist/vscode/extension.d.ts +133 -0
  60. package/dist/vscode/extension.js +241 -0
  61. package/dist/vscode/host.d.ts +79 -0
  62. package/dist/vscode/host.js +16 -0
  63. package/dist/vscode/index.d.ts +7 -0
  64. package/dist/vscode/index.js +36 -0
  65. package/dist/vscode/macro-presentation.d.ts +43 -0
  66. package/dist/vscode/macro-presentation.js +130 -0
  67. package/dist/vscode/package-profile.d.ts +27 -0
  68. package/dist/vscode/package-profile.js +142 -0
  69. package/dist/vscode/profile-state.d.ts +22 -0
  70. package/dist/vscode/profile-state.js +81 -0
  71. package/package.json +129 -0
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ // Copyright (C) 2026 Tencent. All rights reserved.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.createTypeScriptIntegration = createTypeScriptIntegration;
17
+ exports.createHost = createHost;
18
+ exports.ensureTsserverPluginModule = ensureTsserverPluginModule;
19
+ exports.activate = activate;
20
+ exports.deactivate = deactivate;
21
+ const node_module_1 = require("node:module");
22
+ const node_fs_1 = require("node:fs");
23
+ const node_path_1 = require("node:path");
24
+ const version_js_1 = require("../version.js");
25
+ const profile_state_js_1 = require("./profile-state.js");
26
+ const macro_presentation_js_1 = require("./macro-presentation.js");
27
+ const package_profile_js_1 = require("./package-profile.js");
28
+ const document_analysis_js_1 = require("./document-analysis.js");
29
+ const macroExtensionPattern = /\.(?:d\.)?(?:ts|tsx|mts|cts)$/i;
30
+ const macroLanguageIds = new Set(["typescript", "typescriptreact"]);
31
+ function isMacroDocument(document) {
32
+ return macroLanguageIds.has(document.languageId) || macroExtensionPattern.test(document.fileName);
33
+ }
34
+ function toSnapshot(document) {
35
+ return {
36
+ uri: document.uri.toString(),
37
+ isMacroDocument: isMacroDocument(document),
38
+ getText: () => document.getText(),
39
+ };
40
+ }
41
+ /** Optional bridge to VSCode's built-in TypeScript language service. */
42
+ function createTypeScriptIntegration(vscode) {
43
+ return {
44
+ configurePlugin: async (name, configuration) => {
45
+ const extension = vscode.extensions.getExtension("vscode.typescript-language-features");
46
+ if (extension === undefined) {
47
+ return;
48
+ }
49
+ try {
50
+ const exports = (await extension.activate());
51
+ exports.getAPI?.(0)?.configurePlugin(name, configuration);
52
+ }
53
+ catch {
54
+ // The TypeScript language service is optional. Decorations and folding
55
+ // still work when it is unavailable or supplied by another extension.
56
+ }
57
+ },
58
+ restartServer: async () => {
59
+ if (vscode.extensions.getExtension("vscode.typescript-language-features") === undefined) {
60
+ return;
61
+ }
62
+ try {
63
+ await vscode.commands.executeCommand("typescript.restartTsServer");
64
+ }
65
+ catch {
66
+ // Keep the extension usable without VSCode's built-in tsserver.
67
+ }
68
+ },
69
+ reloadProjects: async () => {
70
+ if (vscode.extensions.getExtension("vscode.typescript-language-features") === undefined) {
71
+ return;
72
+ }
73
+ try {
74
+ await vscode.commands.executeCommand("typescript.reloadProjects");
75
+ }
76
+ catch {
77
+ // Keep the extension usable without VSCode's built-in tsserver.
78
+ }
79
+ },
80
+ };
81
+ }
82
+ /** Adapt the real `vscode` API to the host interface the shell depends on. */
83
+ function createHost(vscode) {
84
+ const typeScript = createTypeScriptIntegration(vscode);
85
+ const decorationTypes = new Map();
86
+ let decorationSequence = 0;
87
+ const toRange = (range) => new vscode.Range(range.start.line, range.start.character, range.end.line, range.end.character);
88
+ const severities = {
89
+ [document_analysis_js_1.DiagnosticSeverity.error]: vscode.DiagnosticSeverity.Error,
90
+ [document_analysis_js_1.DiagnosticSeverity.warning]: vscode.DiagnosticSeverity.Warning,
91
+ };
92
+ const toDiagnostic = (diagnostic) => {
93
+ const created = new vscode.Diagnostic(toRange(diagnostic.range), diagnostic.message, severities[diagnostic.severity]);
94
+ created.code = diagnostic.code;
95
+ return created;
96
+ };
97
+ return {
98
+ createStatusBarItem: () => vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100),
99
+ registerCommand: (command, handler) => vscode.commands.registerCommand(command, handler),
100
+ showInformationMessage: (message) => void vscode.window.showInformationMessage(message),
101
+ workspaceRoot: () => vscode.workspace.workspaceFolders?.[0]?.uri.fsPath,
102
+ createDiagnosticCollection: (name) => {
103
+ const collection = vscode.languages.createDiagnosticCollection(name);
104
+ return {
105
+ set: (uri, diagnostics) => collection.set(vscode.Uri.parse(uri), diagnostics.map(toDiagnostic)),
106
+ delete: (uri) => collection.delete(vscode.Uri.parse(uri)),
107
+ clear: () => collection.clear(),
108
+ dispose: () => collection.dispose(),
109
+ };
110
+ },
111
+ createInactiveDecorationType: () => {
112
+ const key = `inactive-${(decorationSequence += 1)}`;
113
+ const type = vscode.window.createTextEditorDecorationType({
114
+ opacity: "0.5",
115
+ isWholeLine: false,
116
+ });
117
+ decorationTypes.set(key, type);
118
+ return {
119
+ key,
120
+ dispose: () => {
121
+ type.dispose();
122
+ decorationTypes.delete(key);
123
+ },
124
+ };
125
+ },
126
+ setDecorations: (uri, decoration, ranges) => {
127
+ const type = decorationTypes.get(decoration.key);
128
+ if (type === undefined) {
129
+ return;
130
+ }
131
+ const vsRanges = ranges.map(toRange);
132
+ for (const editor of vscode.window.visibleTextEditors) {
133
+ if (editor.document.uri.toString() === uri) {
134
+ editor.setDecorations(type, vsRanges);
135
+ }
136
+ }
137
+ },
138
+ macroDocuments: () => vscode.workspace.textDocuments.map(toSnapshot),
139
+ registerFoldingRangeProvider: (provider) => vscode.languages.registerFoldingRangeProvider([{ language: "typescript" }, { language: "typescriptreact" }], {
140
+ provideFoldingRanges: (document) => provider(toSnapshot(document)).map((fold) => new vscode.FoldingRange(fold.start, fold.end)),
141
+ }),
142
+ showErrorMessage: (message) => void vscode.window.showErrorMessage(message),
143
+ configureTypeScriptPlugin: typeScript.configurePlugin,
144
+ restartTypeScriptServer: typeScript.restartServer,
145
+ reloadTypeScriptProjects: typeScript.reloadProjects,
146
+ watchProjectConfiguration: (onChange) => {
147
+ const watcher = vscode.workspace.createFileSystemWatcher("**/{package.json,*.json}");
148
+ const subscriptions = [
149
+ watcher.onDidChange(onChange),
150
+ watcher.onDidCreate(onChange),
151
+ watcher.onDidDelete(onChange),
152
+ ];
153
+ return { dispose: () => { for (const item of subscriptions)
154
+ item.dispose(); watcher.dispose(); } };
155
+ },
156
+ };
157
+ }
158
+ let active;
159
+ /**
160
+ * Ensure the tsserver plugin is resolvable as `node_modules/tsifdef-tsserver`.
161
+ *
162
+ * tsserver loads a workspace plugin by resolving the module named in
163
+ * `typescriptServerPlugins` from the extension directory. vsce does not ship a
164
+ * `node_modules/` tree, so the compiled plugin would otherwise be unreachable
165
+ * and every `#if` would reach the parser as a syntax error. Recreate the tiny
166
+ * forwarder on activation so a fresh install (or a `--force` reinstall that
167
+ * wiped a previous shim) self-heals without manual steps.
168
+ */
169
+ function ensureTsserverPluginModule() {
170
+ try {
171
+ // Compiled to `<ext>/dist/vscode/extension.js`; the extension root is two up.
172
+ const extensionRoot = (0, node_path_1.dirname)((0, node_path_1.dirname)(__dirname));
173
+ const moduleDir = (0, node_path_1.join)(extensionRoot, "node_modules", "tsifdef-tsserver");
174
+ const manifest = (0, node_path_1.join)(moduleDir, "package.json");
175
+ const index = (0, node_path_1.join)(moduleDir, "index.js");
176
+ const expectedManifest = `${JSON.stringify({ name: "tsifdef-tsserver", version: version_js_1.VERSION, private: true, main: "../../dist/tsserver/plugin.js" }, null, 2)}\n`;
177
+ const expectedIndex = 'module.exports = require("../../dist/tsserver/plugin.js");\n';
178
+ let currentManifest;
179
+ let currentIndex;
180
+ try {
181
+ currentManifest = (0, node_fs_1.readFileSync)(manifest, "utf8");
182
+ currentIndex = (0, node_fs_1.readFileSync)(index, "utf8");
183
+ }
184
+ catch {
185
+ currentManifest = undefined;
186
+ currentIndex = undefined;
187
+ }
188
+ if (currentManifest === expectedManifest && currentIndex === expectedIndex)
189
+ return;
190
+ (0, node_fs_1.mkdirSync)(moduleDir, { recursive: true });
191
+ (0, node_fs_1.writeFileSync)(manifest, expectedManifest, "utf8");
192
+ (0, node_fs_1.writeFileSync)(index, expectedIndex, "utf8");
193
+ }
194
+ catch {
195
+ // Best-effort: if the directory is read-only, a reinstall applies. Never
196
+ // block activation over it.
197
+ }
198
+ }
199
+ /** VSCode entry point. Binds the live API to the host and starts the shell. */
200
+ function activate(context) {
201
+ // Resolve `vscode` lazily so the package builds and tests without it present.
202
+ const vscode = (0, node_module_1.createRequire)(__filename)("vscode");
203
+ ensureTsserverPluginModule();
204
+ const host = createHost(vscode);
205
+ let definitions;
206
+ const profileController = new profile_state_js_1.ProfileStateController(host);
207
+ const presentation = new macro_presentation_js_1.MacroPresentationController(host, () => definitions);
208
+ const packageProfile = new package_profile_js_1.PackageProfileController(host, profileController, (next) => {
209
+ definitions = next;
210
+ presentation.refresh();
211
+ });
212
+ profileController.activate();
213
+ presentation.activate();
214
+ packageProfile.activate();
215
+ const subscriptions = [
216
+ vscode.workspace.onDidChangeTextDocument((event) => presentation.refreshDocument(toSnapshot(event.document))),
217
+ vscode.workspace.onDidOpenTextDocument((document) => presentation.refreshDocument(toSnapshot(document))),
218
+ vscode.workspace.onDidCloseTextDocument((document) => presentation.closeDocument(document.uri.toString())),
219
+ vscode.window.onDidChangeVisibleTextEditors(() => presentation.refresh()),
220
+ ];
221
+ active = {
222
+ profileController,
223
+ presentation,
224
+ packageProfile,
225
+ dispose: () => {
226
+ for (const subscription of subscriptions) {
227
+ subscription.dispose();
228
+ }
229
+ presentation.dispose();
230
+ packageProfile.dispose();
231
+ profileController.dispose();
232
+ },
233
+ };
234
+ context.subscriptions.push({ dispose: () => deactivate() });
235
+ }
236
+ /** VSCode shutdown hook. */
237
+ function deactivate() {
238
+ active?.dispose();
239
+ active = undefined;
240
+ }
241
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Minimal, injectable surface of the VSCode API used by the extension shell.
3
+ *
4
+ * The shell depends only on this interface so its logic runs under the standard
5
+ * Node test runner without the VSCode extension host. `src/vscode/extension.ts`
6
+ * binds the real `vscode` module to this surface at activation time.
7
+ */
8
+ import type { DocumentDiagnostic, DocumentRange, FoldingRange } from "./document-analysis.js";
9
+ export interface Disposable {
10
+ dispose(): void;
11
+ }
12
+ /** Subset of `vscode.StatusBarItem`. */
13
+ export interface StatusBarItem extends Disposable {
14
+ text: string;
15
+ tooltip: string | undefined;
16
+ command: string | undefined;
17
+ show(): void;
18
+ hide(): void;
19
+ }
20
+ /** An open macro document the presentation layer must keep in sync. */
21
+ export interface DocumentSnapshot {
22
+ /** Stable document identity (its URI string in the real host). */
23
+ readonly uri: string;
24
+ /** Whether this document holds macro-bearing TypeScript-family source. */
25
+ readonly isMacroDocument: boolean;
26
+ /** The current in-memory text, including unsaved edits. */
27
+ getText(): string;
28
+ }
29
+ /** Subset of `vscode.DiagnosticCollection`. */
30
+ export interface DiagnosticCollection extends Disposable {
31
+ set(uri: string, diagnostics: readonly DocumentDiagnostic[]): void;
32
+ delete(uri: string): void;
33
+ clear(): void;
34
+ }
35
+ /** Opaque handle for a decoration style; maps to `vscode.TextEditorDecorationType`. */
36
+ export interface DecorationType extends Disposable {
37
+ readonly key: string;
38
+ }
39
+ /** Provides folding ranges for one macro document, given its current text. */
40
+ export type FoldingRangeProvider = (document: DocumentSnapshot) => readonly FoldingRange[];
41
+ /**
42
+ * The capabilities the extension shell needs from its host. Every method maps
43
+ * directly onto a real `vscode` API call in the activation adapter.
44
+ */
45
+ export interface ExtensionHost {
46
+ /** Create a left-aligned status-bar item. */
47
+ createStatusBarItem(): StatusBarItem;
48
+ /** Register a command handler, returning its disposable. */
49
+ registerCommand(command: string, handler: () => unknown | Promise<unknown>): Disposable;
50
+ /** Surface a non-blocking informational message. */
51
+ showInformationMessage(message: string): void;
52
+ /** The first workspace folder's filesystem path, if any. */
53
+ workspaceRoot(): string | undefined;
54
+ /** Create the diagnostic collection that owns published macro diagnostics. */
55
+ createDiagnosticCollection(name: string): DiagnosticCollection;
56
+ /** Create the inactive-code decoration style applied to grayed ranges. */
57
+ createInactiveDecorationType(): DecorationType;
58
+ /** Apply a decoration's ranges to a document; an empty list clears them. */
59
+ setDecorations(uri: string, decoration: DecorationType, ranges: readonly DocumentRange[]): void;
60
+ /** Every currently open macro document. */
61
+ macroDocuments(): readonly DocumentSnapshot[];
62
+ /** Register a folding-range provider for macro documents. */
63
+ registerFoldingRangeProvider(provider: FoldingRangeProvider): Disposable;
64
+ /** Surface a non-blocking error message. */
65
+ showErrorMessage(message: string): void;
66
+ /** Send live configuration to the contributed TypeScript server plugin. */
67
+ configureTypeScriptPlugin(name: string, configuration: Readonly<Record<string, unknown>>): Promise<void>;
68
+ /**
69
+ * Restart the TypeScript server after the effective Profile changes.
70
+ * Reloading projects is not sufficient to clear stale language-service
71
+ * diagnostics in every workspace.
72
+ */
73
+ restartTypeScriptServer(): Promise<void>;
74
+ /** Reload projects after the restarted server has received plugin config. */
75
+ reloadTypeScriptProjects(): Promise<void>;
76
+ /** Watch package.json and Profile JSON files that determine editor semantics. */
77
+ watchProjectConfiguration(onChange: () => void): Disposable;
78
+ }
79
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // Copyright (C) 2026 Tencent. All rights reserved.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1,7 @@
1
+ export * from "./host.js";
2
+ export * from "./document-analysis.js";
3
+ export * from "./profile-state.js";
4
+ export * from "./macro-presentation.js";
5
+ export * from "./package-profile.js";
6
+ export * from "./extension.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ // Copyright (C) 2026 Tencent. All rights reserved.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
27
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ __exportStar(require("./host.js"), exports);
31
+ __exportStar(require("./document-analysis.js"), exports);
32
+ __exportStar(require("./profile-state.js"), exports);
33
+ __exportStar(require("./macro-presentation.js"), exports);
34
+ __exportStar(require("./package-profile.js"), exports);
35
+ __exportStar(require("./extension.js"), exports);
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,43 @@
1
+ import type { MacroDefinitions } from "../core/expression.js";
2
+ import type { DocumentSnapshot, ExtensionHost } from "./host.js";
3
+ /** Name of the diagnostic collection contributed by the extension. */
4
+ export declare const diagnosticCollectionName: "tsifdef";
5
+ /**
6
+ * Resolves the macro definitions for the currently effective Profile, or
7
+ * `undefined` when no Profile is selected. Returning a value is synchronous so
8
+ * the controller can refresh without awaiting I/O; the extension caches the
9
+ * loaded Profile and updates it on switch.
10
+ */
11
+ export type DefinitionsProvider = () => MacroDefinitions | undefined;
12
+ /**
13
+ * Publishes macro diagnostics and grays out inactive ranges for open macro
14
+ * documents.
15
+ *
16
+ * It reuses the shared core through `analyzeDocument` and depends only on the
17
+ * injected host, so it runs without the VSCode extension host.
18
+ */
19
+ export declare class MacroPresentationController {
20
+ private readonly host;
21
+ private readonly definitionsProvider;
22
+ private diagnostics;
23
+ private inactiveDecoration;
24
+ private readonly decoratedDocuments;
25
+ private readonly disposables;
26
+ constructor(host: ExtensionHost, definitionsProvider: DefinitionsProvider);
27
+ /** Create the diagnostic collection and decoration style, then render once. */
28
+ activate(): void;
29
+ dispose(): void;
30
+ /** Recompute diagnostics and decorations for every open macro document. */
31
+ refresh(): void;
32
+ /** Refresh a single document, e.g. on edit or open. */
33
+ refreshDocument(document: DocumentSnapshot): void;
34
+ /** Clear diagnostics and decorations for a closed document. */
35
+ closeDocument(uri: string): void;
36
+ /** Folding ranges for one macro document under the effective Profile. */
37
+ foldingRanges(document: DocumentSnapshot): readonly import("./document-analysis.js").FoldingRange[];
38
+ private render;
39
+ private clear;
40
+ private clearDocument;
41
+ private clearDocumentDecoration;
42
+ }
43
+ //# sourceMappingURL=macro-presentation.d.ts.map
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ // Copyright (C) 2026 Tencent. All rights reserved.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.MacroPresentationController = exports.diagnosticCollectionName = void 0;
17
+ const document_analysis_js_1 = require("./document-analysis.js");
18
+ /** Name of the diagnostic collection contributed by the extension. */
19
+ exports.diagnosticCollectionName = "tsifdef";
20
+ /**
21
+ * Publishes macro diagnostics and grays out inactive ranges for open macro
22
+ * documents.
23
+ *
24
+ * It reuses the shared core through `analyzeDocument` and depends only on the
25
+ * injected host, so it runs without the VSCode extension host.
26
+ */
27
+ class MacroPresentationController {
28
+ host;
29
+ definitionsProvider;
30
+ diagnostics;
31
+ inactiveDecoration;
32
+ decoratedDocuments = new Set();
33
+ disposables = [];
34
+ constructor(host, definitionsProvider) {
35
+ this.host = host;
36
+ this.definitionsProvider = definitionsProvider;
37
+ }
38
+ /** Create the diagnostic collection and decoration style, then render once. */
39
+ activate() {
40
+ this.diagnostics = this.host.createDiagnosticCollection(exports.diagnosticCollectionName);
41
+ this.inactiveDecoration = this.host.createInactiveDecorationType();
42
+ this.disposables.push(this.diagnostics, this.inactiveDecoration);
43
+ this.disposables.push(this.host.registerFoldingRangeProvider((document) => this.foldingRanges(document)));
44
+ this.refresh();
45
+ }
46
+ dispose() {
47
+ for (const disposable of this.disposables.splice(0).reverse()) {
48
+ disposable.dispose();
49
+ }
50
+ this.decoratedDocuments.clear();
51
+ this.diagnostics = undefined;
52
+ this.inactiveDecoration = undefined;
53
+ }
54
+ /** Recompute diagnostics and decorations for every open macro document. */
55
+ refresh() {
56
+ if (this.diagnostics === undefined) {
57
+ return;
58
+ }
59
+ const definitions = this.definitionsProvider();
60
+ if (definitions === undefined) {
61
+ this.clear();
62
+ return;
63
+ }
64
+ const live = new Set();
65
+ for (const document of this.host.macroDocuments()) {
66
+ if (!document.isMacroDocument) {
67
+ continue;
68
+ }
69
+ live.add(document.uri);
70
+ this.render(document, definitions);
71
+ }
72
+ // Drop documents that closed or stopped being macro documents since last run.
73
+ for (const uri of [...this.decoratedDocuments]) {
74
+ if (!live.has(uri)) {
75
+ this.clearDocument(uri);
76
+ }
77
+ }
78
+ }
79
+ /** Refresh a single document, e.g. on edit or open. */
80
+ refreshDocument(document) {
81
+ if (this.diagnostics === undefined) {
82
+ return;
83
+ }
84
+ const definitions = this.definitionsProvider();
85
+ if (definitions === undefined || !document.isMacroDocument) {
86
+ this.clearDocument(document.uri);
87
+ return;
88
+ }
89
+ this.render(document, definitions);
90
+ }
91
+ /** Clear diagnostics and decorations for a closed document. */
92
+ closeDocument(uri) {
93
+ this.clearDocument(uri);
94
+ }
95
+ /** Folding ranges for one macro document under the effective Profile. */
96
+ foldingRanges(document) {
97
+ const definitions = this.definitionsProvider();
98
+ if (definitions === undefined || !document.isMacroDocument) {
99
+ return [];
100
+ }
101
+ return (0, document_analysis_js_1.computeFoldingRanges)(document.getText(), definitions);
102
+ }
103
+ render(document, definitions) {
104
+ const analysis = (0, document_analysis_js_1.analyzeDocument)(document.getText(), definitions);
105
+ this.diagnostics?.set(document.uri, analysis.diagnostics);
106
+ if (this.inactiveDecoration !== undefined) {
107
+ this.host.setDecorations(document.uri, this.inactiveDecoration, analysis.inactiveRanges);
108
+ }
109
+ this.decoratedDocuments.add(document.uri);
110
+ }
111
+ clear() {
112
+ this.diagnostics?.clear();
113
+ for (const uri of [...this.decoratedDocuments]) {
114
+ this.clearDocumentDecoration(uri);
115
+ }
116
+ this.decoratedDocuments.clear();
117
+ }
118
+ clearDocument(uri) {
119
+ this.diagnostics?.delete(uri);
120
+ this.clearDocumentDecoration(uri);
121
+ this.decoratedDocuments.delete(uri);
122
+ }
123
+ clearDocumentDecoration(uri) {
124
+ if (this.inactiveDecoration !== undefined) {
125
+ this.host.setDecorations(uri, this.inactiveDecoration, []);
126
+ }
127
+ }
128
+ }
129
+ exports.MacroPresentationController = MacroPresentationController;
130
+ //# sourceMappingURL=macro-presentation.js.map
@@ -0,0 +1,27 @@
1
+ import type { MacroDefinitions } from "../core/expression.js";
2
+ import type { Disposable, ExtensionHost } from "./host.js";
3
+ import { ProfileStateController } from "./profile-state.js";
4
+ /** Watches the package-owned Profile pointer and synchronizes all editor consumers. */
5
+ export declare class PackageProfileController implements Disposable {
6
+ private readonly host;
7
+ private readonly state;
8
+ private readonly onDefinitions;
9
+ private watcher;
10
+ private debounceTimer;
11
+ private appliedIdentity;
12
+ private initialized;
13
+ constructor(host: ExtensionHost, state: ProfileStateController, onDefinitions: (definitions: MacroDefinitions | undefined) => void);
14
+ activate(): void;
15
+ dispose(): void;
16
+ private scheduleReload;
17
+ reload(): Promise<void>;
18
+ private applyTypeScriptProfile;
19
+ /**
20
+ * Load the Profile, retrying a few times on a transient failure. An atomic
21
+ * writer (temp file + rename) briefly leaves the path missing; reacting to
22
+ * that momentary miss made the Profile flap to "none" and back, restarting
23
+ * the server in a loop.
24
+ */
25
+ private loadProfileWithRetry;
26
+ }
27
+ //# sourceMappingURL=package-profile.d.ts.map