@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/plugin.js
ADDED
|
@@ -0,0 +1,837 @@
|
|
|
1
|
+
import { activeDocumentForSnapshot } from "./documentSync.js";
|
|
2
|
+
import { resolveLanguageServerLaneOptions } from "./lane.js";
|
|
3
|
+
import { LanguageServerDocument } from "./document.js";
|
|
4
|
+
import { rangeAroundOffset } from "./sourceText.js";
|
|
5
|
+
import { LANGUAGE_SERVER_COMPLETION_EDIT_FEATURE, createCompletionEditFeature } from "./completion.js";
|
|
6
|
+
import { LanguageServerSet, allLanguageServerFeatures, captureWorkspaceEditOriginGuard, rankedLanguageServerLanes } from "./serverSet.js";
|
|
7
|
+
import { parseWorkspaceEdit } from "./workspaceEdit.js";
|
|
8
|
+
import { currentWorkspaceEditOrigin } from "./workspaceEditProvenance.js";
|
|
9
|
+
import { CodeActionController } from "./codeActions.js";
|
|
10
|
+
import { CompletionController } from "./completionController.js";
|
|
11
|
+
import { COMPLETION_KEY_COMMANDS, SIGNATURE_HELP_KEY_COMMANDS } from "./keyCommands.js";
|
|
12
|
+
import { LanguageServerCompletionSources, createLanguageServerCompletionSource } from "./completionProviders.js";
|
|
13
|
+
import { CompositeDiagnosticsPresenter, DiagnosticsPresenter } from "./diagnosticsPresenter.js";
|
|
14
|
+
import { FormatOnTypeController } from "./formatOnType.js";
|
|
15
|
+
import { DefinitionLinkController } from "./definitionLinkController.js";
|
|
16
|
+
import { createLanguageServerHoverParticipant } from "./hoverParticipant.js";
|
|
17
|
+
import { signatureHelpTriggerFromTypedText } from "./signatureHelp.js";
|
|
18
|
+
import { DocumentHighlightController } from "./documentHighlightController.js";
|
|
19
|
+
import { SemanticTokenLayerOwner } from "./semanticTokens.js";
|
|
20
|
+
import { createRenameWidgetController } from "./renameWidget.js";
|
|
21
|
+
import { formattingChangesText, formattingOptions, prepareFormattingEdits } from "./formatting.js";
|
|
22
|
+
import { wordRangeAtOffset } from "@singapore-editor/core/document";
|
|
23
|
+
import { lspPositionToOffsetInSnapshot, offsetToLspPositionInSnapshot } from "@singapore-editor/lsp";
|
|
24
|
+
import { anchoredSurfaceFollowsUpdate, isInsideEditorPopup } from "@singapore-editor/plugin-ui/anchored-surface";
|
|
25
|
+
import { EDITOR_HOVER_PARTICIPANT } from "@singapore-editor/plugin-ui/hover-participant";
|
|
26
|
+
import { hoverControllerFor } from "@singapore-editor/plugin-ui/hover-registry";
|
|
27
|
+
//#region src/plugin.ts
|
|
28
|
+
var DEFAULT_PLUGIN_NAME = "editor.lsp-plugin";
|
|
29
|
+
var DEFAULT_NAMESPACE = "lsp-plugin";
|
|
30
|
+
var DEFAULT_TIMING_PREFIX = "lspPlugin";
|
|
31
|
+
var DEFAULT_DIAGNOSTICS_SOURCE_ID = "editor.lsp-plugin.diagnostics";
|
|
32
|
+
var DEFAULT_COMPLETION_ACCEPT_TIMING_NAME = "lspPlugin.completion.accept";
|
|
33
|
+
function createLanguageServerPlugin(options) {
|
|
34
|
+
if ("document" in options) return createLanguageServerSetPlugin(options);
|
|
35
|
+
return createLanguageServerSetPlugin({
|
|
36
|
+
lanes: [languageServerLaneFromPluginOptions(options)],
|
|
37
|
+
onApplyWorkspaceEdit: options.onApplyWorkspaceEdit,
|
|
38
|
+
documentSync: options.documentSync,
|
|
39
|
+
semanticTokens: options.semanticTokens ? () => options.semanticTokens : void 0,
|
|
40
|
+
onDiagnostics: options.onDiagnostics,
|
|
41
|
+
onDidNavigateDiagnostic: options.onDidNavigateDiagnostic,
|
|
42
|
+
getDiagnosticActions: options.getDiagnosticActions,
|
|
43
|
+
onDefinitionLinkHover: options.onDefinitionLinkHover,
|
|
44
|
+
onOpenDefinition: options.onOpenDefinition,
|
|
45
|
+
onOpenReferences: options.onOpenReferences,
|
|
46
|
+
onRequestError: options.onRequestError,
|
|
47
|
+
onError: options.onError
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function createLanguageServerSetPlugin(options) {
|
|
51
|
+
return createResolvedLanguageServerPlugin(resolveLanguageServerSetOptions(options));
|
|
52
|
+
}
|
|
53
|
+
function createLanguageServerAdapterPlugin(options) {
|
|
54
|
+
return createResolvedLanguageServerPlugin(resolveAdapterOptions(options));
|
|
55
|
+
}
|
|
56
|
+
function createResolvedLanguageServerPlugin(resolved) {
|
|
57
|
+
return {
|
|
58
|
+
name: resolved.name,
|
|
59
|
+
activate(context) {
|
|
60
|
+
const views = new LanguageServerViews();
|
|
61
|
+
return [
|
|
62
|
+
context.registerViewContribution({ createContribution: (contributionContext) => new LanguageServerContribution(contributionContext, views, resolved) }),
|
|
63
|
+
context.registerCommandContribution({ createContribution: (contributionContext) => new LanguageServerCommandContribution(contributionContext, views, resolved.commands) }),
|
|
64
|
+
context.registerEditContribution({ createContribution: (contributionContext) => new LanguageServerCompletionEditContribution(contributionContext, resolved.completion) })
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** The views of one editor, answering its commands: the first view that acts claims the key. */
|
|
70
|
+
var LanguageServerViews = class {
|
|
71
|
+
views = /* @__PURE__ */ new Set();
|
|
72
|
+
register(view) {
|
|
73
|
+
this.views.add(view);
|
|
74
|
+
}
|
|
75
|
+
unregister(view) {
|
|
76
|
+
this.views.delete(view);
|
|
77
|
+
}
|
|
78
|
+
goToDefinitionFromSelection() {
|
|
79
|
+
return this.runNavigationCommand({
|
|
80
|
+
kind: "definition",
|
|
81
|
+
openMode: "default"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
runNavigationCommand(command) {
|
|
85
|
+
return this.some((view) => view.runNavigationCommand(command));
|
|
86
|
+
}
|
|
87
|
+
moveDiagnosticMarker(direction) {
|
|
88
|
+
return this.some((view) => view.moveDiagnosticMarker(direction));
|
|
89
|
+
}
|
|
90
|
+
formatDocument() {
|
|
91
|
+
return this.some((view) => view.formatDocument());
|
|
92
|
+
}
|
|
93
|
+
renameSymbol() {
|
|
94
|
+
return this.some((view) => view.renameSymbol());
|
|
95
|
+
}
|
|
96
|
+
applyAutoFix() {
|
|
97
|
+
return this.some((view) => view.applyAutoFix());
|
|
98
|
+
}
|
|
99
|
+
completionCommand(command) {
|
|
100
|
+
return this.some((view) => view.completionCommand(command));
|
|
101
|
+
}
|
|
102
|
+
signatureHelpCommand(command) {
|
|
103
|
+
return this.some((view) => view.signatureHelpCommand(command));
|
|
104
|
+
}
|
|
105
|
+
some(run) {
|
|
106
|
+
for (const view of this.views) if (run(view)) return true;
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
var LanguageServerCommandContribution = class {
|
|
111
|
+
commands;
|
|
112
|
+
constructor(context, views, commands) {
|
|
113
|
+
this.commands = commands.map((command) => context.registerCommand(command.id, () => command.run(views)));
|
|
114
|
+
}
|
|
115
|
+
dispose() {
|
|
116
|
+
for (const command of this.commands) command.dispose();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var LanguageServerCompletionEditContribution = class {
|
|
120
|
+
completionFeature;
|
|
121
|
+
constructor(context, options) {
|
|
122
|
+
this.completionFeature = context.registerFeature(options.editFeature, createCompletionEditFeature(context, options.acceptTimingName));
|
|
123
|
+
}
|
|
124
|
+
dispose() {
|
|
125
|
+
this.completionFeature.dispose();
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
var LanguageServerContribution = class {
|
|
129
|
+
context;
|
|
130
|
+
views;
|
|
131
|
+
options;
|
|
132
|
+
document;
|
|
133
|
+
lanes;
|
|
134
|
+
servers;
|
|
135
|
+
diagnostics;
|
|
136
|
+
completionSources;
|
|
137
|
+
completion;
|
|
138
|
+
definitionLink;
|
|
139
|
+
hoverParticipantRegistration;
|
|
140
|
+
/**
|
|
141
|
+
* Loaded on the first `(` or `,` typed, not at boot. The surface it shares with the hover carries
|
|
142
|
+
* a Markdown renderer and its parser, which an editor that never opens an argument list has no
|
|
143
|
+
* reason to download.
|
|
144
|
+
*/
|
|
145
|
+
signatureHelpOptions;
|
|
146
|
+
signatureHelp = null;
|
|
147
|
+
signatureHelpLoad = null;
|
|
148
|
+
typedTextRegistration;
|
|
149
|
+
documentHighlights;
|
|
150
|
+
codeActions;
|
|
151
|
+
/** Absent rather than idle when switched off, so nothing watches the typing at all. */
|
|
152
|
+
formatOnType;
|
|
153
|
+
/** Absent unless the host asked for semantic colour; see LanguageServerSemanticTokensOptions. */
|
|
154
|
+
semanticTokens = null;
|
|
155
|
+
semanticTokensOptions = null;
|
|
156
|
+
semanticTokensOwner = null;
|
|
157
|
+
rename = null;
|
|
158
|
+
renameOperation = null;
|
|
159
|
+
renameActiveDocument = null;
|
|
160
|
+
/** The symbol an open prompt is renaming, which is what the prompt has to stay beside. */
|
|
161
|
+
renamePromptRange = null;
|
|
162
|
+
viewDocument = null;
|
|
163
|
+
disposed = false;
|
|
164
|
+
constructor(context, views, options) {
|
|
165
|
+
this.context = context;
|
|
166
|
+
this.views = views;
|
|
167
|
+
this.options = options;
|
|
168
|
+
const presenter = new DiagnosticsPresenter(context, context.highlightPrefix, {
|
|
169
|
+
...options.diagnostics,
|
|
170
|
+
onDidNavigateDiagnostic: options.onDidNavigateDiagnostic,
|
|
171
|
+
onError: options.onError
|
|
172
|
+
});
|
|
173
|
+
this.diagnostics = new CompositeDiagnosticsPresenter(presenter, rankedLanguageServerLanes(options.lanes, "diagnostics").map((lane) => lane.id), options.onDiagnostics);
|
|
174
|
+
this.document = options.document ?? new LanguageServerDocument({ getSnapshot: () => context.getSnapshot() }, {
|
|
175
|
+
lanes: options.lanes,
|
|
176
|
+
documentSync: options.documentSync
|
|
177
|
+
});
|
|
178
|
+
this.lanes = this.document.lanes.map((lane) => this.createLane(lane));
|
|
179
|
+
this.servers = new LanguageServerSet(this.lanes);
|
|
180
|
+
this.completionSources = new LanguageServerCompletionSources(context, this.servers.declared("completion").map((lane) => createLanguageServerCompletionSource(lane.connection.client, () => this.servers.ready("completion").includes(lane), lane.onInteractiveReady, lane.onRequestError)));
|
|
181
|
+
this.completion = new CompletionController({
|
|
182
|
+
context,
|
|
183
|
+
completionSources: this.completionSources,
|
|
184
|
+
completionEditFeature: options.completion.editFeature,
|
|
185
|
+
completionWidgetClassNamespace: options.completion.widgetClassNamespace,
|
|
186
|
+
completionAcceptOnCommitCharacter: options.completion.acceptOnCommitCharacter,
|
|
187
|
+
getActiveDocument: () => this.activeDocument(),
|
|
188
|
+
ignorePointerTarget: isInsideEditorPopup,
|
|
189
|
+
onBeforeShow: () => {
|
|
190
|
+
hoverControllerFor(context.scrollElement)?.hide();
|
|
191
|
+
this.definitionLink.clearPointerUi();
|
|
192
|
+
},
|
|
193
|
+
onRequestSuccess: () => options.onInteractiveReady?.(),
|
|
194
|
+
onRequestError: (error) => this.handleRequestError(error)
|
|
195
|
+
});
|
|
196
|
+
this.definitionLink = new DefinitionLinkController({
|
|
197
|
+
context,
|
|
198
|
+
router: this.servers,
|
|
199
|
+
linkHighlightNameNamespace: options.hoverDefinition.linkHighlightNameNamespace,
|
|
200
|
+
navigationTimingNamePrefix: options.hoverDefinition.navigationTimingNamePrefix,
|
|
201
|
+
getActiveDocument: () => this.activeDocument(),
|
|
202
|
+
onDefinitionLinkHover: options.onDefinitionLinkHover,
|
|
203
|
+
onOpenDefinition: options.onOpenDefinition,
|
|
204
|
+
onOpenReferences: options.onOpenReferences,
|
|
205
|
+
onRequestError: (error) => this.handleRequestError(error)
|
|
206
|
+
});
|
|
207
|
+
this.hoverParticipantRegistration = context.registerProvider(EDITOR_HOVER_PARTICIPANT, { language: "*" }, createLanguageServerHoverParticipant({
|
|
208
|
+
router: this.servers,
|
|
209
|
+
requestHover: (params, requestOptions, onUpdate) => this.servers.requestHover(params, requestOptions, onUpdate),
|
|
210
|
+
getActiveDocument: () => this.activeDocument(),
|
|
211
|
+
getDiagnostics: () => this.diagnostics.diagnostics,
|
|
212
|
+
getDiagnosticActions: options.getDiagnosticActions,
|
|
213
|
+
openLocation: (target) => {
|
|
214
|
+
options.onOpenDefinition?.(target);
|
|
215
|
+
},
|
|
216
|
+
onRequestSuccess: () => options.onInteractiveReady?.(),
|
|
217
|
+
onRequestError: (error) => this.handleRequestError(error)
|
|
218
|
+
})) ?? null;
|
|
219
|
+
this.typedTextRegistration = context.onDidType((text) => this.handleTypedText(text));
|
|
220
|
+
this.signatureHelpOptions = {
|
|
221
|
+
router: this.servers,
|
|
222
|
+
context,
|
|
223
|
+
getActiveDocument: () => this.activeDocument(),
|
|
224
|
+
onRequestError: (error) => this.handleRequestError(error),
|
|
225
|
+
onRequestSuccess: () => options.onInteractiveReady?.(),
|
|
226
|
+
tooltipClassNamespace: options.hoverDefinition.tooltipClassNamespace
|
|
227
|
+
};
|
|
228
|
+
this.documentHighlights = new DocumentHighlightController({
|
|
229
|
+
router: this.servers,
|
|
230
|
+
context,
|
|
231
|
+
getActiveDocument: () => this.activeDocument(),
|
|
232
|
+
highlightName: `${context.highlightPrefix}-document-highlight`,
|
|
233
|
+
onRequestError: (error) => this.handleRequestError(error)
|
|
234
|
+
});
|
|
235
|
+
this.codeActions = new CodeActionController({
|
|
236
|
+
router: this.servers,
|
|
237
|
+
context,
|
|
238
|
+
getActiveDocument: () => this.activeDocument(),
|
|
239
|
+
getDiagnostics: () => this.diagnostics.diagnostics,
|
|
240
|
+
onRequestError: (error) => this.handleRequestError(error)
|
|
241
|
+
});
|
|
242
|
+
this.formatOnType = options.formatOnType ? new FormatOnTypeController({
|
|
243
|
+
context,
|
|
244
|
+
editFeature: options.completion.editFeature
|
|
245
|
+
}) : null;
|
|
246
|
+
this.views.register(this);
|
|
247
|
+
this.update(context.getSnapshot(), "document", null);
|
|
248
|
+
}
|
|
249
|
+
update(snapshot, kind, change) {
|
|
250
|
+
if (this.disposed) return;
|
|
251
|
+
this.updateViewDocument(snapshot, kind);
|
|
252
|
+
this.abortRenameOnDocumentDrift();
|
|
253
|
+
this.definitionLink.update(snapshot, kind);
|
|
254
|
+
if (anchoredSurfaceFollowsUpdate(kind)) this.reanchorRenamePrompt();
|
|
255
|
+
if (!this.options.document) this.document.synchronize(change ?? null, kind);
|
|
256
|
+
this.completion.update(snapshot, kind, change ?? null);
|
|
257
|
+
this.signatureHelp?.update(snapshot, kind);
|
|
258
|
+
this.documentHighlights.update(snapshot, kind);
|
|
259
|
+
this.codeActions.update(kind);
|
|
260
|
+
this.formatOnType?.update(snapshot, kind, change ?? null);
|
|
261
|
+
this.syncSemanticTokens(snapshot, kind);
|
|
262
|
+
if (kind === "tokens") this.diagnostics.updateTheme(snapshot.theme ?? null);
|
|
263
|
+
}
|
|
264
|
+
dispose() {
|
|
265
|
+
if (this.disposed) return;
|
|
266
|
+
this.disposed = true;
|
|
267
|
+
this.views.unregister(this);
|
|
268
|
+
this.definitionLink.dispose();
|
|
269
|
+
this.hoverParticipantRegistration?.dispose();
|
|
270
|
+
this.completion.hide();
|
|
271
|
+
for (const lane of this.lanes) lane.subscription.dispose();
|
|
272
|
+
if (!this.options.document) this.document.dispose();
|
|
273
|
+
this.diagnostics.clear();
|
|
274
|
+
this.completionSources.dispose();
|
|
275
|
+
this.completion.dispose();
|
|
276
|
+
this.typedTextRegistration?.dispose();
|
|
277
|
+
this.signatureHelpLoad?.then((controller) => controller.dispose());
|
|
278
|
+
this.documentHighlights.dispose();
|
|
279
|
+
this.codeActions.dispose();
|
|
280
|
+
this.formatOnType?.dispose();
|
|
281
|
+
this.semanticTokens?.dispose();
|
|
282
|
+
this.semanticTokensOptions?.dispose?.();
|
|
283
|
+
this.semanticTokensOptions = null;
|
|
284
|
+
this.semanticTokensOwner = null;
|
|
285
|
+
this.cancelRename();
|
|
286
|
+
this.rename?.dispose();
|
|
287
|
+
}
|
|
288
|
+
goToDefinitionFromSelection() {
|
|
289
|
+
return this.runNavigationCommand({
|
|
290
|
+
kind: "definition",
|
|
291
|
+
openMode: "default"
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
runNavigationCommand(command) {
|
|
295
|
+
return this.definitionLink.runNavigationCommand(command);
|
|
296
|
+
}
|
|
297
|
+
completionCommand(command) {
|
|
298
|
+
return this.completion.runKeyCommand(command);
|
|
299
|
+
}
|
|
300
|
+
/** Before the first `(` there is no controller, and so no hint for these to act on. */
|
|
301
|
+
signatureHelpCommand(command) {
|
|
302
|
+
return this.signatureHelp?.runKeyCommand(command) ?? false;
|
|
303
|
+
}
|
|
304
|
+
moveDiagnosticMarker(direction) {
|
|
305
|
+
return this.diagnostics.moveMarker(this.activeDocument(), direction);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Formats the whole document through the language server.
|
|
309
|
+
*
|
|
310
|
+
* Reports handled as soon as the request is on its way: the answer arrives asynchronously, and
|
|
311
|
+
* returning false would let the keystroke fall through to another binding.
|
|
312
|
+
*/
|
|
313
|
+
formatDocument() {
|
|
314
|
+
const active = this.activeDocument();
|
|
315
|
+
if (!active) return false;
|
|
316
|
+
if (!this.servers.hasReady("formatting", "textDocument/formatting")) return false;
|
|
317
|
+
this.requestFormatting(active);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Renames the symbol under the caret.
|
|
322
|
+
*
|
|
323
|
+
* The new name comes from the host when it supplies `onRequestRenameName`, and otherwise from the
|
|
324
|
+
* editor's own input widget, so the engine is usable standalone without dictating a dialog to an
|
|
325
|
+
* application that has one.
|
|
326
|
+
*/
|
|
327
|
+
renameSymbol() {
|
|
328
|
+
const active = this.activeDocument();
|
|
329
|
+
if (!active) return false;
|
|
330
|
+
if (!this.servers.hasReady("rename", "textDocument/rename")) return false;
|
|
331
|
+
this.cancelRename();
|
|
332
|
+
const abort = new AbortController();
|
|
333
|
+
this.renameOperation = abort;
|
|
334
|
+
this.renameActiveDocument = active;
|
|
335
|
+
this.runRename(active, abort).finally(() => this.finishRename(abort));
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
/** Applies the preferred quick fix the oracle already found for the caret. */
|
|
339
|
+
applyAutoFix() {
|
|
340
|
+
return this.codeActions.applyAutoFix();
|
|
341
|
+
}
|
|
342
|
+
createLane(documentLane) {
|
|
343
|
+
const options = documentLane.options;
|
|
344
|
+
const diagnostics = this.diagnostics.forLane(options.id);
|
|
345
|
+
const subscription = documentLane.attach({
|
|
346
|
+
clear: () => diagnostics.clear(),
|
|
347
|
+
render: (document, items) => diagnostics.render(document, items),
|
|
348
|
+
publishSummary: (uri, version, items, freshness) => {
|
|
349
|
+
diagnostics.publishSummary(uri, version, items, freshness);
|
|
350
|
+
this.codeActions?.diagnosticsChanged();
|
|
351
|
+
}
|
|
352
|
+
}, () => {
|
|
353
|
+
if (this.disposed) return;
|
|
354
|
+
this.completion?.hide();
|
|
355
|
+
this.syncSemanticTokens(this.context.getSnapshot(), "document");
|
|
356
|
+
});
|
|
357
|
+
return {
|
|
358
|
+
connection: documentLane.connection,
|
|
359
|
+
subscription,
|
|
360
|
+
features: options.features,
|
|
361
|
+
id: options.id,
|
|
362
|
+
onApplyWorkspaceEdit: this.options.onApplyWorkspaceEdit ?? options.onApplyWorkspaceEdit,
|
|
363
|
+
onRequestError: (method, error) => {
|
|
364
|
+
if (options.onRequestError) options.onRequestError(method, error);
|
|
365
|
+
else this.options.onRequestError?.(options.id, method, error);
|
|
366
|
+
},
|
|
367
|
+
onInteractiveReady: () => {
|
|
368
|
+
if (options.onInteractiveReady) options.onInteractiveReady();
|
|
369
|
+
else this.options.onInteractiveReady?.();
|
|
370
|
+
},
|
|
371
|
+
sync: documentLane.sync
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Nothing is on screen before the controller exists, so `)` closes a signature that was never
|
|
376
|
+
* shown and loads nothing. An opening `(` or a `,` is the first keystroke that needs it.
|
|
377
|
+
*/
|
|
378
|
+
handleTypedText(text) {
|
|
379
|
+
if (this.signatureHelp) {
|
|
380
|
+
this.signatureHelp.handleTypedText(text);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const trigger = signatureHelpTriggerFromTypedText(text);
|
|
384
|
+
if (!trigger || trigger.kind === "close") return;
|
|
385
|
+
this.loadSignatureHelp().then((controller) => controller.handleTypedText(text));
|
|
386
|
+
}
|
|
387
|
+
loadSignatureHelp() {
|
|
388
|
+
this.signatureHelpLoad ??= import("./signatureHelpController.js").then((module) => {
|
|
389
|
+
const controller = new module.SignatureHelpController(this.signatureHelpOptions);
|
|
390
|
+
this.signatureHelp = controller;
|
|
391
|
+
if (this.disposed) controller.dispose();
|
|
392
|
+
return controller;
|
|
393
|
+
});
|
|
394
|
+
return this.signatureHelpLoad;
|
|
395
|
+
}
|
|
396
|
+
syncSemanticTokens(snapshot, kind) {
|
|
397
|
+
const selected = this.options.semanticTokens ? this.servers.ready("semanticTokens")[0] ?? null : null;
|
|
398
|
+
const owner = this.lanes.find((lane) => lane === selected) ?? null;
|
|
399
|
+
if (owner !== this.semanticTokensOwner) this.replaceSemanticTokensOwner(owner);
|
|
400
|
+
this.semanticTokens?.update(snapshot, kind);
|
|
401
|
+
}
|
|
402
|
+
replaceSemanticTokensOwner(owner) {
|
|
403
|
+
this.semanticTokens?.dispose();
|
|
404
|
+
this.semanticTokens = null;
|
|
405
|
+
this.semanticTokensOptions?.dispose?.();
|
|
406
|
+
this.semanticTokensOptions = null;
|
|
407
|
+
this.semanticTokensOwner = owner;
|
|
408
|
+
if (!owner || !this.options.semanticTokens) return;
|
|
409
|
+
const options = this.options.semanticTokens({
|
|
410
|
+
id: owner.id,
|
|
411
|
+
connection: {
|
|
412
|
+
client: owner.connection.client,
|
|
413
|
+
workspace: owner.connection.workspace
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
this.semanticTokensOptions = options;
|
|
417
|
+
this.semanticTokens = new SemanticTokenLayerOwner(this.context, options);
|
|
418
|
+
}
|
|
419
|
+
activeDocument() {
|
|
420
|
+
return this.viewDocument;
|
|
421
|
+
}
|
|
422
|
+
updateViewDocument(snapshot, kind) {
|
|
423
|
+
if (kind === "clear") {
|
|
424
|
+
this.viewDocument = null;
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (this.viewDocument?.textVersion === snapshot.textVersion && kind !== "document") return;
|
|
428
|
+
this.viewDocument = activeDocumentForSnapshot(snapshot, this.options.documentSync);
|
|
429
|
+
}
|
|
430
|
+
async runRename(active, abort) {
|
|
431
|
+
const selection = this.context.getSnapshot().selections[0];
|
|
432
|
+
if (!selection) return;
|
|
433
|
+
const offset = selection.headOffset;
|
|
434
|
+
const owner = this.servers.ready("rename", "textDocument/rename")[0];
|
|
435
|
+
if (!owner) return;
|
|
436
|
+
const prepared = await this.prepareRename(active, offset, owner, abort.signal);
|
|
437
|
+
if (!prepared) return;
|
|
438
|
+
if (!this.renameIsCurrent(active, abort)) return;
|
|
439
|
+
const { range, currentName } = prepared;
|
|
440
|
+
const anchor = this.context.getRangeClientRect(range.start, range.end);
|
|
441
|
+
if (!anchor) return;
|
|
442
|
+
try {
|
|
443
|
+
this.renamePromptRange = range;
|
|
444
|
+
let nextName;
|
|
445
|
+
try {
|
|
446
|
+
nextName = await this.promptRenameName({
|
|
447
|
+
anchor,
|
|
448
|
+
currentName,
|
|
449
|
+
signal: abort.signal
|
|
450
|
+
});
|
|
451
|
+
} finally {
|
|
452
|
+
this.renamePromptRange = null;
|
|
453
|
+
}
|
|
454
|
+
if (nextName === null || nextName === currentName) return;
|
|
455
|
+
if (!this.renameIsCurrent(active, abort)) return;
|
|
456
|
+
const guard = captureWorkspaceEditOriginGuard(owner.connection.workspace);
|
|
457
|
+
const edit = await this.servers.requestSingle(owner, "textDocument/rename", {
|
|
458
|
+
newName: nextName,
|
|
459
|
+
position: offsetToLspPositionInSnapshot(active, offset),
|
|
460
|
+
textDocument: { uri: active.uri }
|
|
461
|
+
}, { signal: abort.signal }, null);
|
|
462
|
+
if (edit === null) return;
|
|
463
|
+
if (!this.renameIsCurrent(active, abort)) return;
|
|
464
|
+
await this.dispatchRenameEdit({
|
|
465
|
+
active,
|
|
466
|
+
currentName,
|
|
467
|
+
edit,
|
|
468
|
+
guard,
|
|
469
|
+
nextName,
|
|
470
|
+
owner,
|
|
471
|
+
signal: abort.signal
|
|
472
|
+
});
|
|
473
|
+
} catch (error) {
|
|
474
|
+
this.handleRequestError(error);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
async prepareRename(active, offset, owner, signal) {
|
|
478
|
+
const fallback = rangeAroundOffset(active, offset, wordRangeAtOffset);
|
|
479
|
+
const provider = owner.connection.client.serverCapabilities?.renameProvider;
|
|
480
|
+
if (!(typeof provider === "object" && provider.prepareProvider === true)) return renameTarget(active, fallback);
|
|
481
|
+
const result = await this.servers.requestSingle(owner, "textDocument/prepareRename", {
|
|
482
|
+
position: offsetToLspPositionInSnapshot(active, offset),
|
|
483
|
+
textDocument: { uri: active.uri }
|
|
484
|
+
}, { signal }, null);
|
|
485
|
+
if (!result) return null;
|
|
486
|
+
if ("defaultBehavior" in result) return renameTarget(active, fallback);
|
|
487
|
+
const protocolRange = "range" in result ? result.range : result;
|
|
488
|
+
const target = renameTarget(active, {
|
|
489
|
+
start: lspPositionToOffsetInSnapshot(active, protocolRange.start),
|
|
490
|
+
end: lspPositionToOffsetInSnapshot(active, protocolRange.end)
|
|
491
|
+
});
|
|
492
|
+
if (!target || !("placeholder" in result)) return target;
|
|
493
|
+
return {
|
|
494
|
+
...target,
|
|
495
|
+
currentName: result.placeholder
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Keeps an open prompt beside the symbol while the view moves under it.
|
|
500
|
+
*
|
|
501
|
+
* A host that supplies its own dialog places it wherever it likes, so there is nothing here to
|
|
502
|
+
* move; a symbol that has scrolled out of the rendered rows has no rect, and the prompt is left
|
|
503
|
+
* where it was rather than thrown at the top of the page.
|
|
504
|
+
*/
|
|
505
|
+
reanchorRenamePrompt() {
|
|
506
|
+
const range = this.renamePromptRange;
|
|
507
|
+
if (!range) return;
|
|
508
|
+
const anchor = this.context.getRangeClientRect(range.start, range.end);
|
|
509
|
+
if (anchor) this.rename?.reanchor(anchor);
|
|
510
|
+
}
|
|
511
|
+
promptRenameName(prompt) {
|
|
512
|
+
if (prompt.signal.aborted) return Promise.resolve(null);
|
|
513
|
+
const host = this.options.onRequestRenameName;
|
|
514
|
+
if (host) return host(prompt);
|
|
515
|
+
return this.renameWidget().prompt(prompt);
|
|
516
|
+
}
|
|
517
|
+
/** Built on first use, so a host that supplies its own prompt never creates the element. */
|
|
518
|
+
renameWidget() {
|
|
519
|
+
if (this.rename) return this.rename;
|
|
520
|
+
this.rename = createRenameWidgetController({
|
|
521
|
+
classNamespace: this.options.hoverDefinition.tooltipClassNamespace ?? "lsp-plugin",
|
|
522
|
+
document: this.context.container.ownerDocument,
|
|
523
|
+
themeSource: this.context.scrollElement,
|
|
524
|
+
returnFocus: () => this.context.focusEditor()
|
|
525
|
+
});
|
|
526
|
+
return this.rename;
|
|
527
|
+
}
|
|
528
|
+
async dispatchRenameEdit(request) {
|
|
529
|
+
const parsed = parseWorkspaceEdit(request.edit);
|
|
530
|
+
if (!parsed.ok) {
|
|
531
|
+
this.reportLaneRequestError(request.owner, "textDocument/rename", new Error(parsed.error.reason));
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const origin = currentWorkspaceEditOrigin(request.guard, request.active, parsed.value);
|
|
535
|
+
if (!origin) return;
|
|
536
|
+
if (request.signal.aborted) return;
|
|
537
|
+
const apply = request.owner.onApplyWorkspaceEdit;
|
|
538
|
+
if (!apply) {
|
|
539
|
+
this.reportLaneRequestError(request.owner, "textDocument/rename", /* @__PURE__ */ new Error("Rename cannot be applied without a workspace edit host."));
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
const result = await apply({
|
|
543
|
+
guard: request.guard,
|
|
544
|
+
label: `Rename ${request.currentName} to ${request.nextName}`,
|
|
545
|
+
logicalRevisionScope: request.owner.connection.logicalRevisionScope,
|
|
546
|
+
originUri: request.active.uri,
|
|
547
|
+
originVersion: origin.version,
|
|
548
|
+
plan: parsed.value,
|
|
549
|
+
serverId: request.owner.id,
|
|
550
|
+
signal: request.signal,
|
|
551
|
+
source: "rename"
|
|
552
|
+
});
|
|
553
|
+
if (result.status !== "failed") return;
|
|
554
|
+
this.reportLaneRequestError(request.owner, "textDocument/rename", /* @__PURE__ */ new Error(`${result.code}: ${result.message}`));
|
|
555
|
+
}
|
|
556
|
+
renameIsCurrent(active, abort) {
|
|
557
|
+
if (this.disposed) return false;
|
|
558
|
+
if (abort.signal.aborted) return false;
|
|
559
|
+
if (this.renameOperation !== abort) return false;
|
|
560
|
+
return active === this.activeDocument();
|
|
561
|
+
}
|
|
562
|
+
abortRenameOnDocumentDrift() {
|
|
563
|
+
if (!this.renameOperation) return;
|
|
564
|
+
if (this.renameActiveDocument === this.activeDocument()) return;
|
|
565
|
+
this.cancelRename();
|
|
566
|
+
}
|
|
567
|
+
cancelRename() {
|
|
568
|
+
const abort = this.renameOperation;
|
|
569
|
+
this.renameOperation = null;
|
|
570
|
+
this.renameActiveDocument = null;
|
|
571
|
+
this.renamePromptRange = null;
|
|
572
|
+
abort?.abort();
|
|
573
|
+
}
|
|
574
|
+
finishRename(abort) {
|
|
575
|
+
if (this.renameOperation !== abort) return;
|
|
576
|
+
this.renameOperation = null;
|
|
577
|
+
this.renameActiveDocument = null;
|
|
578
|
+
}
|
|
579
|
+
reportLaneRequestError(owner, method, error) {
|
|
580
|
+
if (owner.onRequestError) {
|
|
581
|
+
owner.onRequestError(method, error);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
this.handleRequestError(error);
|
|
585
|
+
}
|
|
586
|
+
async requestFormatting(active) {
|
|
587
|
+
try {
|
|
588
|
+
const edits = await this.servers.request("textDocument/formatting", {
|
|
589
|
+
options: formattingOptions(this.context.getSnapshot().tabSize),
|
|
590
|
+
textDocument: { uri: active.uri }
|
|
591
|
+
});
|
|
592
|
+
if (active !== this.activeDocument()) return;
|
|
593
|
+
const converted = prepareFormattingEdits(active, edits);
|
|
594
|
+
if (converted.length === 0) return;
|
|
595
|
+
if (!formattingChangesText(active.textSnapshot, converted)) return;
|
|
596
|
+
this.applyFormattingEdits(converted, active.textSnapshot.length);
|
|
597
|
+
} catch (error) {
|
|
598
|
+
this.handleRequestError(error);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Applies formatting through the same edit feature completions use, so a format is one
|
|
603
|
+
* transaction and one undo step.
|
|
604
|
+
*
|
|
605
|
+
* The caret is pinned to its offset rather than tracked through the edits: formatting moves text
|
|
606
|
+
* wholesale, and an offset that survives is closer to where the user was looking than a position
|
|
607
|
+
* mapped through a rewrite of the whole file.
|
|
608
|
+
*/
|
|
609
|
+
applyFormattingEdits(edits, previousLength) {
|
|
610
|
+
const feature = this.context.getFeature(this.options.completion.editFeature);
|
|
611
|
+
if (!feature) return;
|
|
612
|
+
const length = edits.reduce((size, edit) => size + edit.text.length - (edit.to - edit.from), previousLength);
|
|
613
|
+
const head = Math.min(this.context.getSnapshot().selections[0]?.headOffset ?? 0, length);
|
|
614
|
+
feature.applyCompletion({
|
|
615
|
+
edits,
|
|
616
|
+
selection: {
|
|
617
|
+
anchor: head,
|
|
618
|
+
head
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
handleRequestError(error) {
|
|
623
|
+
if (isAbortError(error)) return;
|
|
624
|
+
this.options.onError?.(error);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
function renameTarget(document, range) {
|
|
628
|
+
if (range.end <= range.start) return null;
|
|
629
|
+
const currentName = document.textSnapshot.readRange(range.start, range.end);
|
|
630
|
+
if (currentName.length === 0) return null;
|
|
631
|
+
return {
|
|
632
|
+
currentName,
|
|
633
|
+
range
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
function resolveAdapterOptions(options) {
|
|
637
|
+
return {
|
|
638
|
+
name: options.name,
|
|
639
|
+
lanes: [resolvedLaneFromAdapterOptions(options)],
|
|
640
|
+
documentSync: options.documentSync ?? {},
|
|
641
|
+
diagnostics: resolveDiagnosticsOptions(options),
|
|
642
|
+
completion: resolveCompletionOptions(options),
|
|
643
|
+
formatOnType: options.formatOnType ?? true,
|
|
644
|
+
hoverDefinition: resolveHoverDefinitionOptions(options),
|
|
645
|
+
commands: options.commands ?? LANGUAGE_SERVER_COMMANDS,
|
|
646
|
+
semanticTokens: options.semanticTokens ? () => options.semanticTokens : void 0,
|
|
647
|
+
onDiagnostics: options.onDiagnostics,
|
|
648
|
+
onDidNavigateDiagnostic: options.onDidNavigateDiagnostic,
|
|
649
|
+
getDiagnosticActions: options.getDiagnosticActions,
|
|
650
|
+
onDefinitionLinkHover: options.onDefinitionLinkHover,
|
|
651
|
+
onOpenDefinition: options.onOpenDefinition,
|
|
652
|
+
onOpenReferences: options.onOpenReferences,
|
|
653
|
+
onRequestRenameName: options.onRequestRenameName,
|
|
654
|
+
onApplyWorkspaceEdit: options.onApplyWorkspaceEdit,
|
|
655
|
+
onRequestError: options.onRequestError,
|
|
656
|
+
onError: options.onError
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
function resolveLanguageServerSetOptions(options) {
|
|
660
|
+
return {
|
|
661
|
+
name: DEFAULT_PLUGIN_NAME,
|
|
662
|
+
document: options.document,
|
|
663
|
+
lanes: options.document ? options.document.lanes.map((lane) => lane.options) : options.lanes.map((lane) => resolveLanguageServerLaneOptions({
|
|
664
|
+
...lane,
|
|
665
|
+
onApplyWorkspaceEdit: options.onApplyWorkspaceEdit ?? lane.onApplyWorkspaceEdit,
|
|
666
|
+
onRequestError: lane.onRequestError ?? ((method, error) => options.onRequestError?.(lane.id, method, error))
|
|
667
|
+
})),
|
|
668
|
+
documentSync: options.document?.syncOptions ?? options.documentSync ?? {},
|
|
669
|
+
diagnostics: resolveDiagnosticsOptions(),
|
|
670
|
+
completion: resolveCompletionOptions(),
|
|
671
|
+
formatOnType: true,
|
|
672
|
+
hoverDefinition: resolveHoverDefinitionOptions(),
|
|
673
|
+
commands: LANGUAGE_SERVER_COMMANDS,
|
|
674
|
+
semanticTokens: options.semanticTokens,
|
|
675
|
+
onDiagnostics: options.onDiagnostics,
|
|
676
|
+
onDidNavigateDiagnostic: options.onDidNavigateDiagnostic,
|
|
677
|
+
getDiagnosticActions: options.getDiagnosticActions,
|
|
678
|
+
onInteractiveReady: options.onInteractiveReady,
|
|
679
|
+
onDefinitionLinkHover: options.onDefinitionLinkHover,
|
|
680
|
+
onOpenDefinition: options.onOpenDefinition,
|
|
681
|
+
onOpenReferences: options.onOpenReferences,
|
|
682
|
+
onApplyWorkspaceEdit: options.onApplyWorkspaceEdit,
|
|
683
|
+
onRequestError: options.onRequestError,
|
|
684
|
+
onError: options.onError
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
function languageServerLaneFromPluginOptions(options) {
|
|
688
|
+
return {
|
|
689
|
+
id: DEFAULT_PLUGIN_NAME,
|
|
690
|
+
features: allLanguageServerFeatures(),
|
|
691
|
+
rootUri: options.rootUri,
|
|
692
|
+
initializationOptions: options.initializationOptions,
|
|
693
|
+
timeoutMs: options.timeoutMs,
|
|
694
|
+
capabilities: options.capabilities,
|
|
695
|
+
clientInfo: options.clientInfo,
|
|
696
|
+
notificationHandlers: options.notificationHandlers,
|
|
697
|
+
serverRequestHandlers: options.serverRequestHandlers,
|
|
698
|
+
webSocketRoute: options.webSocketRoute,
|
|
699
|
+
webSocketTransportOptions: options.webSocketTransportOptions,
|
|
700
|
+
connectionProvider: options.connectionProvider,
|
|
701
|
+
onApplyWorkspaceEdit: options.onApplyWorkspaceEdit,
|
|
702
|
+
onConnectionCreated: options.onConnectionCreated,
|
|
703
|
+
onConnected: options.onConnected,
|
|
704
|
+
onStatusChange: options.onStatusChange,
|
|
705
|
+
onInteractiveReady: options.onInteractiveReady,
|
|
706
|
+
onError: options.onError
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
function resolvedLaneFromAdapterOptions(options) {
|
|
710
|
+
return {
|
|
711
|
+
id: options.name,
|
|
712
|
+
features: allLanguageServerFeatures(),
|
|
713
|
+
rootUri: options.rootUri,
|
|
714
|
+
initializationOptions: options.initializationOptions,
|
|
715
|
+
timeoutMs: options.timeoutMs,
|
|
716
|
+
capabilities: options.capabilities,
|
|
717
|
+
clientInfo: options.clientInfo,
|
|
718
|
+
notificationHandlers: options.notificationHandlers,
|
|
719
|
+
serverRequestHandlers: options.serverRequestHandlers,
|
|
720
|
+
createTransport: options.createTransport,
|
|
721
|
+
connectionProvider: options.connectionProvider,
|
|
722
|
+
onApplyWorkspaceEdit: options.onApplyWorkspaceEdit,
|
|
723
|
+
onConnectionCreated: options.onConnectionCreated,
|
|
724
|
+
onConnected: options.onConnected,
|
|
725
|
+
onStatusChange: options.onStatusChange,
|
|
726
|
+
onInteractiveReady: options.onInteractiveReady,
|
|
727
|
+
onRequestError: (method, error) => options.onRequestError?.(options.name, method, error),
|
|
728
|
+
onError: options.onError
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
function resolveDiagnosticsOptions(options) {
|
|
732
|
+
return {
|
|
733
|
+
minimapSourceId: options?.diagnostics?.minimapSourceId ?? DEFAULT_DIAGNOSTICS_SOURCE_ID,
|
|
734
|
+
highlightNameNamespace: options?.diagnostics?.highlightNameNamespace ?? DEFAULT_NAMESPACE,
|
|
735
|
+
markerTimingNamePrefix: options?.diagnostics?.markerTimingNamePrefix ?? `${DEFAULT_TIMING_PREFIX}.marker`
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
function resolveCompletionOptions(options) {
|
|
739
|
+
return {
|
|
740
|
+
editFeature: options?.completion?.editFeature ?? LANGUAGE_SERVER_COMPLETION_EDIT_FEATURE,
|
|
741
|
+
acceptTimingName: options?.completion?.acceptTimingName ?? DEFAULT_COMPLETION_ACCEPT_TIMING_NAME,
|
|
742
|
+
widgetClassNamespace: options?.completion?.widgetClassNamespace,
|
|
743
|
+
acceptOnCommitCharacter: options?.completion?.acceptOnCommitCharacter ?? false
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function resolveHoverDefinitionOptions(options) {
|
|
747
|
+
return {
|
|
748
|
+
linkHighlightNameNamespace: options?.hoverDefinition?.linkHighlightNameNamespace ?? DEFAULT_NAMESPACE,
|
|
749
|
+
tooltipClassNamespace: options?.hoverDefinition?.tooltipClassNamespace ?? DEFAULT_NAMESPACE,
|
|
750
|
+
navigationTimingNamePrefix: options?.hoverDefinition?.navigationTimingNamePrefix ?? DEFAULT_TIMING_PREFIX
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
var LANGUAGE_SERVER_COMMANDS = [
|
|
754
|
+
{
|
|
755
|
+
id: "goToDefinition",
|
|
756
|
+
run: (state) => state.goToDefinitionFromSelection()
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
id: "editor.action.goToDefinition",
|
|
760
|
+
run: (state) => state.goToDefinitionFromSelection()
|
|
761
|
+
},
|
|
762
|
+
{
|
|
763
|
+
id: "editor.action.peekDefinition",
|
|
764
|
+
run: (state) => state.runNavigationCommand({
|
|
765
|
+
kind: "definition",
|
|
766
|
+
openMode: "peek"
|
|
767
|
+
})
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
id: "editor.action.revealDefinitionAside",
|
|
771
|
+
run: (state) => state.runNavigationCommand({
|
|
772
|
+
kind: "definition",
|
|
773
|
+
openMode: "aside"
|
|
774
|
+
})
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
id: "editor.action.goToImplementation",
|
|
778
|
+
run: (state) => state.runNavigationCommand({
|
|
779
|
+
kind: "implementation",
|
|
780
|
+
openMode: "default"
|
|
781
|
+
})
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
id: "editor.action.goToTypeDefinition",
|
|
785
|
+
run: (state) => state.runNavigationCommand({
|
|
786
|
+
kind: "typeDefinition",
|
|
787
|
+
openMode: "default"
|
|
788
|
+
})
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
id: "editor.action.goToReferences",
|
|
792
|
+
run: (state) => state.runNavigationCommand({
|
|
793
|
+
kind: "references",
|
|
794
|
+
openMode: "peek",
|
|
795
|
+
includeDeclaration: true
|
|
796
|
+
})
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
id: "editor.action.rename",
|
|
800
|
+
run: (state) => state.renameSymbol()
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
id: "editor.action.formatDocument",
|
|
804
|
+
run: (state) => state.formatDocument()
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
id: "editor.action.autoFix",
|
|
808
|
+
run: (state) => state.applyAutoFix()
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
id: "editor.action.marker.next",
|
|
812
|
+
run: (state) => state.moveDiagnosticMarker("next")
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
id: "editor.action.marker.prev",
|
|
816
|
+
run: (state) => state.moveDiagnosticMarker("previous")
|
|
817
|
+
},
|
|
818
|
+
...keyCommandSpecs(COMPLETION_KEY_COMMANDS, (target, command) => target.completionCommand(command)),
|
|
819
|
+
...keyCommandSpecs(SIGNATURE_HELP_KEY_COMMANDS, (target, command) => target.signatureHelpCommand(command))
|
|
820
|
+
];
|
|
821
|
+
/** The completion list and signature hint, driven by the keymap rather than by raw keys. */
|
|
822
|
+
function keyCommandSpecs(ids, run) {
|
|
823
|
+
return Object.keys(ids).map((command) => ({
|
|
824
|
+
id: ids[command],
|
|
825
|
+
run: (target) => run(target, command)
|
|
826
|
+
}));
|
|
827
|
+
}
|
|
828
|
+
function isAbortError(error) {
|
|
829
|
+
if (error instanceof DOMException && error.name === "AbortError") return true;
|
|
830
|
+
if (!isRecord(error)) return false;
|
|
831
|
+
return error.name === "LspRequestCancelledError";
|
|
832
|
+
}
|
|
833
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
834
|
+
//#endregion
|
|
835
|
+
export { createLanguageServerAdapterPlugin, createLanguageServerPlugin, createLanguageServerSetPlugin };
|
|
836
|
+
|
|
837
|
+
//# sourceMappingURL=plugin.js.map
|