@formspec/ts-plugin 0.1.0-alpha.20 → 0.1.0-alpha.21
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 +8 -0
- package/dist/__tests__/handle-query.test.d.ts +2 -0
- package/dist/__tests__/handle-query.test.d.ts.map +1 -0
- package/dist/__tests__/helpers.d.ts +11 -0
- package/dist/__tests__/helpers.d.ts.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/index.cjs +291 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +290 -105
- package/dist/index.js.map +1 -1
- package/dist/service.d.ts +18 -2
- package/dist/service.d.ts.map +1 -1
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/service.ts","../src/workspace.ts","../src/index.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport net from \"node:net\";\nimport * as ts from \"typescript\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n buildFormSpecAnalysisFileSnapshot,\n computeFormSpecTextHash,\n findDeclarationForCommentOffset,\n getSubjectType,\n getCommentHoverInfoAtOffset,\n getSemanticCommentCompletionContextAtOffset,\n isFormSpecSemanticQuery,\n resolveDeclarationPlacement,\n serializeCompletionContext,\n serializeHoverInfo,\n type BuildFormSpecAnalysisFileSnapshotOptions,\n type FormSpecAnalysisFileSnapshot,\n type FormSpecAnalysisManifest,\n type FormSpecSemanticQuery,\n type FormSpecSemanticResponse,\n} from \"@formspec/analysis\";\nimport {\n createFormSpecAnalysisManifest,\n getFormSpecWorkspaceRuntimePaths,\n type FormSpecWorkspaceRuntimePaths,\n} from \"./workspace.js\";\n\ninterface LoggerLike {\n info(message: string): void;\n}\n\nexport interface FormSpecPluginServiceOptions {\n readonly workspaceRoot: string;\n readonly typescriptVersion: string;\n readonly getProgram: () => ts.Program | undefined;\n readonly logger?: LoggerLike;\n readonly snapshotDebounceMs?: number;\n readonly now?: () => Date;\n}\n\ninterface CachedFileSnapshot {\n readonly sourceHash: string;\n readonly snapshot: FormSpecAnalysisFileSnapshot;\n}\n\nexport class FormSpecPluginService {\n private readonly manifest: FormSpecAnalysisManifest;\n private readonly runtimePaths: FormSpecWorkspaceRuntimePaths;\n private readonly snapshotCache = new Map<string, CachedFileSnapshot>();\n private readonly refreshTimers = new Map<string, NodeJS.Timeout>();\n private server: net.Server | null = null;\n\n public constructor(private readonly options: FormSpecPluginServiceOptions) {\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 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.on(\"data\", (chunk) => {\n buffer += String(chunk);\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 for (const timer of this.refreshTimers.values()) {\n clearTimeout(timer);\n }\n this.refreshTimers.clear();\n this.snapshotCache.clear();\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 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 ?? 250);\n\n this.refreshTimers.set(filePath, timer);\n }\n\n public handleQuery(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 environment = this.getSourceEnvironment(query.filePath);\n if (environment === 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 const declaration = findDeclarationForCommentOffset(environment.sourceFile, query.offset);\n const placement = declaration === null ? null : resolveDeclarationPlacement(declaration);\n const subjectType =\n declaration === null ? undefined : getSubjectType(declaration, environment.checker);\n const context = getSemanticCommentCompletionContextAtOffset(\n environment.sourceFile.text,\n query.offset,\n {\n checker: environment.checker,\n ...(placement === null ? {} : { placement }),\n ...(subjectType === undefined ? {} : { subjectType }),\n }\n );\n\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"completion\",\n sourceHash: computeFormSpecTextHash(environment.sourceFile.text),\n context: serializeCompletionContext(context),\n };\n }\n case \"hover\": {\n const environment = this.getSourceEnvironment(query.filePath);\n if (environment === 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 const declaration = findDeclarationForCommentOffset(environment.sourceFile, query.offset);\n const placement = declaration === null ? null : resolveDeclarationPlacement(declaration);\n const subjectType =\n declaration === null ? undefined : getSubjectType(declaration, environment.checker);\n const hover = getCommentHoverInfoAtOffset(environment.sourceFile.text, query.offset, {\n checker: environment.checker,\n ...(placement === null ? {} : { placement }),\n ...(subjectType === undefined ? {} : { subjectType }),\n });\n\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"hover\",\n sourceHash: computeFormSpecTextHash(environment.sourceFile.text),\n hover: serializeHoverInfo(hover),\n };\n }\n case \"diagnostics\": {\n const snapshot = this.getFileSnapshot(query.filePath);\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"diagnostics\",\n sourceHash: snapshot.sourceHash,\n diagnostics: snapshot.diagnostics,\n };\n }\n case \"file-snapshot\":\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"file-snapshot\",\n snapshot: this.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 if (this.runtimePaths.endpoint.kind === \"unix-socket\") {\n await fs.rm(this.runtimePaths.endpoint.address, { force: true });\n }\n }\n\n private getSourceEnvironment(filePath: string): {\n readonly sourceFile: ts.SourceFile;\n readonly checker: ts.TypeChecker;\n } | null {\n const program = this.options.getProgram();\n if (program === undefined) {\n return null;\n }\n\n const sourceFile = program.getSourceFile(filePath);\n if (sourceFile === undefined) {\n return null;\n }\n\n return {\n sourceFile,\n checker: program.getTypeChecker(),\n };\n }\n\n private getFileSnapshot(filePath: string): FormSpecAnalysisFileSnapshot {\n const environment = this.getSourceEnvironment(filePath);\n if (environment === null) {\n return {\n filePath,\n sourceHash: \"\",\n generatedAt: this.getNow().toISOString(),\n comments: [],\n diagnostics: [\n {\n code: \"MISSING_SOURCE_FILE\",\n message: `Unable to resolve TypeScript source file for ${filePath}`,\n range: { start: 0, end: 0 },\n severity: \"warning\",\n },\n ],\n };\n }\n\n const sourceHash = computeFormSpecTextHash(environment.sourceFile.text);\n const cached = this.snapshotCache.get(filePath);\n if (cached?.sourceHash === sourceHash) {\n return cached.snapshot;\n }\n\n const snapshot = buildFormSpecAnalysisFileSnapshot(environment.sourceFile, {\n checker: environment.checker,\n } satisfies BuildFormSpecAnalysisFileSnapshotOptions);\n this.snapshotCache.set(filePath, {\n sourceHash,\n snapshot,\n });\n return snapshot;\n }\n\n private getNow(): Date {\n return this.options.now?.() ?? new Date();\n }\n}\n\nexport function createLanguageServiceProxy(\n languageService: ts.LanguageService,\n semanticService: FormSpecPluginService\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 // The plugin keeps semantic snapshots fresh for the lightweight LSP. The\n // underlying tsserver results still come from the original language service.\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","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\";\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 type * as tsServer from \"typescript/lib/tsserverlibrary.js\";\nimport { createLanguageServiceProxy, FormSpecPluginService } from \"./service.js\";\n\ninterface ServiceEntry {\n readonly service: FormSpecPluginService;\n referenceCount: number;\n}\n\nconst services = new Map<string, ServiceEntry>();\n\nfunction formatPluginError(error: unknown): string {\n return error instanceof Error ? (error.stack ?? error.message) : String(error);\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 service = new FormSpecPluginService({\n workspaceRoot,\n typescriptVersion,\n getProgram: () => info.languageService.getProgram(),\n logger: info.project.projectService.logger,\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);\n },\n };\n}\n"],"mappings":"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","names":["FORMSPEC_ANALYSIS_PROTOCOL_VERSION","FORMSPEC_ANALYSIS_PROTOCOL_VERSION"]}
|
|
1
|
+
{"version":3,"sources":["../src/service.ts","../src/workspace.ts","../src/constants.ts","../src/index.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport net from \"node:net\";\nimport * as ts from \"typescript\";\nimport {\n FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n computeFormSpecTextHash,\n isFormSpecSemanticQuery,\n type FormSpecAnalysisManifest,\n type FormSpecSemanticQuery,\n type FormSpecSemanticResponse,\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 FormSpecAnalysisFileSnapshot,\n type FormSpecPerformanceEvent,\n type FormSpecPerformanceRecorder,\n} from \"@formspec/analysis/internal\";\nimport {\n createFormSpecAnalysisManifest,\n getFormSpecWorkspaceRuntimePaths,\n type FormSpecWorkspaceRuntimePaths,\n} from \"./workspace.js\";\nimport {\n FORM_SPEC_PLUGIN_DEFAULT_PERFORMANCE_LOG_THRESHOLD_MS,\n FORM_SPEC_PLUGIN_DEFAULT_SNAPSHOT_DEBOUNCE_MS,\n FORM_SPEC_PLUGIN_MAX_SOCKET_PAYLOAD_BYTES,\n FORM_SPEC_PLUGIN_PERFORMANCE_EVENT,\n FORM_SPEC_PLUGIN_SOCKET_IDLE_TIMEOUT_MS,\n} from \"./constants.js\";\n\ninterface LoggerLike {\n info(message: string): void;\n}\n\nexport interface FormSpecPluginServiceOptions {\n readonly workspaceRoot: string;\n readonly typescriptVersion: string;\n readonly getProgram: () => ts.Program | undefined;\n readonly logger?: LoggerLike;\n /**\n * Enables structured hotspot logging for semantic queries.\n *\n * The tsserver plugin sets this from `FORMSPEC_PLUGIN_PROFILE=1`.\n */\n readonly enablePerformanceLogging?: boolean;\n /**\n * Minimum total query duration in milliseconds before profiling is logged.\n *\n * Defaults to `50` when unset. The tsserver plugin sets this from\n * `FORMSPEC_PLUGIN_PROFILE_THRESHOLD_MS`.\n */\n readonly performanceLogThresholdMs?: number;\n readonly snapshotDebounceMs?: number;\n readonly now?: () => Date;\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\nexport class FormSpecPluginService {\n private readonly manifest: FormSpecAnalysisManifest;\n private readonly runtimePaths: FormSpecWorkspaceRuntimePaths;\n private readonly snapshotCache = new Map<string, CachedFileSnapshot>();\n private readonly refreshTimers = new Map<string, NodeJS.Timeout>();\n private server: net.Server | null = null;\n\n public constructor(private readonly options: FormSpecPluginServiceOptions) {\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 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 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 for (const timer of this.refreshTimers.values()) {\n clearTimeout(timer);\n }\n this.refreshTimers.clear();\n this.snapshotCache.clear();\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 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, undefined);\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\n this.refreshTimers.set(filePath, timer);\n }\n\n public handleQuery(query: FormSpecSemanticQuery): FormSpecSemanticResponse {\n const performance =\n this.options.enablePerformanceLogging === true\n ? createFormSpecPerformanceRecorder()\n : undefined;\n const response = optionalMeasure(\n performance,\n FORM_SPEC_PLUGIN_PERFORMANCE_EVENT.handleQuery,\n {\n kind: query.kind,\n ...(query.kind === \"health\" ? {} : { filePath: query.filePath }),\n },\n () => this.executeQuery(query, performance)\n );\n\n if (performance !== undefined) {\n this.logPerformanceEvents(performance.events);\n }\n\n return response;\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 if (this.runtimePaths.endpoint.kind === \"unix-socket\") {\n await fs.rm(this.runtimePaths.endpoint.address, { force: true });\n }\n }\n\n private withCommentQueryContext(\n filePath: string,\n offset: number,\n handler: (context: CommentQueryContext) => FormSpecSemanticResponse,\n performance: FormSpecPerformanceRecorder | undefined\n ): FormSpecSemanticResponse {\n return optionalMeasure(\n performance,\n \"plugin.resolveCommentQueryContext\",\n {\n filePath,\n offset,\n },\n () => {\n const environment = this.getSourceEnvironment(filePath, performance);\n if (environment === null) {\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"error\",\n error: `Unable to resolve TypeScript source file for ${filePath}`,\n };\n }\n\n const declaration = optionalMeasure(\n performance,\n \"plugin.findDeclarationForCommentOffset\",\n {\n filePath,\n offset,\n },\n () => findDeclarationForCommentOffset(environment.sourceFile, offset)\n );\n const placement =\n declaration === null\n ? null\n : optionalMeasure(performance, \"plugin.resolveDeclarationPlacement\", undefined, () =>\n resolveDeclarationPlacement(declaration)\n );\n const subjectType =\n declaration === null\n ? undefined\n : optionalMeasure(performance, \"plugin.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 getFileSnapshot(\n filePath: string,\n performance: FormSpecPerformanceRecorder | undefined\n ): FormSpecAnalysisFileSnapshot {\n const startedAt = getFormSpecPerformanceNow();\n const environment = this.getSourceEnvironment(filePath, performance);\n if (environment === null) {\n const missingSourceSnapshot: FormSpecAnalysisFileSnapshot = {\n filePath,\n sourceHash: \"\",\n generatedAt: this.getNow().toISOString(),\n comments: [],\n diagnostics: [\n {\n code: \"MISSING_SOURCE_FILE\",\n message: `Unable to resolve TypeScript source file for ${filePath}`,\n range: { start: 0, end: 0 },\n severity: \"warning\",\n },\n ],\n };\n performance?.record({\n name: \"plugin.getFileSnapshot\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"missing-source\",\n },\n });\n return missingSourceSnapshot;\n }\n\n const cached = this.snapshotCache.get(filePath);\n if (cached?.sourceHash === environment.sourceHash) {\n performance?.record({\n name: \"plugin.getFileSnapshot\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"hit\",\n },\n });\n return cached.snapshot;\n }\n\n const snapshot = buildFormSpecAnalysisFileSnapshot(environment.sourceFile, {\n checker: environment.checker,\n now: () => this.getNow(),\n ...(performance === undefined ? {} : { performance }),\n } satisfies BuildFormSpecAnalysisFileSnapshotOptions);\n this.snapshotCache.set(filePath, {\n sourceHash: environment.sourceHash,\n snapshot,\n });\n performance?.record({\n name: \"plugin.getFileSnapshot\",\n durationMs: getFormSpecPerformanceNow() - startedAt,\n detail: {\n filePath,\n cache: \"miss\",\n },\n });\n return snapshot;\n }\n\n private getNow(): Date {\n return this.options.now?.() ?? new Date();\n }\n\n private executeQuery(\n query: FormSpecSemanticQuery,\n performance: FormSpecPerformanceRecorder | undefined\n ): 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 return this.withCommentQueryContext(\n query.filePath,\n query.offset,\n (context) => ({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"completion\",\n sourceHash: context.sourceHash,\n context: serializeCompletionContext(\n getSemanticCommentCompletionContextAtOffset(context.sourceFile.text, query.offset, {\n checker: context.checker,\n ...(context.placement === null ? {} : { placement: context.placement }),\n ...(context.subjectType === undefined ? {} : { subjectType: context.subjectType }),\n })\n ),\n }),\n performance\n );\n case \"hover\":\n return this.withCommentQueryContext(\n query.filePath,\n query.offset,\n (context) => ({\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"hover\",\n sourceHash: context.sourceHash,\n hover: serializeHoverInfo(\n getCommentHoverInfoAtOffset(context.sourceFile.text, query.offset, {\n checker: context.checker,\n ...(context.placement === null ? {} : { placement: context.placement }),\n ...(context.subjectType === undefined ? {} : { subjectType: context.subjectType }),\n })\n ),\n }),\n performance\n );\n case \"diagnostics\": {\n const snapshot = this.getFileSnapshot(query.filePath, performance);\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"diagnostics\",\n sourceHash: snapshot.sourceHash,\n diagnostics: snapshot.diagnostics,\n };\n }\n case \"file-snapshot\":\n return {\n protocolVersion: FORMSPEC_ANALYSIS_PROTOCOL_VERSION,\n kind: \"file-snapshot\",\n snapshot: this.getFileSnapshot(query.filePath, performance),\n };\n default: {\n throw new Error(`Unhandled semantic query: ${JSON.stringify(query)}`);\n }\n }\n }\n\n private getSourceEnvironment(\n filePath: string,\n performance: FormSpecPerformanceRecorder | undefined\n ): SourceEnvironment | null {\n return optionalMeasure(\n performance,\n \"plugin.getSourceEnvironment\",\n {\n filePath,\n },\n () => {\n const program = optionalMeasure(\n performance,\n \"plugin.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 \"plugin.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 \"plugin.sourceEnvironment.getTypeChecker\",\n undefined,\n () => program.getTypeChecker()\n );\n const sourceHash = optionalMeasure(\n performance,\n \"plugin.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 logPerformanceEvents(events: readonly FormSpecPerformanceEvent[]): void {\n const logger = this.options.logger;\n if (logger === undefined || events.length === 0) {\n return;\n }\n\n let rootEvent: FormSpecPerformanceEvent | undefined;\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const candidate = events[index];\n if (candidate?.name === FORM_SPEC_PLUGIN_PERFORMANCE_EVENT.handleQuery) {\n rootEvent = candidate;\n break;\n }\n }\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 !== FORM_SPEC_PLUGIN_PERFORMANCE_EVENT.handleQuery)\n .sort((left, right) => right.durationMs - left.durationMs)\n .slice(0, 8);\n const lines = [\n `[FormSpec][perf] ${rootEvent.name} ${formatPerformanceEvent(rootEvent)}`,\n ...sortedHotspots.map((event) => ` ${formatPerformanceEvent(event)}`),\n ];\n logger.info(lines.join(\"\\n\"));\n }\n}\n\nfunction 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\nexport function createLanguageServiceProxy(\n languageService: ts.LanguageService,\n semanticService: FormSpecPluginService\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 // The plugin keeps semantic snapshots fresh for the lightweight LSP. The\n // underlying tsserver results still come from the original language service.\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","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","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 * as tsServer from \"typescript/lib/tsserverlibrary.js\";\nimport { createLanguageServiceProxy, FormSpecPluginService } from \"./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);\n },\n };\n}\n"],"mappings":"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","names":["FORMSPEC_ANALYSIS_PROTOCOL_VERSION","FORMSPEC_ANALYSIS_PROTOCOL_VERSION"]}
|
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";
|
|
2
|
+
import { type FormSpecAnalysisManifest, type FormSpecSemanticQuery, type FormSpecSemanticResponse } from "@formspec/analysis/protocol";
|
|
3
3
|
interface LoggerLike {
|
|
4
4
|
info(message: string): void;
|
|
5
5
|
}
|
|
@@ -8,6 +8,19 @@ export interface FormSpecPluginServiceOptions {
|
|
|
8
8
|
readonly typescriptVersion: string;
|
|
9
9
|
readonly getProgram: () => ts.Program | undefined;
|
|
10
10
|
readonly logger?: LoggerLike;
|
|
11
|
+
/**
|
|
12
|
+
* Enables structured hotspot logging for semantic queries.
|
|
13
|
+
*
|
|
14
|
+
* The tsserver plugin sets this from `FORMSPEC_PLUGIN_PROFILE=1`.
|
|
15
|
+
*/
|
|
16
|
+
readonly enablePerformanceLogging?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Minimum total query duration in milliseconds before profiling is logged.
|
|
19
|
+
*
|
|
20
|
+
* Defaults to `50` when unset. The tsserver plugin sets this from
|
|
21
|
+
* `FORMSPEC_PLUGIN_PROFILE_THRESHOLD_MS`.
|
|
22
|
+
*/
|
|
23
|
+
readonly performanceLogThresholdMs?: number;
|
|
11
24
|
readonly snapshotDebounceMs?: number;
|
|
12
25
|
readonly now?: () => Date;
|
|
13
26
|
}
|
|
@@ -27,9 +40,12 @@ export declare class FormSpecPluginService {
|
|
|
27
40
|
private respondToSocket;
|
|
28
41
|
private writeManifest;
|
|
29
42
|
private cleanupRuntimeArtifacts;
|
|
30
|
-
private
|
|
43
|
+
private withCommentQueryContext;
|
|
31
44
|
private getFileSnapshot;
|
|
32
45
|
private getNow;
|
|
46
|
+
private executeQuery;
|
|
47
|
+
private getSourceEnvironment;
|
|
48
|
+
private logPerformanceEvents;
|
|
33
49
|
}
|
|
34
50
|
export declare function createLanguageServiceProxy(languageService: ts.LanguageService, semanticService: FormSpecPluginService): ts.LanguageService;
|
|
35
51
|
export {};
|
package/dist/service.d.ts.map
CHANGED
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAIL,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AA+BrC,UAAU,UAAU;IAClB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,OAAO,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAmBD,qBAAa,qBAAqB;IAOb,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyC;IACvE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,MAAM,CAA2B;gBAEL,OAAO,EAAE,4BAA4B;IASlE,WAAW,IAAI,wBAAwB;IAIjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA+DtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAoB/C,WAAW,CAAC,KAAK,EAAE,qBAAqB,GAAG,wBAAwB;IAsB1E,OAAO,CAAC,eAAe;YAmBT,aAAa;YAMb,uBAAuB;IAOrC,OAAO,CAAC,uBAAuB;IAuD/B,OAAO,CAAC,eAAe;IAiEvB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,YAAY;IAoEpB,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,oBAAoB;CAmC7B;AASD,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,eAAe,EAAE,qBAAqB,GACrC,EAAE,CAAC,eAAe,CAuCpB"}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FormSpecAnalysisManifest, type FormSpecIpcEndpoint } from "@formspec/analysis";
|
|
1
|
+
import { type FormSpecAnalysisManifest, type FormSpecIpcEndpoint } from "@formspec/analysis/protocol";
|
|
2
2
|
export interface FormSpecWorkspaceRuntimePaths {
|
|
3
3
|
readonly workspaceRoot: string;
|
|
4
4
|
readonly workspaceId: string;
|
package/dist/workspace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;CACxC;AAED,wBAAgB,gCAAgC,CAC9C,aAAa,EAAE,MAAM,EACrB,QAAQ,kBAAmB,EAC3B,SAAS,SAAyB,GACjC,6BAA6B,CAsB/B;AAED,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,EAClB,oBAAoB,SAAY,GAC/B,wBAAwB,CAa1B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formspec/ts-plugin",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.21",
|
|
4
4
|
"description": "TypeScript language service plugin for FormSpec semantic comment analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.cjs",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"README.md"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@formspec/analysis": "0.1.0-alpha.
|
|
22
|
+
"@formspec/analysis": "0.1.0-alpha.21"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"typescript": "^5.0.0"
|