@formspec/ts-plugin 0.1.0-alpha.22 → 0.1.0-alpha.26
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 +0 -1
- package/dist/index.cjs +57 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -5
- package/dist/index.js.map +1 -1
- package/dist/semantic-service.d.ts +40 -6
- package/dist/semantic-service.d.ts.map +1 -1
- package/dist/service.d.ts +28 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/ts-plugin-alpha.d.ts +635 -0
- package/dist/ts-plugin-beta.d.ts +635 -0
- package/dist/ts-plugin-internal.d.ts +645 -0
- package/dist/ts-plugin.d.ts +185 -20
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -44,7 +44,6 @@ See:
|
|
|
44
44
|
These source-repository references intentionally show a downstream host that
|
|
45
45
|
renders diagnostics from `code` + `data` instead of reusing FormSpec's default
|
|
46
46
|
message text.
|
|
47
|
-
|
|
48
47
|
## White-Label Diagnostics
|
|
49
48
|
|
|
50
49
|
Diagnostics returned by the semantic service and plugin transport include:
|
package/dist/index.cjs
CHANGED
|
@@ -45,15 +45,16 @@ var import_promises = __toESM(require("fs/promises"), 1);
|
|
|
45
45
|
var import_node_net = __toESM(require("net"), 1);
|
|
46
46
|
var ts2 = require("typescript");
|
|
47
47
|
var import_protocol3 = require("@formspec/analysis/protocol");
|
|
48
|
-
var
|
|
48
|
+
var import_internal3 = require("@formspec/analysis/internal");
|
|
49
49
|
|
|
50
50
|
// src/workspace.ts
|
|
51
51
|
var import_node_os = __toESM(require("os"), 1);
|
|
52
52
|
var import_node_path = __toESM(require("path"), 1);
|
|
53
53
|
var import_protocol = require("@formspec/analysis/protocol");
|
|
54
|
+
var import_internal = require("@formspec/analysis/internal");
|
|
54
55
|
function getFormSpecWorkspaceRuntimePaths(workspaceRoot, platform = process.platform, userScope = getFormSpecUserScope()) {
|
|
55
|
-
const workspaceId = (0,
|
|
56
|
-
const runtimeDirectory = (0,
|
|
56
|
+
const workspaceId = (0, import_internal.getFormSpecWorkspaceId)(workspaceRoot);
|
|
57
|
+
const runtimeDirectory = (0, import_internal.getFormSpecWorkspaceRuntimeDirectory)(workspaceRoot);
|
|
57
58
|
const sanitizedUserScope = sanitizeScopeSegment(userScope);
|
|
58
59
|
const endpoint = platform === "win32" ? {
|
|
59
60
|
kind: "windows-pipe",
|
|
@@ -66,7 +67,7 @@ function getFormSpecWorkspaceRuntimePaths(workspaceRoot, platform = process.plat
|
|
|
66
67
|
workspaceRoot,
|
|
67
68
|
workspaceId,
|
|
68
69
|
runtimeDirectory,
|
|
69
|
-
manifestPath: (0,
|
|
70
|
+
manifestPath: (0, import_internal.getFormSpecManifestPath)(workspaceRoot),
|
|
70
71
|
endpoint
|
|
71
72
|
};
|
|
72
73
|
}
|
|
@@ -102,7 +103,7 @@ function sanitizeScopeSegment(value) {
|
|
|
102
103
|
// src/semantic-service.ts
|
|
103
104
|
var ts = require("typescript");
|
|
104
105
|
var import_protocol2 = require("@formspec/analysis/protocol");
|
|
105
|
-
var
|
|
106
|
+
var import_internal2 = require("@formspec/analysis/internal");
|
|
106
107
|
|
|
107
108
|
// src/constants.ts
|
|
108
109
|
var FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES = 256 * 1024;
|
|
@@ -180,8 +181,8 @@ var FormSpecSemanticService = class {
|
|
|
180
181
|
(performance2) => this.withCommentQueryContext(filePath, offset, performance2, (context) => ({
|
|
181
182
|
protocolVersion: import_protocol2.FORMSPEC_ANALYSIS_PROTOCOL_VERSION,
|
|
182
183
|
sourceHash: context.sourceHash,
|
|
183
|
-
context: (0,
|
|
184
|
-
(0,
|
|
184
|
+
context: (0, import_internal2.serializeCompletionContext)(
|
|
185
|
+
(0, import_internal2.getSemanticCommentCompletionContextAtOffset)(context.sourceFile.text, offset, {
|
|
185
186
|
checker: context.checker,
|
|
186
187
|
...context.placement === null ? {} : { placement: context.placement },
|
|
187
188
|
...context.subjectType === void 0 ? {} : { subjectType: context.subjectType }
|
|
@@ -199,8 +200,8 @@ var FormSpecSemanticService = class {
|
|
|
199
200
|
(performance2) => this.withCommentQueryContext(filePath, offset, performance2, (context) => ({
|
|
200
201
|
protocolVersion: import_protocol2.FORMSPEC_ANALYSIS_PROTOCOL_VERSION,
|
|
201
202
|
sourceHash: context.sourceHash,
|
|
202
|
-
hover: (0,
|
|
203
|
-
(0,
|
|
203
|
+
hover: (0, import_internal2.serializeHoverInfo)(
|
|
204
|
+
(0, import_internal2.getCommentHoverInfoAtOffset)(context.sourceFile.text, offset, {
|
|
204
205
|
checker: context.checker,
|
|
205
206
|
...context.placement === null ? {} : { placement: context.placement },
|
|
206
207
|
...context.subjectType === void 0 ? {} : { subjectType: context.subjectType }
|
|
@@ -275,8 +276,8 @@ var FormSpecSemanticService = class {
|
|
|
275
276
|
};
|
|
276
277
|
}
|
|
277
278
|
runMeasured(name, detail, fn) {
|
|
278
|
-
const performance2 = this.options.enablePerformanceLogging === true ? (0,
|
|
279
|
-
const result = (0,
|
|
279
|
+
const performance2 = this.options.enablePerformanceLogging === true ? (0, import_internal2.createFormSpecPerformanceRecorder)() : new StatsOnlyPerformanceRecorder();
|
|
280
|
+
const result = (0, import_internal2.optionalMeasure)(performance2, name, detail, () => fn(performance2));
|
|
280
281
|
this.updateStatsFromPerformanceEvents(performance2.events);
|
|
281
282
|
if (this.options.enablePerformanceLogging === true) {
|
|
282
283
|
this.logPerformanceEvents(name, performance2.events);
|
|
@@ -284,7 +285,7 @@ var FormSpecSemanticService = class {
|
|
|
284
285
|
return result;
|
|
285
286
|
}
|
|
286
287
|
withCommentQueryContext(filePath, offset, performance2, handler) {
|
|
287
|
-
return (0,
|
|
288
|
+
return (0, import_internal2.optionalMeasure)(
|
|
288
289
|
performance2,
|
|
289
290
|
"semantic.resolveCommentQueryContext",
|
|
290
291
|
{
|
|
@@ -296,26 +297,26 @@ var FormSpecSemanticService = class {
|
|
|
296
297
|
if (environment === null) {
|
|
297
298
|
return null;
|
|
298
299
|
}
|
|
299
|
-
const declaration = (0,
|
|
300
|
+
const declaration = (0, import_internal2.optionalMeasure)(
|
|
300
301
|
performance2,
|
|
301
302
|
"semantic.findDeclarationForCommentOffset",
|
|
302
303
|
{
|
|
303
304
|
filePath,
|
|
304
305
|
offset
|
|
305
306
|
},
|
|
306
|
-
() => (0,
|
|
307
|
+
() => (0, import_internal2.findDeclarationForCommentOffset)(environment.sourceFile, offset)
|
|
307
308
|
);
|
|
308
|
-
const placement = declaration === null ? null : (0,
|
|
309
|
+
const placement = declaration === null ? null : (0, import_internal2.optionalMeasure)(
|
|
309
310
|
performance2,
|
|
310
311
|
"semantic.resolveDeclarationPlacement",
|
|
311
312
|
void 0,
|
|
312
|
-
() => (0,
|
|
313
|
+
() => (0, import_internal2.resolveDeclarationPlacement)(declaration)
|
|
313
314
|
);
|
|
314
|
-
const subjectType = declaration === null ? void 0 : (0,
|
|
315
|
+
const subjectType = declaration === null ? void 0 : (0, import_internal2.optionalMeasure)(
|
|
315
316
|
performance2,
|
|
316
317
|
"semantic.getSubjectType",
|
|
317
318
|
void 0,
|
|
318
|
-
() => (0,
|
|
319
|
+
() => (0, import_internal2.getSubjectType)(declaration, environment.checker)
|
|
319
320
|
);
|
|
320
321
|
return handler({
|
|
321
322
|
...environment,
|
|
@@ -327,7 +328,7 @@ var FormSpecSemanticService = class {
|
|
|
327
328
|
);
|
|
328
329
|
}
|
|
329
330
|
getFileSnapshotWithCacheState(filePath, performance2) {
|
|
330
|
-
const startedAt = (0,
|
|
331
|
+
const startedAt = (0, import_internal2.getFormSpecPerformanceNow)();
|
|
331
332
|
const environment = this.getSourceEnvironment(filePath, performance2);
|
|
332
333
|
if (environment === null) {
|
|
333
334
|
this.stats.fileSnapshotCacheMisses += 1;
|
|
@@ -352,7 +353,7 @@ var FormSpecSemanticService = class {
|
|
|
352
353
|
};
|
|
353
354
|
performance2.record({
|
|
354
355
|
name: "semantic.getFileSnapshot.result",
|
|
355
|
-
durationMs: (0,
|
|
356
|
+
durationMs: (0, import_internal2.getFormSpecPerformanceNow)() - startedAt,
|
|
356
357
|
detail: {
|
|
357
358
|
filePath,
|
|
358
359
|
cache: "missing-source"
|
|
@@ -368,7 +369,7 @@ var FormSpecSemanticService = class {
|
|
|
368
369
|
this.stats.fileSnapshotCacheHits += 1;
|
|
369
370
|
performance2.record({
|
|
370
371
|
name: "semantic.getFileSnapshot.result",
|
|
371
|
-
durationMs: (0,
|
|
372
|
+
durationMs: (0, import_internal2.getFormSpecPerformanceNow)() - startedAt,
|
|
372
373
|
detail: {
|
|
373
374
|
filePath,
|
|
374
375
|
cache: "hit"
|
|
@@ -380,7 +381,7 @@ var FormSpecSemanticService = class {
|
|
|
380
381
|
};
|
|
381
382
|
}
|
|
382
383
|
this.stats.fileSnapshotCacheMisses += 1;
|
|
383
|
-
const snapshot = (0,
|
|
384
|
+
const snapshot = (0, import_internal2.buildFormSpecAnalysisFileSnapshot)(environment.sourceFile, {
|
|
384
385
|
checker: environment.checker,
|
|
385
386
|
now: () => this.getNow(),
|
|
386
387
|
performance: performance2
|
|
@@ -391,7 +392,7 @@ var FormSpecSemanticService = class {
|
|
|
391
392
|
});
|
|
392
393
|
performance2.record({
|
|
393
394
|
name: "semantic.getFileSnapshot.result",
|
|
394
|
-
durationMs: (0,
|
|
395
|
+
durationMs: (0, import_internal2.getFormSpecPerformanceNow)() - startedAt,
|
|
395
396
|
detail: {
|
|
396
397
|
filePath,
|
|
397
398
|
cache: "miss"
|
|
@@ -406,14 +407,14 @@ var FormSpecSemanticService = class {
|
|
|
406
407
|
return this.options.now?.() ?? /* @__PURE__ */ new Date();
|
|
407
408
|
}
|
|
408
409
|
getSourceEnvironment(filePath, performance2) {
|
|
409
|
-
return (0,
|
|
410
|
+
return (0, import_internal2.optionalMeasure)(
|
|
410
411
|
performance2,
|
|
411
412
|
"semantic.getSourceEnvironment",
|
|
412
413
|
{
|
|
413
414
|
filePath
|
|
414
415
|
},
|
|
415
416
|
() => {
|
|
416
|
-
const program = (0,
|
|
417
|
+
const program = (0, import_internal2.optionalMeasure)(
|
|
417
418
|
performance2,
|
|
418
419
|
"semantic.sourceEnvironment.getProgram",
|
|
419
420
|
void 0,
|
|
@@ -422,7 +423,7 @@ var FormSpecSemanticService = class {
|
|
|
422
423
|
if (program === void 0) {
|
|
423
424
|
return null;
|
|
424
425
|
}
|
|
425
|
-
const sourceFile = (0,
|
|
426
|
+
const sourceFile = (0, import_internal2.optionalMeasure)(
|
|
426
427
|
performance2,
|
|
427
428
|
"semantic.sourceEnvironment.getSourceFile",
|
|
428
429
|
void 0,
|
|
@@ -431,13 +432,13 @@ var FormSpecSemanticService = class {
|
|
|
431
432
|
if (sourceFile === void 0) {
|
|
432
433
|
return null;
|
|
433
434
|
}
|
|
434
|
-
const checker = (0,
|
|
435
|
+
const checker = (0, import_internal2.optionalMeasure)(
|
|
435
436
|
performance2,
|
|
436
437
|
"semantic.sourceEnvironment.getTypeChecker",
|
|
437
438
|
void 0,
|
|
438
439
|
() => program.getTypeChecker()
|
|
439
440
|
);
|
|
440
|
-
const sourceHash = (0,
|
|
441
|
+
const sourceHash = (0, import_internal2.optionalMeasure)(
|
|
441
442
|
performance2,
|
|
442
443
|
"semantic.sourceEnvironment.computeTextHash",
|
|
443
444
|
void 0,
|
|
@@ -515,6 +516,11 @@ var FormSpecPluginService = class {
|
|
|
515
516
|
runtimePaths;
|
|
516
517
|
semanticService;
|
|
517
518
|
server = null;
|
|
519
|
+
/**
|
|
520
|
+
* Returns the manifest written by the plugin service for workspace discovery.
|
|
521
|
+
*
|
|
522
|
+
* @internal
|
|
523
|
+
*/
|
|
518
524
|
getManifest() {
|
|
519
525
|
return this.manifest;
|
|
520
526
|
}
|
|
@@ -526,6 +532,13 @@ var FormSpecPluginService = class {
|
|
|
526
532
|
getSemanticService() {
|
|
527
533
|
return this.semanticService;
|
|
528
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Starts the IPC transport and writes the current workspace manifest.
|
|
537
|
+
*
|
|
538
|
+
* Calling this more than once is a no-op.
|
|
539
|
+
*
|
|
540
|
+
* @public
|
|
541
|
+
*/
|
|
529
542
|
async start() {
|
|
530
543
|
if (this.server !== null) {
|
|
531
544
|
return;
|
|
@@ -583,6 +596,11 @@ var FormSpecPluginService = class {
|
|
|
583
596
|
});
|
|
584
597
|
await this.writeManifest();
|
|
585
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* Stops the IPC transport, clears semantic state, and removes runtime artifacts.
|
|
601
|
+
*
|
|
602
|
+
* @public
|
|
603
|
+
*/
|
|
586
604
|
async stop() {
|
|
587
605
|
this.semanticService.dispose();
|
|
588
606
|
const server = this.server;
|
|
@@ -600,9 +618,19 @@ var FormSpecPluginService = class {
|
|
|
600
618
|
}
|
|
601
619
|
await this.cleanupRuntimeArtifacts();
|
|
602
620
|
}
|
|
621
|
+
/**
|
|
622
|
+
* Schedules a background refresh for the cached semantic snapshot of a file.
|
|
623
|
+
*
|
|
624
|
+
* @public
|
|
625
|
+
*/
|
|
603
626
|
scheduleSnapshotRefresh(filePath) {
|
|
604
627
|
this.semanticService.scheduleSnapshotRefresh(filePath);
|
|
605
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Handles a semantic query issued against the plugin transport.
|
|
631
|
+
*
|
|
632
|
+
* @internal
|
|
633
|
+
*/
|
|
606
634
|
handleQuery(query) {
|
|
607
635
|
if (this.options.enablePerformanceLogging === true) {
|
|
608
636
|
const startedAt = performance.now();
|
|
@@ -669,7 +697,7 @@ var FormSpecPluginService = class {
|
|
|
669
697
|
respondToSocket(socket, payload) {
|
|
670
698
|
try {
|
|
671
699
|
const query = JSON.parse(payload);
|
|
672
|
-
if (!(0,
|
|
700
|
+
if (!(0, import_internal3.isFormSpecSemanticQuery)(query)) {
|
|
673
701
|
throw new Error("Invalid FormSpec semantic query payload");
|
|
674
702
|
}
|
|
675
703
|
const response = this.handleQuery(query);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/service.ts","../src/workspace.ts","../src/semantic-service.ts","../src/constants.ts","../src/perf-utils.ts"],"sourcesContent":["import type * as tsServer from \"typescript/lib/tsserverlibrary.js\";\nexport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n FORMSPEC_ANALYSIS_SCHEMA_VERSION,\n type CommentSourceSpan,\n type CommentSpan,\n type FormSpecAnalysisCommentSnapshot,\n type FormSpecAnalysisDiagnostic,\n type FormSpecAnalysisDiagnosticCategory,\n type FormSpecAnalysisDiagnosticDataValue,\n type FormSpecAnalysisDiagnosticLocation,\n type FormSpecAnalysisManifest,\n type FormSpecAnalysisFileSnapshot,\n type FormSpecAnalysisTagSnapshot,\n type FormSpecIpcEndpoint,\n type FormSpecPlacement,\n type FormSpecSemanticQuery,\n type FormSpecSemanticResponse,\n type FormSpecSerializedCommentTargetSpecifier,\n type FormSpecSerializedCompletionContext,\n type FormSpecSerializedHoverInfo,\n type FormSpecSerializedTagDefinition,\n type FormSpecSerializedTagSemanticContext,\n type FormSpecSerializedTagSignature,\n type FormSpecTargetKind,\n} from \"@formspec/analysis/protocol\";\nimport { createLanguageServiceProxy, FormSpecPluginService } from \"./service.js\";\nexport {\n createLanguageServiceProxy,\n FormSpecPluginService,\n type FormSpecPluginServiceOptions,\n type LoggerLike,\n} from \"./service.js\";\nexport {\n FormSpecSemanticService,\n type FormSpecSemanticCompletionResult,\n type FormSpecSemanticDiagnosticsResult,\n type FormSpecSemanticHoverResult,\n type FormSpecSemanticServiceOptions,\n type FormSpecSemanticServiceStats,\n} from \"./semantic-service.js\";\n\ninterface ServiceEntry {\n readonly service: FormSpecPluginService;\n referenceCount: number;\n}\n\nconst services = new Map<string, ServiceEntry>();\nconst PERF_LOG_ENV_VAR = \"FORMSPEC_PLUGIN_PROFILE\";\nconst PERF_LOG_THRESHOLD_ENV_VAR = \"FORMSPEC_PLUGIN_PROFILE_THRESHOLD_MS\";\n\nfunction formatPluginError(error: unknown): string {\n return error instanceof Error ? (error.stack ?? error.message) : String(error);\n}\n\nfunction readBooleanEnvFlag(name: string): boolean {\n const rawValue = process.env[name];\n return rawValue === \"1\" || rawValue === \"true\";\n}\n\nfunction readNumberEnvFlag(name: string): number | undefined {\n const rawValue = process.env[name];\n if (rawValue === undefined || rawValue.trim() === \"\") {\n return undefined;\n }\n\n const parsed = Number(rawValue);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction getOrCreateService(\n info: tsServer.server.PluginCreateInfo,\n typescriptVersion: string\n): FormSpecPluginService {\n const workspaceRoot = info.project.getCurrentDirectory();\n const existing = services.get(workspaceRoot);\n if (existing !== undefined) {\n existing.referenceCount += 1;\n attachProjectCloseHandler(info, workspaceRoot, existing);\n return existing.service;\n }\n\n const performanceLogThresholdMs = readNumberEnvFlag(PERF_LOG_THRESHOLD_ENV_VAR);\n const service = new FormSpecPluginService({\n workspaceRoot,\n typescriptVersion,\n getProgram: () => info.languageService.getProgram(),\n logger: info.project.projectService.logger,\n enablePerformanceLogging: readBooleanEnvFlag(PERF_LOG_ENV_VAR),\n ...(performanceLogThresholdMs === undefined ? {} : { performanceLogThresholdMs }),\n });\n\n const serviceEntry: ServiceEntry = {\n service,\n referenceCount: 1,\n };\n attachProjectCloseHandler(info, workspaceRoot, serviceEntry);\n\n service.start().catch((error: unknown) => {\n info.project.projectService.logger.info(\n `[FormSpec] Plugin service failed to start for ${workspaceRoot}: ${formatPluginError(error)}`\n );\n services.delete(workspaceRoot);\n });\n services.set(workspaceRoot, serviceEntry);\n return service;\n}\n\nfunction attachProjectCloseHandler(\n info: tsServer.server.PluginCreateInfo,\n workspaceRoot: string,\n serviceEntry: ServiceEntry\n): void {\n const originalClose = info.project.close.bind(info.project);\n let closed = false;\n\n info.project.close = () => {\n if (closed) {\n originalClose();\n return;\n }\n\n closed = true;\n serviceEntry.referenceCount -= 1;\n if (serviceEntry.referenceCount <= 0) {\n services.delete(workspaceRoot);\n void serviceEntry.service.stop().catch((error: unknown) => {\n info.project.projectService.logger.info(\n `[FormSpec] Failed to stop plugin service for ${workspaceRoot}: ${formatPluginError(error)}`\n );\n });\n }\n originalClose();\n };\n}\n\n/**\n * Initializes the FormSpec TypeScript language service plugin.\n *\n * @public\n */\nexport function init(modules: {\n readonly typescript: typeof tsServer;\n}): tsServer.server.PluginModule {\n const typescriptVersion = modules.typescript.version;\n return {\n create(info) {\n const service = getOrCreateService(info, typescriptVersion);\n return createLanguageServiceProxy(info.languageService, service.getSemanticService());\n },\n };\n}\n","import fs from \"node:fs/promises\";\nimport net from \"node:net\";\nimport * as ts from \"typescript\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n isFormSpecSemanticQuery,\n type FormSpecAnalysisManifest,\n type FormSpecSemanticQuery,\n type FormSpecSemanticResponse,\n} from \"@formspec/analysis/protocol\";\nimport { type FormSpecPerformanceEvent } from \"@formspec/analysis/internal\";\nimport {\n createFormSpecAnalysisManifest,\n getFormSpecWorkspaceRuntimePaths,\n type FormSpecWorkspaceRuntimePaths,\n} from \"./workspace.js\";\nimport {\n FormSpecSemanticService,\n type FormSpecSemanticServiceOptions,\n type LoggerLike,\n} from \"./semantic-service.js\";\nimport {\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS,\n FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES,\n FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS,\n} from \"./constants.js\";\nimport { formatPerformanceEvent } from \"./perf-utils.js\";\n\n/**\n * Public configuration for the reference plugin wrapper that exposes\n * `FormSpecSemanticService` over the local manifest + IPC transport.\n *\n * Supports the same semantic-service options, including\n * `enablePerformanceLogging`, `performanceLogThresholdMs`, and\n * `snapshotDebounceMs`. The packaged tsserver plugin wires these from\n * `FORMSPEC_PLUGIN_PROFILE=1` and `FORMSPEC_PLUGIN_PROFILE_THRESHOLD_MS`.\n *\n * @public\n */\nexport type FormSpecPluginServiceOptions = FormSpecSemanticServiceOptions;\n\n/**\n * Reference manifest/socket wrapper around `FormSpecSemanticService`.\n *\n * Downstream TypeScript hosts that already control their own plugin/runtime\n * lifecycle can use `FormSpecSemanticService` directly and skip this wrapper.\n *\n * @public\n */\nexport class FormSpecPluginService {\n private readonly manifest: FormSpecAnalysisManifest;\n private readonly runtimePaths: FormSpecWorkspaceRuntimePaths;\n private readonly semanticService: FormSpecSemanticService;\n private server: net.Server | null = null;\n\n public constructor(private readonly options: FormSpecPluginServiceOptions) {\n this.semanticService = new FormSpecSemanticService(options);\n this.runtimePaths = getFormSpecWorkspaceRuntimePaths(options.workspaceRoot);\n this.manifest = createFormSpecAnalysisManifest(\n options.workspaceRoot,\n options.typescriptVersion,\n Date.now()\n );\n }\n\n public getManifest(): FormSpecAnalysisManifest {\n return this.manifest;\n }\n\n /**\n * Returns the underlying semantic service used by this reference wrapper.\n *\n * @public\n */\n public getSemanticService(): FormSpecSemanticService {\n return this.semanticService;\n }\n\n public async start(): Promise<void> {\n if (this.server !== null) {\n return;\n }\n\n await fs.mkdir(this.runtimePaths.runtimeDirectory, { recursive: true });\n if (this.runtimePaths.endpoint.kind === \"unix-socket\") {\n await fs.rm(this.runtimePaths.endpoint.address, { force: true });\n }\n\n this.server = net.createServer((socket) => {\n let buffer = \"\";\n socket.setEncoding(\"utf8\");\n socket.setTimeout(FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS, () => {\n this.options.logger?.info(\n `[FormSpec] Closing idle semantic query socket for ${this.runtimePaths.workspaceRoot}`\n );\n socket.destroy();\n });\n socket.on(\"data\", (chunk) => {\n buffer += String(chunk);\n if (buffer.length > FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES) {\n socket.end(\n `${JSON.stringify({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `FormSpec semantic query exceeded ${String(FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES)} bytes`,\n } satisfies FormSpecSemanticResponse)}\\n`\n );\n return;\n }\n\n const newlineIndex = buffer.indexOf(\"\\n\");\n if (newlineIndex < 0) {\n return;\n }\n\n const payload = buffer.slice(0, newlineIndex);\n const remaining = buffer.slice(newlineIndex + 1);\n if (remaining.trim().length > 0) {\n this.options.logger?.info(\n `[FormSpec] Ignoring extra semantic query payload data for ${this.runtimePaths.workspaceRoot}`\n );\n }\n buffer = remaining;\n // The FormSpec IPC transport is intentionally one-request-per-connection.\n this.respondToSocket(socket, payload);\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n const handleError = (error: Error) => {\n reject(error);\n };\n this.server?.once(\"error\", handleError);\n this.server?.listen(this.runtimePaths.endpoint.address, () => {\n this.server?.off(\"error\", handleError);\n resolve();\n });\n });\n\n await this.writeManifest();\n }\n\n public async stop(): Promise<void> {\n this.semanticService.dispose();\n\n const server = this.server;\n this.server = null;\n if (server?.listening === true) {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error === undefined) {\n resolve();\n return;\n }\n reject(error);\n });\n });\n }\n\n await this.cleanupRuntimeArtifacts();\n }\n\n public scheduleSnapshotRefresh(filePath: string): void {\n this.semanticService.scheduleSnapshotRefresh(filePath);\n }\n\n public handleQuery(query: FormSpecSemanticQuery): FormSpecSemanticResponse {\n if (this.options.enablePerformanceLogging === true) {\n const startedAt = performance.now();\n const response = this.executeQuery(query);\n this.logQueryDuration(query, performance.now() - startedAt);\n return response;\n }\n\n return this.executeQuery(query);\n }\n\n private executeQuery(query: FormSpecSemanticQuery): FormSpecSemanticResponse {\n switch (query.kind) {\n case \"health\":\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"health\",\n manifest: this.manifest,\n };\n case \"completion\": {\n const result = this.semanticService.getCompletionContext(query.filePath, query.offset);\n if (result === null) {\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `Unable to resolve TypeScript source file for ${query.filePath}`,\n };\n }\n\n return {\n ...result,\n kind: \"completion\",\n };\n }\n case \"hover\": {\n const result = this.semanticService.getHover(query.filePath, query.offset);\n if (result === null) {\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `Unable to resolve TypeScript source file for ${query.filePath}`,\n };\n }\n\n return {\n ...result,\n kind: \"hover\",\n };\n }\n case \"diagnostics\": {\n const result = this.semanticService.getDiagnostics(query.filePath);\n return {\n ...result,\n kind: \"diagnostics\",\n };\n }\n case \"file-snapshot\":\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"file-snapshot\",\n snapshot: this.semanticService.getFileSnapshot(query.filePath),\n };\n default: {\n throw new Error(`Unhandled semantic query: ${JSON.stringify(query)}`);\n }\n }\n }\n\n private respondToSocket(socket: net.Socket, payload: string): void {\n try {\n const query = JSON.parse(payload) as unknown;\n if (!isFormSpecSemanticQuery(query)) {\n throw new Error(\"Invalid FormSpec semantic query payload\");\n }\n const response = this.handleQuery(query);\n socket.end(`${JSON.stringify(response)}\\n`);\n } catch (error) {\n socket.end(\n `${JSON.stringify({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: error instanceof Error ? error.message : String(error),\n } satisfies FormSpecSemanticResponse)}\\n`\n );\n }\n }\n\n private async writeManifest(): Promise<void> {\n const tempManifestPath = `${this.runtimePaths.manifestPath}.tmp`;\n await fs.writeFile(tempManifestPath, `${JSON.stringify(this.manifest, null, 2)}\\n`, \"utf8\");\n await fs.rename(tempManifestPath, this.runtimePaths.manifestPath);\n }\n\n private async cleanupRuntimeArtifacts(): Promise<void> {\n await fs.rm(this.runtimePaths.manifestPath, { force: true });\n\n if (this.runtimePaths.endpoint.kind === \"unix-socket\") {\n await fs.rm(this.runtimePaths.endpoint.address, { force: true });\n }\n }\n\n private logQueryDuration(query: FormSpecSemanticQuery, durationMs: number): void {\n const logger = this.options.logger;\n if (logger === undefined) {\n return;\n }\n\n const thresholdMs =\n this.options.performanceLogThresholdMs ??\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS;\n if (durationMs < thresholdMs) {\n return;\n }\n\n const event: FormSpecPerformanceEvent = {\n name: \"plugin.handleQuery\",\n durationMs,\n detail: {\n kind: query.kind,\n ...(query.kind === \"health\" ? {} : { filePath: query.filePath }),\n },\n };\n logger.info(`[FormSpec][perf] ${formatPerformanceEvent(event)}`);\n }\n}\n\n/**\n * Reference proxy wrapper that keeps FormSpec semantic snapshots fresh while\n * delegating actual TypeScript editor features to the original service.\n *\n * @public\n */\nexport function createLanguageServiceProxy(\n languageService: ts.LanguageService,\n semanticService: FormSpecSemanticService\n): ts.LanguageService {\n const wrapWithSnapshotRefresh = <Args extends readonly unknown[], Result>(\n fn: (fileName: string, ...args: Args) => Result\n ) => {\n return (fileName: string, ...args: Args): Result => {\n semanticService.scheduleSnapshotRefresh(fileName);\n return fn(fileName, ...args);\n };\n };\n\n const getSemanticDiagnostics = wrapWithSnapshotRefresh((fileName) =>\n languageService.getSemanticDiagnostics(fileName)\n );\n\n const getCompletionsAtPosition = wrapWithSnapshotRefresh(\n (fileName: string, position: number, options: ts.GetCompletionsAtPositionOptions | undefined) =>\n languageService.getCompletionsAtPosition(fileName, position, options)\n );\n\n const getQuickInfoAtPosition = wrapWithSnapshotRefresh((fileName, position: number) =>\n languageService.getQuickInfoAtPosition(fileName, position)\n );\n\n return new Proxy(languageService, {\n get(target, property, receiver) {\n switch (property) {\n case \"getSemanticDiagnostics\":\n return getSemanticDiagnostics;\n case \"getCompletionsAtPosition\":\n return getCompletionsAtPosition;\n case \"getQuickInfoAtPosition\":\n return getQuickInfoAtPosition;\n default:\n return Reflect.get(target, property, receiver) as unknown;\n }\n },\n });\n}\n\nexport type { LoggerLike };\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n FORMSPEC_ANALYSIS_SCHEMA_VERSION,\n getFormSpecManifestPath,\n getFormSpecWorkspaceId,\n getFormSpecWorkspaceRuntimeDirectory,\n type FormSpecAnalysisManifest,\n type FormSpecIpcEndpoint,\n} from \"@formspec/analysis/protocol\";\n\nexport interface FormSpecWorkspaceRuntimePaths {\n readonly workspaceRoot: string;\n readonly workspaceId: string;\n readonly runtimeDirectory: string;\n readonly manifestPath: string;\n readonly endpoint: FormSpecIpcEndpoint;\n}\n\nexport function getFormSpecWorkspaceRuntimePaths(\n workspaceRoot: string,\n platform = process.platform,\n userScope = getFormSpecUserScope()\n): FormSpecWorkspaceRuntimePaths {\n const workspaceId = getFormSpecWorkspaceId(workspaceRoot);\n const runtimeDirectory = getFormSpecWorkspaceRuntimeDirectory(workspaceRoot);\n const sanitizedUserScope = sanitizeScopeSegment(userScope);\n const endpoint: FormSpecIpcEndpoint =\n platform === \"win32\"\n ? {\n kind: \"windows-pipe\",\n address: `\\\\\\\\.\\\\pipe\\\\formspec-${sanitizedUserScope}-${workspaceId}`,\n }\n : {\n kind: \"unix-socket\",\n address: path.join(os.tmpdir(), `formspec-${sanitizedUserScope}-${workspaceId}.sock`),\n };\n\n return {\n workspaceRoot,\n workspaceId,\n runtimeDirectory,\n manifestPath: getFormSpecManifestPath(workspaceRoot),\n endpoint,\n };\n}\n\nexport function createFormSpecAnalysisManifest(\n workspaceRoot: string,\n typescriptVersion: string,\n generation: number,\n extensionFingerprint = \"builtin\"\n): FormSpecAnalysisManifest {\n const paths = getFormSpecWorkspaceRuntimePaths(workspaceRoot);\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n analysisSchemaVersion: FORMSPEC_ANALYSIS_SCHEMA_VERSION,\n workspaceRoot,\n workspaceId: paths.workspaceId,\n endpoint: paths.endpoint,\n typescriptVersion,\n extensionFingerprint,\n generation,\n updatedAt: new Date().toISOString(),\n };\n}\n\nfunction getFormSpecUserScope(): string {\n try {\n return sanitizeScopeSegment(os.userInfo().username);\n } catch {\n return sanitizeScopeSegment(\n process.env[\"USER\"] ?? process.env[\"USERNAME\"] ?? process.env[\"LOGNAME\"] ?? \"formspec\"\n );\n }\n}\n\nfunction sanitizeScopeSegment(value: string): string {\n const trimmed = value.trim().toLowerCase();\n const sanitized = trimmed.replace(/[^a-z0-9_-]+/gu, \"-\").replace(/-+/gu, \"-\");\n return sanitized.length > 0 ? sanitized : \"formspec\";\n}\n","import * as ts from \"typescript\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n computeFormSpecTextHash,\n type FormSpecAnalysisDiagnostic,\n type FormSpecAnalysisFileSnapshot,\n type FormSpecSerializedCompletionContext,\n type FormSpecSerializedHoverInfo,\n} from \"@formspec/analysis/protocol\";\nimport {\n buildFormSpecAnalysisFileSnapshot,\n createFormSpecPerformanceRecorder,\n findDeclarationForCommentOffset,\n getCommentHoverInfoAtOffset,\n getSemanticCommentCompletionContextAtOffset,\n getFormSpecPerformanceNow,\n getSubjectType,\n optionalMeasure,\n resolveDeclarationPlacement,\n serializeCompletionContext,\n serializeHoverInfo,\n type BuildFormSpecAnalysisFileSnapshotOptions,\n type FormSpecPerformanceEvent,\n type FormSpecPerformanceRecorder,\n} from \"@formspec/analysis/internal\";\nimport {\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS,\n FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS,\n} from \"./constants.js\";\nimport { formatPerformanceEvent } from \"./perf-utils.js\";\n\n/** @public */\nexport interface LoggerLike {\n info(message: string): void;\n}\n\n/** @public */\nexport interface FormSpecSemanticServiceOptions {\n /** Workspace root used for runtime paths and contextual logging. */\n readonly workspaceRoot: string;\n /** TypeScript version string reported by the host runtime. */\n readonly typescriptVersion: string;\n /** Supplies the current host program. Returns `undefined` until ready. */\n readonly getProgram: () => ts.Program | undefined;\n /** Optional logger used for profiling and refresh-failure messages. */\n readonly logger?: LoggerLike;\n /** Enables structured hotspot logging for semantic queries. */\n readonly enablePerformanceLogging?: boolean;\n /** Minimum query duration, in milliseconds, required before logging. */\n readonly performanceLogThresholdMs?: number;\n /** Debounce window, in milliseconds, for background snapshot refresh. */\n readonly snapshotDebounceMs?: number;\n /** Injectable clock used by tests and runtime snapshot timestamps. */\n readonly now?: () => Date;\n}\n\n/** @public */\nexport interface FormSpecSemanticCompletionResult {\n readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;\n readonly sourceHash: string;\n readonly context: FormSpecSerializedCompletionContext;\n}\n\n/** @public */\nexport interface FormSpecSemanticHoverResult {\n readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;\n readonly sourceHash: string;\n readonly hover: FormSpecSerializedHoverInfo | null;\n}\n\n/** @public */\nexport interface FormSpecSemanticDiagnosticsResult {\n readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;\n readonly sourceHash: string;\n readonly diagnostics: readonly FormSpecAnalysisDiagnostic[];\n}\n\n/** @public */\nexport interface FormSpecSemanticServiceStats {\n /** Total number of calls by semantic query kind. */\n readonly queryTotals: {\n readonly completion: number;\n readonly hover: number;\n readonly diagnostics: number;\n readonly fileSnapshot: number;\n };\n /** Cold vs warm query path counts for snapshot-backed operations. */\n readonly queryPathTotals: {\n readonly diagnostics: { readonly cold: number; readonly warm: number };\n readonly fileSnapshot: { readonly cold: number; readonly warm: number };\n };\n /** Number of file snapshot cache hits. */\n readonly fileSnapshotCacheHits: number;\n /** Number of file snapshot cache misses. */\n readonly fileSnapshotCacheMisses: number;\n /** Number of synthetic batch cache hits. */\n readonly syntheticBatchCacheHits: number;\n /** Number of synthetic batch cache misses. */\n readonly syntheticBatchCacheMisses: number;\n /** Number of synthetic compiler program creations. */\n readonly syntheticCompileCount: number;\n /** Total synthetic application count compiled across misses. */\n readonly syntheticCompileApplications: number;\n}\n\ninterface CachedFileSnapshot {\n readonly sourceHash: string;\n readonly snapshot: FormSpecAnalysisFileSnapshot;\n}\n\ninterface SourceEnvironment {\n readonly sourceFile: ts.SourceFile;\n readonly checker: ts.TypeChecker;\n readonly sourceHash: string;\n}\n\ninterface CommentQueryContext extends SourceEnvironment {\n readonly declaration: ts.Node | null;\n readonly placement: ReturnType<typeof resolveDeclarationPlacement>;\n readonly subjectType: ts.Type | undefined;\n}\n\ntype SnapshotCacheState = \"hit\" | \"miss\" | \"missing-source\";\n\ninterface MutableSemanticServiceStats {\n queryTotals: {\n completion: number;\n hover: number;\n diagnostics: number;\n fileSnapshot: number;\n };\n queryPathTotals: {\n diagnostics: { cold: number; warm: number };\n fileSnapshot: { cold: number; warm: number };\n };\n fileSnapshotCacheHits: number;\n fileSnapshotCacheMisses: number;\n syntheticBatchCacheHits: number;\n syntheticBatchCacheMisses: number;\n syntheticCompileCount: number;\n syntheticCompileApplications: number;\n}\n\nconst STATS_ONLY_EVENT_NAMES = new Set<string>([\n \"analysis.syntheticCheckBatch.cacheHit\",\n \"analysis.narrowSyntheticCheckBatch.cacheHit\",\n \"analysis.syntheticCheckBatch.cacheMiss\",\n \"analysis.narrowSyntheticCheckBatch.cacheMiss\",\n \"analysis.syntheticCheckBatch.createProgram\",\n \"analysis.narrowSyntheticCheckBatch.createProgram\",\n]);\n\nclass StatsOnlyPerformanceRecorder implements FormSpecPerformanceRecorder {\n private readonly mutableEvents: FormSpecPerformanceEvent[] = [];\n\n public get events(): readonly FormSpecPerformanceEvent[] {\n return this.mutableEvents;\n }\n\n public measure<T>(\n name: string,\n detail: Readonly<Record<string, string | number | boolean>> | undefined,\n callback: () => T\n ): T {\n const result = callback();\n if (STATS_ONLY_EVENT_NAMES.has(name)) {\n this.mutableEvents.push({\n name,\n durationMs: 0,\n ...(detail === undefined ? {} : { detail }),\n });\n }\n return result;\n }\n\n public record(event: FormSpecPerformanceEvent): void {\n if (STATS_ONLY_EVENT_NAMES.has(event.name)) {\n this.mutableEvents.push(event);\n }\n }\n}\n\n/**\n * Reusable in-process semantic service for FormSpec authoring features.\n *\n * Downstream TypeScript hosts can construct this directly against their own\n * `Program` and own the final presentation of completions, hover, and\n * diagnostics. The shipped tsserver plugin is a reference wrapper over this\n * public service.\n *\n * @public\n */\nexport class FormSpecSemanticService {\n private readonly snapshotCache = new Map<string, CachedFileSnapshot>();\n private readonly refreshTimers = new Map<string, NodeJS.Timeout>();\n private readonly stats: MutableSemanticServiceStats = {\n queryTotals: {\n completion: 0,\n hover: 0,\n diagnostics: 0,\n fileSnapshot: 0,\n },\n queryPathTotals: {\n diagnostics: { cold: 0, warm: 0 },\n fileSnapshot: { cold: 0, warm: 0 },\n },\n fileSnapshotCacheHits: 0,\n fileSnapshotCacheMisses: 0,\n syntheticBatchCacheHits: 0,\n syntheticBatchCacheMisses: 0,\n syntheticCompileCount: 0,\n syntheticCompileApplications: 0,\n };\n\n public constructor(private readonly options: FormSpecSemanticServiceOptions) {}\n\n /** Resolves semantic completion context for a comment cursor position. */\n public getCompletionContext(\n filePath: string,\n offset: number\n ): FormSpecSemanticCompletionResult | null {\n this.stats.queryTotals.completion += 1;\n return this.runMeasured(\"semantic.getCompletionContext\", { filePath, offset }, (performance) =>\n this.withCommentQueryContext(filePath, offset, performance, (context) => ({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n sourceHash: context.sourceHash,\n context: serializeCompletionContext(\n getSemanticCommentCompletionContextAtOffset(context.sourceFile.text, offset, {\n checker: context.checker,\n ...(context.placement === null ? {} : { placement: context.placement }),\n ...(context.subjectType === undefined ? {} : { subjectType: context.subjectType }),\n })\n ),\n }))\n );\n }\n\n /** Resolves semantic hover payload for a comment cursor position. */\n public getHover(filePath: string, offset: number): FormSpecSemanticHoverResult | null {\n this.stats.queryTotals.hover += 1;\n return this.runMeasured(\"semantic.getHover\", { filePath, offset }, (performance) =>\n this.withCommentQueryContext(filePath, offset, performance, (context) => ({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n sourceHash: context.sourceHash,\n hover: serializeHoverInfo(\n getCommentHoverInfoAtOffset(context.sourceFile.text, offset, {\n checker: context.checker,\n ...(context.placement === null ? {} : { placement: context.placement }),\n ...(context.subjectType === undefined ? {} : { subjectType: context.subjectType }),\n })\n ),\n }))\n );\n }\n\n /** Returns canonical FormSpec diagnostics for a file in the current host program. */\n public getDiagnostics(filePath: string): FormSpecSemanticDiagnosticsResult {\n this.stats.queryTotals.diagnostics += 1;\n return this.runMeasured(\"semantic.getDiagnostics\", { filePath }, (performance) => {\n const { snapshot, cacheState } = this.getFileSnapshotWithCacheState(filePath, performance);\n this.recordQueryPath(\"diagnostics\", cacheState);\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n sourceHash: snapshot.sourceHash,\n diagnostics: snapshot.diagnostics,\n };\n });\n }\n\n /** Returns the full serialized semantic snapshot for a file. */\n public getFileSnapshot(filePath: string): FormSpecAnalysisFileSnapshot {\n this.stats.queryTotals.fileSnapshot += 1;\n return this.runMeasured(\"semantic.getFileSnapshot\", { filePath }, (performance) => {\n const { snapshot, cacheState } = this.getFileSnapshotWithCacheState(filePath, performance);\n this.recordQueryPath(\"fileSnapshot\", cacheState);\n return snapshot;\n });\n }\n\n /** Schedules a debounced background refresh for the file snapshot cache. */\n public scheduleSnapshotRefresh(filePath: string): void {\n const existing = this.refreshTimers.get(filePath);\n if (existing !== undefined) {\n clearTimeout(existing);\n }\n\n const timer = setTimeout(() => {\n try {\n this.getFileSnapshot(filePath);\n } catch (error: unknown) {\n this.options.logger?.info(\n `[FormSpec] Failed to refresh semantic snapshot for ${filePath}: ${String(error)}`\n );\n }\n this.refreshTimers.delete(filePath);\n }, this.options.snapshotDebounceMs ?? FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS);\n timer.unref();\n\n this.refreshTimers.set(filePath, timer);\n }\n\n /** Clears pending timers and cached semantic snapshots. */\n public dispose(): void {\n for (const timer of this.refreshTimers.values()) {\n clearTimeout(timer);\n }\n this.refreshTimers.clear();\n this.snapshotCache.clear();\n }\n\n /** Returns a copy of the current performance and cache counters. */\n public getStats(): FormSpecSemanticServiceStats {\n return {\n queryTotals: { ...this.stats.queryTotals },\n queryPathTotals: {\n diagnostics: { ...this.stats.queryPathTotals.diagnostics },\n fileSnapshot: { ...this.stats.queryPathTotals.fileSnapshot },\n },\n fileSnapshotCacheHits: this.stats.fileSnapshotCacheHits,\n fileSnapshotCacheMisses: this.stats.fileSnapshotCacheMisses,\n syntheticBatchCacheHits: this.stats.syntheticBatchCacheHits,\n syntheticBatchCacheMisses: this.stats.syntheticBatchCacheMisses,\n syntheticCompileCount: this.stats.syntheticCompileCount,\n syntheticCompileApplications: this.stats.syntheticCompileApplications,\n };\n }\n\n private runMeasured<T>(\n name: string,\n detail: Record<string, string | number>,\n fn: (performance: FormSpecPerformanceRecorder) => T\n ): T {\n const performance =\n this.options.enablePerformanceLogging === true\n ? createFormSpecPerformanceRecorder()\n : new StatsOnlyPerformanceRecorder();\n const result = optionalMeasure(performance, name, detail, () => fn(performance));\n this.updateStatsFromPerformanceEvents(performance.events);\n if (this.options.enablePerformanceLogging === true) {\n this.logPerformanceEvents(name, performance.events);\n }\n return result;\n }\n\n private withCommentQueryContext<T>(\n filePath: string,\n offset: number,\n performance: FormSpecPerformanceRecorder,\n handler: (context: CommentQueryContext) => T\n ): T | null {\n return optionalMeasure(\n performance,\n \"semantic.resolveCommentQueryContext\",\n {\n filePath,\n offset,\n },\n () => {\n const environment = this.getSourceEnvironment(filePath, performance);\n if (environment === null) {\n return null;\n }\n\n const declaration = optionalMeasure(\n performance,\n \"semantic.findDeclarationForCommentOffset\",\n {\n filePath,\n offset,\n },\n () => findDeclarationForCommentOffset(environment.sourceFile, offset)\n );\n const placement =\n declaration === null\n ? null\n : optionalMeasure(performance, \"semantic.resolveDeclarationPlacement\", undefined, () =>\n resolveDeclarationPlacement(declaration)\n );\n const subjectType =\n declaration === null\n ? undefined\n : optionalMeasure(performance, \"semantic.getSubjectType\", undefined, () =>\n getSubjectType(declaration, environment.checker)\n );\n\n return handler({\n ...environment,\n declaration,\n placement,\n subjectType,\n });\n }\n );\n }\n\n private getFileSnapshotWithCacheState(\n filePath: string,\n performance: FormSpecPerformanceRecorder\n ): {\n readonly snapshot: FormSpecAnalysisFileSnapshot;\n readonly cacheState: SnapshotCacheState;\n } {\n const startedAt = getFormSpecPerformanceNow();\n const environment = this.getSourceEnvironment(filePath, performance);\n if (environment === null) {\n this.stats.fileSnapshotCacheMisses += 1;\n const snapshot: FormSpecAnalysisFileSnapshot = {\n filePath,\n sourceHash: \"\",\n generatedAt: this.getNow().toISOString(),\n comments: [],\n diagnostics: [\n {\n code: \"MISSING_SOURCE_FILE\",\n category: \"infrastructure\",\n message: `Unable to resolve TypeScript source file for ${filePath}`,\n range: { start: 0, end: 0 },\n severity: \"warning\",\n relatedLocations: [],\n data: {\n filePath,\n },\n },\n ],\n };\n performance.record({\n name: \"semantic.getFileSnapshot.result\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"missing-source\",\n },\n });\n return {\n snapshot,\n cacheState: \"missing-source\",\n };\n }\n\n const cached = this.snapshotCache.get(filePath);\n if (cached?.sourceHash === environment.sourceHash) {\n this.stats.fileSnapshotCacheHits += 1;\n performance.record({\n name: \"semantic.getFileSnapshot.result\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"hit\",\n },\n });\n return {\n snapshot: cached.snapshot,\n cacheState: \"hit\",\n };\n }\n\n this.stats.fileSnapshotCacheMisses += 1;\n const snapshot = buildFormSpecAnalysisFileSnapshot(environment.sourceFile, {\n checker: environment.checker,\n now: () => this.getNow(),\n performance,\n } satisfies BuildFormSpecAnalysisFileSnapshotOptions);\n this.snapshotCache.set(filePath, {\n sourceHash: environment.sourceHash,\n snapshot,\n });\n performance.record({\n name: \"semantic.getFileSnapshot.result\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"miss\",\n },\n });\n return {\n snapshot,\n cacheState: \"miss\",\n };\n }\n\n private getNow(): Date {\n return this.options.now?.() ?? new Date();\n }\n\n private getSourceEnvironment(\n filePath: string,\n performance: FormSpecPerformanceRecorder\n ): SourceEnvironment | null {\n return optionalMeasure(\n performance,\n \"semantic.getSourceEnvironment\",\n {\n filePath,\n },\n () => {\n const program = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.getProgram\",\n undefined,\n () => this.options.getProgram()\n );\n if (program === undefined) {\n return null;\n }\n\n const sourceFile = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.getSourceFile\",\n undefined,\n () => program.getSourceFile(filePath)\n );\n if (sourceFile === undefined) {\n return null;\n }\n\n const checker = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.getTypeChecker\",\n undefined,\n () => program.getTypeChecker()\n );\n const sourceHash = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.computeTextHash\",\n undefined,\n () => computeFormSpecTextHash(sourceFile.text)\n );\n\n return {\n sourceFile,\n checker,\n sourceHash,\n };\n }\n );\n }\n\n private recordQueryPath(\n kind: \"diagnostics\" | \"fileSnapshot\",\n cacheState: SnapshotCacheState\n ): void {\n if (cacheState === \"hit\") {\n this.stats.queryPathTotals[kind].warm += 1;\n return;\n }\n\n this.stats.queryPathTotals[kind].cold += 1;\n }\n\n private updateStatsFromPerformanceEvents(events: readonly FormSpecPerformanceEvent[]): void {\n for (const event of events) {\n if (\n event.name === \"analysis.syntheticCheckBatch.cacheHit\" ||\n event.name === \"analysis.narrowSyntheticCheckBatch.cacheHit\"\n ) {\n this.stats.syntheticBatchCacheHits += 1;\n continue;\n }\n\n if (\n event.name === \"analysis.syntheticCheckBatch.cacheMiss\" ||\n event.name === \"analysis.narrowSyntheticCheckBatch.cacheMiss\"\n ) {\n this.stats.syntheticBatchCacheMisses += 1;\n const applicationCount = event.detail?.[\"applicationCount\"];\n if (typeof applicationCount === \"number\") {\n this.stats.syntheticCompileApplications += applicationCount;\n }\n continue;\n }\n\n if (\n event.name === \"analysis.syntheticCheckBatch.createProgram\" ||\n event.name === \"analysis.narrowSyntheticCheckBatch.createProgram\"\n ) {\n this.stats.syntheticCompileCount += 1;\n }\n }\n }\n\n private logPerformanceEvents(\n rootEventName: string,\n events: readonly FormSpecPerformanceEvent[]\n ): void {\n const logger = this.options.logger;\n if (logger === undefined || events.length === 0) {\n return;\n }\n\n const rootEvent = [...events].reverse().find((event) => event.name === rootEventName);\n if (rootEvent === undefined) {\n return;\n }\n\n const thresholdMs =\n this.options.performanceLogThresholdMs ??\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS;\n if (rootEvent.durationMs < thresholdMs) {\n return;\n }\n\n const sortedHotspots = [...events]\n .filter((event) => event.name !== rootEventName)\n .sort((left, right) => right.durationMs - left.durationMs)\n .slice(0, 8);\n const lines = [\n `[FormSpec][perf] ${formatPerformanceEvent(rootEvent)}`,\n ...sortedHotspots.map((event) => ` ${formatPerformanceEvent(event)}`),\n ];\n logger.info(lines.join(\"\\n\"));\n }\n}\n","export const FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES = 256 * 1024;\nexport const FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS = 30_000;\nexport const FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS = 50;\nexport const FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS = 250;\n\nexport const FORM_SPEC_PLUGIN_PERFORMANCE_EVENT = {\n handleQuery: \"plugin.handleQuery\",\n} as const;\n","import type { FormSpecPerformanceEvent } from \"@formspec/analysis/internal\";\n\nexport function formatPerformanceEvent(event: FormSpecPerformanceEvent): string {\n const detailEntries = Object.entries(event.detail ?? {})\n .map(([key, value]) => `${key}=${String(value)}`)\n .join(\" \");\n return `${event.durationMs.toFixed(1)}ms ${event.name}${detailEntries === \"\" ? \"\" : ` ${detailEntries}`}`;\n}\n"],"mappings":"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","names":["import_protocol","ts","import_protocol","import_internal","path","os","import_protocol","performance","snapshot","fs","net"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/service.ts","../src/workspace.ts","../src/semantic-service.ts","../src/constants.ts","../src/perf-utils.ts"],"sourcesContent":["/**\n * TypeScript language service plugin entrypoint for FormSpec.\n *\n * This package exposes the reference tsserver plugin and the reusable semantic\n * service used by downstream TypeScript hosts.\n *\n * @packageDocumentation\n */\nimport type * as tsServer from \"typescript/lib/tsserverlibrary.js\";\nexport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n FORMSPEC_ANALYSIS_SCHEMA_VERSION,\n type CommentHoverInfo,\n type CommentSourceSpan,\n type CommentSpan,\n type FormSpecAnalysisCommentSnapshot,\n type FormSpecAnalysisDiagnostic,\n type FormSpecAnalysisDiagnosticCategory,\n type FormSpecAnalysisDiagnosticDataValue,\n type FormSpecAnalysisDiagnosticLocation,\n type FormSpecAnalysisFileSnapshot,\n type FormSpecAnalysisTagSnapshot,\n type FormSpecPlacement,\n type FormSpecTargetKind,\n type FormSpecSerializedCommentTargetSpecifier,\n type FormSpecSerializedCompletionContext,\n type FormSpecSerializedHoverInfo,\n type FormSpecSerializedTagDefinition,\n type FormSpecSerializedTagSemanticContext,\n type FormSpecSerializedTagSignature,\n} from \"@formspec/analysis/protocol\";\nimport { createLanguageServiceProxy, FormSpecPluginService } from \"./service.js\";\nexport {\n createLanguageServiceProxy,\n FormSpecPluginService,\n type FormSpecPluginServiceOptions,\n type LoggerLike,\n} from \"./service.js\";\nexport {\n FormSpecSemanticService,\n type FormSpecSemanticCompletionResult,\n type FormSpecSemanticDiagnosticsResult,\n type FormSpecSemanticHoverResult,\n type FormSpecSemanticServiceOptions,\n type FormSpecSemanticServiceStats,\n} from \"./semantic-service.js\";\n\ninterface ServiceEntry {\n readonly service: FormSpecPluginService;\n referenceCount: number;\n}\n\nconst services = new Map<string, ServiceEntry>();\nconst PERF_LOG_ENV_VAR = \"FORMSPEC_PLUGIN_PROFILE\";\nconst PERF_LOG_THRESHOLD_ENV_VAR = \"FORMSPEC_PLUGIN_PROFILE_THRESHOLD_MS\";\n\nfunction formatPluginError(error: unknown): string {\n return error instanceof Error ? (error.stack ?? error.message) : String(error);\n}\n\nfunction readBooleanEnvFlag(name: string): boolean {\n const rawValue = process.env[name];\n return rawValue === \"1\" || rawValue === \"true\";\n}\n\nfunction readNumberEnvFlag(name: string): number | undefined {\n const rawValue = process.env[name];\n if (rawValue === undefined || rawValue.trim() === \"\") {\n return undefined;\n }\n\n const parsed = Number(rawValue);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction getOrCreateService(\n info: tsServer.server.PluginCreateInfo,\n typescriptVersion: string\n): FormSpecPluginService {\n const workspaceRoot = info.project.getCurrentDirectory();\n const existing = services.get(workspaceRoot);\n if (existing !== undefined) {\n existing.referenceCount += 1;\n attachProjectCloseHandler(info, workspaceRoot, existing);\n return existing.service;\n }\n\n const performanceLogThresholdMs = readNumberEnvFlag(PERF_LOG_THRESHOLD_ENV_VAR);\n const service = new FormSpecPluginService({\n workspaceRoot,\n typescriptVersion,\n getProgram: () => info.languageService.getProgram(),\n logger: info.project.projectService.logger,\n enablePerformanceLogging: readBooleanEnvFlag(PERF_LOG_ENV_VAR),\n ...(performanceLogThresholdMs === undefined ? {} : { performanceLogThresholdMs }),\n });\n\n const serviceEntry: ServiceEntry = {\n service,\n referenceCount: 1,\n };\n attachProjectCloseHandler(info, workspaceRoot, serviceEntry);\n\n service.start().catch((error: unknown) => {\n info.project.projectService.logger.info(\n `[FormSpec] Plugin service failed to start for ${workspaceRoot}: ${formatPluginError(error)}`\n );\n services.delete(workspaceRoot);\n });\n services.set(workspaceRoot, serviceEntry);\n return service;\n}\n\nfunction attachProjectCloseHandler(\n info: tsServer.server.PluginCreateInfo,\n workspaceRoot: string,\n serviceEntry: ServiceEntry\n): void {\n const originalClose = info.project.close.bind(info.project);\n let closed = false;\n\n info.project.close = () => {\n if (closed) {\n originalClose();\n return;\n }\n\n closed = true;\n serviceEntry.referenceCount -= 1;\n if (serviceEntry.referenceCount <= 0) {\n services.delete(workspaceRoot);\n void serviceEntry.service.stop().catch((error: unknown) => {\n info.project.projectService.logger.info(\n `[FormSpec] Failed to stop plugin service for ${workspaceRoot}: ${formatPluginError(error)}`\n );\n });\n }\n originalClose();\n };\n}\n\n/**\n * Initializes the FormSpec TypeScript language service plugin.\n *\n * @public\n */\nexport function init(modules: {\n readonly typescript: typeof tsServer;\n}): tsServer.server.PluginModule {\n const typescriptVersion = modules.typescript.version;\n return {\n create(info) {\n const service = getOrCreateService(info, typescriptVersion);\n return createLanguageServiceProxy(info.languageService, service.getSemanticService());\n },\n };\n}\n","import fs from \"node:fs/promises\";\nimport net from \"node:net\";\nimport * as ts from \"typescript\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n} from \"@formspec/analysis/protocol\";\nimport {\n isFormSpecSemanticQuery,\n type FormSpecAnalysisManifest,\n type FormSpecPerformanceEvent,\n type FormSpecSemanticQuery,\n type FormSpecSemanticResponse,\n} from \"@formspec/analysis/internal\";\nimport {\n createFormSpecAnalysisManifest,\n getFormSpecWorkspaceRuntimePaths,\n type FormSpecWorkspaceRuntimePaths,\n} from \"./workspace.js\";\nimport {\n FormSpecSemanticService,\n type FormSpecSemanticServiceOptions,\n type LoggerLike,\n} from \"./semantic-service.js\";\nimport {\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS,\n FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES,\n FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS,\n} from \"./constants.js\";\nimport { formatPerformanceEvent } from \"./perf-utils.js\";\n\n/**\n * Public configuration for the reference plugin wrapper that exposes\n * `FormSpecSemanticService` over the local manifest + IPC transport.\n *\n * Supports the same semantic-service options, including\n * `enablePerformanceLogging`, `performanceLogThresholdMs`, and\n * `snapshotDebounceMs`. The packaged tsserver plugin wires these from\n * `FORMSPEC_PLUGIN_PROFILE=1` and `FORMSPEC_PLUGIN_PROFILE_THRESHOLD_MS`.\n *\n * @public\n */\nexport type FormSpecPluginServiceOptions = FormSpecSemanticServiceOptions;\n\n/**\n * Reference manifest/socket wrapper around `FormSpecSemanticService`.\n *\n * Downstream TypeScript hosts that already control their own plugin/runtime\n * lifecycle can use `FormSpecSemanticService` directly and skip this wrapper.\n *\n * @public\n */\nexport class FormSpecPluginService {\n private readonly manifest: FormSpecAnalysisManifest;\n private readonly runtimePaths: FormSpecWorkspaceRuntimePaths;\n private readonly semanticService: FormSpecSemanticService;\n private server: net.Server | null = null;\n\n public constructor(private readonly options: FormSpecPluginServiceOptions) {\n this.semanticService = new FormSpecSemanticService(options);\n this.runtimePaths = getFormSpecWorkspaceRuntimePaths(options.workspaceRoot);\n this.manifest = createFormSpecAnalysisManifest(\n options.workspaceRoot,\n options.typescriptVersion,\n Date.now()\n );\n }\n\n /**\n * Returns the manifest written by the plugin service for workspace discovery.\n *\n * @internal\n */\n public getManifest(): FormSpecAnalysisManifest {\n return this.manifest;\n }\n\n /**\n * Returns the underlying semantic service used by this reference wrapper.\n *\n * @public\n */\n public getSemanticService(): FormSpecSemanticService {\n return this.semanticService;\n }\n\n /**\n * Starts the IPC transport and writes the current workspace manifest.\n *\n * Calling this more than once is a no-op.\n *\n * @public\n */\n public async start(): Promise<void> {\n if (this.server !== null) {\n return;\n }\n\n await fs.mkdir(this.runtimePaths.runtimeDirectory, { recursive: true });\n if (this.runtimePaths.endpoint.kind === \"unix-socket\") {\n await fs.rm(this.runtimePaths.endpoint.address, { force: true });\n }\n\n this.server = net.createServer((socket) => {\n let buffer = \"\";\n socket.setEncoding(\"utf8\");\n socket.setTimeout(FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS, () => {\n this.options.logger?.info(\n `[FormSpec] Closing idle semantic query socket for ${this.runtimePaths.workspaceRoot}`\n );\n socket.destroy();\n });\n socket.on(\"data\", (chunk) => {\n buffer += String(chunk);\n if (buffer.length > FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES) {\n socket.end(\n `${JSON.stringify({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `FormSpec semantic query exceeded ${String(FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES)} bytes`,\n } satisfies FormSpecSemanticResponse)}\\n`\n );\n return;\n }\n\n const newlineIndex = buffer.indexOf(\"\\n\");\n if (newlineIndex < 0) {\n return;\n }\n\n const payload = buffer.slice(0, newlineIndex);\n const remaining = buffer.slice(newlineIndex + 1);\n if (remaining.trim().length > 0) {\n this.options.logger?.info(\n `[FormSpec] Ignoring extra semantic query payload data for ${this.runtimePaths.workspaceRoot}`\n );\n }\n buffer = remaining;\n // The FormSpec IPC transport is intentionally one-request-per-connection.\n this.respondToSocket(socket, payload);\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n const handleError = (error: Error) => {\n reject(error);\n };\n this.server?.once(\"error\", handleError);\n this.server?.listen(this.runtimePaths.endpoint.address, () => {\n this.server?.off(\"error\", handleError);\n resolve();\n });\n });\n\n await this.writeManifest();\n }\n\n /**\n * Stops the IPC transport, clears semantic state, and removes runtime artifacts.\n *\n * @public\n */\n public async stop(): Promise<void> {\n this.semanticService.dispose();\n\n const server = this.server;\n this.server = null;\n if (server?.listening === true) {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error === undefined) {\n resolve();\n return;\n }\n reject(error);\n });\n });\n }\n\n await this.cleanupRuntimeArtifacts();\n }\n\n /**\n * Schedules a background refresh for the cached semantic snapshot of a file.\n *\n * @public\n */\n public scheduleSnapshotRefresh(filePath: string): void {\n this.semanticService.scheduleSnapshotRefresh(filePath);\n }\n\n /**\n * Handles a semantic query issued against the plugin transport.\n *\n * @internal\n */\n public handleQuery(query: FormSpecSemanticQuery): FormSpecSemanticResponse {\n if (this.options.enablePerformanceLogging === true) {\n const startedAt = performance.now();\n const response = this.executeQuery(query);\n this.logQueryDuration(query, performance.now() - startedAt);\n return response;\n }\n\n return this.executeQuery(query);\n }\n\n private executeQuery(query: FormSpecSemanticQuery): FormSpecSemanticResponse {\n switch (query.kind) {\n case \"health\":\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"health\",\n manifest: this.manifest,\n };\n case \"completion\": {\n const result = this.semanticService.getCompletionContext(query.filePath, query.offset);\n if (result === null) {\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `Unable to resolve TypeScript source file for ${query.filePath}`,\n };\n }\n\n return {\n ...result,\n kind: \"completion\",\n };\n }\n case \"hover\": {\n const result = this.semanticService.getHover(query.filePath, query.offset);\n if (result === null) {\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `Unable to resolve TypeScript source file for ${query.filePath}`,\n };\n }\n\n return {\n ...result,\n kind: \"hover\",\n };\n }\n case \"diagnostics\": {\n const result = this.semanticService.getDiagnostics(query.filePath);\n return {\n ...result,\n kind: \"diagnostics\",\n };\n }\n case \"file-snapshot\":\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"file-snapshot\",\n snapshot: this.semanticService.getFileSnapshot(query.filePath),\n };\n default: {\n throw new Error(`Unhandled semantic query: ${JSON.stringify(query)}`);\n }\n }\n }\n\n private respondToSocket(socket: net.Socket, payload: string): void {\n try {\n const query = JSON.parse(payload) as unknown;\n if (!isFormSpecSemanticQuery(query)) {\n throw new Error(\"Invalid FormSpec semantic query payload\");\n }\n const response = this.handleQuery(query);\n socket.end(`${JSON.stringify(response)}\\n`);\n } catch (error) {\n socket.end(\n `${JSON.stringify({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: error instanceof Error ? error.message : String(error),\n } satisfies FormSpecSemanticResponse)}\\n`\n );\n }\n }\n\n private async writeManifest(): Promise<void> {\n const tempManifestPath = `${this.runtimePaths.manifestPath}.tmp`;\n await fs.writeFile(tempManifestPath, `${JSON.stringify(this.manifest, null, 2)}\\n`, \"utf8\");\n await fs.rename(tempManifestPath, this.runtimePaths.manifestPath);\n }\n\n private async cleanupRuntimeArtifacts(): Promise<void> {\n await fs.rm(this.runtimePaths.manifestPath, { force: true });\n\n if (this.runtimePaths.endpoint.kind === \"unix-socket\") {\n await fs.rm(this.runtimePaths.endpoint.address, { force: true });\n }\n }\n\n private logQueryDuration(query: FormSpecSemanticQuery, durationMs: number): void {\n const logger = this.options.logger;\n if (logger === undefined) {\n return;\n }\n\n const thresholdMs =\n this.options.performanceLogThresholdMs ??\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS;\n if (durationMs < thresholdMs) {\n return;\n }\n\n const event: FormSpecPerformanceEvent = {\n name: \"plugin.handleQuery\",\n durationMs,\n detail: {\n kind: query.kind,\n ...(query.kind === \"health\" ? {} : { filePath: query.filePath }),\n },\n };\n logger.info(`[FormSpec][perf] ${formatPerformanceEvent(event)}`);\n }\n}\n\n/**\n * Reference proxy wrapper that keeps FormSpec semantic snapshots fresh while\n * delegating actual TypeScript editor features to the original service.\n *\n * @public\n */\nexport function createLanguageServiceProxy(\n languageService: ts.LanguageService,\n semanticService: FormSpecSemanticService\n): ts.LanguageService {\n const wrapWithSnapshotRefresh = <Args extends readonly unknown[], Result>(\n fn: (fileName: string, ...args: Args) => Result\n ) => {\n return (fileName: string, ...args: Args): Result => {\n semanticService.scheduleSnapshotRefresh(fileName);\n return fn(fileName, ...args);\n };\n };\n\n const getSemanticDiagnostics = wrapWithSnapshotRefresh((fileName) =>\n languageService.getSemanticDiagnostics(fileName)\n );\n\n const getCompletionsAtPosition = wrapWithSnapshotRefresh(\n (fileName: string, position: number, options: ts.GetCompletionsAtPositionOptions | undefined) =>\n languageService.getCompletionsAtPosition(fileName, position, options)\n );\n\n const getQuickInfoAtPosition = wrapWithSnapshotRefresh((fileName, position: number) =>\n languageService.getQuickInfoAtPosition(fileName, position)\n );\n\n return new Proxy(languageService, {\n get(target, property, receiver) {\n switch (property) {\n case \"getSemanticDiagnostics\":\n return getSemanticDiagnostics;\n case \"getCompletionsAtPosition\":\n return getCompletionsAtPosition;\n case \"getQuickInfoAtPosition\":\n return getQuickInfoAtPosition;\n default:\n return Reflect.get(target, property, receiver) as unknown;\n }\n },\n });\n}\n\nexport type { LoggerLike };\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n FORMSPEC_ANALYSIS_SCHEMA_VERSION,\n} from \"@formspec/analysis/protocol\";\nimport {\n getFormSpecManifestPath,\n getFormSpecWorkspaceId,\n getFormSpecWorkspaceRuntimeDirectory,\n type FormSpecAnalysisManifest,\n type FormSpecIpcEndpoint,\n} from \"@formspec/analysis/internal\";\n\nexport interface FormSpecWorkspaceRuntimePaths {\n readonly workspaceRoot: string;\n readonly workspaceId: string;\n readonly runtimeDirectory: string;\n readonly manifestPath: string;\n readonly endpoint: FormSpecIpcEndpoint;\n}\n\nexport function getFormSpecWorkspaceRuntimePaths(\n workspaceRoot: string,\n platform = process.platform,\n userScope = getFormSpecUserScope()\n): FormSpecWorkspaceRuntimePaths {\n const workspaceId = getFormSpecWorkspaceId(workspaceRoot);\n const runtimeDirectory = getFormSpecWorkspaceRuntimeDirectory(workspaceRoot);\n const sanitizedUserScope = sanitizeScopeSegment(userScope);\n const endpoint: FormSpecIpcEndpoint =\n platform === \"win32\"\n ? {\n kind: \"windows-pipe\",\n address: `\\\\\\\\.\\\\pipe\\\\formspec-${sanitizedUserScope}-${workspaceId}`,\n }\n : {\n kind: \"unix-socket\",\n address: path.join(os.tmpdir(), `formspec-${sanitizedUserScope}-${workspaceId}.sock`),\n };\n\n return {\n workspaceRoot,\n workspaceId,\n runtimeDirectory,\n manifestPath: getFormSpecManifestPath(workspaceRoot),\n endpoint,\n };\n}\n\nexport function createFormSpecAnalysisManifest(\n workspaceRoot: string,\n typescriptVersion: string,\n generation: number,\n extensionFingerprint = \"builtin\"\n): FormSpecAnalysisManifest {\n const paths = getFormSpecWorkspaceRuntimePaths(workspaceRoot);\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n analysisSchemaVersion: FORMSPEC_ANALYSIS_SCHEMA_VERSION,\n workspaceRoot,\n workspaceId: paths.workspaceId,\n endpoint: paths.endpoint,\n typescriptVersion,\n extensionFingerprint,\n generation,\n updatedAt: new Date().toISOString(),\n };\n}\n\nfunction getFormSpecUserScope(): string {\n try {\n return sanitizeScopeSegment(os.userInfo().username);\n } catch {\n return sanitizeScopeSegment(\n process.env[\"USER\"] ?? process.env[\"USERNAME\"] ?? process.env[\"LOGNAME\"] ?? \"formspec\"\n );\n }\n}\n\nfunction sanitizeScopeSegment(value: string): string {\n const trimmed = value.trim().toLowerCase();\n const sanitized = trimmed.replace(/[^a-z0-9_-]+/gu, \"-\").replace(/-+/gu, \"-\");\n return sanitized.length > 0 ? sanitized : \"formspec\";\n}\n","import * as ts from \"typescript\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n computeFormSpecTextHash,\n type FormSpecAnalysisDiagnostic,\n type FormSpecAnalysisFileSnapshot,\n type FormSpecSerializedCompletionContext,\n type FormSpecSerializedHoverInfo,\n} from \"@formspec/analysis/protocol\";\nimport {\n buildFormSpecAnalysisFileSnapshot,\n createFormSpecPerformanceRecorder,\n findDeclarationForCommentOffset,\n getCommentHoverInfoAtOffset,\n getSemanticCommentCompletionContextAtOffset,\n getFormSpecPerformanceNow,\n getSubjectType,\n optionalMeasure,\n resolveDeclarationPlacement,\n serializeCompletionContext,\n serializeHoverInfo,\n type BuildFormSpecAnalysisFileSnapshotOptions,\n type FormSpecPerformanceEvent,\n type FormSpecPerformanceRecorder,\n} from \"@formspec/analysis/internal\";\nimport {\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS,\n FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS,\n} from \"./constants.js\";\nimport { formatPerformanceEvent } from \"./perf-utils.js\";\n\n/**\n * Minimal logging surface used by the semantic service and plugin wrapper.\n *\n * @public\n */\nexport interface LoggerLike {\n /** Writes a human-readable diagnostic or profiling message. */\n info(message: string): void;\n}\n\n/**\n * Configuration for the reusable in-process semantic service.\n *\n * @public\n */\nexport interface FormSpecSemanticServiceOptions {\n /** Workspace root used for runtime paths and contextual logging. */\n readonly workspaceRoot: string;\n /** TypeScript version string reported by the host runtime. */\n readonly typescriptVersion: string;\n /** Supplies the current host program. Returns `undefined` until ready. */\n readonly getProgram: () => ts.Program | undefined;\n /** Optional logger used for profiling and refresh-failure messages. */\n readonly logger?: LoggerLike;\n /** Enables structured hotspot logging for semantic queries. */\n readonly enablePerformanceLogging?: boolean;\n /** Minimum query duration, in milliseconds, required before logging. */\n readonly performanceLogThresholdMs?: number;\n /** Debounce window, in milliseconds, for background snapshot refresh. */\n readonly snapshotDebounceMs?: number;\n /** Injectable clock used by tests and runtime snapshot timestamps. */\n readonly now?: () => Date;\n}\n\n/**\n * Serialized completion result returned by the semantic service.\n *\n * @public\n */\nexport interface FormSpecSemanticCompletionResult {\n /** Protocol version used by the serialized response. */\n readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;\n /** Hash of the source file used to compute the response. */\n readonly sourceHash: string;\n /** Serialized completion payload for the active cursor context. */\n readonly context: FormSpecSerializedCompletionContext;\n}\n\n/**\n * Serialized hover result returned by the semantic service.\n *\n * @public\n */\nexport interface FormSpecSemanticHoverResult {\n /** Protocol version used by the serialized response. */\n readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;\n /** Hash of the source file used to compute the response. */\n readonly sourceHash: string;\n /** Serialized hover payload, or `null` when nothing is available at the cursor. */\n readonly hover: FormSpecSerializedHoverInfo | null;\n}\n\n/**\n * Serialized diagnostics result returned by the semantic service.\n *\n * @public\n */\nexport interface FormSpecSemanticDiagnosticsResult {\n /** Protocol version used by the serialized response. */\n readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;\n /** Hash of the source file used to compute the response. */\n readonly sourceHash: string;\n /** Canonical FormSpec diagnostics for the requested file. */\n readonly diagnostics: readonly FormSpecAnalysisDiagnostic[];\n}\n\n/**\n * Performance and cache counters exposed by the semantic service.\n *\n * @public\n */\nexport interface FormSpecSemanticServiceStats {\n /** Total number of calls by semantic query kind. */\n readonly queryTotals: {\n readonly completion: number;\n readonly hover: number;\n readonly diagnostics: number;\n readonly fileSnapshot: number;\n };\n /** Cold vs warm query path counts for snapshot-backed operations. */\n readonly queryPathTotals: {\n readonly diagnostics: { readonly cold: number; readonly warm: number };\n readonly fileSnapshot: { readonly cold: number; readonly warm: number };\n };\n /** Number of file snapshot cache hits. */\n readonly fileSnapshotCacheHits: number;\n /** Number of file snapshot cache misses. */\n readonly fileSnapshotCacheMisses: number;\n /** Number of synthetic batch cache hits. */\n readonly syntheticBatchCacheHits: number;\n /** Number of synthetic batch cache misses. */\n readonly syntheticBatchCacheMisses: number;\n /** Number of synthetic compiler program creations. */\n readonly syntheticCompileCount: number;\n /** Total synthetic application count compiled across misses. */\n readonly syntheticCompileApplications: number;\n}\n\ninterface CachedFileSnapshot {\n readonly sourceHash: string;\n readonly snapshot: FormSpecAnalysisFileSnapshot;\n}\n\ninterface SourceEnvironment {\n readonly sourceFile: ts.SourceFile;\n readonly checker: ts.TypeChecker;\n readonly sourceHash: string;\n}\n\ninterface CommentQueryContext extends SourceEnvironment {\n readonly declaration: ts.Node | null;\n readonly placement: ReturnType<typeof resolveDeclarationPlacement>;\n readonly subjectType: ts.Type | undefined;\n}\n\ntype SnapshotCacheState = \"hit\" | \"miss\" | \"missing-source\";\n\ninterface MutableSemanticServiceStats {\n queryTotals: {\n completion: number;\n hover: number;\n diagnostics: number;\n fileSnapshot: number;\n };\n queryPathTotals: {\n diagnostics: { cold: number; warm: number };\n fileSnapshot: { cold: number; warm: number };\n };\n fileSnapshotCacheHits: number;\n fileSnapshotCacheMisses: number;\n syntheticBatchCacheHits: number;\n syntheticBatchCacheMisses: number;\n syntheticCompileCount: number;\n syntheticCompileApplications: number;\n}\n\nconst STATS_ONLY_EVENT_NAMES = new Set<string>([\n \"analysis.syntheticCheckBatch.cacheHit\",\n \"analysis.narrowSyntheticCheckBatch.cacheHit\",\n \"analysis.syntheticCheckBatch.cacheMiss\",\n \"analysis.narrowSyntheticCheckBatch.cacheMiss\",\n \"analysis.syntheticCheckBatch.createProgram\",\n \"analysis.narrowSyntheticCheckBatch.createProgram\",\n]);\n\nclass StatsOnlyPerformanceRecorder implements FormSpecPerformanceRecorder {\n private readonly mutableEvents: FormSpecPerformanceEvent[] = [];\n\n public get events(): readonly FormSpecPerformanceEvent[] {\n return this.mutableEvents;\n }\n\n public measure<T>(\n name: string,\n detail: Readonly<Record<string, string | number | boolean>> | undefined,\n callback: () => T\n ): T {\n const result = callback();\n if (STATS_ONLY_EVENT_NAMES.has(name)) {\n this.mutableEvents.push({\n name,\n durationMs: 0,\n ...(detail === undefined ? {} : { detail }),\n });\n }\n return result;\n }\n\n public record(event: FormSpecPerformanceEvent): void {\n if (STATS_ONLY_EVENT_NAMES.has(event.name)) {\n this.mutableEvents.push(event);\n }\n }\n}\n/**\n * Reusable in-process semantic service for FormSpec authoring features.\n *\n * Downstream TypeScript hosts can construct this directly against their own\n * `Program` and own the final presentation of completions, hover, and\n * diagnostics. The shipped tsserver plugin is a reference wrapper over this\n * public service.\n *\n * @public\n */\nexport class FormSpecSemanticService {\n private readonly snapshotCache = new Map<string, CachedFileSnapshot>();\n private readonly refreshTimers = new Map<string, NodeJS.Timeout>();\n private readonly stats: MutableSemanticServiceStats = {\n queryTotals: {\n completion: 0,\n hover: 0,\n diagnostics: 0,\n fileSnapshot: 0,\n },\n queryPathTotals: {\n diagnostics: { cold: 0, warm: 0 },\n fileSnapshot: { cold: 0, warm: 0 },\n },\n fileSnapshotCacheHits: 0,\n fileSnapshotCacheMisses: 0,\n syntheticBatchCacheHits: 0,\n syntheticBatchCacheMisses: 0,\n syntheticCompileCount: 0,\n syntheticCompileApplications: 0,\n };\n\n public constructor(private readonly options: FormSpecSemanticServiceOptions) {}\n\n /** Resolves semantic completion context for a comment cursor position. */\n public getCompletionContext(\n filePath: string,\n offset: number\n ): FormSpecSemanticCompletionResult | null {\n this.stats.queryTotals.completion += 1;\n return this.runMeasured(\"semantic.getCompletionContext\", { filePath, offset }, (performance) =>\n this.withCommentQueryContext(filePath, offset, performance, (context) => ({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n sourceHash: context.sourceHash,\n context: serializeCompletionContext(\n getSemanticCommentCompletionContextAtOffset(context.sourceFile.text, offset, {\n checker: context.checker,\n ...(context.placement === null ? {} : { placement: context.placement }),\n ...(context.subjectType === undefined ? {} : { subjectType: context.subjectType }),\n })\n ),\n }))\n );\n }\n\n /** Resolves semantic hover payload for a comment cursor position. */\n public getHover(filePath: string, offset: number): FormSpecSemanticHoverResult | null {\n this.stats.queryTotals.hover += 1;\n return this.runMeasured(\"semantic.getHover\", { filePath, offset }, (performance) =>\n this.withCommentQueryContext(filePath, offset, performance, (context) => ({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n sourceHash: context.sourceHash,\n hover: serializeHoverInfo(\n getCommentHoverInfoAtOffset(context.sourceFile.text, offset, {\n checker: context.checker,\n ...(context.placement === null ? {} : { placement: context.placement }),\n ...(context.subjectType === undefined ? {} : { subjectType: context.subjectType }),\n })\n ),\n }))\n );\n }\n\n /** Returns canonical FormSpec diagnostics for a file in the current host program. */\n public getDiagnostics(filePath: string): FormSpecSemanticDiagnosticsResult {\n this.stats.queryTotals.diagnostics += 1;\n return this.runMeasured(\"semantic.getDiagnostics\", { filePath }, (performance) => {\n const { snapshot, cacheState } = this.getFileSnapshotWithCacheState(filePath, performance);\n this.recordQueryPath(\"diagnostics\", cacheState);\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n sourceHash: snapshot.sourceHash,\n diagnostics: snapshot.diagnostics,\n };\n });\n }\n\n /** Returns the full serialized semantic snapshot for a file. */\n public getFileSnapshot(filePath: string): FormSpecAnalysisFileSnapshot {\n this.stats.queryTotals.fileSnapshot += 1;\n return this.runMeasured(\"semantic.getFileSnapshot\", { filePath }, (performance) => {\n const { snapshot, cacheState } = this.getFileSnapshotWithCacheState(filePath, performance);\n this.recordQueryPath(\"fileSnapshot\", cacheState);\n return snapshot;\n });\n }\n\n /** Schedules a debounced background refresh for the file snapshot cache. */\n public scheduleSnapshotRefresh(filePath: string): void {\n const existing = this.refreshTimers.get(filePath);\n if (existing !== undefined) {\n clearTimeout(existing);\n }\n\n const timer = setTimeout(() => {\n try {\n this.getFileSnapshot(filePath);\n } catch (error: unknown) {\n this.options.logger?.info(\n `[FormSpec] Failed to refresh semantic snapshot for ${filePath}: ${String(error)}`\n );\n }\n this.refreshTimers.delete(filePath);\n }, this.options.snapshotDebounceMs ?? FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS);\n timer.unref();\n\n this.refreshTimers.set(filePath, timer);\n }\n\n /** Clears pending timers and cached semantic snapshots. */\n public dispose(): void {\n for (const timer of this.refreshTimers.values()) {\n clearTimeout(timer);\n }\n this.refreshTimers.clear();\n this.snapshotCache.clear();\n }\n\n /** Returns a copy of the current performance and cache counters. */\n public getStats(): FormSpecSemanticServiceStats {\n return {\n queryTotals: { ...this.stats.queryTotals },\n queryPathTotals: {\n diagnostics: { ...this.stats.queryPathTotals.diagnostics },\n fileSnapshot: { ...this.stats.queryPathTotals.fileSnapshot },\n },\n fileSnapshotCacheHits: this.stats.fileSnapshotCacheHits,\n fileSnapshotCacheMisses: this.stats.fileSnapshotCacheMisses,\n syntheticBatchCacheHits: this.stats.syntheticBatchCacheHits,\n syntheticBatchCacheMisses: this.stats.syntheticBatchCacheMisses,\n syntheticCompileCount: this.stats.syntheticCompileCount,\n syntheticCompileApplications: this.stats.syntheticCompileApplications,\n };\n }\n\n private runMeasured<T>(\n name: string,\n detail: Record<string, string | number>,\n fn: (performance: FormSpecPerformanceRecorder) => T\n ): T {\n const performance =\n this.options.enablePerformanceLogging === true\n ? createFormSpecPerformanceRecorder()\n : new StatsOnlyPerformanceRecorder();\n const result = optionalMeasure(performance, name, detail, () => fn(performance));\n this.updateStatsFromPerformanceEvents(performance.events);\n if (this.options.enablePerformanceLogging === true) {\n this.logPerformanceEvents(name, performance.events);\n }\n return result;\n }\n\n private withCommentQueryContext<T>(\n filePath: string,\n offset: number,\n performance: FormSpecPerformanceRecorder,\n handler: (context: CommentQueryContext) => T\n ): T | null {\n return optionalMeasure(\n performance,\n \"semantic.resolveCommentQueryContext\",\n {\n filePath,\n offset,\n },\n () => {\n const environment = this.getSourceEnvironment(filePath, performance);\n if (environment === null) {\n return null;\n }\n\n const declaration = optionalMeasure(\n performance,\n \"semantic.findDeclarationForCommentOffset\",\n {\n filePath,\n offset,\n },\n () => findDeclarationForCommentOffset(environment.sourceFile, offset)\n );\n const placement =\n declaration === null\n ? null\n : optionalMeasure(performance, \"semantic.resolveDeclarationPlacement\", undefined, () =>\n resolveDeclarationPlacement(declaration)\n );\n const subjectType =\n declaration === null\n ? undefined\n : optionalMeasure(performance, \"semantic.getSubjectType\", undefined, () =>\n getSubjectType(declaration, environment.checker)\n );\n\n return handler({\n ...environment,\n declaration,\n placement,\n subjectType,\n });\n }\n );\n }\n\n private getFileSnapshotWithCacheState(\n filePath: string,\n performance: FormSpecPerformanceRecorder\n ): {\n readonly snapshot: FormSpecAnalysisFileSnapshot;\n readonly cacheState: SnapshotCacheState;\n } {\n const startedAt = getFormSpecPerformanceNow();\n const environment = this.getSourceEnvironment(filePath, performance);\n if (environment === null) {\n this.stats.fileSnapshotCacheMisses += 1;\n const snapshot: FormSpecAnalysisFileSnapshot = {\n filePath,\n sourceHash: \"\",\n generatedAt: this.getNow().toISOString(),\n comments: [],\n diagnostics: [\n {\n code: \"MISSING_SOURCE_FILE\",\n category: \"infrastructure\",\n message: `Unable to resolve TypeScript source file for ${filePath}`,\n range: { start: 0, end: 0 },\n severity: \"warning\",\n relatedLocations: [],\n data: {\n filePath,\n },\n },\n ],\n };\n performance.record({\n name: \"semantic.getFileSnapshot.result\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"missing-source\",\n },\n });\n return {\n snapshot,\n cacheState: \"missing-source\",\n };\n }\n\n const cached = this.snapshotCache.get(filePath);\n if (cached?.sourceHash === environment.sourceHash) {\n this.stats.fileSnapshotCacheHits += 1;\n performance.record({\n name: \"semantic.getFileSnapshot.result\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"hit\",\n },\n });\n return {\n snapshot: cached.snapshot,\n cacheState: \"hit\",\n };\n }\n\n this.stats.fileSnapshotCacheMisses += 1;\n const snapshot = buildFormSpecAnalysisFileSnapshot(environment.sourceFile, {\n checker: environment.checker,\n now: () => this.getNow(),\n performance,\n } satisfies BuildFormSpecAnalysisFileSnapshotOptions);\n this.snapshotCache.set(filePath, {\n sourceHash: environment.sourceHash,\n snapshot,\n });\n performance.record({\n name: \"semantic.getFileSnapshot.result\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"miss\",\n },\n });\n return {\n snapshot,\n cacheState: \"miss\",\n };\n }\n\n private getNow(): Date {\n return this.options.now?.() ?? new Date();\n }\n\n private getSourceEnvironment(\n filePath: string,\n performance: FormSpecPerformanceRecorder\n ): SourceEnvironment | null {\n return optionalMeasure(\n performance,\n \"semantic.getSourceEnvironment\",\n {\n filePath,\n },\n () => {\n const program = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.getProgram\",\n undefined,\n () => this.options.getProgram()\n );\n if (program === undefined) {\n return null;\n }\n\n const sourceFile = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.getSourceFile\",\n undefined,\n () => program.getSourceFile(filePath)\n );\n if (sourceFile === undefined) {\n return null;\n }\n\n const checker = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.getTypeChecker\",\n undefined,\n () => program.getTypeChecker()\n );\n const sourceHash = optionalMeasure(\n performance,\n \"semantic.sourceEnvironment.computeTextHash\",\n undefined,\n () => computeFormSpecTextHash(sourceFile.text)\n );\n\n return {\n sourceFile,\n checker,\n sourceHash,\n };\n }\n );\n }\n\n private recordQueryPath(\n kind: \"diagnostics\" | \"fileSnapshot\",\n cacheState: SnapshotCacheState\n ): void {\n if (cacheState === \"hit\") {\n this.stats.queryPathTotals[kind].warm += 1;\n return;\n }\n\n this.stats.queryPathTotals[kind].cold += 1;\n }\n\n private updateStatsFromPerformanceEvents(events: readonly FormSpecPerformanceEvent[]): void {\n for (const event of events) {\n if (\n event.name === \"analysis.syntheticCheckBatch.cacheHit\" ||\n event.name === \"analysis.narrowSyntheticCheckBatch.cacheHit\"\n ) {\n this.stats.syntheticBatchCacheHits += 1;\n continue;\n }\n\n if (\n event.name === \"analysis.syntheticCheckBatch.cacheMiss\" ||\n event.name === \"analysis.narrowSyntheticCheckBatch.cacheMiss\"\n ) {\n this.stats.syntheticBatchCacheMisses += 1;\n const applicationCount = event.detail?.[\"applicationCount\"];\n if (typeof applicationCount === \"number\") {\n this.stats.syntheticCompileApplications += applicationCount;\n }\n continue;\n }\n\n if (\n event.name === \"analysis.syntheticCheckBatch.createProgram\" ||\n event.name === \"analysis.narrowSyntheticCheckBatch.createProgram\"\n ) {\n this.stats.syntheticCompileCount += 1;\n }\n }\n }\n\n private logPerformanceEvents(\n rootEventName: string,\n events: readonly FormSpecPerformanceEvent[]\n ): void {\n const logger = this.options.logger;\n if (logger === undefined || events.length === 0) {\n return;\n }\n\n const rootEvent = [...events].reverse().find((event) => event.name === rootEventName);\n if (rootEvent === undefined) {\n return;\n }\n\n const thresholdMs =\n this.options.performanceLogThresholdMs ??\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS;\n if (rootEvent.durationMs < thresholdMs) {\n return;\n }\n\n const sortedHotspots = [...events]\n .filter((event) => event.name !== rootEventName)\n .sort((left, right) => right.durationMs - left.durationMs)\n .slice(0, 8);\n const lines = [\n `[FormSpec][perf] ${formatPerformanceEvent(rootEvent)}`,\n ...sortedHotspots.map((event) => ` ${formatPerformanceEvent(event)}`),\n ];\n logger.info(lines.join(\"\\n\"));\n }\n}\n","export const FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES = 256 * 1024;\nexport const FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS = 30_000;\nexport const FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS = 50;\nexport const FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS = 250;\n\nexport const FORM_SPEC_PLUGIN_PERFORMANCE_EVENT = {\n handleQuery: \"plugin.handleQuery\",\n} as const;\n","import type { FormSpecPerformanceEvent } from \"@formspec/analysis/internal\";\n\nexport function formatPerformanceEvent(event: FormSpecPerformanceEvent): string {\n const detailEntries = Object.entries(event.detail ?? {})\n .map(([key, value]) => `${key}=${String(value)}`)\n .join(\" \");\n return `${event.durationMs.toFixed(1)}ms ${event.name}${detailEntries === \"\" ? \"\" : ` ${detailEntries}`}`;\n}\n"],"mappings":"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","names":["import_protocol","ts","import_protocol","import_internal","path","os","import_protocol","import_internal","performance","snapshot","fs","net"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript language service plugin entrypoint for FormSpec.
|
|
3
|
+
*
|
|
4
|
+
* This package exposes the reference tsserver plugin and the reusable semantic
|
|
5
|
+
* service used by downstream TypeScript hosts.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
1
9
|
import type * as tsServer from "typescript/lib/tsserverlibrary.js";
|
|
2
|
-
export { FORMSPEC_ANALYSIS_PROTOCOL_VERSION, FORMSPEC_ANALYSIS_SCHEMA_VERSION, type CommentSourceSpan, type CommentSpan, type FormSpecAnalysisCommentSnapshot, type FormSpecAnalysisDiagnostic, type FormSpecAnalysisDiagnosticCategory, type FormSpecAnalysisDiagnosticDataValue, type FormSpecAnalysisDiagnosticLocation, type
|
|
10
|
+
export { FORMSPEC_ANALYSIS_PROTOCOL_VERSION, FORMSPEC_ANALYSIS_SCHEMA_VERSION, type CommentHoverInfo, type CommentSourceSpan, type CommentSpan, type FormSpecAnalysisCommentSnapshot, type FormSpecAnalysisDiagnostic, type FormSpecAnalysisDiagnosticCategory, type FormSpecAnalysisDiagnosticDataValue, type FormSpecAnalysisDiagnosticLocation, type FormSpecAnalysisFileSnapshot, type FormSpecAnalysisTagSnapshot, type FormSpecPlacement, type FormSpecTargetKind, type FormSpecSerializedCommentTargetSpecifier, type FormSpecSerializedCompletionContext, type FormSpecSerializedHoverInfo, type FormSpecSerializedTagDefinition, type FormSpecSerializedTagSemanticContext, type FormSpecSerializedTagSignature, } from "@formspec/analysis/protocol";
|
|
3
11
|
export { createLanguageServiceProxy, FormSpecPluginService, type FormSpecPluginServiceOptions, type LoggerLike, } from "./service.js";
|
|
4
12
|
export { FormSpecSemanticService, type FormSpecSemanticCompletionResult, type FormSpecSemanticDiagnosticsResult, type FormSpecSemanticHoverResult, type FormSpecSemanticServiceOptions, type FormSpecSemanticServiceStats, } from "./semantic-service.js";
|
|
5
13
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,QAAQ,MAAM,mCAAmC,CAAC;AACnE,OAAO,EACL,kCAAkC,EAClC,gCAAgC,EAChC,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,+BAA+B,EACpC,KAAK,0BAA0B,EAC/B,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EACxC,KAAK,kCAAkC,EACvC,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,KAAK,QAAQ,MAAM,mCAAmC,CAAC;AACnE,OAAO,EACL,kCAAkC,EAClC,gCAAgC,EAChC,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,+BAA+B,EACpC,KAAK,0BAA0B,EAC/B,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EACxC,KAAK,kCAAkC,EACvC,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,wCAAwC,EAC7C,KAAK,mCAAmC,EACxC,KAAK,2BAA2B,EAChC,KAAK,+BAA+B,EACpC,KAAK,oCAAoC,EACzC,KAAK,8BAA8B,GACpC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,UAAU,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,KAAK,gCAAgC,EACrC,KAAK,iCAAiC,EACtC,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC;AAgG/B;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE;IAC5B,QAAQ,CAAC,UAAU,EAAE,OAAO,QAAQ,CAAC;CACtC,GAAG,QAAQ,CAAC,MAAM,CAAC,YAAY,CAQ/B"}
|