@adecore/lsp 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/completion-defaults.d.ts +4 -0
- package/dist/completion-defaults.js +83 -0
- package/dist/document.d.ts +5 -1
- package/dist/document.js +14 -0
- package/dist/file-operations.d.ts +9 -1
- package/dist/file-operations.js +12 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/protocol.d.ts +29 -0
- package/dist/service.d.ts +11 -1
- package/dist/session.d.ts +11 -3
- package/dist/session.js +47 -4
- package/dist/workspace-operations.d.ts +45 -0
- package/dist/workspace-operations.js +232 -0
- package/package.json +1 -1
- package/src/completion-defaults.ts +97 -0
- package/src/document.ts +21 -0
- package/src/file-operations.ts +25 -5
- package/src/index.ts +14 -1
- package/src/protocol.ts +42 -0
- package/src/service.ts +22 -0
- package/src/session.ts +62 -5
- package/src/workspace-operations.ts +341 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
function validRange(range, singleLine = true) {
|
|
2
|
+
if (range === null || typeof range !== 'object') {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
const { start, end } = range;
|
|
6
|
+
return (start !== undefined &&
|
|
7
|
+
start !== null &&
|
|
8
|
+
typeof start === 'object' &&
|
|
9
|
+
end !== undefined &&
|
|
10
|
+
end !== null &&
|
|
11
|
+
typeof end === 'object' &&
|
|
12
|
+
[start.line, start.character, end.line, end.character].every((value) => Number.isSafeInteger(value) && value >= 0) &&
|
|
13
|
+
(!singleLine || start.line === end.line) &&
|
|
14
|
+
(start.line < end.line || (start.line === end.line && start.character <= end.character)));
|
|
15
|
+
}
|
|
16
|
+
function validEditRange(range, singleLine = true) {
|
|
17
|
+
if (range === null || typeof range !== 'object' || Array.isArray(range)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if ('start' in range) {
|
|
21
|
+
return validRange(range, singleLine);
|
|
22
|
+
}
|
|
23
|
+
return (validRange(range.insert) &&
|
|
24
|
+
validRange(range.replace) &&
|
|
25
|
+
range.insert.start.line === range.replace.start.line &&
|
|
26
|
+
range.insert.start.character === range.replace.start.character &&
|
|
27
|
+
range.insert.end.character <= range.replace.end.character);
|
|
28
|
+
}
|
|
29
|
+
export function applyCompletionDefaults(item, defaults, options) {
|
|
30
|
+
if (typeof item?.label !== 'string') {
|
|
31
|
+
throw new TypeError('A completion item must have a string label.');
|
|
32
|
+
}
|
|
33
|
+
for (const value of [item.filterText, item.sortText, item.insertText, item.textEditText]) {
|
|
34
|
+
if (value !== undefined && typeof value !== 'string') {
|
|
35
|
+
throw new TypeError('Completion ranking and insertion text must be strings.');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (item.textEdit !== undefined) {
|
|
39
|
+
const edit = item.textEdit;
|
|
40
|
+
if (edit === null ||
|
|
41
|
+
typeof edit !== 'object' ||
|
|
42
|
+
typeof edit.newText !== 'string' ||
|
|
43
|
+
!('range' in edit ? validEditRange(edit.range, false) : validEditRange(edit))) {
|
|
44
|
+
throw new RangeError('Invalid completion item edit.');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (defaults === undefined) {
|
|
48
|
+
return item;
|
|
49
|
+
}
|
|
50
|
+
const next = { ...item };
|
|
51
|
+
if (next.commitCharacters === undefined && defaults.commitCharacters !== undefined) {
|
|
52
|
+
next.commitCharacters = defaults.commitCharacters;
|
|
53
|
+
}
|
|
54
|
+
if (next.insertTextFormat === undefined && defaults.insertTextFormat !== undefined) {
|
|
55
|
+
next.insertTextFormat = defaults.insertTextFormat;
|
|
56
|
+
}
|
|
57
|
+
if (next.insertTextMode === undefined && defaults.insertTextMode !== undefined) {
|
|
58
|
+
next.insertTextMode = defaults.insertTextMode;
|
|
59
|
+
}
|
|
60
|
+
if (next.data === undefined && defaults.data !== undefined) {
|
|
61
|
+
next.data = defaults.data;
|
|
62
|
+
}
|
|
63
|
+
if (next.textEdit === undefined && defaults.editRange !== undefined) {
|
|
64
|
+
const range = defaults.editRange;
|
|
65
|
+
const newText = item.textEditText ?? item.label;
|
|
66
|
+
if (typeof newText !== 'string') {
|
|
67
|
+
throw new TypeError('Completion edit text must be a string.');
|
|
68
|
+
}
|
|
69
|
+
const invalid = (message) => {
|
|
70
|
+
const error = new RangeError(message);
|
|
71
|
+
if (options?.onInvalidRange === undefined) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
options.onInvalidRange(error);
|
|
75
|
+
return next;
|
|
76
|
+
};
|
|
77
|
+
if (!validEditRange(range)) {
|
|
78
|
+
return invalid('Invalid completion default edit range.');
|
|
79
|
+
}
|
|
80
|
+
next.textEdit = 'start' in range ? { range, newText } : { insert: range.insert, replace: range.replace, newText };
|
|
81
|
+
}
|
|
82
|
+
return next;
|
|
83
|
+
}
|
package/dist/document.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LspSession } from './session.ts';
|
|
2
|
-
import type { CodeAction, CodeActionContext, CodeLens, Command, CompletionContext, CompletionItem, CompletionResult, ContentChange, DocumentDiagnosticReport, DocumentHighlight, DocumentItem, DocumentRequestOptions, DocumentSymbolResult, FoldingRange, FormattingOptions, Hover, InlayHint, Location, NavigationResult, Position, PrepareRenameResult, Range, SelectionRange, SemanticTokens, SemanticTokensDelta, SignatureHelp, SignatureHelpContext, TextEdit, WorkspaceEdit } from './protocol.ts';
|
|
2
|
+
import type { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, CodeAction, CodeActionContext, CodeLens, Command, CompletionContext, CompletionItem, CompletionResult, ContentChange, DocumentDiagnosticReport, DocumentHighlight, DocumentItem, DocumentRequestOptions, DocumentSymbolResult, FoldingRange, FormattingOptions, Hover, InlayHint, Location, NavigationResult, Position, PrepareRenameResult, Range, SelectionRange, SemanticTokens, SemanticTokensDelta, SignatureHelp, SignatureHelpContext, TextEdit, WorkspaceEdit } from './protocol.ts';
|
|
3
3
|
export declare class LspDocument {
|
|
4
4
|
readonly session: LspSession;
|
|
5
5
|
readonly uri: string;
|
|
@@ -39,6 +39,7 @@ export declare class LspDocument {
|
|
|
39
39
|
resolveCodeLens(lens: CodeLens, options?: DocumentRequestOptions): Promise<CodeLens>;
|
|
40
40
|
formatting(formatting: FormattingOptions, options?: DocumentRequestOptions): Promise<TextEdit[] | null>;
|
|
41
41
|
rangeFormatting(range: Range, formatting: FormattingOptions, options?: DocumentRequestOptions): Promise<TextEdit[] | null>;
|
|
42
|
+
onTypeFormatting(position: Position, ch: string, formatting: FormattingOptions, options?: DocumentRequestOptions): Promise<TextEdit[] | null>;
|
|
42
43
|
foldingRanges(options?: DocumentRequestOptions): Promise<FoldingRange[] | null>;
|
|
43
44
|
selectionRanges(positions: readonly Position[], options?: DocumentRequestOptions): Promise<SelectionRange[] | null>;
|
|
44
45
|
semanticTokens(options?: DocumentRequestOptions): Promise<SemanticTokens | null>;
|
|
@@ -46,6 +47,9 @@ export declare class LspDocument {
|
|
|
46
47
|
semanticTokensRange(range: Range, options?: DocumentRequestOptions): Promise<SemanticTokens | null>;
|
|
47
48
|
inlayHints(range: Range, options?: DocumentRequestOptions): Promise<InlayHint[] | null>;
|
|
48
49
|
resolveInlayHint(hint: InlayHint, options?: DocumentRequestOptions): Promise<InlayHint>;
|
|
50
|
+
prepareCallHierarchy(position: Position, options?: DocumentRequestOptions): Promise<CallHierarchyItem[] | null>;
|
|
51
|
+
incomingCalls(item: CallHierarchyItem, options?: DocumentRequestOptions): Promise<CallHierarchyIncomingCall[] | null>;
|
|
52
|
+
outgoingCalls(item: CallHierarchyItem, options?: DocumentRequestOptions): Promise<CallHierarchyOutgoingCall[] | null>;
|
|
49
53
|
diagnostics(previousResultId?: string, identifier?: string, options?: DocumentRequestOptions): Promise<DocumentDiagnosticReport>;
|
|
50
54
|
request<T = unknown>(method: string, params: object, options?: DocumentRequestOptions): Promise<T>;
|
|
51
55
|
close(): Promise<void>;
|
package/dist/document.js
CHANGED
|
@@ -149,6 +149,10 @@ export class LspDocument {
|
|
|
149
149
|
rangeFormatting(range, formatting, options) {
|
|
150
150
|
return this.feature('textDocument/rangeFormatting', { range, options: formatting }, options);
|
|
151
151
|
}
|
|
152
|
+
/* `ch` is the character that was typed; `position` is where the caret is after it. */
|
|
153
|
+
onTypeFormatting(position, ch, formatting, options) {
|
|
154
|
+
return this.feature('textDocument/onTypeFormatting', { position, ch, options: formatting }, options);
|
|
155
|
+
}
|
|
152
156
|
foldingRanges(options) {
|
|
153
157
|
return this.feature('textDocument/foldingRange', {}, options);
|
|
154
158
|
}
|
|
@@ -170,6 +174,16 @@ export class LspDocument {
|
|
|
170
174
|
resolveInlayHint(hint, options) {
|
|
171
175
|
return this.resolve('inlayHint/resolve', hint, options);
|
|
172
176
|
}
|
|
177
|
+
prepareCallHierarchy(position, options) {
|
|
178
|
+
return this.feature('textDocument/prepareCallHierarchy', { position }, options);
|
|
179
|
+
}
|
|
180
|
+
/* The callers of an item the server gave. Neighbouring expansions run beside each other, so a newer one does not cancel an older unless `cancelPrevious` says so. */
|
|
181
|
+
incomingCalls(item, options) {
|
|
182
|
+
return this.perform('callHierarchy/incomingCalls', { item }, { cancelPrevious: false, ...options });
|
|
183
|
+
}
|
|
184
|
+
outgoingCalls(item, options) {
|
|
185
|
+
return this.perform('callHierarchy/outgoingCalls', { item }, { cancelPrevious: false, ...options });
|
|
186
|
+
}
|
|
173
187
|
diagnostics(previousResultId, identifier, options) {
|
|
174
188
|
return this.feature('textDocument/diagnostic', { previousResultId, identifier }, options);
|
|
175
189
|
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import type { FileOperationFilter, FileRename } from './protocol.ts';
|
|
1
|
+
import type { FileCreate, FileDelete, FileOperationFilter, FileRename } from './protocol.ts';
|
|
2
2
|
export interface RenamedFile extends FileRename {
|
|
3
3
|
directory: boolean;
|
|
4
4
|
}
|
|
5
|
+
export interface CreatedFile extends FileCreate {
|
|
6
|
+
directory: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface DeletedFile extends FileDelete {
|
|
9
|
+
directory: boolean;
|
|
10
|
+
}
|
|
5
11
|
export declare function renamesTaken(filters: readonly FileOperationFilter[], files: readonly RenamedFile[]): FileRename[];
|
|
12
|
+
export declare function createsTaken(filters: readonly FileOperationFilter[], files: readonly CreatedFile[]): FileCreate[];
|
|
13
|
+
export declare function deletesTaken(filters: readonly FileOperationFilter[], files: readonly DeletedFile[]): FileDelete[];
|
package/dist/file-operations.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { globMatch } from './glob.js';
|
|
2
|
-
function filterTakes(filter,
|
|
2
|
+
function filterTakes(filter, uri, directory) {
|
|
3
3
|
const { matches, glob, options } = filter.pattern;
|
|
4
|
-
if (matches !== undefined && (matches === 'folder') !==
|
|
4
|
+
if (matches !== undefined && (matches === 'folder') !== directory) {
|
|
5
5
|
return false;
|
|
6
6
|
}
|
|
7
7
|
let url;
|
|
8
8
|
try {
|
|
9
|
-
url = new URL(
|
|
9
|
+
url = new URL(uri);
|
|
10
10
|
}
|
|
11
11
|
catch {
|
|
12
12
|
return false;
|
|
@@ -19,5 +19,13 @@ function filterTakes(filter, file) {
|
|
|
19
19
|
}
|
|
20
20
|
/* The renames a server asked to hear about, by the filters it registered. A rename is matched on the place it leaves. */
|
|
21
21
|
export function renamesTaken(filters, files) {
|
|
22
|
-
return files.filter((file) => filters.some((filter) => filterTakes(filter, file))).map(({ oldUri, newUri }) => ({ oldUri, newUri }));
|
|
22
|
+
return files.filter((file) => filters.some((filter) => filterTakes(filter, file.oldUri, file.directory))).map(({ oldUri, newUri }) => ({ oldUri, newUri }));
|
|
23
|
+
}
|
|
24
|
+
/* The files made that a server asked to hear about, by the filters it registered. */
|
|
25
|
+
export function createsTaken(filters, files) {
|
|
26
|
+
return files.filter((file) => filters.some((filter) => filterTakes(filter, file.uri, file.directory))).map(({ uri }) => ({ uri }));
|
|
27
|
+
}
|
|
28
|
+
/* The files deleted that a server asked to hear about, by the filters it registered. A folder is matched as one, not by what was in it. */
|
|
29
|
+
export function deletesTaken(filters, files) {
|
|
30
|
+
return files.filter((file) => filters.some((filter) => filterTakes(filter, file.uri, file.directory))).map(({ uri }) => ({ uri }));
|
|
23
31
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { ErrorCodes, JsonRpcConnection, LspError, StaleResultError, type RequestHandler } from './connection.ts';
|
|
2
|
+
export { applyCompletionDefaults } from './completion-defaults.ts';
|
|
2
3
|
export { LspDocument } from './document.ts';
|
|
3
4
|
export { applyContentChanges, applyTextEdits, endPosition, minimalChange, offsetAt, planWorkspaceEdit, positionAt, type DocumentSnapshot, type PlannedDocumentEdit } from './edits.ts';
|
|
4
|
-
export {
|
|
5
|
+
export { planWorkspaceOperations, type PlannedCreateStep, type PlannedDeleteStep, type PlannedRenameStep, type PlannedTextStep, type ResourceOperationKind, type WorkspaceEditPlan, type WorkspaceEditSource, type WorkspaceEditStep, type WorkspaceEditText } from './workspace-operations.ts';
|
|
6
|
+
export { createsTaken, deletesTaken, renamesTaken, type CreatedFile, type DeletedFile, type RenamedFile } from './file-operations.ts';
|
|
5
7
|
export { watchesFile, type FileChangeType } from './watched-files.ts';
|
|
6
8
|
export { LspSession, type LspSessionOptions, type SessionState } from './session.ts';
|
|
7
9
|
export type { DiagnosticsReport, LanguageDocument, LanguageRequestOptions, LanguageService } from './service.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { ErrorCodes, JsonRpcConnection, LspError, StaleResultError } from './connection.js';
|
|
2
|
+
export { applyCompletionDefaults } from './completion-defaults.js';
|
|
2
3
|
export { LspDocument } from './document.js';
|
|
3
4
|
export { applyContentChanges, applyTextEdits, endPosition, minimalChange, offsetAt, planWorkspaceEdit, positionAt } from './edits.js';
|
|
4
|
-
export {
|
|
5
|
+
export { planWorkspaceOperations } from './workspace-operations.js';
|
|
6
|
+
export { createsTaken, deletesTaken, renamesTaken } from './file-operations.js';
|
|
5
7
|
export { watchesFile } from './watched-files.js';
|
|
6
8
|
export { LspSession } from './session.js';
|
|
7
9
|
export { ContentLengthDecoder, connectWebSocket, createMemoryTransportPair, createStreamTransport, encodeMessage } from './transport.js';
|
package/dist/protocol.d.ts
CHANGED
|
@@ -185,6 +185,24 @@ export interface WorkspaceSymbol {
|
|
|
185
185
|
};
|
|
186
186
|
data?: unknown;
|
|
187
187
|
}
|
|
188
|
+
export interface CallHierarchyItem {
|
|
189
|
+
name: string;
|
|
190
|
+
kind: SymbolKind;
|
|
191
|
+
tags?: 1[];
|
|
192
|
+
detail?: string;
|
|
193
|
+
uri: string;
|
|
194
|
+
range: Range;
|
|
195
|
+
selectionRange: Range;
|
|
196
|
+
data?: unknown;
|
|
197
|
+
}
|
|
198
|
+
export interface CallHierarchyIncomingCall {
|
|
199
|
+
from: CallHierarchyItem;
|
|
200
|
+
fromRanges: Range[];
|
|
201
|
+
}
|
|
202
|
+
export interface CallHierarchyOutgoingCall {
|
|
203
|
+
to: CallHierarchyItem;
|
|
204
|
+
fromRanges: Range[];
|
|
205
|
+
}
|
|
188
206
|
export type DocumentSymbolResult = DocumentSymbol[] | SymbolInformation[] | null;
|
|
189
207
|
export type WorkspaceSymbolResult = SymbolInformation[] | WorkspaceSymbol[] | null;
|
|
190
208
|
export interface ParameterInformation {
|
|
@@ -262,6 +280,13 @@ export interface FileRename {
|
|
|
262
280
|
oldUri: string;
|
|
263
281
|
newUri: string;
|
|
264
282
|
}
|
|
283
|
+
export interface FileCreate {
|
|
284
|
+
uri: string;
|
|
285
|
+
}
|
|
286
|
+
export interface FileDelete {
|
|
287
|
+
uri: string;
|
|
288
|
+
}
|
|
289
|
+
export type FileOperation = 'willRename' | 'didRename' | 'willCreate' | 'didCreate' | 'willDelete' | 'didDelete';
|
|
265
290
|
export interface FileOperationFilter {
|
|
266
291
|
scheme?: string;
|
|
267
292
|
pattern: {
|
|
@@ -393,6 +418,8 @@ export interface ProviderOptions {
|
|
|
393
418
|
resolveProvider?: boolean;
|
|
394
419
|
prepareProvider?: boolean;
|
|
395
420
|
triggerCharacters?: string[];
|
|
421
|
+
firstTriggerCharacter?: string;
|
|
422
|
+
moreTriggerCharacter?: string[];
|
|
396
423
|
retriggerCharacters?: string[];
|
|
397
424
|
commands?: string[];
|
|
398
425
|
watchers?: FileSystemWatcher[];
|
|
@@ -440,6 +467,8 @@ export interface ServerCapabilities {
|
|
|
440
467
|
legend: SemanticTokensLegend;
|
|
441
468
|
};
|
|
442
469
|
inlayHintProvider?: boolean | ProviderOptions;
|
|
470
|
+
callHierarchyProvider?: boolean | ProviderOptions;
|
|
471
|
+
documentOnTypeFormattingProvider?: ProviderOptions;
|
|
443
472
|
diagnosticProvider?: ProviderOptions;
|
|
444
473
|
[capability: string]: unknown;
|
|
445
474
|
}
|
package/dist/service.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CodeAction, CodeActionContext, CodeLens, Command, CompletionContext, CompletionItem, CompletionResult, ContentChange, Diagnostic, Disposable, DocumentHighlight, DocumentSymbolResult, FoldingRange, FormattingOptions, Hover, InlayHint, Location, NavigationResult, Position, PrepareRenameResult, ProviderOptions, Range, SelectionRange, SemanticTokens, SemanticTokensDelta, SignatureHelp, SignatureHelpContext, TextEdit, WorkspaceEdit, WorkspaceSymbolResult } from './protocol.ts';
|
|
1
|
+
import type { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, CodeAction, CodeActionContext, CodeLens, Command, CompletionContext, CompletionItem, CompletionResult, ContentChange, Diagnostic, Disposable, DocumentHighlight, DocumentSymbolResult, FoldingRange, FormattingOptions, Hover, InlayHint, Location, NavigationResult, Position, PrepareRenameResult, ProviderOptions, Range, SelectionRange, SemanticTokens, SemanticTokensDelta, SignatureHelp, SignatureHelpContext, TextEdit, WorkspaceEdit, WorkspaceSymbolResult } from './protocol.ts';
|
|
2
|
+
import type { CreatedFile, DeletedFile } from './file-operations.ts';
|
|
2
3
|
export interface LanguageDocument {
|
|
3
4
|
uri: string;
|
|
4
5
|
languageId: string;
|
|
@@ -18,6 +19,7 @@ export interface LanguageService {
|
|
|
18
19
|
openDocument(document: LanguageDocument): Promise<void>;
|
|
19
20
|
changeDocument(uri: string, changes: readonly ContentChange[]): Promise<void>;
|
|
20
21
|
closeDocument(uri: string): Promise<void>;
|
|
22
|
+
versionOf?(uri: string): number | null;
|
|
21
23
|
supports(method: string, uri: string): boolean;
|
|
22
24
|
providerOptions(method: string, uri: string): ProviderOptions | undefined;
|
|
23
25
|
onProvidersChanged(listener: (uri: string) => void): Disposable;
|
|
@@ -40,6 +42,7 @@ export interface LanguageService {
|
|
|
40
42
|
executeCommand(uri: string, command: Command, options?: LanguageRequestOptions): Promise<unknown>;
|
|
41
43
|
formatting(uri: string, formatting: FormattingOptions, options?: LanguageRequestOptions): Promise<TextEdit[] | null>;
|
|
42
44
|
rangeFormatting(uri: string, range: Range, formatting: FormattingOptions, options?: LanguageRequestOptions): Promise<TextEdit[] | null>;
|
|
45
|
+
onTypeFormatting?(uri: string, position: Position, ch: string, formatting: FormattingOptions, options?: LanguageRequestOptions): Promise<TextEdit[] | null>;
|
|
43
46
|
semanticTokens(uri: string, options?: LanguageRequestOptions): Promise<SemanticTokens | null>;
|
|
44
47
|
semanticTokensDelta(uri: string, previousResultId: string, options?: LanguageRequestOptions): Promise<SemanticTokens | SemanticTokensDelta | null>;
|
|
45
48
|
semanticTokensRange(uri: string, range: Range, options?: LanguageRequestOptions): Promise<SemanticTokens | null>;
|
|
@@ -48,6 +51,13 @@ export interface LanguageService {
|
|
|
48
51
|
workspaceSymbols(uri: string, query: string, options?: LanguageRequestOptions): Promise<WorkspaceSymbolResult>;
|
|
49
52
|
foldingRanges(uri: string, options?: LanguageRequestOptions): Promise<FoldingRange[] | null>;
|
|
50
53
|
selectionRanges(uri: string, positions: readonly Position[], options?: LanguageRequestOptions): Promise<SelectionRange[] | null>;
|
|
54
|
+
prepareCallHierarchy?(uri: string, position: Position, options?: LanguageRequestOptions): Promise<CallHierarchyItem[] | null>;
|
|
55
|
+
incomingCalls?(uri: string, item: CallHierarchyItem, options?: LanguageRequestOptions): Promise<CallHierarchyIncomingCall[] | null>;
|
|
56
|
+
outgoingCalls?(uri: string, item: CallHierarchyItem, options?: LanguageRequestOptions): Promise<CallHierarchyOutgoingCall[] | null>;
|
|
57
|
+
willCreateFiles?(files: readonly CreatedFile[], options?: LanguageRequestOptions): Promise<WorkspaceEdit | null>;
|
|
58
|
+
didCreateFiles?(files: readonly CreatedFile[]): Promise<void>;
|
|
59
|
+
willDeleteFiles?(files: readonly DeletedFile[], options?: LanguageRequestOptions): Promise<WorkspaceEdit | null>;
|
|
60
|
+
didDeleteFiles?(files: readonly DeletedFile[]): Promise<void>;
|
|
51
61
|
codeLenses(uri: string, options?: LanguageRequestOptions): Promise<CodeLens[] | null>;
|
|
52
62
|
resolveCodeLens(uri: string, lens: CodeLens, options?: LanguageRequestOptions): Promise<CodeLens>;
|
|
53
63
|
}
|
package/dist/session.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { JsonRpcConnection, type RequestHandler } from './connection.ts';
|
|
2
2
|
import { LspDocument } from './document.ts';
|
|
3
|
-
import { type RenamedFile } from './file-operations.ts';
|
|
4
|
-
import type {
|
|
3
|
+
import { type CreatedFile, type DeletedFile, type RenamedFile } from './file-operations.ts';
|
|
4
|
+
import type { ResourceOperationKind } from './workspace-operations.ts';
|
|
5
|
+
import type { ApplyWorkspaceEditParams, ApplyWorkspaceEditResult, Command, ConfigurationItem, Disposable, DocumentItem, FileEvent, FileOperation, FileOperationFilter, FileSystemWatcher, InitializeResult, LspTransport, ProgressParams, ProviderOptions, PublishDiagnosticsParams, RequestOptions, ServerCapabilities, TextDocumentSyncOptions, WorkspaceEdit, WorkspaceFolder, WorkspaceSymbol, WorkspaceSymbolResult } from './protocol.ts';
|
|
5
6
|
export type SessionState = 'new' | 'initializing' | 'ready' | 'closing' | 'closed';
|
|
6
7
|
export interface LspSessionOptions {
|
|
7
8
|
rootUri?: string | null;
|
|
@@ -14,6 +15,9 @@ export interface LspSessionOptions {
|
|
|
14
15
|
};
|
|
15
16
|
timeoutMs?: number;
|
|
16
17
|
snippetSupport?: boolean;
|
|
18
|
+
insertTextModes?: readonly (1 | 2)[];
|
|
19
|
+
completionItemDefaults?: readonly string[];
|
|
20
|
+
resourceOperations?: readonly ResourceOperationKind[];
|
|
17
21
|
onConfiguration?: (item: ConfigurationItem) => unknown | Promise<unknown>;
|
|
18
22
|
onApplyEdit?: (params: ApplyWorkspaceEditParams) => ApplyWorkspaceEditResult | Promise<ApplyWorkspaceEditResult>;
|
|
19
23
|
onShowMessage?: (params: {
|
|
@@ -64,9 +68,13 @@ export declare class LspSession {
|
|
|
64
68
|
onDiagnostics(listener: (params: PublishDiagnosticsParams) => void): Disposable;
|
|
65
69
|
watchedFiles(): FileSystemWatcher[];
|
|
66
70
|
didChangeWatchedFiles(changes: readonly FileEvent[]): Promise<void>;
|
|
67
|
-
fileOperationFilters(operation:
|
|
71
|
+
fileOperationFilters(operation: FileOperation): FileOperationFilter[];
|
|
68
72
|
willRenameFiles(files: readonly RenamedFile[], options?: RequestOptions): Promise<WorkspaceEdit | null>;
|
|
69
73
|
didRenameFiles(files: readonly RenamedFile[]): Promise<void>;
|
|
74
|
+
willCreateFiles(files: readonly CreatedFile[], options?: RequestOptions): Promise<WorkspaceEdit | null>;
|
|
75
|
+
didCreateFiles(files: readonly CreatedFile[]): Promise<void>;
|
|
76
|
+
willDeleteFiles(files: readonly DeletedFile[], options?: RequestOptions): Promise<WorkspaceEdit | null>;
|
|
77
|
+
didDeleteFiles(files: readonly DeletedFile[]): Promise<void>;
|
|
70
78
|
onCapabilitiesChanged(listener: () => void): Disposable;
|
|
71
79
|
shutdown(): Promise<void>;
|
|
72
80
|
forgetDocument(document: LspDocument): void;
|
package/dist/session.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ErrorCodes, JsonRpcConnection, LspError } from './connection.js';
|
|
2
2
|
import { LspDocument } from './document.js';
|
|
3
|
-
import { renamesTaken } from './file-operations.js';
|
|
3
|
+
import { createsTaken, deletesTaken, renamesTaken } from './file-operations.js';
|
|
4
4
|
import { globMatch } from './glob.js';
|
|
5
5
|
/* The capability that advertises each method statically. */
|
|
6
6
|
const PROVIDERS = {
|
|
@@ -26,6 +26,7 @@ const PROVIDERS = {
|
|
|
26
26
|
'workspace/executeCommand': 'executeCommandProvider',
|
|
27
27
|
'textDocument/formatting': 'documentFormattingProvider',
|
|
28
28
|
'textDocument/rangeFormatting': 'documentRangeFormattingProvider',
|
|
29
|
+
'textDocument/onTypeFormatting': 'documentOnTypeFormattingProvider',
|
|
29
30
|
'textDocument/foldingRange': 'foldingRangeProvider',
|
|
30
31
|
'textDocument/selectionRange': 'selectionRangeProvider',
|
|
31
32
|
'textDocument/semanticTokens/full': 'semanticTokensProvider',
|
|
@@ -33,6 +34,9 @@ const PROVIDERS = {
|
|
|
33
34
|
'textDocument/semanticTokens/range': 'semanticTokensProvider',
|
|
34
35
|
'textDocument/inlayHint': 'inlayHintProvider',
|
|
35
36
|
'inlayHint/resolve': 'inlayHintProvider',
|
|
37
|
+
'textDocument/prepareCallHierarchy': 'callHierarchyProvider',
|
|
38
|
+
'callHierarchy/incomingCalls': 'callHierarchyProvider',
|
|
39
|
+
'callHierarchy/outgoingCalls': 'callHierarchyProvider',
|
|
36
40
|
'textDocument/diagnostic': 'diagnosticProvider'
|
|
37
41
|
};
|
|
38
42
|
/* A method whose dynamic registration is made under the name of another. */
|
|
@@ -41,6 +45,8 @@ const REGISTRATION_METHODS = {
|
|
|
41
45
|
'codeAction/resolve': 'textDocument/codeAction',
|
|
42
46
|
'codeLens/resolve': 'textDocument/codeLens',
|
|
43
47
|
'inlayHint/resolve': 'textDocument/inlayHint',
|
|
48
|
+
'callHierarchy/incomingCalls': 'textDocument/prepareCallHierarchy',
|
|
49
|
+
'callHierarchy/outgoingCalls': 'textDocument/prepareCallHierarchy',
|
|
44
50
|
'textDocument/prepareRename': 'textDocument/rename',
|
|
45
51
|
'workspaceSymbol/resolve': 'workspace/symbol',
|
|
46
52
|
'textDocument/semanticTokens/full': 'textDocument/semanticTokens',
|
|
@@ -287,7 +293,7 @@ export class LspSession {
|
|
|
287
293
|
didChangeWatchedFiles(changes) {
|
|
288
294
|
return this.notify('workspace/didChangeWatchedFiles', { changes });
|
|
289
295
|
}
|
|
290
|
-
/* The files a server asked to hear about when they are renamed, from its capabilities and its registrations. */
|
|
296
|
+
/* The files a server asked to hear about when they are renamed, created or deleted, from its capabilities and its registrations. */
|
|
291
297
|
fileOperationFilters(operation) {
|
|
292
298
|
const fileOperations = this.serverCapabilities.workspace?.fileOperations;
|
|
293
299
|
const method = `workspace/${operation}Files`;
|
|
@@ -310,6 +316,30 @@ export class LspSession {
|
|
|
310
316
|
await this.notify('workspace/didRenameFiles', { files: taken });
|
|
311
317
|
}
|
|
312
318
|
}
|
|
319
|
+
/* What the server would change before these files are made, or null when it takes none of them or has nothing to say. */
|
|
320
|
+
async willCreateFiles(files, options) {
|
|
321
|
+
const taken = createsTaken(this.fileOperationFilters('willCreate'), files);
|
|
322
|
+
return taken.length === 0 || this.phase !== 'ready' ? null : this.request('workspace/willCreateFiles', { files: taken }, options);
|
|
323
|
+
}
|
|
324
|
+
/* Tells the server which of these files were made, those its filters take. */
|
|
325
|
+
async didCreateFiles(files) {
|
|
326
|
+
const taken = createsTaken(this.fileOperationFilters('didCreate'), files);
|
|
327
|
+
if (taken.length > 0 && this.phase === 'ready') {
|
|
328
|
+
await this.notify('workspace/didCreateFiles', { files: taken });
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/* What the server would change before these files are deleted, or null when it takes none of them or has nothing to say. */
|
|
332
|
+
async willDeleteFiles(files, options) {
|
|
333
|
+
const taken = deletesTaken(this.fileOperationFilters('willDelete'), files);
|
|
334
|
+
return taken.length === 0 || this.phase !== 'ready' ? null : this.request('workspace/willDeleteFiles', { files: taken }, options);
|
|
335
|
+
}
|
|
336
|
+
/* Tells the server which of these files were deleted, those its filters take. */
|
|
337
|
+
async didDeleteFiles(files) {
|
|
338
|
+
const taken = deletesTaken(this.fileOperationFilters('didDelete'), files);
|
|
339
|
+
if (taken.length > 0 && this.phase === 'ready') {
|
|
340
|
+
await this.notify('workspace/didDeleteFiles', { files: taken });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
313
343
|
/* Registrations and the refresh requests of the server both land here, since each can change what a document may ask. */
|
|
314
344
|
onCapabilitiesChanged(listener) {
|
|
315
345
|
this.capabilityListeners.add(listener);
|
|
@@ -394,8 +424,16 @@ function clientCapabilities(options) {
|
|
|
394
424
|
general: { positionEncodings: ['utf-16'] },
|
|
395
425
|
workspace: {
|
|
396
426
|
applyEdit: !!options.onApplyEdit,
|
|
397
|
-
workspaceEdit: { documentChanges: true, resourceOperations: ['create', 'rename'], failureHandling: 'abort' },
|
|
398
|
-
fileOperations: {
|
|
427
|
+
workspaceEdit: { documentChanges: true, resourceOperations: [...(options.resourceOperations ?? ['create', 'rename'])], failureHandling: 'abort' },
|
|
428
|
+
fileOperations: {
|
|
429
|
+
dynamicRegistration: true,
|
|
430
|
+
willRename: true,
|
|
431
|
+
didRename: true,
|
|
432
|
+
willCreate: true,
|
|
433
|
+
didCreate: true,
|
|
434
|
+
willDelete: true,
|
|
435
|
+
didDelete: true
|
|
436
|
+
},
|
|
399
437
|
configuration: true,
|
|
400
438
|
workspaceFolders: true,
|
|
401
439
|
executeCommand: dynamic,
|
|
@@ -419,8 +457,11 @@ function clientCapabilities(options) {
|
|
|
419
457
|
completion: {
|
|
420
458
|
...dynamic,
|
|
421
459
|
contextSupport: true,
|
|
460
|
+
insertTextMode: 1,
|
|
461
|
+
...(options.completionItemDefaults?.length ? { completionList: { itemDefaults: [...options.completionItemDefaults] } } : {}),
|
|
422
462
|
completionItem: {
|
|
423
463
|
snippetSupport: options.snippetSupport ?? false,
|
|
464
|
+
...(options.insertTextModes?.length ? { insertTextModeSupport: { valueSet: [...options.insertTextModes] } } : {}),
|
|
424
465
|
commitCharactersSupport: true,
|
|
425
466
|
documentationFormat: ['markdown', 'plaintext'],
|
|
426
467
|
deprecatedSupport: true,
|
|
@@ -474,6 +515,7 @@ function clientCapabilities(options) {
|
|
|
474
515
|
codeLens: dynamic,
|
|
475
516
|
formatting: dynamic,
|
|
476
517
|
rangeFormatting: dynamic,
|
|
518
|
+
onTypeFormatting: dynamic,
|
|
477
519
|
foldingRange: { ...dynamic, lineFoldingOnly: false, foldingRange: { collapsedText: false } },
|
|
478
520
|
selectionRange: dynamic,
|
|
479
521
|
semanticTokens: {
|
|
@@ -521,6 +563,7 @@ function clientCapabilities(options) {
|
|
|
521
563
|
multilineTokenSupport: false
|
|
522
564
|
},
|
|
523
565
|
inlayHint: { ...dynamic, resolveSupport: { properties: ['tooltip', 'textEdits', 'label.tooltip', 'label.location', 'label.command'] } },
|
|
566
|
+
callHierarchy: { dynamicRegistration: false },
|
|
524
567
|
diagnostic: { ...dynamic, relatedDocumentSupport: true }
|
|
525
568
|
}
|
|
526
569
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { TextEdit, WorkspaceEdit } from './protocol.ts';
|
|
2
|
+
export type ResourceOperationKind = 'create' | 'rename' | 'delete';
|
|
3
|
+
export interface WorkspaceEditText {
|
|
4
|
+
readonly text: string;
|
|
5
|
+
readonly version: number | null;
|
|
6
|
+
readonly open: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface WorkspaceEditSource {
|
|
9
|
+
read(uri: string): Promise<WorkspaceEditText | null>;
|
|
10
|
+
exists?(uri: string): Promise<boolean>;
|
|
11
|
+
isFolder?(uri: string): Promise<boolean>;
|
|
12
|
+
readonly operations: readonly ResourceOperationKind[];
|
|
13
|
+
}
|
|
14
|
+
export interface PlannedTextStep {
|
|
15
|
+
readonly kind: 'edits';
|
|
16
|
+
readonly uri: string;
|
|
17
|
+
readonly readUri: string;
|
|
18
|
+
readonly edits: readonly TextEdit[];
|
|
19
|
+
readonly before: string;
|
|
20
|
+
readonly after: string;
|
|
21
|
+
readonly version: number | null;
|
|
22
|
+
readonly open: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface PlannedCreateStep {
|
|
25
|
+
readonly kind: 'create';
|
|
26
|
+
readonly uri: string;
|
|
27
|
+
readonly text: string;
|
|
28
|
+
readonly overwrite: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface PlannedRenameStep {
|
|
31
|
+
readonly kind: 'rename';
|
|
32
|
+
readonly oldUri: string;
|
|
33
|
+
readonly newUri: string;
|
|
34
|
+
readonly overwrite: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface PlannedDeleteStep {
|
|
37
|
+
readonly kind: 'delete';
|
|
38
|
+
readonly uri: string;
|
|
39
|
+
readonly recursive: boolean;
|
|
40
|
+
}
|
|
41
|
+
export type WorkspaceEditStep = PlannedTextStep | PlannedCreateStep | PlannedRenameStep | PlannedDeleteStep;
|
|
42
|
+
export interface WorkspaceEditPlan {
|
|
43
|
+
readonly steps: readonly WorkspaceEditStep[];
|
|
44
|
+
}
|
|
45
|
+
export declare function planWorkspaceOperations(edit: WorkspaceEdit, source: WorkspaceEditSource): Promise<WorkspaceEditPlan>;
|