@singapore-editor/lsp-plugin 0.1.1
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 +103 -0
- package/dist/bufferSync.d.ts +12 -0
- package/dist/bufferSync.d.ts.map +1 -0
- package/dist/bufferSync.js +35 -0
- package/dist/bufferSync.js.map +1 -0
- package/dist/codeActions.d.ts +83 -0
- package/dist/codeActions.d.ts.map +1 -0
- package/dist/codeActions.js +294 -0
- package/dist/codeActions.js.map +1 -0
- package/dist/colorAlpha.d.ts +4 -0
- package/dist/colorAlpha.d.ts.map +1 -0
- package/dist/colorAlpha.js +28 -0
- package/dist/colorAlpha.js.map +1 -0
- package/dist/completion.d.ts +124 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +609 -0
- package/dist/completion.js.map +1 -0
- package/dist/completionCommit.d.ts +19 -0
- package/dist/completionCommit.d.ts.map +1 -0
- package/dist/completionCommit.js +57 -0
- package/dist/completionCommit.js.map +1 -0
- package/dist/completionController.d.ts +89 -0
- package/dist/completionController.d.ts.map +1 -0
- package/dist/completionController.js +376 -0
- package/dist/completionController.js.map +1 -0
- package/dist/completionProviders.d.ts +50 -0
- package/dist/completionProviders.d.ts.map +1 -0
- package/dist/completionProviders.js +64 -0
- package/dist/completionProviders.js.map +1 -0
- package/dist/connectionContext.d.ts +7 -0
- package/dist/connectionContext.d.ts.map +1 -0
- package/dist/definitionLinkController.d.ts +54 -0
- package/dist/definitionLinkController.d.ts.map +1 -0
- package/dist/definitionLinkController.js +221 -0
- package/dist/definitionLinkController.js.map +1 -0
- package/dist/definitionNavigation.d.ts +76 -0
- package/dist/definitionNavigation.d.ts.map +1 -0
- package/dist/definitionNavigation.js +143 -0
- package/dist/definitionNavigation.js.map +1 -0
- package/dist/diagnosticNotes.d.ts +7 -0
- package/dist/diagnosticNotes.d.ts.map +1 -0
- package/dist/diagnosticNotes.js +37 -0
- package/dist/diagnosticNotes.js.map +1 -0
- package/dist/diagnosticProjection.d.ts +31 -0
- package/dist/diagnosticProjection.d.ts.map +1 -0
- package/dist/diagnosticProjection.js +79 -0
- package/dist/diagnosticProjection.js.map +1 -0
- package/dist/diagnostics.d.ts +16 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +94 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/diagnosticsPresenter.d.ts +64 -0
- package/dist/diagnosticsPresenter.d.ts.map +1 -0
- package/dist/diagnosticsPresenter.js +305 -0
- package/dist/diagnosticsPresenter.js.map +1 -0
- package/dist/document.d.ts +69 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +190 -0
- package/dist/document.js.map +1 -0
- package/dist/documentHighlightController.d.ts +34 -0
- package/dist/documentHighlightController.d.ts.map +1 -0
- package/dist/documentHighlightController.js +101 -0
- package/dist/documentHighlightController.js.map +1 -0
- package/dist/documentSnapshot.d.ts +9 -0
- package/dist/documentSnapshot.d.ts.map +1 -0
- package/dist/documentSnapshot.js +31 -0
- package/dist/documentSnapshot.js.map +1 -0
- package/dist/documentSync.d.ts +53 -0
- package/dist/documentSync.d.ts.map +1 -0
- package/dist/documentSync.js +334 -0
- package/dist/documentSync.js.map +1 -0
- package/dist/documentSyncController.d.ts +26 -0
- package/dist/documentSyncController.d.ts.map +1 -0
- package/dist/documentSyncController.js +24 -0
- package/dist/documentSyncController.js.map +1 -0
- package/dist/formatOnType.d.ts +43 -0
- package/dist/formatOnType.d.ts.map +1 -0
- package/dist/formatOnType.js +198 -0
- package/dist/formatOnType.js.map +1 -0
- package/dist/formatting.d.ts +18 -0
- package/dist/formatting.d.ts.map +1 -0
- package/dist/formatting.js +52 -0
- package/dist/formatting.js.map +1 -0
- package/dist/fuzzyMatch.d.ts +22 -0
- package/dist/fuzzyMatch.d.ts.map +1 -0
- package/dist/fuzzyMatch.js +216 -0
- package/dist/fuzzyMatch.js.map +1 -0
- package/dist/hoverParticipant.d.ts +24 -0
- package/dist/hoverParticipant.d.ts.map +1 -0
- package/dist/hoverParticipant.js +156 -0
- package/dist/hoverParticipant.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/keyCommands.d.ts +19 -0
- package/dist/keyCommands.d.ts.map +1 -0
- package/dist/keyCommands.js +21 -0
- package/dist/keyCommands.js.map +1 -0
- package/dist/lane.d.ts +28 -0
- package/dist/lane.d.ts.map +1 -0
- package/dist/lane.js +138 -0
- package/dist/lane.js.map +1 -0
- package/dist/lspConnection.d.ts +94 -0
- package/dist/lspConnection.d.ts.map +1 -0
- package/dist/lspConnection.js +195 -0
- package/dist/lspConnection.js.map +1 -0
- package/dist/lspConnectionPool.d.ts +34 -0
- package/dist/lspConnectionPool.d.ts.map +1 -0
- package/dist/lspConnectionPool.js +255 -0
- package/dist/lspConnectionPool.js.map +1 -0
- package/dist/minimalEdits.d.ts +21 -0
- package/dist/minimalEdits.d.ts.map +1 -0
- package/dist/minimalEdits.js +181 -0
- package/dist/minimalEdits.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +38 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugin.d.ts +100 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +837 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugin.styles.d.ts +31 -0
- package/dist/plugin.styles.d.ts.map +1 -0
- package/dist/plugin.styles.js +102 -0
- package/dist/plugin.styles.js.map +1 -0
- package/dist/pluginTypes.d.ts +41 -0
- package/dist/pluginTypes.d.ts.map +1 -0
- package/dist/pluginTypes.js +0 -0
- package/dist/pullDiagnostics.d.ts +30 -0
- package/dist/pullDiagnostics.d.ts.map +1 -0
- package/dist/pullDiagnostics.js +94 -0
- package/dist/pullDiagnostics.js.map +1 -0
- package/dist/renameWidget.d.ts +30 -0
- package/dist/renameWidget.d.ts.map +1 -0
- package/dist/renameWidget.js +117 -0
- package/dist/renameWidget.js.map +1 -0
- package/dist/semanticTokenDecoder.d.ts +81 -0
- package/dist/semanticTokenDecoder.d.ts.map +1 -0
- package/dist/semanticTokenDecoder.js +132 -0
- package/dist/semanticTokenDecoder.js.map +1 -0
- package/dist/semanticTokens.d.ts +47 -0
- package/dist/semanticTokens.d.ts.map +1 -0
- package/dist/semanticTokens.js +68 -0
- package/dist/semanticTokens.js.map +1 -0
- package/dist/serverSet.d.ts +69 -0
- package/dist/serverSet.d.ts.map +1 -0
- package/dist/serverSet.js +331 -0
- package/dist/serverSet.js.map +1 -0
- package/dist/signatureHelp.d.ts +40 -0
- package/dist/signatureHelp.d.ts.map +1 -0
- package/dist/signatureHelp.js +108 -0
- package/dist/signatureHelp.js.map +1 -0
- package/dist/signatureHelpController.d.ts +52 -0
- package/dist/signatureHelpController.d.ts.map +1 -0
- package/dist/signatureHelpController.js +160 -0
- package/dist/signatureHelpController.js.map +1 -0
- package/dist/sourceText.d.ts +22 -0
- package/dist/sourceText.d.ts.map +1 -0
- package/dist/sourceText.js +70 -0
- package/dist/sourceText.js.map +1 -0
- package/dist/types.d.ts +238 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/viewDocumentSnapshot.d.ts +5 -0
- package/dist/viewDocumentSnapshot.d.ts.map +1 -0
- package/dist/viewDocumentSnapshot.js +12 -0
- package/dist/viewDocumentSnapshot.js.map +1 -0
- package/dist/websocket.d.ts +6 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +4 -0
- package/dist/workspaceEdit.d.ts +66 -0
- package/dist/workspaceEdit.d.ts.map +1 -0
- package/dist/workspaceEdit.js +276 -0
- package/dist/workspaceEdit.js.map +1 -0
- package/dist/workspaceEditProvenance.d.ts +5 -0
- package/dist/workspaceEditProvenance.d.ts.map +1 -0
- package/dist/workspaceEditProvenance.js +16 -0
- package/dist/workspaceEditProvenance.js.map +1 -0
- package/dist/workspaceTextEdits.d.ts +60 -0
- package/dist/workspaceTextEdits.d.ts.map +1 -0
- package/dist/workspaceTextEdits.js +395 -0
- package/dist/workspaceTextEdits.js.map +1 -0
- package/package.json +118 -0
package/dist/lane.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { LspConnection, createWebSocketLspTransportFactory } from "./lspConnection.js";
|
|
2
|
+
import { createDocumentLogicalRevisionScope } from "@singapore-editor/core/document";
|
|
3
|
+
import { composeWorkspaceEditClientCapabilities } from "@singapore-editor/lsp";
|
|
4
|
+
//#region src/lane.ts
|
|
5
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
6
|
+
var logicalRevisionScopes = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function acquireLanguageServerLane(options, callbacks = {}) {
|
|
8
|
+
return acquireResolvedLanguageServerLane(resolveLanguageServerLaneOptions(options), callbacks);
|
|
9
|
+
}
|
|
10
|
+
function acquireResolvedLanguageServerLane(options, callbacks = {}) {
|
|
11
|
+
const connectionOptions = resolveConnectionOptions(options);
|
|
12
|
+
const ready = readyPromise();
|
|
13
|
+
let connectionLease = null;
|
|
14
|
+
let connection;
|
|
15
|
+
let registration = null;
|
|
16
|
+
let released = false;
|
|
17
|
+
let usable = false;
|
|
18
|
+
const connectionCallbacks = {
|
|
19
|
+
onConnected: () => {
|
|
20
|
+
finishConnection();
|
|
21
|
+
},
|
|
22
|
+
onDiagnosticRefresh: () => callbacks.onDiagnosticRefresh?.(),
|
|
23
|
+
onReconnecting: () => {
|
|
24
|
+
usable = false;
|
|
25
|
+
callbacks.onReconnecting?.();
|
|
26
|
+
},
|
|
27
|
+
onUnavailable: () => {
|
|
28
|
+
usable = false;
|
|
29
|
+
callbacks.onUnavailable?.();
|
|
30
|
+
},
|
|
31
|
+
onPublishDiagnostics: (params) => callbacks.onPublishDiagnostics?.(params),
|
|
32
|
+
onStatusChange: (status) => reportTransportStatus(options, status, released),
|
|
33
|
+
onError: (error) => {
|
|
34
|
+
options.onError?.(error);
|
|
35
|
+
ready.reject(error);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
connectionLease = options.connectionProvider?.acquire(connectionOptions, connectionCallbacks) ?? null;
|
|
39
|
+
connection = connectionLease?.connection ?? new LspConnection(connectionOptions, connectionCallbacks);
|
|
40
|
+
const context = connectionContext(connection);
|
|
41
|
+
const logicalRevisionScope = logicalRevisionScopeFor(connection.workspace);
|
|
42
|
+
registration = options.onConnectionCreated?.(context) ?? null;
|
|
43
|
+
if (!connectionLease) connection.connect();
|
|
44
|
+
return {
|
|
45
|
+
id: options.id,
|
|
46
|
+
client: connection.client,
|
|
47
|
+
logicalRevisionScope,
|
|
48
|
+
workspace: connection.workspace,
|
|
49
|
+
ready: ready.promise,
|
|
50
|
+
isReady: () => usable && !released,
|
|
51
|
+
release: () => {
|
|
52
|
+
if (released) return;
|
|
53
|
+
released = true;
|
|
54
|
+
usable = false;
|
|
55
|
+
ready.reject(/* @__PURE__ */ new Error(`Language-server lane "${options.id}" was released before readiness.`));
|
|
56
|
+
registration?.dispose();
|
|
57
|
+
registration = null;
|
|
58
|
+
if (connectionLease) connectionLease.release();
|
|
59
|
+
else connection.dispose();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
async function finishConnection() {
|
|
63
|
+
if (released) return;
|
|
64
|
+
try {
|
|
65
|
+
for (const notification of options.readyNotifications ?? []) {
|
|
66
|
+
await connection.client.notify(notification.method, notification.params);
|
|
67
|
+
if (released) return;
|
|
68
|
+
}
|
|
69
|
+
usable = true;
|
|
70
|
+
options.onStatusChange?.("ready");
|
|
71
|
+
callbacks.onReady?.();
|
|
72
|
+
options.onConnected?.(context);
|
|
73
|
+
ready.resolve(context);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (released) return;
|
|
76
|
+
usable = false;
|
|
77
|
+
options.onStatusChange?.("error");
|
|
78
|
+
options.onError?.(error);
|
|
79
|
+
ready.reject(error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function resolveLanguageServerLaneOptions(options) {
|
|
84
|
+
return {
|
|
85
|
+
...options,
|
|
86
|
+
rootUri: options.rootUri ?? "file:///",
|
|
87
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
88
|
+
capabilities: composeWorkspaceEditClientCapabilities(options.capabilities, options.onApplyWorkspaceEdit !== void 0),
|
|
89
|
+
createTransport: createWebSocketLspTransportFactory(options.webSocketRoute, options.webSocketTransportOptions)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function resolveConnectionOptions(options) {
|
|
93
|
+
return {
|
|
94
|
+
rootUri: options.rootUri ?? "file:///",
|
|
95
|
+
initializationOptions: options.initializationOptions,
|
|
96
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
97
|
+
capabilities: composeWorkspaceEditClientCapabilities(options.capabilities, options.onApplyWorkspaceEdit !== void 0),
|
|
98
|
+
clientInfo: options.clientInfo,
|
|
99
|
+
notificationHandlers: options.notificationHandlers,
|
|
100
|
+
serverRequestHandlers: options.serverRequestHandlers,
|
|
101
|
+
reconnect: options.reconnect,
|
|
102
|
+
createTransport: options.createTransport
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function logicalRevisionScopeFor(workspace) {
|
|
106
|
+
const current = logicalRevisionScopes.get(workspace);
|
|
107
|
+
if (current) return current;
|
|
108
|
+
const created = createDocumentLogicalRevisionScope();
|
|
109
|
+
logicalRevisionScopes.set(workspace, created);
|
|
110
|
+
return created;
|
|
111
|
+
}
|
|
112
|
+
function reportTransportStatus(options, status, released) {
|
|
113
|
+
if (released) return;
|
|
114
|
+
if (status === "ready") return;
|
|
115
|
+
options.onStatusChange?.(status);
|
|
116
|
+
}
|
|
117
|
+
function connectionContext(connection) {
|
|
118
|
+
return {
|
|
119
|
+
client: connection.client,
|
|
120
|
+
workspace: connection.workspace
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function readyPromise() {
|
|
124
|
+
let resolve;
|
|
125
|
+
let reject;
|
|
126
|
+
return {
|
|
127
|
+
promise: new Promise((resolveReady, rejectReady) => {
|
|
128
|
+
resolve = resolveReady;
|
|
129
|
+
reject = rejectReady;
|
|
130
|
+
}),
|
|
131
|
+
resolve,
|
|
132
|
+
reject
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { acquireLanguageServerLane, acquireResolvedLanguageServerLane, logicalRevisionScopeFor, resolveLanguageServerLaneOptions };
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=lane.js.map
|
package/dist/lane.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lane.js","names":[],"sources":["../src/lane.ts"],"sourcesContent":["import {\n createDocumentLogicalRevisionScope,\n type DocumentLogicalRevisionScope,\n} from '@singapore-editor/core/document'\nimport {\n composeWorkspaceEditClientCapabilities,\n type LspClient,\n type LspWorkspace,\n} from '@singapore-editor/lsp'\n\nimport {\n createWebSocketLspTransportFactory,\n LspConnection,\n type LspConnectionCallbacks,\n type LspConnectionLease,\n type LspConnectionOptions,\n type LspConnectionTransportFactory,\n} from './lspConnection'\nimport type {\n LanguageServerConnectionContext,\n LanguageServerLaneOptions,\n LanguageServerStatus,\n} from './types'\n\nconst DEFAULT_TIMEOUT_MS = 15_000\nconst logicalRevisionScopes = new WeakMap<LspWorkspace, DocumentLogicalRevisionScope>()\n\nexport type AcquiredLanguageServerLane = {\n readonly id: string\n readonly client: LspClient\n readonly logicalRevisionScope: DocumentLogicalRevisionScope\n readonly workspace: LspWorkspace\n readonly ready: Promise<LanguageServerConnectionContext>\n isReady(): boolean\n release(): void\n}\n\nexport type LanguageServerLaneCallbacks = {\n onDiagnosticRefresh?(): void\n onReconnecting?(): void\n onPublishDiagnostics?(params: unknown): void\n onReady?(): void\n onUnavailable?(): void\n}\n\nexport type LanguageServerResolvedLaneOptions = Omit<\n LanguageServerLaneOptions,\n 'webSocketRoute' | 'webSocketTransportOptions'\n> & {\n createTransport: LspConnectionTransportFactory\n}\n\ntype ReadyPromise = {\n readonly promise: Promise<LanguageServerConnectionContext>\n resolve(context: LanguageServerConnectionContext): void\n reject(error: unknown): void\n}\n\nexport function acquireLanguageServerLane(\n options: LanguageServerLaneOptions,\n callbacks: LanguageServerLaneCallbacks = {},\n): AcquiredLanguageServerLane {\n return acquireResolvedLanguageServerLane(resolveLanguageServerLaneOptions(options), callbacks)\n}\n\nexport function acquireResolvedLanguageServerLane(\n options: LanguageServerResolvedLaneOptions,\n callbacks: LanguageServerLaneCallbacks = {},\n): AcquiredLanguageServerLane {\n const connectionOptions = resolveConnectionOptions(options)\n const ready = readyPromise()\n let connectionLease: LspConnectionLease | null = null\n let connection: LspConnection\n let registration: { dispose(): void } | null = null\n let released = false\n let usable = false\n\n const connectionCallbacks: LspConnectionCallbacks = {\n onConnected: () => {\n void finishConnection()\n },\n onDiagnosticRefresh: () => callbacks.onDiagnosticRefresh?.(),\n onReconnecting: () => {\n usable = false\n callbacks.onReconnecting?.()\n },\n onUnavailable: () => {\n usable = false\n callbacks.onUnavailable?.()\n },\n onPublishDiagnostics: (params) => callbacks.onPublishDiagnostics?.(params),\n onStatusChange: (status) => reportTransportStatus(options, status, released),\n onError: (error) => {\n options.onError?.(error)\n ready.reject(error)\n },\n }\n\n connectionLease =\n options.connectionProvider?.acquire(connectionOptions, connectionCallbacks) ?? null\n connection =\n connectionLease?.connection ?? new LspConnection(connectionOptions, connectionCallbacks)\n const context = connectionContext(connection)\n const logicalRevisionScope = logicalRevisionScopeFor(connection.workspace)\n registration = options.onConnectionCreated?.(context) ?? null\n if (!connectionLease) connection.connect()\n\n return {\n id: options.id,\n client: connection.client,\n logicalRevisionScope,\n workspace: connection.workspace,\n ready: ready.promise,\n isReady: () => usable && !released,\n release: () => {\n if (released) return\n\n released = true\n usable = false\n ready.reject(new Error(`Language-server lane \"${options.id}\" was released before readiness.`))\n registration?.dispose()\n registration = null\n if (connectionLease) connectionLease.release()\n else connection.dispose()\n },\n }\n\n async function finishConnection(): Promise<void> {\n if (released) return\n\n try {\n for (const notification of options.readyNotifications ?? []) {\n await connection.client.notify(notification.method, notification.params)\n if (released) return\n }\n\n usable = true\n options.onStatusChange?.('ready')\n callbacks.onReady?.()\n options.onConnected?.(context)\n ready.resolve(context)\n } catch (error) {\n if (released) return\n\n usable = false\n options.onStatusChange?.('error')\n options.onError?.(error)\n ready.reject(error)\n }\n }\n}\n\nexport function resolveLanguageServerLaneOptions(\n options: LanguageServerLaneOptions,\n): LanguageServerResolvedLaneOptions {\n return {\n ...options,\n rootUri: options.rootUri ?? 'file:///',\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n capabilities: composeWorkspaceEditClientCapabilities(\n options.capabilities,\n options.onApplyWorkspaceEdit !== undefined,\n ),\n createTransport: createWebSocketLspTransportFactory(\n options.webSocketRoute,\n options.webSocketTransportOptions,\n ),\n }\n}\n\nfunction resolveConnectionOptions(\n options: LanguageServerResolvedLaneOptions,\n): LspConnectionOptions {\n return {\n rootUri: options.rootUri ?? 'file:///',\n initializationOptions: options.initializationOptions,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n capabilities: composeWorkspaceEditClientCapabilities(\n options.capabilities,\n options.onApplyWorkspaceEdit !== undefined,\n ),\n clientInfo: options.clientInfo,\n notificationHandlers: options.notificationHandlers,\n serverRequestHandlers: options.serverRequestHandlers,\n reconnect: options.reconnect,\n createTransport: options.createTransport,\n }\n}\n\nexport function logicalRevisionScopeFor(workspace: LspWorkspace): DocumentLogicalRevisionScope {\n const current = logicalRevisionScopes.get(workspace)\n if (current) return current\n\n const created = createDocumentLogicalRevisionScope()\n logicalRevisionScopes.set(workspace, created)\n return created\n}\n\nfunction reportTransportStatus(\n options: LanguageServerResolvedLaneOptions,\n status: LanguageServerStatus,\n released: boolean,\n): void {\n if (released) return\n if (status === 'ready') return\n\n options.onStatusChange?.(status)\n}\n\nfunction connectionContext(connection: LspConnection): LanguageServerConnectionContext {\n return {\n client: connection.client,\n workspace: connection.workspace,\n }\n}\n\nfunction readyPromise(): ReadyPromise {\n let resolve!: ReadyPromise['resolve']\n let reject!: ReadyPromise['reject']\n const promise = new Promise<LanguageServerConnectionContext>((resolveReady, rejectReady) => {\n resolve = resolveReady\n reject = rejectReady\n })\n\n return { promise, resolve, reject }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { LspClient, LspWorkspace, type LspManagedTransport, type LspNotificationHandler, type LspServerRequestHandler, type LspWebSocketTransportOptions, type LspWorkerLike } from '@singapore-editor/lsp';
|
|
2
|
+
import type * as lsp from 'vscode-languageserver-protocol';
|
|
3
|
+
import type { LanguageServerStatus } from './types';
|
|
4
|
+
export type LspReconnectOptions = {
|
|
5
|
+
/** One delay per attempt; when they run out the connection gives up and reports unavailable. */
|
|
6
|
+
readonly delaysMs: readonly number[];
|
|
7
|
+
};
|
|
8
|
+
export type LspConnectionTransportFactory = () => LspManagedTransport | Promise<LspManagedTransport>;
|
|
9
|
+
export type LspConnectionOptions = {
|
|
10
|
+
readonly rootUri: lsp.DocumentUri | null;
|
|
11
|
+
readonly initializationOptions: unknown;
|
|
12
|
+
readonly timeoutMs: number;
|
|
13
|
+
/**
|
|
14
|
+
* Merged over `defaultClientCapabilities()` by the client itself, so a host declares only what it
|
|
15
|
+
* adds. This is how a host turns on a feature the defaults deliberately leave off —
|
|
16
|
+
* `textDocument.semanticTokens` among them, which no server sends without being asked.
|
|
17
|
+
*/
|
|
18
|
+
readonly capabilities?: lsp.ClientCapabilities;
|
|
19
|
+
/**
|
|
20
|
+
* Load-bearing rather than cosmetic: at least one real server branches on the client name and
|
|
21
|
+
* withholds a request from clients it does not recognise. The value is the host's to pick.
|
|
22
|
+
*/
|
|
23
|
+
readonly clientInfo?: lsp.InitializeParams['clientInfo'];
|
|
24
|
+
/**
|
|
25
|
+
* Merged around the connection's own handlers rather than replacing them. See createClient.
|
|
26
|
+
*/
|
|
27
|
+
readonly notificationHandlers?: Readonly<Record<string, LspNotificationHandler<LspClient>>>;
|
|
28
|
+
/** Answers the server's requests; the connection's own `workspace/diagnostic/refresh` stays its. */
|
|
29
|
+
readonly serverRequestHandlers?: Readonly<Record<string, LspServerRequestHandler<LspClient>>>;
|
|
30
|
+
/** Reconnects a transport that closed or failed on its own. Absent, the first loss is final. */
|
|
31
|
+
readonly reconnect?: LspReconnectOptions;
|
|
32
|
+
createTransport(): LspManagedTransport | Promise<LspManagedTransport>;
|
|
33
|
+
};
|
|
34
|
+
export type LspConnectionCallbacks = {
|
|
35
|
+
/** Also called again after a reconnect: the client re-initialized and re-opened its documents. */
|
|
36
|
+
onConnected(): void;
|
|
37
|
+
onDiagnosticRefresh?(): void;
|
|
38
|
+
/** The transport is gone and another is on its way; what the server said so far is stale. */
|
|
39
|
+
onReconnecting?(error: unknown): void;
|
|
40
|
+
onUnavailable(): void;
|
|
41
|
+
onPublishDiagnostics(params: unknown): void;
|
|
42
|
+
onStatusChange?: (status: LanguageServerStatus) => void;
|
|
43
|
+
onError?: (error: unknown) => void;
|
|
44
|
+
};
|
|
45
|
+
/** A connection a view borrows. `release` ends its interest; closing is the provider's call. */
|
|
46
|
+
export type LspConnectionLease = {
|
|
47
|
+
readonly connection: LspConnection;
|
|
48
|
+
release(): void;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Supplies connections that outlive one view, so a file switch does not pay a handshake and an
|
|
52
|
+
* `initialize` round trip. `options` is the connection the plugin would have built: build from it on
|
|
53
|
+
* a new key, ignore it on a known one.
|
|
54
|
+
*
|
|
55
|
+
* **`callbacks.onConnected` must never fire synchronously from `acquire`** — the caller is
|
|
56
|
+
* mid-construction. Replay it on a microtask.
|
|
57
|
+
*/
|
|
58
|
+
export type LspConnectionProvider = {
|
|
59
|
+
acquire(options: LspConnectionOptions, callbacks: LspConnectionCallbacks): LspConnectionLease;
|
|
60
|
+
};
|
|
61
|
+
export declare class LspConnection {
|
|
62
|
+
private readonly options;
|
|
63
|
+
private readonly callbacks;
|
|
64
|
+
readonly workspace: LspWorkspace;
|
|
65
|
+
readonly client: LspClient;
|
|
66
|
+
private transport;
|
|
67
|
+
private removeTransportCloseListener;
|
|
68
|
+
private disposed;
|
|
69
|
+
private status;
|
|
70
|
+
private reconnectAttempts;
|
|
71
|
+
private readyAt;
|
|
72
|
+
private reconnectTimer;
|
|
73
|
+
/** Why the server said it is going, reported as the reason for the close that follows. */
|
|
74
|
+
private exit;
|
|
75
|
+
constructor(options: LspConnectionOptions, callbacks: LspConnectionCallbacks);
|
|
76
|
+
connect(): void;
|
|
77
|
+
dispose(): void;
|
|
78
|
+
private createClient;
|
|
79
|
+
private connectTransport;
|
|
80
|
+
private connectManagedTransport;
|
|
81
|
+
/** A server that says anything after announcing its exit did not exit; a later close is its own. */
|
|
82
|
+
private readonly forgetExitOnLaterMessage;
|
|
83
|
+
private handleConnected;
|
|
84
|
+
private handleConnectError;
|
|
85
|
+
private handleTransportClose;
|
|
86
|
+
private detachTransport;
|
|
87
|
+
private giveUpOrReconnect;
|
|
88
|
+
private scheduleReconnect;
|
|
89
|
+
private setStatus;
|
|
90
|
+
private handleError;
|
|
91
|
+
}
|
|
92
|
+
export declare function createWebSocketLspTransportFactory(route: string | URL, options?: LspWebSocketTransportOptions): LspConnectionTransportFactory;
|
|
93
|
+
export declare function createWorkerLspTransportFactory(workerFactory: () => LspWorkerLike): LspConnectionTransportFactory;
|
|
94
|
+
//# sourceMappingURL=lspConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lspConnection.d.ts","sourceRoot":"","sources":["../src/lspConnection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { LSP_SERVER_EXITED, LspClient, LspServerExitedError, LspWorkspace, createWebSocketLspTransport, createWorkerLspTransport } from "@singapore-editor/lsp";
|
|
2
|
+
//#region src/lspConnection.ts
|
|
3
|
+
var DIAGNOSTIC_REFRESH_METHOD = "workspace/diagnostic/refresh";
|
|
4
|
+
/** A connection that stayed up this long ended a crash streak; its next loss starts a new one. */
|
|
5
|
+
var STABLE_CONNECTION_MS = 6e4;
|
|
6
|
+
var LspConnection = class {
|
|
7
|
+
options;
|
|
8
|
+
callbacks;
|
|
9
|
+
workspace = new LspWorkspace();
|
|
10
|
+
client;
|
|
11
|
+
transport = null;
|
|
12
|
+
removeTransportCloseListener = null;
|
|
13
|
+
disposed = false;
|
|
14
|
+
status = "idle";
|
|
15
|
+
reconnectAttempts = 0;
|
|
16
|
+
readyAt = null;
|
|
17
|
+
reconnectTimer = null;
|
|
18
|
+
/** Why the server said it is going, reported as the reason for the close that follows. */
|
|
19
|
+
exit = null;
|
|
20
|
+
constructor(options, callbacks) {
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.callbacks = callbacks;
|
|
23
|
+
this.client = this.createClient();
|
|
24
|
+
}
|
|
25
|
+
connect() {
|
|
26
|
+
this.setStatus("loading");
|
|
27
|
+
this.connectTransport();
|
|
28
|
+
}
|
|
29
|
+
dispose() {
|
|
30
|
+
if (this.disposed) return;
|
|
31
|
+
this.disposed = true;
|
|
32
|
+
if (this.reconnectTimer !== null) clearTimeout(this.reconnectTimer);
|
|
33
|
+
this.reconnectTimer = null;
|
|
34
|
+
this.removeTransportCloseListener?.();
|
|
35
|
+
this.removeTransportCloseListener = null;
|
|
36
|
+
this.client.disconnect();
|
|
37
|
+
this.transport?.close();
|
|
38
|
+
this.transport = null;
|
|
39
|
+
this.setStatus("idle");
|
|
40
|
+
}
|
|
41
|
+
createClient() {
|
|
42
|
+
const hostHandlers = this.options.notificationHandlers;
|
|
43
|
+
return new LspClient({
|
|
44
|
+
rootUri: this.options.rootUri,
|
|
45
|
+
workspaceFolders: null,
|
|
46
|
+
workspace: this.workspace,
|
|
47
|
+
timeoutMs: this.options.timeoutMs,
|
|
48
|
+
initializationOptions: this.options.initializationOptions,
|
|
49
|
+
capabilities: this.options.capabilities,
|
|
50
|
+
clientInfo: this.options.clientInfo,
|
|
51
|
+
notificationHandlers: {
|
|
52
|
+
...hostHandlers,
|
|
53
|
+
[DIAGNOSTIC_REFRESH_METHOD]: (client, params, message) => {
|
|
54
|
+
this.callbacks.onDiagnosticRefresh?.();
|
|
55
|
+
hostHandlers?.[DIAGNOSTIC_REFRESH_METHOD]?.(client, params, message);
|
|
56
|
+
return true;
|
|
57
|
+
},
|
|
58
|
+
[LSP_SERVER_EXITED]: (client, params, message) => {
|
|
59
|
+
this.exit = serverExitedParams(params);
|
|
60
|
+
hostHandlers?.[LSP_SERVER_EXITED]?.(client, params, message);
|
|
61
|
+
return true;
|
|
62
|
+
},
|
|
63
|
+
"textDocument/publishDiagnostics": (client, params, message) => {
|
|
64
|
+
this.callbacks.onPublishDiagnostics(params);
|
|
65
|
+
hostHandlers?.["textDocument/publishDiagnostics"]?.(client, params, message);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
serverRequestHandlers: {
|
|
70
|
+
...this.options.serverRequestHandlers,
|
|
71
|
+
[DIAGNOSTIC_REFRESH_METHOD]: () => {
|
|
72
|
+
this.callbacks.onDiagnosticRefresh?.();
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
connectTransport() {
|
|
79
|
+
try {
|
|
80
|
+
const transport = this.options.createTransport();
|
|
81
|
+
if (isTransportPromise(transport)) {
|
|
82
|
+
transport.then((value) => this.connectManagedTransport(value)).catch((error) => {
|
|
83
|
+
this.handleConnectError(error);
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.connectManagedTransport(transport);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
this.handleConnectError(error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
connectManagedTransport(transport) {
|
|
93
|
+
if (this.disposed) {
|
|
94
|
+
transport.close();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.transport = transport;
|
|
98
|
+
this.exit = null;
|
|
99
|
+
this.removeTransportCloseListener = transport.onDidClose((error) => this.handleTransportClose(error));
|
|
100
|
+
transport.subscribe(this.forgetExitOnLaterMessage);
|
|
101
|
+
this.client.connect(transport).then(() => {
|
|
102
|
+
if (this.transport === transport) this.handleConnected();
|
|
103
|
+
}).catch((error) => {
|
|
104
|
+
if (this.transport === transport) this.handleConnectError(error);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/** A server that says anything after announcing its exit did not exit; a later close is its own. */
|
|
108
|
+
forgetExitOnLaterMessage = (message) => {
|
|
109
|
+
if (this.exit && !message.includes(LSP_SERVER_EXITED)) this.exit = null;
|
|
110
|
+
};
|
|
111
|
+
handleConnected() {
|
|
112
|
+
if (this.disposed) return;
|
|
113
|
+
this.readyAt = now();
|
|
114
|
+
this.setStatus("ready");
|
|
115
|
+
this.callbacks.onConnected();
|
|
116
|
+
}
|
|
117
|
+
handleConnectError(error) {
|
|
118
|
+
if (this.disposed) return;
|
|
119
|
+
this.detachTransport();
|
|
120
|
+
this.giveUpOrReconnect(error);
|
|
121
|
+
}
|
|
122
|
+
handleTransportClose(error) {
|
|
123
|
+
if (this.disposed) return;
|
|
124
|
+
const exit = this.exit;
|
|
125
|
+
this.exit = null;
|
|
126
|
+
this.detachTransport();
|
|
127
|
+
if (exit) {
|
|
128
|
+
this.giveUpOrReconnect(new LspServerExitedError(exit));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.giveUpOrReconnect(error ?? /* @__PURE__ */ new Error("LSP transport closed"));
|
|
132
|
+
}
|
|
133
|
+
detachTransport() {
|
|
134
|
+
this.removeTransportCloseListener?.();
|
|
135
|
+
this.removeTransportCloseListener = null;
|
|
136
|
+
this.transport?.unsubscribe(this.forgetExitOnLaterMessage);
|
|
137
|
+
this.client.disconnect();
|
|
138
|
+
this.transport?.close();
|
|
139
|
+
this.transport = null;
|
|
140
|
+
}
|
|
141
|
+
giveUpOrReconnect(error) {
|
|
142
|
+
if (this.scheduleReconnect(error)) return;
|
|
143
|
+
this.setStatus("error");
|
|
144
|
+
this.callbacks.onUnavailable();
|
|
145
|
+
this.handleError(error);
|
|
146
|
+
}
|
|
147
|
+
scheduleReconnect(error) {
|
|
148
|
+
if (this.readyAt !== null && now() - this.readyAt >= STABLE_CONNECTION_MS) this.reconnectAttempts = 0;
|
|
149
|
+
this.readyAt = null;
|
|
150
|
+
const delay = this.options.reconnect?.delaysMs[this.reconnectAttempts];
|
|
151
|
+
if (delay === void 0) return false;
|
|
152
|
+
this.reconnectAttempts += 1;
|
|
153
|
+
this.setStatus("loading");
|
|
154
|
+
this.callbacks.onReconnecting?.(error);
|
|
155
|
+
this.reconnectTimer = setTimeout(() => {
|
|
156
|
+
this.reconnectTimer = null;
|
|
157
|
+
if (!this.disposed) this.connectTransport();
|
|
158
|
+
}, delay);
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
setStatus(status) {
|
|
162
|
+
if (this.status === status) return;
|
|
163
|
+
this.status = status;
|
|
164
|
+
this.callbacks.onStatusChange?.(status);
|
|
165
|
+
}
|
|
166
|
+
handleError(error) {
|
|
167
|
+
this.callbacks.onError?.(error);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
function createWebSocketLspTransportFactory(route, options) {
|
|
171
|
+
return () => createWebSocketLspTransport(route, {
|
|
172
|
+
protocols: options?.protocols,
|
|
173
|
+
WebSocketCtor: options?.WebSocketCtor
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function createWorkerLspTransportFactory(workerFactory) {
|
|
177
|
+
return () => createWorkerLspTransport(workerFactory(), {
|
|
178
|
+
messageFormat: "json",
|
|
179
|
+
terminateOnClose: true
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function now() {
|
|
183
|
+
return typeof performance === "undefined" ? Date.now() : performance.now();
|
|
184
|
+
}
|
|
185
|
+
function isTransportPromise(value) {
|
|
186
|
+
return typeof value.then === "function";
|
|
187
|
+
}
|
|
188
|
+
function serverExitedParams(params) {
|
|
189
|
+
if (typeof params !== "object" || params === null) return null;
|
|
190
|
+
return typeof params.outcome === "string" ? params : null;
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
export { LspConnection, createWebSocketLspTransportFactory, createWorkerLspTransportFactory };
|
|
194
|
+
|
|
195
|
+
//# sourceMappingURL=lspConnection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lspConnection.js","names":[],"sources":["../src/lspConnection.ts"],"sourcesContent":["import {\n createWebSocketLspTransport,\n createWorkerLspTransport,\n LSP_SERVER_EXITED,\n LspClient,\n LspServerExitedError,\n LspWorkspace,\n type LspServerExitedParams,\n type LspManagedTransport,\n type LspNotificationHandler,\n type LspServerRequestHandler,\n type LspWebSocketTransportOptions,\n type LspWorkerLike,\n} from '@singapore-editor/lsp'\nimport type * as lsp from 'vscode-languageserver-protocol'\n\nimport type { LanguageServerStatus } from './types'\n\nconst DIAGNOSTIC_REFRESH_METHOD = 'workspace/diagnostic/refresh'\n/** A connection that stayed up this long ended a crash streak; its next loss starts a new one. */\nconst STABLE_CONNECTION_MS = 60_000\n\nexport type LspReconnectOptions = {\n /** One delay per attempt; when they run out the connection gives up and reports unavailable. */\n readonly delaysMs: readonly number[]\n}\n\nexport type LspConnectionTransportFactory = () => LspManagedTransport | Promise<LspManagedTransport>\n\nexport type LspConnectionOptions = {\n readonly rootUri: lsp.DocumentUri | null\n readonly initializationOptions: unknown\n readonly timeoutMs: number\n /**\n * Merged over `defaultClientCapabilities()` by the client itself, so a host declares only what it\n * adds. This is how a host turns on a feature the defaults deliberately leave off —\n * `textDocument.semanticTokens` among them, which no server sends without being asked.\n */\n readonly capabilities?: lsp.ClientCapabilities\n /**\n * Load-bearing rather than cosmetic: at least one real server branches on the client name and\n * withholds a request from clients it does not recognise. The value is the host's to pick.\n */\n readonly clientInfo?: lsp.InitializeParams['clientInfo']\n /**\n * Merged around the connection's own handlers rather than replacing them. See createClient.\n */\n readonly notificationHandlers?: Readonly<Record<string, LspNotificationHandler<LspClient>>>\n /** Answers the server's requests; the connection's own `workspace/diagnostic/refresh` stays its. */\n readonly serverRequestHandlers?: Readonly<Record<string, LspServerRequestHandler<LspClient>>>\n /** Reconnects a transport that closed or failed on its own. Absent, the first loss is final. */\n readonly reconnect?: LspReconnectOptions\n createTransport(): LspManagedTransport | Promise<LspManagedTransport>\n}\n\nexport type LspConnectionCallbacks = {\n /** Also called again after a reconnect: the client re-initialized and re-opened its documents. */\n onConnected(): void\n onDiagnosticRefresh?(): void\n /** The transport is gone and another is on its way; what the server said so far is stale. */\n onReconnecting?(error: unknown): void\n onUnavailable(): void\n onPublishDiagnostics(params: unknown): void\n onStatusChange?: (status: LanguageServerStatus) => void\n onError?: (error: unknown) => void\n}\n\n/** A connection a view borrows. `release` ends its interest; closing is the provider's call. */\nexport type LspConnectionLease = {\n readonly connection: LspConnection\n release(): void\n}\n\n/**\n * Supplies connections that outlive one view, so a file switch does not pay a handshake and an\n * `initialize` round trip. `options` is the connection the plugin would have built: build from it on\n * a new key, ignore it on a known one.\n *\n * **`callbacks.onConnected` must never fire synchronously from `acquire`** — the caller is\n * mid-construction. Replay it on a microtask.\n */\nexport type LspConnectionProvider = {\n acquire(options: LspConnectionOptions, callbacks: LspConnectionCallbacks): LspConnectionLease\n}\n\nexport class LspConnection {\n public readonly workspace = new LspWorkspace()\n public readonly client: LspClient\n\n private transport: LspManagedTransport | null = null\n private removeTransportCloseListener: (() => void) | null = null\n private disposed = false\n private status: LanguageServerStatus = 'idle'\n private reconnectAttempts = 0\n private readyAt: number | null = null\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n /** Why the server said it is going, reported as the reason for the close that follows. */\n private exit: LspServerExitedParams | null = null\n\n public constructor(\n private readonly options: LspConnectionOptions,\n private readonly callbacks: LspConnectionCallbacks,\n ) {\n this.client = this.createClient()\n }\n\n public connect(): void {\n this.setStatus('loading')\n this.connectTransport()\n }\n\n public dispose(): void {\n if (this.disposed) return\n\n this.disposed = true\n if (this.reconnectTimer !== null) clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n this.removeTransportCloseListener?.()\n this.removeTransportCloseListener = null\n this.client.disconnect()\n this.transport?.close()\n this.transport = null\n this.setStatus('idle')\n }\n\n private createClient(): LspClient {\n const hostHandlers = this.options.notificationHandlers\n return new LspClient({\n rootUri: this.options.rootUri,\n workspaceFolders: null,\n workspace: this.workspace,\n timeoutMs: this.options.timeoutMs,\n initializationOptions: this.options.initializationOptions,\n capabilities: this.options.capabilities,\n clientInfo: this.options.clientInfo,\n // Host handlers are merged *around* the connection's own rather than replacing them: the\n // whole diagnostics feature hangs off publishDiagnostics, so a host that happens to want that\n // notification too must not be able to take it away. Its handler runs after ours.\n notificationHandlers: {\n ...hostHandlers,\n [DIAGNOSTIC_REFRESH_METHOD]: (client, params, message) => {\n this.callbacks.onDiagnosticRefresh?.()\n hostHandlers?.[DIAGNOSTIC_REFRESH_METHOD]?.(client, params, message)\n return true\n },\n [LSP_SERVER_EXITED]: (client, params, message) => {\n this.exit = serverExitedParams(params)\n hostHandlers?.[LSP_SERVER_EXITED]?.(client, params, message)\n return true\n },\n 'textDocument/publishDiagnostics': (client, params, message) => {\n this.callbacks.onPublishDiagnostics(params)\n hostHandlers?.['textDocument/publishDiagnostics']?.(client, params, message)\n return true\n },\n },\n serverRequestHandlers: {\n ...this.options.serverRequestHandlers,\n [DIAGNOSTIC_REFRESH_METHOD]: () => {\n this.callbacks.onDiagnosticRefresh?.()\n return null\n },\n },\n })\n }\n\n private connectTransport(): void {\n try {\n const transport = this.options.createTransport()\n if (isTransportPromise(transport)) {\n void transport\n .then((value) => this.connectManagedTransport(value))\n .catch((error) => {\n this.handleConnectError(error)\n })\n return\n }\n\n this.connectManagedTransport(transport)\n } catch (error) {\n this.handleConnectError(error)\n }\n }\n\n private connectManagedTransport(transport: LspManagedTransport): void {\n if (this.disposed) {\n transport.close()\n return\n }\n\n this.transport = transport\n this.exit = null\n this.removeTransportCloseListener = transport.onDidClose((error) =>\n this.handleTransportClose(error),\n )\n transport.subscribe(this.forgetExitOnLaterMessage)\n // Only while this transport is still the connection's: a close that already detached it made\n // the report, and the initialize it rejected on the way out must not make a second one.\n void this.client\n .connect(transport)\n .then(() => {\n if (this.transport === transport) this.handleConnected()\n })\n .catch((error: unknown) => {\n if (this.transport === transport) this.handleConnectError(error)\n })\n }\n\n /** A server that says anything after announcing its exit did not exit; a later close is its own. */\n private readonly forgetExitOnLaterMessage = (message: string): void => {\n if (this.exit && !message.includes(LSP_SERVER_EXITED)) this.exit = null\n }\n\n private handleConnected(): void {\n if (this.disposed) return\n\n this.readyAt = now()\n this.setStatus('ready')\n this.callbacks.onConnected()\n }\n\n private handleConnectError(error: unknown): void {\n if (this.disposed) return\n\n this.detachTransport()\n this.giveUpOrReconnect(error)\n }\n\n private handleTransportClose(error?: unknown): void {\n if (this.disposed) return\n\n const exit = this.exit\n this.exit = null\n this.detachTransport()\n if (exit) {\n this.giveUpOrReconnect(new LspServerExitedError(exit))\n return\n }\n this.giveUpOrReconnect(error ?? new Error('LSP transport closed'))\n }\n\n private detachTransport(): void {\n this.removeTransportCloseListener?.()\n this.removeTransportCloseListener = null\n this.transport?.unsubscribe(this.forgetExitOnLaterMessage)\n this.client.disconnect()\n this.transport?.close()\n this.transport = null\n }\n\n private giveUpOrReconnect(error: unknown): void {\n if (this.scheduleReconnect(error)) return\n\n this.setStatus('error')\n this.callbacks.onUnavailable()\n this.handleError(error)\n }\n\n private scheduleReconnect(error: unknown): boolean {\n if (this.readyAt !== null && now() - this.readyAt >= STABLE_CONNECTION_MS) {\n this.reconnectAttempts = 0\n }\n this.readyAt = null\n const delay = this.options.reconnect?.delaysMs[this.reconnectAttempts]\n if (delay === undefined) return false\n\n this.reconnectAttempts += 1\n this.setStatus('loading')\n this.callbacks.onReconnecting?.(error)\n // @justification A reconnect backoff, not rendering work: the handle is kept, cleared on dispose,\n // and a disposed connection ignores it.\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null\n if (!this.disposed) this.connectTransport()\n }, delay)\n return true\n }\n\n private setStatus(status: LanguageServerStatus): void {\n if (this.status === status) return\n\n this.status = status\n this.callbacks.onStatusChange?.(status)\n }\n\n private handleError(error: unknown): void {\n this.callbacks.onError?.(error)\n }\n}\n\nexport function createWebSocketLspTransportFactory(\n route: string | URL,\n options?: LspWebSocketTransportOptions,\n): LspConnectionTransportFactory {\n return () =>\n createWebSocketLspTransport(route, {\n protocols: options?.protocols,\n WebSocketCtor: options?.WebSocketCtor,\n })\n}\n\nexport function createWorkerLspTransportFactory(\n workerFactory: () => LspWorkerLike,\n): LspConnectionTransportFactory {\n return () =>\n createWorkerLspTransport(workerFactory(), {\n messageFormat: 'json',\n terminateOnClose: true,\n })\n}\n\nfunction now(): number {\n return typeof performance === 'undefined' ? Date.now() : performance.now()\n}\n\nfunction isTransportPromise(\n value: LspManagedTransport | Promise<LspManagedTransport>,\n): value is Promise<LspManagedTransport> {\n return typeof (value as Promise<LspManagedTransport>).then === 'function'\n}\n\nfunction serverExitedParams(params: unknown): LspServerExitedParams | null {\n if (typeof params !== 'object' || params === null) return null\n const outcome = (params as { outcome?: unknown }).outcome\n return typeof outcome === 'string' ? (params as LspServerExitedParams) : null\n}\n"],"mappings":";;AAkBA,IAAM,4BAA4B;;AAElC,IAAM,uBAAuB;AAiE7B,IAAa,gBAAb,MAA2B;CAeN;CACA;CAfnB,YAA4B,IAAI,aAAa;CAC7C;CAEA,YAAgD;CAChD,+BAA4D;CAC5D,WAAmB;CACnB,SAAuC;CACvC,oBAA4B;CAC5B,UAAiC;CACjC,iBAA+D;;CAE/D,OAA6C;CAE7C,YACE,SACA,WACA;EAFiB,KAAA,UAAA;EACA,KAAA,YAAA;EAEjB,KAAK,SAAS,KAAK,aAAa;CAClC;CAEA,UAAuB;EACrB,KAAK,UAAU,SAAS;EACxB,KAAK,iBAAiB;CACxB;CAEA,UAAuB;EACrB,IAAI,KAAK,UAAU;EAEnB,KAAK,WAAW;EAChB,IAAI,KAAK,mBAAmB,MAAM,aAAa,KAAK,cAAc;EAClE,KAAK,iBAAiB;EACtB,KAAK,+BAA+B;EACpC,KAAK,+BAA+B;EACpC,KAAK,OAAO,WAAW;EACvB,KAAK,WAAW,MAAM;EACtB,KAAK,YAAY;EACjB,KAAK,UAAU,MAAM;CACvB;CAEA,eAAkC;EAChC,MAAM,eAAe,KAAK,QAAQ;EAClC,OAAO,IAAI,UAAU;GACnB,SAAS,KAAK,QAAQ;GACtB,kBAAkB;GAClB,WAAW,KAAK;GAChB,WAAW,KAAK,QAAQ;GACxB,uBAAuB,KAAK,QAAQ;GACpC,cAAc,KAAK,QAAQ;GAC3B,YAAY,KAAK,QAAQ;GAIzB,sBAAsB;IACpB,GAAG;KACF,6BAA6B,QAAQ,QAAQ,YAAY;KACxD,KAAK,UAAU,sBAAsB;KACrC,eAAe,0BAA0B,GAAG,QAAQ,QAAQ,OAAO;KACnE,OAAO;IACT;KACC,qBAAqB,QAAQ,QAAQ,YAAY;KAChD,KAAK,OAAO,mBAAmB,MAAM;KACrC,eAAe,kBAAkB,GAAG,QAAQ,QAAQ,OAAO;KAC3D,OAAO;IACT;IACA,oCAAoC,QAAQ,QAAQ,YAAY;KAC9D,KAAK,UAAU,qBAAqB,MAAM;KAC1C,eAAe,kCAAkC,GAAG,QAAQ,QAAQ,OAAO;KAC3E,OAAO;IACT;GACF;GACA,uBAAuB;IACrB,GAAG,KAAK,QAAQ;KACf,kCAAkC;KACjC,KAAK,UAAU,sBAAsB;KACrC,OAAO;IACT;GACF;EACF,CAAC;CACH;CAEA,mBAAiC;EAC/B,IAAI;GACF,MAAM,YAAY,KAAK,QAAQ,gBAAgB;GAC/C,IAAI,mBAAmB,SAAS,GAAG;IACjC,UACG,MAAM,UAAU,KAAK,wBAAwB,KAAK,CAAC,CAAC,CACpD,OAAO,UAAU;KAChB,KAAK,mBAAmB,KAAK;IAC/B,CAAC;IACH;GACF;GAEA,KAAK,wBAAwB,SAAS;EACxC,SAAS,OAAO;GACd,KAAK,mBAAmB,KAAK;EAC/B;CACF;CAEA,wBAAgC,WAAsC;EACpE,IAAI,KAAK,UAAU;GACjB,UAAU,MAAM;GAChB;EACF;EAEA,KAAK,YAAY;EACjB,KAAK,OAAO;EACZ,KAAK,+BAA+B,UAAU,YAAY,UACxD,KAAK,qBAAqB,KAAK,CACjC;EACA,UAAU,UAAU,KAAK,wBAAwB;EAGjD,KAAU,OACP,QAAQ,SAAS,CAAC,CAClB,WAAW;GACV,IAAI,KAAK,cAAc,WAAW,KAAK,gBAAgB;EACzD,CAAC,CAAC,CACD,OAAO,UAAmB;GACzB,IAAI,KAAK,cAAc,WAAW,KAAK,mBAAmB,KAAK;EACjE,CAAC;CACL;;CAGA,4BAA6C,YAA0B;EACrE,IAAI,KAAK,QAAQ,CAAC,QAAQ,SAAS,iBAAiB,GAAG,KAAK,OAAO;CACrE;CAEA,kBAAgC;EAC9B,IAAI,KAAK,UAAU;EAEnB,KAAK,UAAU,IAAI;EACnB,KAAK,UAAU,OAAO;EACtB,KAAK,UAAU,YAAY;CAC7B;CAEA,mBAA2B,OAAsB;EAC/C,IAAI,KAAK,UAAU;EAEnB,KAAK,gBAAgB;EACrB,KAAK,kBAAkB,KAAK;CAC9B;CAEA,qBAA6B,OAAuB;EAClD,IAAI,KAAK,UAAU;EAEnB,MAAM,OAAO,KAAK;EAClB,KAAK,OAAO;EACZ,KAAK,gBAAgB;EACrB,IAAI,MAAM;GACR,KAAK,kBAAkB,IAAI,qBAAqB,IAAI,CAAC;GACrD;EACF;EACA,KAAK,kBAAkB,yBAAS,IAAI,MAAM,sBAAsB,CAAC;CACnE;CAEA,kBAAgC;EAC9B,KAAK,+BAA+B;EACpC,KAAK,+BAA+B;EACpC,KAAK,WAAW,YAAY,KAAK,wBAAwB;EACzD,KAAK,OAAO,WAAW;EACvB,KAAK,WAAW,MAAM;EACtB,KAAK,YAAY;CACnB;CAEA,kBAA0B,OAAsB;EAC9C,IAAI,KAAK,kBAAkB,KAAK,GAAG;EAEnC,KAAK,UAAU,OAAO;EACtB,KAAK,UAAU,cAAc;EAC7B,KAAK,YAAY,KAAK;CACxB;CAEA,kBAA0B,OAAyB;EACjD,IAAI,KAAK,YAAY,QAAQ,IAAI,IAAI,KAAK,WAAW,sBACnD,KAAK,oBAAoB;EAE3B,KAAK,UAAU;EACf,MAAM,QAAQ,KAAK,QAAQ,WAAW,SAAS,KAAK;EACpD,IAAI,UAAU,KAAA,GAAW,OAAO;EAEhC,KAAK,qBAAqB;EAC1B,KAAK,UAAU,SAAS;EACxB,KAAK,UAAU,iBAAiB,KAAK;EAGrC,KAAK,iBAAiB,iBAAiB;GACrC,KAAK,iBAAiB;GACtB,IAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;EAC5C,GAAG,KAAK;EACR,OAAO;CACT;CAEA,UAAkB,QAAoC;EACpD,IAAI,KAAK,WAAW,QAAQ;EAE5B,KAAK,SAAS;EACd,KAAK,UAAU,iBAAiB,MAAM;CACxC;CAEA,YAAoB,OAAsB;EACxC,KAAK,UAAU,UAAU,KAAK;CAChC;AACF;AAEA,SAAgB,mCACd,OACA,SAC+B;CAC/B,aACE,4BAA4B,OAAO;EACjC,WAAW,SAAS;EACpB,eAAe,SAAS;CAC1B,CAAC;AACL;AAEA,SAAgB,gCACd,eAC+B;CAC/B,aACE,yBAAyB,cAAc,GAAG;EACxC,eAAe;EACf,kBAAkB;CACpB,CAAC;AACL;AAEA,SAAS,MAAc;CACrB,OAAO,OAAO,gBAAgB,cAAc,KAAK,IAAI,IAAI,YAAY,IAAI;AAC3E;AAEA,SAAS,mBACP,OACuC;CACvC,OAAO,OAAQ,MAAuC,SAAS;AACjE;AAEA,SAAS,mBAAmB,QAA+C;CACzE,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM,OAAO;CAE1D,OAAO,OADU,OAAiC,YACxB,WAAY,SAAmC;AAC3E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type LspConnectionCallbacks, type LspConnectionLease, type LspConnectionOptions, type LspConnectionProvider } from './lspConnection';
|
|
2
|
+
import type { LanguageServerStatus } from './types';
|
|
3
|
+
/** What a pooled connection just did, for a host that wants to log it. */
|
|
4
|
+
export type LspConnectionPoolEvent = {
|
|
5
|
+
readonly kind: 'created' | 'reused' | 'ready' | 'released' | 'closed' | 'retired' | 'reconnecting' | 'error' | 'handler_ignored';
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly leaseCount: number;
|
|
8
|
+
readonly status: LanguageServerStatus;
|
|
9
|
+
/** Time to `initialize` for `ready`; the connection's life so far for `closed`, `retired` and `error`. */
|
|
10
|
+
readonly durationMs?: number;
|
|
11
|
+
readonly reachedReady?: boolean;
|
|
12
|
+
readonly error?: unknown;
|
|
13
|
+
/** Methods a late borrower declared that this connection cannot dispatch. */
|
|
14
|
+
readonly methods?: readonly string[];
|
|
15
|
+
};
|
|
16
|
+
export type LspConnectionPoolOptions = {
|
|
17
|
+
readonly idleGraceMs?: number;
|
|
18
|
+
readonly onEvent?: (event: LspConnectionPoolEvent) => void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* One connection per key, outliving the views that borrow it. A view contribution is rebuilt on
|
|
22
|
+
* every file switch, and a connection it owns dies with it — thirteen handshakes in twenty-two
|
|
23
|
+
* seconds, measured. The key is opaque: how a server session is named is the host's vocabulary.
|
|
24
|
+
*/
|
|
25
|
+
export declare class LspConnectionPool {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(options?: LspConnectionPoolOptions);
|
|
28
|
+
/** A provider bound to one key, in the shape the plugin takes. */
|
|
29
|
+
provider(key: string): LspConnectionProvider;
|
|
30
|
+
acquire(key: string, options: LspConnectionOptions, callbacks: LspConnectionCallbacks): LspConnectionLease;
|
|
31
|
+
/** Closes every connection. For teardown and for tests, not for routine use. */
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=lspConnectionPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lspConnectionPool.d.ts","sourceRoot":"","sources":["../src/lspConnectionPool.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AASnD,0EAA0E;AAC1E,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,IAAI,EACT,SAAS,GACT,QAAQ,GACR,OAAO,GACP,UAAU,GACV,QAAQ,GACR,SAAS,GACT,cAAc,GACd,OAAO,GACP,iBAAiB,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;IACrC,0GAA0G;IAC1G,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAA;CAC3D,CAAA;AAiCD;;;;GAIG;AACH,qBAAa,iBAAiB;;gBAKT,OAAO,GAAE,wBAA6B;IAKzD,kEAAkE;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB;IAI5C,OAAO,CACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,sBAAsB,GAChC,kBAAkB;IA0BrB,gFAAgF;IACzE,OAAO,IAAI,IAAI;CAmLvB"}
|