@formspec/ts-plugin 0.1.0-alpha.23 → 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/dist/index.js.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 type FormSpecAnalysisManifest,\n type FormSpecIpcEndpoint,\n} from \"@formspec/analysis/protocol\";\nimport {\n getFormSpecManifestPath,\n getFormSpecWorkspaceId,\n getFormSpecWorkspaceRuntimeDirectory,\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/** @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":["FORMSPEC_ANALYSIS_PROTOCOL_VERSION","FORMSPEC_ANALYSIS_SCHEMA_VERSION","FORMSPEC_ANALYSIS_PROTOCOL_VERSION","FORMSPEC_ANALYSIS_PROTOCOL_VERSION","performance","FORMSPEC_ANALYSIS_PROTOCOL_VERSION","snapshot","FORMSPEC_ANALYSIS_PROTOCOL_VERSION"]}
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":["FORMSPEC_ANALYSIS_PROTOCOL_VERSION","FORMSPEC_ANALYSIS_SCHEMA_VERSION","FORMSPEC_ANALYSIS_PROTOCOL_VERSION","FORMSPEC_ANALYSIS_PROTOCOL_VERSION","performance","FORMSPEC_ANALYSIS_PROTOCOL_VERSION","snapshot","FORMSPEC_ANALYSIS_PROTOCOL_VERSION"]}
@@ -1,10 +1,19 @@
1
1
  import * as ts from "typescript";
2
2
  import { FORMSPEC_ANALYSIS_PROTOCOL_VERSION, type FormSpecAnalysisDiagnostic, type FormSpecAnalysisFileSnapshot, type FormSpecSerializedCompletionContext, type FormSpecSerializedHoverInfo } from "@formspec/analysis/protocol";
3
- /** @public */
3
+ /**
4
+ * Minimal logging surface used by the semantic service and plugin wrapper.
5
+ *
6
+ * @public
7
+ */
4
8
  export interface LoggerLike {
9
+ /** Writes a human-readable diagnostic or profiling message. */
5
10
  info(message: string): void;
6
11
  }
