1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "protocol.h" |
6 | #include "newprotocol.h" |
7 | #include "common/util/processutil.h" |
8 | |
9 | #include <QVariantMap> |
10 | #include <QJsonDocument> |
11 | #include <QJsonObject> |
12 | #include <QJsonArray> |
13 | #include <QCoreApplication> |
14 | #include <QQueue> |
15 | #include <QUrl> |
16 | #include <QDir> |
17 | #include <QDebug> |
18 | #include <QFile> |
19 | #include <QFileInfo> |
20 | |
21 | namespace lsp { |
22 | |
23 | const QString C_CPP{"C/C++" }; |
24 | const QString JAVA{"Java" }; |
25 | const QString PYTHON{"Python" }; |
26 | const QString JS{"JS" }; |
27 | const QString K_ID {"id" }; |
28 | const QString K_JSON_RPC {"jsonrpc" }; |
29 | const QString K_METHOD {"method" }; |
30 | const QString K_RESULT {"result" }; |
31 | const QString K_PARAMS {"params" }; |
32 | const QString K_CAPABILITIES {"capabilities" }; |
33 | const QString K_TEXTDOCUMENT {"textDocument" }; |
34 | const QString K_DOCUMENTSYMBOL {"documentSymbol" }; |
35 | const QString K_HIERARCHICALDOCUMENTSYMBOLSUPPORT {"hierarchicalDocumentSymbolSupport" }; |
36 | const QString K_PUBLISHDIAGNOSTICS {"publishDiagnostics" }; |
37 | const QString K_RELATEDINFOMATION {"relatedInformation" }; |
38 | const QString K_INITIALIZATIONOPTIONS {"initializationOptions" }; |
39 | const QString K_PROCESSID {"processId" }; |
40 | const QString K_ROOTPATH {"rootPath" }; |
41 | const QString K_ROOTURI {"rootUri" }; |
42 | const QString K_URI {"uri" }; // value QString from file url |
43 | const QString K_VERSION {"version" }; // value int |
44 | const QString K_LANGUAGEID {"languageId" }; |
45 | const QString K_TEXT {"text" }; |
46 | const QString K_CONTAINERNAME {"containerName" }; |
47 | const QString K_KIND {"kind" }; |
48 | const QString K_LOCATION {"location" }; |
49 | const QString K_POSITION {"position" }; |
50 | const QString K_DATA{"data" }; |
51 | const QString K_NewName{"newName" }; |
52 | const QString K_NewText{"newText" }; |
53 | |
54 | const QString H_CONTENT_LENGTH {"Content-Length" }; |
55 | const QString V_2_0 {"2.0" }; |
56 | const QString V_INITIALIZE {"initialize" }; //has request result |
57 | const QString V_SHUTDOWN {"shutdown" }; //has request result |
58 | const QString V_EXIT{"exit" }; //has request result |
59 | const QString V_TEXTDOCUMENT_DIDOPEN {"textDocument/didOpen" }; //no request result |
60 | const QString V_TEXTDOCUMENT_PUBLISHDIAGNOSTICS {"textDocument/publishDiagnostics" }; //server call |
61 | const QString V_TEXTDOCUMENT_DIDCHANGE {"textDocument/didChange" }; //no request result, json error |
62 | const QString V_TEXTDOCUMENT_DOCUMENTSYMBOL {"textDocument/documentSymbol" }; // has request result |
63 | const QString V_TEXTDOCUMENT_HOVER {"textDocument/hover" }; // has request result |
64 | const QString V_TEXTDOCUMENT_RENAME {"textDocument/rename" }; // has request result |
65 | const QString V_TEXTDOCUMENT_DEFINITION {"textDocument/definition" }; |
66 | const QString V_TEXTDOCUMENT_DIDCLOSE {"textDocument/didClose" }; |
67 | const QString V_TEXTDOCUMENT_COMPLETION {"textDocument/completion" }; |
68 | const QString V_TEXTDOCUMENT_SIGNATUREHELP {"textDocument/signatureHelp" }; |
69 | const QString V_TEXTDOCUMENT_REFERENCES {"textDocument/references" }; |
70 | const QString V_TEXTDOCUMENT_DOCUMENTHIGHLIGHT {"textDocument/documentHighlight" }; |
71 | const QString V_TEXTDOCUMENT_SEMANTICTOKENS {"textDocument/semanticTokens" }; |
72 | const QString V_TEXTDOCUMENT_SEMANTICTOKENS_FULL{"textDocument/semanticTokens/full" }; |
73 | const QString K_WORKSPACEFOLDERS {"workspaceFolders" }; |
74 | |
75 | const QString K_CONTENTCHANGES {"contentChanges" }; |
76 | const QString K_DIAGNOSTICS {"diagnostics" }; |
77 | const QString K_RANGE {"range" }; |
78 | const QString K_MESSAGE {"message" }; |
79 | const QString K_SEVERITY {"severity" }; |
80 | const QString K_END {"end" }; |
81 | const QString K_START {"start" }; |
82 | const QString K_CHARACTER {"character" }; |
83 | const QString K_LINE {"line" }; |
84 | const QString K_CONTEXT {"context" }; |
85 | const QString K_INCLUDEDECLARATION {"includeDeclaration" }; |
86 | |
87 | const QString K_ERROR {"error" }; |
88 | const QString K_CODE {"code" }; |
89 | |
90 | QList<int> fromTokenModifiers(int modifiers) |
91 | { |
92 | QList<int> ret; |
93 | int temp = modifiers; |
94 | ret.push_front((int)(temp %10)); |
95 | while (temp / 10 >= 1) { |
96 | temp = temp / 10; |
97 | ret.push_front((int)(temp %10)); |
98 | } |
99 | |
100 | return ret; |
101 | } |
102 | |
103 | QJsonArray tokenTypes() |
104 | { |
105 | return { |
106 | "namespace" , |
107 | "type" , |
108 | "class" , |
109 | "enum" , |
110 | "interface" , |
111 | "struct" , |
112 | "typeParameter" , |
113 | "parameter" , |
114 | "variable" , |
115 | "property" , |
116 | "enumMember" , |
117 | "event" , |
118 | "function" , |
119 | "method" , |
120 | "macro" , |
121 | "keyword" , |
122 | "modifier" , |
123 | "comment" , |
124 | "string" , |
125 | "number" , |
126 | "regexp" , |
127 | "operator" |
128 | }; |
129 | } |
130 | |
131 | QJsonArray tokenModifiers() |
132 | { |
133 | return { |
134 | "declaration" , |
135 | "definition" , |
136 | "readonly" , |
137 | "static" , |
138 | "deprecated" , |
139 | "abstract" , |
140 | "async" , |
141 | "modification" , |
142 | "documentation" , |
143 | "defaultLibrary" |
144 | }; |
145 | } |
146 | |
147 | QJsonObject workspace() |
148 | { |
149 | QJsonObject didChangeConfiguration { |
150 | { "dynamicRegistration" , true } |
151 | }; |
152 | QJsonObject codeLens { |
153 | { "refreshSupport" , true } |
154 | }; |
155 | QJsonObject didChangeWatchedFiles { |
156 | { "dynamicRegistration" , true} |
157 | }; |
158 | QJsonObject executeCommand{ |
159 | { "dynamicRegistration" , true} |
160 | }; |
161 | QJsonObject fileOperations { |
162 | { "didCreate" , true}, |
163 | { "didDelete" , true}, |
164 | { "didRename" , true}, |
165 | { "dynamicRegistration" , true}, |
166 | { "willCreate" , true}, |
167 | { "willDelete" , true}, |
168 | { "willRename" , true} |
169 | }; |
170 | QJsonObject semanticTokens{ |
171 | { "refreshSupport" , true } |
172 | }; |
173 | |
174 | QJsonArray symbolKind_valueSet { 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 }; |
175 | QJsonObject symbolKind{ { "valueSet" , symbolKind_valueSet } }; |
176 | QJsonArray tagSupport_valueSet{1}; |
177 | QJsonObject tagSupport{ { "valueSet" , tagSupport_valueSet } }; |
178 | QJsonObject symbol{ |
179 | { "dynamicRegistration" , true}, |
180 | { "symbolKind" , symbolKind }, |
181 | { "tagSupport" , tagSupport } |
182 | }; |
183 | |
184 | QJsonArray resourceOperations{ |
185 | { "create" , "rename" , "delete" } |
186 | }; |
187 | |
188 | QJsonObject changeAnnotationSupport{ |
189 | { "groupsOnLabel" , true } |
190 | }; |
191 | QJsonObject workspaceEdit{ |
192 | { "changeAnnotationSupport" ,changeAnnotationSupport }, |
193 | { "documentChanges" , true }, |
194 | { "failureHandling" , "textOnlyTransactional" }, |
195 | { "normalizesLineEndings" , true }, |
196 | { "resourceOperations" , resourceOperations} |
197 | }; |
198 | |
199 | QJsonObject workspace { |
200 | { "applyEdit" , true }, |
201 | { "codeLens" , codeLens }, |
202 | { "configuration" , true }, |
203 | { "didChangeConfiguration" , didChangeConfiguration }, |
204 | { "didChangeWatchedFiles" , didChangeWatchedFiles }, |
205 | { "executeCommand" , executeCommand }, |
206 | { "fileOperations" , fileOperations }, |
207 | { "semanticTokens" , semanticTokens }, |
208 | { "symbol" ,symbol }, |
209 | { "workspaceEdit" , workspaceEdit }, |
210 | { "workspaceFolders" , true } |
211 | }; |
212 | |
213 | return workspace; |
214 | } |
215 | |
216 | QJsonObject initialize(const QString &workspaceFolder, const QString &language, const QString &compile) |
217 | { |
218 | QJsonObject params; |
219 | if (language == C_CPP) { |
220 | QJsonObject capabilitiesSemanticTokens{{ |
221 | {"dynamicRegistration" , true}, |
222 | {"formats" , QJsonArray{"relative" }}, |
223 | {"multilineTokenSupport" , false}, |
224 | {"overlappingTokenSupport" , false}, |
225 | {"requests" , QJsonArray{"full" ,QJsonObject{{"delta" , true}},QJsonObject{{"range" , true}}}}, |
226 | {"tokenModifiers" , tokenModifiers()}, |
227 | {"tokenTypes" , tokenTypes()}}}; |
228 | |
229 | QJsonObject capabilities { |
230 | { |
231 | K_TEXTDOCUMENT, QJsonObject { |
232 | {"documentLink" , QJsonObject{{"dynamicRegistration" , true}}}, |
233 | {"documentHighlight" , QJsonObject{{"dynamicRegistration" , true}}}, |
234 | {K_DOCUMENTSYMBOL, QJsonObject{{K_HIERARCHICALDOCUMENTSYMBOLSUPPORT, true}},}, |
235 | {K_PUBLISHDIAGNOSTICS, QJsonObject{{K_RELATEDINFOMATION, true}}}, |
236 | {"definition" , QJsonObject{{{"dynamicRegistration" , true},{"linkSupport" , true}}}}, |
237 | {"colorProvider" , QJsonObject{{"dynamicRegistration" , true}}}, |
238 | {"declaration" , QJsonObject{{"dynamicRegistration" , true},{"linkSupport" , true}}}, |
239 | {"semanticHighlightingCapabilities" , QJsonObject{{"semanticHighlighting" , true}}}, |
240 | {"semanticTokens" , capabilitiesSemanticTokens} |
241 | } |
242 | },{ |
243 | "workspace" , workspace() |
244 | },{ |
245 | "foldingRangeProvider" , true, |
246 | } |
247 | }; |
248 | |
249 | QJsonObject highlight { |
250 | {"largeFileSize" , 2097152}, |
251 | {"lsRanges" , false}, |
252 | {"blacklist" , QJsonArray()}, |
253 | {"whitelist" , QJsonArray()} |
254 | }; |
255 | |
256 | QJsonObject client{ |
257 | {"diagnosticsRelatedInformation" , true}, |
258 | {"hierarchicalDocumentSymbolSupport" , true}, |
259 | {"linkSupport" ,true}, |
260 | {"snippetSupport" ,true}, |
261 | }; |
262 | |
263 | QJsonObject workspace { |
264 | { "name" , QFileInfo(workspaceFolder).fileName() }, |
265 | { K_URI, QUrl::fromLocalFile(workspaceFolder).toString() } |
266 | }; |
267 | |
268 | QJsonArray workspaceFolders{workspace}; |
269 | |
270 | QJsonObject initializationOptions { |
271 | {"compilationDatabasePath" , compile} |
272 | }; |
273 | |
274 | QJsonObject params { |
275 | { K_PROCESSID, QCoreApplication::applicationPid() }, |
276 | { K_ROOTPATH, workspace }, |
277 | { K_ROOTURI, workspace }, |
278 | { K_CAPABILITIES, capabilities }, |
279 | { "highlight" , highlight }, |
280 | { "client" , client }, |
281 | { "initializationOptions" , initializationOptions}, |
282 | { "workspaceFolders" , workspaceFolders }, |
283 | }; |
284 | |
285 | return params; |
286 | |
287 | } else if (language == JAVA || language == PYTHON || language == JS) { |
288 | |
289 | using namespace newlsp; |
290 | |
291 | std::string workspaceFolderUriStr = QUrl::fromLocalFile(workspaceFolder).toString().toStdString(); |
292 | std::string workspaceNameStr = QFileInfo(workspaceFolder).fileName().toStdString(); |
293 | |
294 | InitializeParams params; |
295 | |
296 | /* processId */ |
297 | params.processId = QCoreApplication::applicationPid(); |
298 | |
299 | /* rootUri */ |
300 | params.rootUri = workspaceFolderUriStr; |
301 | |
302 | /* rootPath */ |
303 | params.rootPath = workspaceFolder.toStdString(); |
304 | |
305 | /* capabilities |
306 | * std::optional<Workspace> workspace{}; |
307 | * std::optional<TextDocumentClientCapabilities> textDocument{}; |
308 | * std::optional<NotebookDocumentClientCapabilities> notebookDocument{}; |
309 | * std::optional<Window> window{}; |
310 | * std::optional<General> general{}; |
311 | */ |
312 | { |
313 | /* workspace */ |
314 | { |
315 | params.capabilities.workspace = newlsp::Workspace{}; |
316 | params.capabilities.workspace->applyEdit = true; |
317 | /* WorkspaceEditClientCapabilities */ |
318 | params.capabilities.workspace->workspaceEdit = newlsp::WorkspaceEditClientCapabilities{}; |
319 | params.capabilities.workspace->workspaceEdit->documentChanges = true; |
320 | params.capabilities.workspace->workspaceEdit->resourceOperations = newlsp::Enum::ResourceOperationKind::toStdVector(); |
321 | params.capabilities.workspace->workspaceEdit->failureHandling = newlsp::Enum::FailureHandlingKind::get()->TextOnlyTransactional; |
322 | params.capabilities.workspace->workspaceEdit->normalizesLineEndings = true; |
323 | params.capabilities.workspace->workspaceEdit->changeAnnotationSupport = ChangeAnotationSupport{}; |
324 | params.capabilities.workspace->workspaceEdit->changeAnnotationSupport->groupsOnLabel = true; |
325 | |
326 | /* DidChangeConfigurationClientCapabilities */ |
327 | params.capabilities.workspace->didChangeConfiguration = DidChangeConfigurationClientCapabilities{}; |
328 | params.capabilities.workspace->didChangeConfiguration->dynamicRegistration = true; |
329 | |
330 | /* DidChangeWatchedFilesClientCapabilities */ |
331 | params.capabilities.workspace->didChangeWatchedFiles = DidChangeWatchedFilesClientCapabilities{}; |
332 | params.capabilities.workspace->didChangeWatchedFiles->dynamicRegistration = true; |
333 | // no setting from vscode |
334 | // params.capabilities.workspace->didChangeWatchedFiles->relativePatternSupport = true; |
335 | |
336 | /* WorkspaceSymbolClientCapabilities*/ |
337 | params.capabilities.workspace->symbol = WorkspaceSymbolClientCapabilities{}; |
338 | params.capabilities.workspace->symbol->dynamicRegistration = true; |
339 | params.capabilities.workspace->symbol->symbolKind = SymbolKind{}; |
340 | params.capabilities.workspace->symbol->symbolKind->valueSet = newlsp::Enum::SymbolKind::toStdVector(); |
341 | params.capabilities.workspace->symbol->tagSupport = WorkspaceSymbolClientCapabilities::TagSupport{}; |
342 | params.capabilities.workspace->symbol->tagSupport->valueSet = newlsp::Enum::SymbolTag::toStdVector(); |
343 | // no setting from vscode |
344 | // params.capabilities.workspace->symbol->resolveSupport = {}; |
345 | |
346 | /* ExecuteCommandClientCapabilities */ |
347 | params.capabilities.workspace->executeCommand = ExecuteCommandClientCapabilities{}; |
348 | params.capabilities.workspace->executeCommand->dynamicRegistration = true; |
349 | |
350 | /* workspaceFolders */ |
351 | params.capabilities.workspace->workspaceFolders = true; |
352 | |
353 | /* configuration */ |
354 | params.capabilities.workspace->configuration = true; |
355 | |
356 | /* SemanticTokensWorkspaceClientCapabilities */ |
357 | params.capabilities.workspace->semanticTokens = SemanticTokensWorkspaceClientCapabilities{}; |
358 | params.capabilities.workspace->semanticTokens->refreshSupport = true; |
359 | |
360 | /* CodeLensWorkspaceClientCapabilities */ |
361 | params.capabilities.workspace->codeLens = CodeLensWorkspaceClientCapabilities{}; |
362 | params.capabilities.workspace->codeLens->refreshSupport = true; |
363 | |
364 | /* FileOperations */ |
365 | params.capabilities.workspace->fileOperations = FileOperations{}; |
366 | params.capabilities.workspace->fileOperations->dynamicRegistration = true; |
367 | params.capabilities.workspace->fileOperations->didCreate = true; |
368 | params.capabilities.workspace->fileOperations->willCreate = true; |
369 | params.capabilities.workspace->fileOperations->didRename = true; |
370 | params.capabilities.workspace->fileOperations->willRename = true; |
371 | params.capabilities.workspace->fileOperations->didDelete = true; |
372 | params.capabilities.workspace->fileOperations->willDelete = true; |
373 | |
374 | /* InlineValueWorkspaceClientCapabilities */ |
375 | //no setting from vscode |
376 | // params.capabilities.workspace->inlineValue = InlineValueWorkspaceClientCapabilities{}; |
377 | // params.capabilities.workspace->inlineValue->refreshSupport = true; |
378 | |
379 | /* InlayHintWorkspaceClientCapabilities */ |
380 | // no setting from vscode |
381 | // params.capabilities.workspace->inlayHint = InlayHintWorkspaceClientCapabilities{}; |
382 | // params.capabilities.workspace->inlayHint->refreshSupport = true; |
383 | |
384 | /* DiagnosticWorkspaceClientCapabilities */ |
385 | // no setting from vscode |
386 | // params.capabilities.workspace->diagnostics = DiagnosticWorkspaceClientCapabilities{}; |
387 | // params.capabilities.workspace->diagnostics->refreshSupport = true; |
388 | } |
389 | /* textDocument */ |
390 | { |
391 | params.capabilities.textDocument = TextDocumentClientCapabilities{}; |
392 | |
393 | /* TextDocumentSyncClientCapabilities */ |
394 | params.capabilities.textDocument->synchronization = TextDocumentSyncClientCapabilities{}; |
395 | params.capabilities.textDocument->synchronization->dynamicRegistration = true; |
396 | params.capabilities.textDocument->synchronization->willSave = true; |
397 | params.capabilities.textDocument->synchronization->willSaveWaitUntil = true; |
398 | params.capabilities.textDocument->synchronization->didSave = true; |
399 | |
400 | /* CompletionClientCapabilities */ |
401 | params.capabilities.textDocument->completion = CompletionClientCapabilities{}; |
402 | params.capabilities.textDocument->completion->dynamicRegistration = true; |
403 | params.capabilities.textDocument->completion->contextSupport = true; |
404 | |
405 | params.capabilities.textDocument->completion->completionItem = CompletionClientCapabilities::CompletionItem{}; |
406 | params.capabilities.textDocument->completion->completionItem->snippetSupport = true; |
407 | params.capabilities.textDocument->completion->completionItem->commitCharactersSupport = true; |
408 | params.capabilities.textDocument->completion->completionItem->documentationFormat = newlsp::Enum::MarkupKind::toStdVector(); |
409 | params.capabilities.textDocument->completion->completionItem->deprecatedSupport = true; |
410 | params.capabilities.textDocument->completion->completionItem->preselectSupport = true; |
411 | params.capabilities.textDocument->completion->completionItem->tagSupport |
412 | = CompletionClientCapabilities::CompletionItem::TagSupport{}; |
413 | params.capabilities.textDocument->completion->completionItem->tagSupport->valueSet |
414 | = newlsp::Enum::CompletionItemTag::toStdVector(); |
415 | params.capabilities.textDocument->completion->completionItem->insertReplaceSupport = true; |
416 | params.capabilities.textDocument->completion->completionItem->resolveSupport = ResolveSupport{}; |
417 | params.capabilities.textDocument->completion->completionItem->resolveSupport->properties = { |
418 | "documentation" , |
419 | "detail" , |
420 | "additionalTextEdits" |
421 | }; // from vs code |
422 | params.capabilities.textDocument->completion->completionItem->insertTextModeSupport |
423 | = CompletionClientCapabilities::CompletionItem::InsertTextModeSupport{}; |
424 | params.capabilities.textDocument->completion->completionItem->insertTextModeSupport->valueSet |
425 | = newlsp::Enum::InsertTextMode::toStdVector(); |
426 | params.capabilities.textDocument->completion->completionItem->labelDetailsSupport = true; |
427 | |
428 | /* insertTextMode: 2 */ |
429 | params.capabilities.textDocument->completion->insertTextMode |
430 | = newlsp::Enum::InsertTextMode::get()->adjustIndentation; // from vscode |
431 | |
432 | /* completionItemKind */ |
433 | params.capabilities.textDocument->completion->completionItemKind |
434 | = CompletionClientCapabilities::CompletionItemKind{}; |
435 | params.capabilities.textDocument->completion->completionItemKind->valueSet |
436 | = newlsp::Enum::CompletionItemKind::toStdVector(); |
437 | |
438 | /* itemDefaults */ // no setting from vscode |
439 | // params.capabilities.textDocument->completion->itemDefaults = {std::nullopt}; |
440 | |
441 | /* contextSupport */ |
442 | params.capabilities.textDocument->completion->contextSupport = true; |
443 | |
444 | /* HoverClientCapabilities */ |
445 | params.capabilities.textDocument->hover = HoverClientCapabilities{}; |
446 | params.capabilities.textDocument->hover->dynamicRegistration = true; |
447 | params.capabilities.textDocument->hover->contentFormat = newlsp::Enum::MarkupKind::toStdVector(); |
448 | |
449 | /* SignatureHelpClientCapabilities */ |
450 | params.capabilities.textDocument->signatureHelp = SignatureHelpClientCapabilities{}; |
451 | params.capabilities.textDocument->signatureHelp->dynamicRegistration = true; |
452 | params.capabilities.textDocument->signatureHelp->signatureInformation = SignatureHelpClientCapabilities::SignatureInformation{}; |
453 | params.capabilities.textDocument->signatureHelp->signatureInformation->documentationFormat = newlsp::Enum::MarkupKind::toStdVector(); |
454 | params.capabilities.textDocument->signatureHelp->signatureInformation->parameterInformation |
455 | = SignatureHelpClientCapabilities::SignatureInformation::ParameterInformation{}; |
456 | params.capabilities.textDocument->signatureHelp->signatureInformation->parameterInformation->labelOffsetSupport = true; |
457 | params.capabilities.textDocument->signatureHelp->signatureInformation->activeParameterSupport = true; |
458 | params.capabilities.textDocument->signatureHelp->contextSupport = true; |
459 | |
460 | /* DeclarationClientCapabilities */ |
461 | params.capabilities.textDocument->declaration = DeclarationClientCapabilities{}; |
462 | params.capabilities.textDocument->declaration->dynamicRegistration = true; |
463 | params.capabilities.textDocument->declaration->linkSupport = true; |
464 | |
465 | /* DefinitionClientCapabilities */ |
466 | params.capabilities.textDocument->definition = DefinitionClientCapabilities{}; |
467 | params.capabilities.textDocument->definition->dynamicRegistration = true; |
468 | params.capabilities.textDocument->definition->linkSupport = true; |
469 | |
470 | /* TypeDefinitionClientCapabilities */ |
471 | params.capabilities.textDocument->typeDefinition = TypeDefinitionClientCapabilities{}; |
472 | params.capabilities.textDocument->typeDefinition->dynamicRegistration = true; |
473 | params.capabilities.textDocument->typeDefinition->linkSupport = true; |
474 | |
475 | /* ImplementationClientCapabilities */ |
476 | params.capabilities.textDocument->implementation = ImplementationClientCapabilities{}; |
477 | params.capabilities.textDocument->implementation->dynamicRegistration = true; |
478 | params.capabilities.textDocument->implementation->linkSupport = true; |
479 | |
480 | /* ReferenceClientCapabilities */ |
481 | params.capabilities.textDocument->references = ReferenceClientCapabilities{}; |
482 | params.capabilities.textDocument->references->dynamicRegistration = true; |
483 | |
484 | /* DocumentHighlightClientCapabilities */ |
485 | params.capabilities.textDocument->documentHighlight = DocumentHighlightClientCapabilities{}; |
486 | params.capabilities.textDocument->documentHighlight->dynamicRegistration = true; |
487 | |
488 | /* DocumentSymbolClientCapabilities */ |
489 | params.capabilities.textDocument->documentSymbol = DocumentSymbolClientCapabilities{}; |
490 | params.capabilities.textDocument->documentSymbol->dynamicRegistration = true; |
491 | params.capabilities.textDocument->documentSymbol->symbolKind = SymbolKind{}; |
492 | params.capabilities.textDocument->documentSymbol->symbolKind->valueSet = newlsp::Enum::SymbolKind::toStdVector(); |
493 | params.capabilities.textDocument->documentSymbol->hierarchicalDocumentSymbolSupport = true; |
494 | params.capabilities.textDocument->documentSymbol->tagSupport = DocumentSymbolClientCapabilities::TagSupport{}; |
495 | params.capabilities.textDocument->documentSymbol->tagSupport->valueSet = newlsp::Enum::SymbolTag::toStdVector(); |
496 | params.capabilities.textDocument->documentSymbol->labelSupport = true; |
497 | |
498 | /* CodeActionClientCapabilities */ //func |
499 | params.capabilities.textDocument->codeAction = CodeActionClientCapabilities{}; |
500 | params.capabilities.textDocument->codeAction->dynamicRegistration = true; |
501 | params.capabilities.textDocument->codeAction->isPreferredSupport = true; |
502 | params.capabilities.textDocument->codeAction->disabledSupport = true; |
503 | params.capabilities.textDocument->codeAction->dataSupport = true; |
504 | params.capabilities.textDocument->codeAction->resolveSupport = ResolveSupport{}; |
505 | params.capabilities.textDocument->codeAction->resolveSupport->properties = {newlsp::Enum::Properties::get()->edit}; |
506 | params.capabilities.textDocument->codeAction->codeActionLiteralSupport = CodeActionLiteralSupport{}; |
507 | params.capabilities.textDocument->codeAction->codeActionLiteralSupport->codeActionKind = CodeActionKind{}; |
508 | params.capabilities.textDocument->codeAction->codeActionLiteralSupport->codeActionKind.valueSet |
509 | = newlsp::Enum::CodeActionKind::toStdVector(); |
510 | params.capabilities.textDocument->codeAction->honorsChangeAnnotations = false; |
511 | |
512 | /* CodeLensClientCapabilities */ |
513 | params.capabilities.textDocument->codeLens = CodeLensClientCapabilities{}; |
514 | params.capabilities.textDocument->codeLens->dynamicRegistration = true; |
515 | |
516 | /* DocumentLinkClientCapabilities */ |
517 | params.capabilities.textDocument->documentLink = DocumentLinkClientCapabilities {}; |
518 | params.capabilities.textDocument->documentLink->dynamicRegistration = true; |
519 | params.capabilities.textDocument->documentLink->tooltipSupport = true; |
520 | |
521 | /* DocumentColorClientCapabilities */ |
522 | params.capabilities.textDocument->colorProvider = DocumentColorClientCapabilities{}; |
523 | params.capabilities.textDocument->colorProvider->dynamicRegistration = true; |
524 | |
525 | /* DocumentFormattingClientCapabilities */ |
526 | params.capabilities.textDocument->formatting = DocumentFormattingClientCapabilities{}; |
527 | params.capabilities.textDocument->formatting->dynamicRegistration = true; |
528 | |
529 | /* DocumentFormattingClientCapabilities */ |
530 | params.capabilities.textDocument->rangeFormatting = DocumentRangeFormattingClientCapabilities{}; |
531 | params.capabilities.textDocument->rangeFormatting->dynamicRegistration = true; |
532 | |
533 | /* DocumentRangeFormattingClientCapabilities */ |
534 | params.capabilities.textDocument->onTypeFormatting = DocumentOnTypeFormattingClientCapabilities{}; |
535 | params.capabilities.textDocument->onTypeFormatting->dynamicRegistration = true; |
536 | |
537 | /* RenameClientCapabilities */ |
538 | params.capabilities.textDocument->rename = RenameClientCapabilities{}; |
539 | params.capabilities.textDocument->rename->dynamicRegistration = true; |
540 | params.capabilities.textDocument->rename->prepareSupport = true; |
541 | params.capabilities.textDocument->rename->prepareSupportDefaultBehavior |
542 | = newlsp::Enum::PrepareSupportDefaultBehavior::get()->Identifier; |
543 | params.capabilities.textDocument->rename->honorsChangeAnnotations = true; |
544 | |
545 | /* PublishDiagnosticsClientCapabilities */ |
546 | params.capabilities.textDocument->publishDiagnostics = PublishDiagnosticsClientCapabilities{}; |
547 | params.capabilities.textDocument->publishDiagnostics->relatedInformation = true; |
548 | params.capabilities.textDocument->publishDiagnostics->tagSupport |
549 | = PublishDiagnosticsClientCapabilities::TagSupport{}; |
550 | params.capabilities.textDocument->publishDiagnostics->tagSupport->valueSet = newlsp::Enum::DiagnosticTag::toStdVector(); |
551 | params.capabilities.textDocument->publishDiagnostics->versionSupport = false; |
552 | params.capabilities.textDocument->publishDiagnostics->codeDescriptionSupport = true; |
553 | params.capabilities.textDocument->publishDiagnostics->dataSupport = true; |
554 | |
555 | /* FoldingRangeClientCapabilities */ |
556 | params.capabilities.textDocument->foldingRange = FoldingRangeClientCapabilities{}; |
557 | params.capabilities.textDocument->foldingRange->dynamicRegistration = true; |
558 | params.capabilities.textDocument->foldingRange->rangeLimit = 5000; // vscode 5000 |
559 | params.capabilities.textDocument->foldingRange->lineFoldingOnly = true; |
560 | // no setting from vscode |
561 | // params.capabilities.textDocument->foldingRange->foldingRangeKind = FoldingRangeKind{}; |
562 | // params.capabilities.textDocument->foldingRange->foldingRangeKind->valueSet = {newlsp::Enum::FoldingRangeKind::toStdVector()}; |
563 | // params.capabilities.textDocument->foldingRange->foldingRange = FoldingRange{}; |
564 | // params.capabilities.textDocument->foldingRange->foldingRange->collapsedText = true; |
565 | |
566 | /* SelectionRangeClientCapabilities */ |
567 | params.capabilities.textDocument->selectionRange = SelectionRangeClientCapabilities{}; |
568 | params.capabilities.textDocument->selectionRange->dynamicRegistration = true; |
569 | |
570 | /* LinkedEditingRangeClientCapabilities */ |
571 | params.capabilities.textDocument->linkedEditingRange = LinkedEditingRangeClientCapabilities{}; |
572 | params.capabilities.textDocument->linkedEditingRange->dynamicRegistration = true; |
573 | |
574 | /* CallHierarchyClientCapabilities */ |
575 | params.capabilities.textDocument->callHierarchy = CallHierarchyClientCapabilities{}; |
576 | params.capabilities.textDocument->callHierarchy->dynamicRegistration = true; |
577 | |
578 | /* SemanticTokensClientCapabilities */ |
579 | params.capabilities.textDocument->semanticTokens = SemanticTokensClientCapabilities{}; |
580 | params.capabilities.textDocument->semanticTokens->dynamicRegistration = true; |
581 | params.capabilities.textDocument->semanticTokens->tokenTypes = newlsp::Enum::SemanticTokenTypes::toStdVector(); |
582 | params.capabilities.textDocument->semanticTokens->tokenModifiers = newlsp::Enum::SemanticTokenModifiers::toStdVector(); |
583 | params.capabilities.textDocument->semanticTokens->formats = newlsp::Enum::TokenFormat::toStdVector(); |
584 | params.capabilities.textDocument->semanticTokens->requests = SemanticTokensClientCapabilities::Requests{}; |
585 | params.capabilities.textDocument->semanticTokens->requests.full = SemanticTokensClientCapabilities::Requests::Full{}; |
586 | params.capabilities.textDocument->semanticTokens->requests.full->delta = true; |
587 | params.capabilities.textDocument->semanticTokens->requests.range = std::optional<std::any>(true); |
588 | params.capabilities.textDocument->semanticTokens->multilineTokenSupport = false; // from vscode |
589 | params.capabilities.textDocument->semanticTokens->overlappingTokenSupport = false; // from vscode |
590 | // no setting from vscode |
591 | // params.capabilities.textDocument->semanticTokens->serverCancelSupport = true; |
592 | // params.capabilities.textDocument->semanticTokens->augmentsSyntaxTokens = true; |
593 | |
594 | /* MonikerClientCapabilities */ // no setting from vscode |
595 | // MonikerClientCapabilities monikerClientCapabilities{}; |
596 | // monikerClientCapabilities.dynamicRegistration = true; |
597 | // params.capabilities.textDocument->moniker = {monikerClientCapabilities}; |
598 | |
599 | /* TypeHierarchyClientCapabilities */ // no setting from vscode |
600 | // TypeHierarchyClientCapabilities typeHierarchyClientCapabilities{}; |
601 | // typeHierarchyClientCapabilities.dynamicRegistration = true; |
602 | // params.capabilities.textDocument->typeHierarchy = {typeHierarchyClientCapabilities}; |
603 | |
604 | /* InlineValueClientCapabilities */ // no setting from vscode |
605 | // InlineValueClientCapabilities inlineValueClientCapabilities{}; |
606 | // inlineValueClientCapabilities.dynamicRegistration = true; |
607 | // params.capabilities.textDocument->inlineValue = {inlineValueClientCapabilities}; |
608 | |
609 | /* InlayHintClientCapabilities */ // no setting from vscode |
610 | // params.capabilities.textDocument->inlayHint = InlayHintClientCapabilities{}; |
611 | // params.capabilities.textDocument->inlayHint->dynamicRegistration = true; |
612 | // params.capabilities.textDocument->inlayHint->resolveSupport = ResolveSupport{}; |
613 | // params.capabilities.textDocument->inlayHint->resolveSupport->properties |
614 | // = {newlsp::Enum::Properties::get()->label_location}; |
615 | |
616 | /* DiagnosticClientCapabilities */ // no setting from vscode |
617 | // DiagnosticClientCapabilities diagnosticClientCapabilities{}; |
618 | // diagnosticClientCapabilities.dynamicRegistration = true; |
619 | // diagnosticClientCapabilities.relatedDocumentSupport = true; |
620 | // params.capabilities.textDocument->diagnostic = {diagnosticClientCapabilities}; |
621 | } |
622 | /* notebookDocument */ |
623 | { |
624 | // no setting from vscode |
625 | // params.capabilities.notebookDocument = NotebookDocumentClientCapabilities{}; |
626 | // params.capabilities.notebookDocument->synchronization.dynamicRegistration = true; |
627 | // params.capabilities.notebookDocument->synchronization.executionSummarySupport = true; |
628 | } |
629 | /* window */ |
630 | { |
631 | params.capabilities.window = Window{}; |
632 | params.capabilities.window->workDoneProgress = true; |
633 | params.capabilities.window->showMessage = ShowMessageRequestClientCapabilities{}; |
634 | params.capabilities.window->showMessage->messageActionItem = MessageActionItem{}; |
635 | params.capabilities.window->showMessage->messageActionItem->additionalPropertiesSupport = true; |
636 | params.capabilities.window->showDocument = ShowDocumentClientCapabilities{}; |
637 | params.capabilities.window->showDocument->support = true; |
638 | } |
639 | /* general */ |
640 | { |
641 | params.capabilities.general = General{}; |
642 | params.capabilities.general->staleRequestSupport = StaleRequestSupport{}; |
643 | params.capabilities.general->staleRequestSupport->cancel = true; |
644 | params.capabilities.general->staleRequestSupport->retryOnContentModified = { |
645 | "textDocument/semanticTokens/full" , |
646 | "textDocument/semanticTokens/range" , |
647 | "textDocument/semanticTokens/full/delta" |
648 | }; |
649 | params.capabilities.general->regularExpressions = RegularExpressionsClientCapabilities{}; |
650 | params.capabilities.general->regularExpressions->engine = "ECMAScript" ; |
651 | params.capabilities.general->regularExpressions->version = "ES2020" ; |
652 | params.capabilities.general->markdown = MarkdownClientCapabilities{}; |
653 | params.capabilities.general->markdown->parser = "marked" ; |
654 | params.capabilities.general->markdown->version = "1.1.0" ; |
655 | } |
656 | } |
657 | |
658 | /* trace */ |
659 | { |
660 | params.trace = newlsp::Enum::TraceValue::get()->Verbose; |
661 | } |
662 | |
663 | /* workspaceFolders */ |
664 | { |
665 | std::vector<WorkspaceFolder> workspaceFolders{}; |
666 | WorkspaceFolder folderParams; |
667 | folderParams.uri = workspaceFolderUriStr; |
668 | folderParams.name = workspaceNameStr; |
669 | workspaceFolders.push_back(folderParams); |
670 | params.workspaceFolders = {workspaceFolders}; |
671 | } |
672 | |
673 | QJsonParseError err; |
674 | auto jsonDoc = QJsonDocument::fromJson(QByteArray::fromStdString(toJsonValueStr(params)), &err); |
675 | if (err.error != QJsonParseError::NoError) |
676 | qCritical() << err.errorString(); |
677 | return jsonDoc.object(); |
678 | } |
679 | return {}; |
680 | } |
681 | |
682 | QJsonObject didOpen(const QString &filePath) |
683 | { |
684 | QFile file(filePath); |
685 | QString text; |
686 | if (!file.open(QFile::ReadOnly)) { |
687 | qCritical()<< "Failed, open file: " |
688 | << filePath <<file.errorString(); |
689 | } |
690 | text = file.readAll(); |
691 | file.close(); |
692 | |
693 | QJsonObject textDocument{ |
694 | { K_URI, QUrl::fromLocalFile(filePath).toString() }, |
695 | { K_LANGUAGEID, "cpp" }, |
696 | { K_VERSION, 1 }, |
697 | { K_TEXT, text } |
698 | }; |
699 | |
700 | QJsonObject params{ |
701 | { K_TEXTDOCUMENT, textDocument } |
702 | }; |
703 | |
704 | return params; |
705 | } |
706 | |
707 | // full mode |
708 | QJsonObject didChange(const QString &filePath, const QByteArray &text, int version) |
709 | { |
710 | QJsonObject changeEvent |
711 | { |
712 | { K_TEXT, QString::fromUtf8(text)} |
713 | }; |
714 | |
715 | QJsonArray contentChanges |
716 | { |
717 | changeEvent |
718 | }; |
719 | |
720 | QJsonObject textDocument |
721 | { |
722 | { K_URI, QUrl::fromLocalFile(filePath).toString() }, |
723 | { K_VERSION, version } |
724 | }; |
725 | |
726 | QJsonObject params { |
727 | { K_TEXTDOCUMENT, textDocument }, |
728 | { "contentChanges" , contentChanges } |
729 | }; |
730 | |
731 | return params; |
732 | } |
733 | |
734 | QJsonObject didClose(const QString &filePath) |
735 | { |
736 | QJsonObject textDocument { |
737 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
738 | }; |
739 | |
740 | QJsonObject params{ |
741 | { K_TEXTDOCUMENT, textDocument}, |
742 | }; |
743 | |
744 | return params; |
745 | } |
746 | |
747 | QJsonObject hover(const QString &filePath, const Position &pos) |
748 | { |
749 | QJsonObject textDocument { |
750 | { K_URI, QUrl::fromLocalFile(filePath).toString() }, |
751 | }; |
752 | |
753 | QJsonObject position { |
754 | { K_CHARACTER, pos.character }, |
755 | { K_LINE, pos.line } |
756 | }; |
757 | |
758 | QJsonObject params { |
759 | { K_TEXTDOCUMENT, textDocument}, |
760 | { K_POSITION, position } |
761 | }; |
762 | |
763 | return params; |
764 | } |
765 | |
766 | QJsonObject definition(const QString &filePath, const Position &pos) |
767 | { |
768 | QJsonObject textDocument { |
769 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
770 | }; |
771 | |
772 | QJsonObject position { |
773 | { K_CHARACTER, pos.character }, |
774 | { K_LINE, pos.line } |
775 | }; |
776 | |
777 | QJsonObject params { |
778 | { K_TEXTDOCUMENT, textDocument }, |
779 | { K_POSITION, position} |
780 | }; |
781 | |
782 | return params; |
783 | } |
784 | |
785 | QJsonObject signatureHelp(const QString &filePath, const Position &pos) |
786 | { |
787 | QJsonObject textDocument { |
788 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
789 | }; |
790 | |
791 | QJsonObject position { |
792 | { K_CHARACTER, pos.character }, |
793 | { K_LINE, pos.line } |
794 | }; |
795 | |
796 | QJsonObject params { |
797 | { K_TEXTDOCUMENT, textDocument }, |
798 | { K_POSITION, position} |
799 | }; |
800 | |
801 | return params; |
802 | } |
803 | |
804 | QJsonObject references(const QString &filePath, const Position &pos) |
805 | { |
806 | QJsonObject textDocument { |
807 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
808 | }; |
809 | |
810 | QJsonObject position { |
811 | { K_CHARACTER, pos.character }, |
812 | { K_LINE, pos.line } |
813 | }; |
814 | |
815 | QJsonObject context { |
816 | { K_INCLUDEDECLARATION, true} |
817 | }; |
818 | |
819 | QJsonObject params { |
820 | { K_CONTEXT, context}, |
821 | { K_TEXTDOCUMENT, textDocument }, |
822 | { K_POSITION, position} |
823 | }; |
824 | |
825 | return params; |
826 | } |
827 | |
828 | QJsonObject documentHighlight(const QString &filePath, const Position &pos) |
829 | { |
830 | QJsonObject textDocument { |
831 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
832 | }; |
833 | |
834 | QJsonObject position { |
835 | { K_CHARACTER, pos.character }, |
836 | { K_LINE, pos.line } |
837 | }; |
838 | |
839 | QJsonObject params { |
840 | { K_TEXTDOCUMENT, textDocument }, |
841 | { K_POSITION, position } |
842 | }; |
843 | |
844 | return params; |
845 | } |
846 | |
847 | //more see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens |
848 | QJsonObject documentSemanticTokensFull(const QString &filePath) |
849 | { |
850 | QJsonObject textDocument { |
851 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
852 | }; |
853 | |
854 | QJsonObject params { |
855 | { K_TEXTDOCUMENT, textDocument } |
856 | }; |
857 | |
858 | return params; |
859 | } |
860 | |
861 | QJsonObject documentSemanticTokensRange(const QString &filePath) |
862 | { |
863 | Q_UNUSED(filePath) |
864 | return {}; |
865 | } |
866 | |
867 | QJsonObject documentSemanticTokensDelta(const QString &filePath) |
868 | { |
869 | Q_UNUSED(filePath) |
870 | return {}; |
871 | } |
872 | |
873 | QJsonObject shutdown() |
874 | { |
875 | return {}; |
876 | } |
877 | |
878 | QJsonObject symbol(const QString &filePath) |
879 | { |
880 | QJsonObject textDocument { |
881 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
882 | }; |
883 | |
884 | QJsonObject params { |
885 | { K_TEXTDOCUMENT, textDocument } |
886 | }; |
887 | |
888 | return params; |
889 | } |
890 | |
891 | QJsonObject rename(const QString &filePath, const Position &pos, const QString &newName) |
892 | { |
893 | QJsonObject params; |
894 | params[K_NewName] = newName; |
895 | params[K_POSITION] = QJsonObject{{K_LINE, pos.line},{K_CHARACTER, pos.character}}; |
896 | params[K_TEXTDOCUMENT] = QJsonObject{{K_URI, QUrl::fromLocalFile(filePath).toString()}} ; |
897 | |
898 | return params; |
899 | } |
900 | |
901 | QJsonObject completion(const QString &filePath, const Position &pos) |
902 | { |
903 | QJsonObject textDocument { |
904 | { K_URI, QUrl::fromLocalFile(filePath).toString() } |
905 | }; |
906 | |
907 | QJsonObject position { |
908 | { K_CHARACTER, pos.character }, |
909 | { K_LINE, pos.line } |
910 | }; |
911 | |
912 | QJsonObject params { |
913 | { K_TEXTDOCUMENT, textDocument }, |
914 | { K_POSITION, position} |
915 | }; |
916 | |
917 | return params; |
918 | } |
919 | |
920 | bool isRequestResult(const QJsonObject &object) |
921 | { |
922 | QStringList keys = object.keys(); |
923 | if (keys.contains(K_ID) && keys.contains(K_RESULT)) |
924 | return true; |
925 | return false; |
926 | } |
927 | |
928 | bool isRequestError(const QJsonObject &object) |
929 | { |
930 | if (object.keys().contains(K_ERROR)) { |
931 | qInfo() << "Failed, Request error" ; |
932 | return true; |
933 | } |
934 | return false; |
935 | } |
936 | |
937 | QJsonObject exit() |
938 | { |
939 | return {}; |
940 | } |
941 | |
942 | } |
943 | |