/
registerFeatures.ts
215 lines (212 loc) · 7.17 KB
/
registerFeatures.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
import * as embedded from '@volar/language-service';
import { DiagnosticModel, LanguageServerPlugin, LanguageServerInitializationOptions } from './types';
import * as vscode from 'vscode-languageserver';
import { ClientCapabilities } from 'vscode-languageserver';
// https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide#standard-token-types-and-modifiers
export const semanticTokensLegend: vscode.SemanticTokensLegend = {
tokenTypes: [
'namespace',
'class',
'enum',
'interface',
'struct',
'typeParameter',
'type',
'parameter',
'variable',
'property',
'enumMember',
'decorator',
'event',
'function',
'method',
'macro',
'label',
'comment',
'string',
'keyword',
'number',
'regexp',
'operator',
],
tokenModifiers: [
'declaration',
'definition',
'readonly',
'static',
'deprecated',
'abstract',
'async',
'modification',
'documentation',
'defaultLibrary',
],
};
export function setupSyntacticCapabilities(
params: ClientCapabilities,
server: vscode.ServerCapabilities,
initOptions: LanguageServerInitializationOptions,
) {
if (!initOptions.respectClientCapabilities || params.textDocument?.selectionRange) {
server.selectionRangeProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.foldingRange) {
server.foldingRangeProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.linkedEditingRange) {
server.linkedEditingRangeProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.colorProvider) {
server.colorProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.documentSymbol) {
server.documentSymbolProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.formatting) {
server.documentFormattingProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.rangeFormatting) {
server.documentRangeFormattingProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.onTypeFormatting) {
// https://github.com/microsoft/vscode/blob/ce119308e8fd4cd3f992d42b297588e7abe33a0c/extensions/typescript-language-features/src/languageFeatures/formatting.ts#L99
server.documentOnTypeFormattingProvider = {
firstTriggerCharacter: ';',
moreTriggerCharacter: ['}', '\n'],
};
}
}
export function setupSemanticCapabilities(
params: ClientCapabilities,
server: vscode.ServerCapabilities,
initOptions: LanguageServerInitializationOptions,
plugins: ReturnType<LanguageServerPlugin>[],
) {
if (!initOptions.respectClientCapabilities || params.textDocument?.references) {
server.referencesProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.implementation) {
server.implementationProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.definition) {
server.definitionProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.typeDefinition) {
server.typeDefinitionProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.callHierarchy) {
server.callHierarchyProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.hover) {
server.hoverProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.rename) {
server.renameProvider = {
prepareProvider: true,
};
}
if (!initOptions.respectClientCapabilities || params.workspace?.fileOperations) {
server.workspace = {
fileOperations: {
willRename: {
filters: [
...plugins.map(plugin => plugin.extraFileExtensions.map(ext => ({ pattern: { glob: `**/*.${ext.extension}` } }))).flat(),
{ pattern: { glob: '**/*.js' } },
{ pattern: { glob: '**/*.cjs' } },
{ pattern: { glob: '**/*.mjs' } },
{ pattern: { glob: '**/*.ts' } },
{ pattern: { glob: '**/*.cts' } },
{ pattern: { glob: '**/*.mts' } },
{ pattern: { glob: '**/*.jsx' } },
{ pattern: { glob: '**/*.tsx' } },
{ pattern: { glob: '**/*.json' } },
]
}
}
};
}
if (!initOptions.respectClientCapabilities || params.textDocument?.signatureHelp) {
server.signatureHelpProvider = {
triggerCharacters: ['(', ',', '<'],
retriggerCharacters: [')'],
};
}
if (!initOptions.respectClientCapabilities || params.textDocument?.completion) {
server.completionProvider = {
// triggerCharacters: '!@#$%^&*()_+-=`~{}|[]\:";\'<>?,./ '.split(''), // all symbols on keyboard
// hardcode to fix https://github.com/sublimelsp/LSP-volar/issues/114
triggerCharacters: [...new Set([
'/', '-', ':', // css
...'>+^*()#.[]$@-{}'.split(''), // emmet
'.', ':', '<', '"', '=', '/', // html, vue
'@', // vue-event
'"', ':', // json
'.', '"', '\'', '`', '/', '<', '@', '#', ' ', // typescript
'*', // typescript-jsdoc
'@', // typescript-comment
])],
resolveProvider: true,
};
if (initOptions.ignoreTriggerCharacters) {
server.completionProvider.triggerCharacters = server.completionProvider.triggerCharacters
?.filter(c => !initOptions.ignoreTriggerCharacters!.includes(c));
}
}
if (!initOptions.respectClientCapabilities || params.textDocument?.documentHighlight) {
server.documentHighlightProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.documentLink) {
server.documentLinkProvider = {
resolveProvider: false, // TODO
};
}
if (!initOptions.respectClientCapabilities || params.workspace?.symbol) {
server.workspaceSymbolProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.codeLens) {
server.codeLensProvider = {
resolveProvider: true,
};
server.executeCommandProvider = { commands: [...server.executeCommandProvider?.commands ?? []] };
// @ts-expect-error
if (!initOptions.__noPluginCommands) {
server.executeCommandProvider.commands.push(embedded.executePluginCommand);
}
}
if (!initOptions.respectClientCapabilities || params.textDocument?.semanticTokens) {
server.semanticTokensProvider = {
range: true,
full: false,
legend: semanticTokensLegend,
};
}
if (!initOptions.respectClientCapabilities || params.textDocument?.codeAction) {
server.codeActionProvider = {
codeActionKinds: [
vscode.CodeActionKind.Empty,
vscode.CodeActionKind.QuickFix,
vscode.CodeActionKind.Refactor,
vscode.CodeActionKind.RefactorExtract,
vscode.CodeActionKind.RefactorInline,
vscode.CodeActionKind.RefactorRewrite,
vscode.CodeActionKind.Source,
vscode.CodeActionKind.SourceFixAll,
vscode.CodeActionKind.SourceOrganizeImports,
],
resolveProvider: true,
};
}
if (!initOptions.respectClientCapabilities || params.textDocument?.inlayHint) {
server.inlayHintProvider = true;
}
if (!initOptions.respectClientCapabilities || params.textDocument?.diagnostic && (initOptions.diagnosticModel ?? DiagnosticModel.Push) === DiagnosticModel.Pull) {
server.diagnosticProvider = {
documentSelector: [
...plugins.map(plugin => plugin.extraFileExtensions.map(ext => ({ pattern: `**/*.${ext.extension}` }))).flat(),
{ pattern: '**/*.{ts,js,tsx,jsx}' },
],
interFileDependencies: true,
workspaceDiagnostics: false,
};
}
}