7
- /** @public */
12
+ /**
13
+ * Configuration for the reusable in-process semantic service.
14
+ *
15
+ * @public
16
+ */
8
17
  export interface FormSpecSemanticServiceOptions {
9
18
  /** Workspace root used for runtime paths and contextual logging. */
10
19
  readonly workspaceRoot: string;
@@ -23,25 +32,50 @@ export interface FormSpecSemanticServiceOptions {
23
32
  /** Injectable clock used by tests and runtime snapshot timestamps. */
24
33
  readonly now?: () => Date;
25
34
  }
26
- /** @public */
35
+ /**
36
+ * Serialized completion result returned by the semantic service.
37
+ *
38
+ * @public
39
+ */
27
40
  export interface FormSpecSemanticCompletionResult {
41
+ /** Protocol version used by the serialized response. */
28
42
  readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;
43
+ /** Hash of the source file used to compute the response. */
29
44
  readonly sourceHash: string;
45
+ /** Serialized completion payload for the active cursor context. */
30
46
  readonly context: FormSpecSerializedCompletionContext;
31
47
  }
32
- /** @public */
48
+ /**
49
+ * Serialized hover result returned by the semantic service.
50
+ *
51
+ * @public
52
+ */
33
53
  export interface FormSpecSemanticHoverResult {
54
+ /** Protocol version used by the serialized response. */
34
55
  readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;
56
+ /** Hash of the source file used to compute the response. */
35
57
  readonly sourceHash: string;
58
+ /** Serialized hover payload, or `null` when nothing is available at the cursor. */
36
59
  readonly hover: FormSpecSerializedHoverInfo | null;
37
60
  }
38
- /** @public */
61
+ /**
62
+ * Serialized diagnostics result returned by the semantic service.
63
+ *
64
+ * @public
65
+ */
39
66
  export interface FormSpecSemanticDiagnosticsResult {
67
+ /** Protocol version used by the serialized response. */
40
68
  readonly protocolVersion: typeof FORMSPEC_ANALYSIS_PROTOCOL_VERSION;
69
+ /** Hash of the source file used to compute the response. */
41
70
  readonly sourceHash: string;
71
+ /** Canonical FormSpec diagnostics for the requested file. */
42
72
  readonly diagnostics: readonly FormSpecAnalysisDiagnostic[];
43
73
  }
44
- /** @public */
74
+ /**
75
+ * Performance and cache counters exposed by the semantic service.
76
+ *
77
+ * @public
78
+ */
45
79
  export interface FormSpecSemanticServiceStats {
46
80
  /** Total number of calls by semantic query kind. */
47
81
  readonly queryTotals: {
@@ -1 +1 @@
1
- {"version":3,"file":"semantic-service.d.ts","sourceRoot":"","sources":["../src/semantic-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"semantic-service.d.ts","sourceRoot":"","sources":["../src/semantic-service.ts"],"names":[],"mappings":"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"}
package/dist/service.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as ts from "typescript";
2
- import { type FormSpecAnalysisManifest, type FormSpecSemanticQuery, type FormSpecSemanticResponse } from "@formspec/analysis/protocol";
2
+ import { type FormSpecAnalysisManifest, type FormSpecSemanticQuery, type FormSpecSemanticResponse } from "@formspec/analysis/internal";
3
3
  import { FormSpecSemanticService, type FormSpecSemanticServiceOptions, type LoggerLike } from "./semantic-service.js";
4
4
  /**
5
5
  * Public configuration for the reference plugin wrapper that exposes
@@ -28,6 +28,11 @@ export declare class FormSpecPluginService {
28
28
  private readonly semanticService;
29
29
  private server;
30
30
  constructor(options: FormSpecPluginServiceOptions);
31
+ /**
32
+ * Returns the manifest written by the plugin service for workspace discovery.
33
+ *
34
+ * @internal
35
+ */
31
36
  getManifest(): FormSpecAnalysisManifest;
32
37
  /**
33
38
  * Returns the underlying semantic service used by this reference wrapper.
@@ -35,9 +40,31 @@ export declare class FormSpecPluginService {
35
40
  * @public
36
41
  */
37
42
  getSemanticService(): FormSpecSemanticService;
43
+ /**
44
+ * Starts the IPC transport and writes the current workspace manifest.
45
+ *
46
+ * Calling this more than once is a no-op.
47
+ *
48
+ * @public
49
+ */
38
50
  start(): Promise<void>;
51
+ /**
52
+ * Stops the IPC transport, clears semantic state, and removes runtime artifacts.
53
+ *
54
+ * @public
55
+ */
39
56
  stop(): Promise<void>;
57
+ /**
58
+ * Schedules a background refresh for the cached semantic snapshot of a file.
59
+ *
60
+ * @public
61
+ */
40
62
  scheduleSnapshotRefresh(filePath: string): void;
63
+ /**
64
+ * Handles a semantic query issued against the plugin transport.
65
+ *
66
+ * @internal
67
+ */
41
68
  handleQuery(query: FormSpecSemanticQuery): FormSpecSemanticResponse;
42
69
  private executeQuery;
43
70
  private respondToSocket;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AAOrC,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,EACnC,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAQ/B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,4BAA4B,GAAG,8BAA8B,CAAC;AAE1E;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IAMb,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,MAAM,CAA2B;gBAEL,OAAO,EAAE,4BAA4B;IAUlE,WAAW,IAAI,wBAAwB;IAI9C;;;;OAIG;IACI,kBAAkB,IAAI,uBAAuB;IAIvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgEtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI/C,WAAW,CAAC,KAAK,EAAE,qBAAqB,GAAG,wBAAwB;IAW1E,OAAO,CAAC,YAAY;IAyDpB,OAAO,CAAC,eAAe;YAmBT,aAAa;YAMb,uBAAuB;IAQrC,OAAO,CAAC,gBAAgB;CAuBzB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,eAAe,EAAE,uBAAuB,GACvC,EAAE,CAAC,eAAe,CAqCpB;AAED,YAAY,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAIjC,OAAO,EAEL,KAAK,wBAAwB,EAE7B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AAMrC,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,EACnC,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAQ/B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,4BAA4B,GAAG,8BAA8B,CAAC;AAE1E;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IAMb,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,MAAM,CAA2B;gBAEL,OAAO,EAAE,4BAA4B;IAUzE;;;;OAIG;IACI,WAAW,IAAI,wBAAwB;IAI9C;;;;OAIG;IACI,kBAAkB,IAAI,uBAAuB;IAIpD;;;;;;OAMG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgEnC;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBlC;;;;OAIG;IACI,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAItD;;;;OAIG;IACI,WAAW,CAAC,KAAK,EAAE,qBAAqB,GAAG,wBAAwB;IAW1E,OAAO,CAAC,YAAY;IAyDpB,OAAO,CAAC,eAAe;YAmBT,aAAa;YAMb,uBAAuB;IAQrC,OAAO,CAAC,gBAAgB;CAuBzB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,eAAe,EAAE,uBAAuB,GACvC,EAAE,CAAC,eAAe,CAqCpB;AAED,YAAY,EAAE,UAAU,EAAE,CAAC"}