1 //===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains the serialization code for the LSP structs.
11 //===----------------------------------------------------------------------===//
15 #include "support/Logger.h"
16 #include "clang/Basic/LLVM.h"
17 #include "clang/Index/IndexSymbol.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/JSON.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/raw_ostream.h"
30 // Helper that doesn't treat `null` and absent fields as failures.
32 bool mapOptOrNull(const llvm::json::Value
&Params
, llvm::StringLiteral Prop
,
33 T
&Out
, llvm::json::Path P
) {
34 auto *O
= Params
.getAsObject();
36 auto *V
= O
->get(Prop
);
37 // Field is missing or null.
38 if (!V
|| V
->getAsNull())
40 return fromJSON(*V
, Out
, P
.field(Prop
));
46 URIForFile
URIForFile::canonicalize(llvm::StringRef AbsPath
,
47 llvm::StringRef TUPath
) {
48 assert(llvm::sys::path::is_absolute(AbsPath
) && "the path is relative");
49 auto Resolved
= URI::resolvePath(AbsPath
, TUPath
);
51 elog("URIForFile: failed to resolve path {0} with TU path {1}: "
52 "{2}.\nUsing unresolved path.",
53 AbsPath
, TUPath
, Resolved
.takeError());
54 return URIForFile(std::string(AbsPath
));
56 return URIForFile(std::move(*Resolved
));
59 llvm::Expected
<URIForFile
> URIForFile::fromURI(const URI
&U
,
60 llvm::StringRef HintPath
) {
61 auto Resolved
= URI::resolve(U
, HintPath
);
63 return Resolved
.takeError();
64 return URIForFile(std::move(*Resolved
));
67 bool fromJSON(const llvm::json::Value
&E
, URIForFile
&R
, llvm::json::Path P
) {
68 if (auto S
= E
.getAsString()) {
69 auto Parsed
= URI::parse(*S
);
71 consumeError(Parsed
.takeError());
72 P
.report("failed to parse URI");
75 if (Parsed
->scheme() != "file" && Parsed
->scheme() != "test") {
76 P
.report("clangd only supports 'file' URI scheme for workspace files");
79 // "file" and "test" schemes do not require hint path.
80 auto U
= URIForFile::fromURI(*Parsed
, /*HintPath=*/"");
82 P
.report("unresolvable URI");
83 consumeError(U
.takeError());
92 llvm::json::Value
toJSON(const URIForFile
&U
) { return U
.uri(); }
94 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const URIForFile
&U
) {
98 llvm::json::Value
toJSON(const TextDocumentIdentifier
&R
) {
99 return llvm::json::Object
{{"uri", R
.uri
}};
102 bool fromJSON(const llvm::json::Value
&Params
, TextDocumentIdentifier
&R
,
103 llvm::json::Path P
) {
104 llvm::json::ObjectMapper
O(Params
, P
);
105 return O
&& O
.map("uri", R
.uri
);
108 llvm::json::Value
toJSON(const VersionedTextDocumentIdentifier
&R
) {
109 auto Result
= toJSON(static_cast<const TextDocumentIdentifier
&>(R
));
110 Result
.getAsObject()->try_emplace("version", R
.version
);
114 bool fromJSON(const llvm::json::Value
&Params
,
115 VersionedTextDocumentIdentifier
&R
, llvm::json::Path P
) {
116 llvm::json::ObjectMapper
O(Params
, P
);
117 return fromJSON(Params
, static_cast<TextDocumentIdentifier
&>(R
), P
) && O
&&
118 O
.map("version", R
.version
);
121 bool fromJSON(const llvm::json::Value
&Params
, Position
&R
,
122 llvm::json::Path P
) {
123 llvm::json::ObjectMapper
O(Params
, P
);
124 return O
&& O
.map("line", R
.line
) && O
.map("character", R
.character
);
127 llvm::json::Value
toJSON(const Position
&P
) {
128 return llvm::json::Object
{
130 {"character", P
.character
},
134 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Position
&P
) {
135 return OS
<< P
.line
<< ':' << P
.character
;
138 bool fromJSON(const llvm::json::Value
&Params
, Range
&R
, llvm::json::Path P
) {
139 llvm::json::ObjectMapper
O(Params
, P
);
140 return O
&& O
.map("start", R
.start
) && O
.map("end", R
.end
);
143 llvm::json::Value
toJSON(const Range
&P
) {
144 return llvm::json::Object
{
150 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Range
&R
) {
151 return OS
<< R
.start
<< '-' << R
.end
;
154 llvm::json::Value
toJSON(const Location
&P
) {
155 return llvm::json::Object
{
161 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Location
&L
) {
162 return OS
<< L
.range
<< '@' << L
.uri
;
165 llvm::json::Value
toJSON(const ReferenceLocation
&P
) {
166 llvm::json::Object Result
{
171 Result
.insert({"containerName", P
.containerName
});
175 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
,
176 const ReferenceLocation
&L
) {
177 return OS
<< L
.range
<< '@' << L
.uri
<< " (container: " << L
.containerName
181 bool fromJSON(const llvm::json::Value
&Params
, TextDocumentItem
&R
,
182 llvm::json::Path P
) {
183 llvm::json::ObjectMapper
O(Params
, P
);
184 return O
&& O
.map("uri", R
.uri
) && O
.map("languageId", R
.languageId
) &&
185 O
.map("version", R
.version
) && O
.map("text", R
.text
);
188 bool fromJSON(const llvm::json::Value
&Params
, TextEdit
&R
,
189 llvm::json::Path P
) {
190 llvm::json::ObjectMapper
O(Params
, P
);
191 return O
&& O
.map("range", R
.range
) && O
.map("newText", R
.newText
) &&
192 O
.mapOptional("annotationId", R
.annotationId
);
195 llvm::json::Value
toJSON(const TextEdit
&P
) {
196 llvm::json::Object Result
{
198 {"newText", P
.newText
},
200 if (!P
.annotationId
.empty())
201 Result
["annotationId"] = P
.annotationId
;
205 bool fromJSON(const llvm::json::Value
&Params
, ChangeAnnotation
&R
,
206 llvm::json::Path P
) {
207 llvm::json::ObjectMapper
O(Params
, P
);
208 return O
&& O
.map("label", R
.label
) &&
209 O
.map("needsConfirmation", R
.needsConfirmation
) &&
210 O
.mapOptional("description", R
.description
);
212 llvm::json::Value
toJSON(const ChangeAnnotation
& CA
) {
213 llvm::json::Object Result
{{"label", CA
.label
}};
214 if (CA
.needsConfirmation
)
215 Result
["needsConfirmation"] = *CA
.needsConfirmation
;
216 if (!CA
.description
.empty())
217 Result
["description"] = CA
.description
;
221 bool fromJSON(const llvm::json::Value
&Params
, TextDocumentEdit
&R
,
222 llvm::json::Path P
) {
223 llvm::json::ObjectMapper
O(Params
, P
);
224 return O
&& O
.map("textDocument", R
.textDocument
) && O
.map("edits", R
.edits
);
226 llvm::json::Value
toJSON(const TextDocumentEdit
&P
) {
227 llvm::json::Object Result
{{"textDocument", P
.textDocument
},
232 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const TextEdit
&TE
) {
233 OS
<< TE
.range
<< " => \"";
234 llvm::printEscapedString(TE
.newText
, OS
);
238 bool fromJSON(const llvm::json::Value
&E
, TraceLevel
&Out
, llvm::json::Path P
) {
239 if (auto S
= E
.getAsString()) {
241 Out
= TraceLevel::Off
;
244 if (*S
== "messages") {
245 Out
= TraceLevel::Messages
;
248 if (*S
== "verbose") {
249 Out
= TraceLevel::Verbose
;
256 bool fromJSON(const llvm::json::Value
&E
, SymbolKind
&Out
, llvm::json::Path P
) {
257 if (auto T
= E
.getAsInteger()) {
258 if (*T
< static_cast<int>(SymbolKind::File
) ||
259 *T
> static_cast<int>(SymbolKind::TypeParameter
))
261 Out
= static_cast<SymbolKind
>(*T
);
267 bool fromJSON(const llvm::json::Value
&E
, SymbolKindBitset
&Out
,
268 llvm::json::Path P
) {
269 if (auto *A
= E
.getAsArray()) {
270 for (size_t I
= 0; I
< A
->size(); ++I
) {
272 if (fromJSON((*A
)[I
], KindOut
, P
.index(I
)))
273 Out
.set(size_t(KindOut
));
280 SymbolKind
adjustKindToCapability(SymbolKind Kind
,
281 SymbolKindBitset
&SupportedSymbolKinds
) {
282 auto KindVal
= static_cast<size_t>(Kind
);
283 if (KindVal
>= SymbolKindMin
&& KindVal
<= SupportedSymbolKinds
.size() &&
284 SupportedSymbolKinds
[KindVal
])
288 // Provide some fall backs for common kinds that are close enough.
289 case SymbolKind::Struct
:
290 return SymbolKind::Class
;
291 case SymbolKind::EnumMember
:
292 return SymbolKind::Enum
;
294 return SymbolKind::String
;
298 SymbolKind
indexSymbolKindToSymbolKind(index::SymbolKind Kind
) {
300 case index::SymbolKind::Unknown
:
301 return SymbolKind::Variable
;
302 case index::SymbolKind::Module
:
303 return SymbolKind::Module
;
304 case index::SymbolKind::Namespace
:
305 return SymbolKind::Namespace
;
306 case index::SymbolKind::NamespaceAlias
:
307 return SymbolKind::Namespace
;
308 case index::SymbolKind::Macro
:
309 return SymbolKind::String
;
310 case index::SymbolKind::Enum
:
311 return SymbolKind::Enum
;
312 case index::SymbolKind::Struct
:
313 return SymbolKind::Struct
;
314 case index::SymbolKind::Class
:
315 return SymbolKind::Class
;
316 case index::SymbolKind::Protocol
:
317 return SymbolKind::Interface
;
318 case index::SymbolKind::Extension
:
319 return SymbolKind::Interface
;
320 case index::SymbolKind::Union
:
321 return SymbolKind::Class
;
322 case index::SymbolKind::TypeAlias
:
323 return SymbolKind::Class
;
324 case index::SymbolKind::Function
:
325 return SymbolKind::Function
;
326 case index::SymbolKind::Variable
:
327 return SymbolKind::Variable
;
328 case index::SymbolKind::Field
:
329 return SymbolKind::Field
;
330 case index::SymbolKind::EnumConstant
:
331 return SymbolKind::EnumMember
;
332 case index::SymbolKind::InstanceMethod
:
333 case index::SymbolKind::ClassMethod
:
334 case index::SymbolKind::StaticMethod
:
335 return SymbolKind::Method
;
336 case index::SymbolKind::InstanceProperty
:
337 case index::SymbolKind::ClassProperty
:
338 case index::SymbolKind::StaticProperty
:
339 return SymbolKind::Property
;
340 case index::SymbolKind::Constructor
:
341 case index::SymbolKind::Destructor
:
342 return SymbolKind::Constructor
;
343 case index::SymbolKind::ConversionFunction
:
344 return SymbolKind::Function
;
345 case index::SymbolKind::Parameter
:
346 case index::SymbolKind::NonTypeTemplateParm
:
347 return SymbolKind::Variable
;
348 case index::SymbolKind::Using
:
349 return SymbolKind::Namespace
;
350 case index::SymbolKind::TemplateTemplateParm
:
351 case index::SymbolKind::TemplateTypeParm
:
352 return SymbolKind::TypeParameter
;
353 case index::SymbolKind::Concept
:
354 return SymbolKind::Interface
;
356 llvm_unreachable("invalid symbol kind");
359 bool fromJSON(const llvm::json::Value
&Params
, ClientCapabilities
&R
,
360 llvm::json::Path P
) {
361 const llvm::json::Object
*O
= Params
.getAsObject();
363 P
.report("expected object");
366 if (auto *TextDocument
= O
->getObject("textDocument")) {
367 if (auto *SemanticHighlighting
=
368 TextDocument
->getObject("semanticHighlightingCapabilities")) {
369 if (auto SemanticHighlightingSupport
=
370 SemanticHighlighting
->getBoolean("semanticHighlighting"))
371 R
.TheiaSemanticHighlighting
= *SemanticHighlightingSupport
;
373 if (auto *InactiveRegions
=
374 TextDocument
->getObject("inactiveRegionsCapabilities")) {
375 if (auto InactiveRegionsSupport
=
376 InactiveRegions
->getBoolean("inactiveRegions")) {
377 R
.InactiveRegions
= *InactiveRegionsSupport
;
380 if (TextDocument
->getObject("semanticTokens"))
381 R
.SemanticTokens
= true;
382 if (auto *Diagnostics
= TextDocument
->getObject("publishDiagnostics")) {
383 if (auto CategorySupport
= Diagnostics
->getBoolean("categorySupport"))
384 R
.DiagnosticCategory
= *CategorySupport
;
385 if (auto CodeActions
= Diagnostics
->getBoolean("codeActionsInline"))
386 R
.DiagnosticFixes
= *CodeActions
;
387 if (auto RelatedInfo
= Diagnostics
->getBoolean("relatedInformation"))
388 R
.DiagnosticRelatedInformation
= *RelatedInfo
;
390 if (auto *References
= TextDocument
->getObject("references"))
391 if (auto ContainerSupport
= References
->getBoolean("container"))
392 R
.ReferenceContainer
= *ContainerSupport
;
393 if (auto *Completion
= TextDocument
->getObject("completion")) {
394 if (auto *Item
= Completion
->getObject("completionItem")) {
395 if (auto SnippetSupport
= Item
->getBoolean("snippetSupport"))
396 R
.CompletionSnippets
= *SnippetSupport
;
397 if (auto LabelDetailsSupport
= Item
->getBoolean("labelDetailsSupport"))
398 R
.CompletionLabelDetail
= *LabelDetailsSupport
;
399 if (const auto *DocumentationFormat
=
400 Item
->getArray("documentationFormat")) {
401 for (const auto &Format
: *DocumentationFormat
) {
402 if (fromJSON(Format
, R
.CompletionDocumentationFormat
, P
))
407 if (auto *ItemKind
= Completion
->getObject("completionItemKind")) {
408 if (auto *ValueSet
= ItemKind
->get("valueSet")) {
409 R
.CompletionItemKinds
.emplace();
410 if (!fromJSON(*ValueSet
, *R
.CompletionItemKinds
,
411 P
.field("textDocument")
413 .field("completionItemKind")
418 if (auto EditsNearCursor
= Completion
->getBoolean("editsNearCursor"))
419 R
.CompletionFixes
= *EditsNearCursor
;
421 if (auto *CodeAction
= TextDocument
->getObject("codeAction")) {
422 if (CodeAction
->getObject("codeActionLiteralSupport"))
423 R
.CodeActionStructure
= true;
425 if (auto *DocumentSymbol
= TextDocument
->getObject("documentSymbol")) {
426 if (auto HierarchicalSupport
=
427 DocumentSymbol
->getBoolean("hierarchicalDocumentSymbolSupport"))
428 R
.HierarchicalDocumentSymbol
= *HierarchicalSupport
;
430 if (auto *Hover
= TextDocument
->getObject("hover")) {
431 if (auto *ContentFormat
= Hover
->getArray("contentFormat")) {
432 for (const auto &Format
: *ContentFormat
) {
433 if (fromJSON(Format
, R
.HoverContentFormat
, P
))
438 if (auto *Help
= TextDocument
->getObject("signatureHelp")) {
439 R
.HasSignatureHelp
= true;
440 if (auto *Info
= Help
->getObject("signatureInformation")) {
441 if (auto *Parameter
= Info
->getObject("parameterInformation")) {
442 if (auto OffsetSupport
= Parameter
->getBoolean("labelOffsetSupport"))
443 R
.OffsetsInSignatureHelp
= *OffsetSupport
;
445 if (const auto *DocumentationFormat
=
446 Info
->getArray("documentationFormat")) {
447 for (const auto &Format
: *DocumentationFormat
) {
448 if (fromJSON(Format
, R
.SignatureHelpDocumentationFormat
, P
))
454 if (auto *Folding
= TextDocument
->getObject("foldingRange")) {
455 if (auto LineFolding
= Folding
->getBoolean("lineFoldingOnly"))
456 R
.LineFoldingOnly
= *LineFolding
;
458 if (auto *Rename
= TextDocument
->getObject("rename")) {
459 if (auto RenameSupport
= Rename
->getBoolean("prepareSupport"))
460 R
.RenamePrepareSupport
= *RenameSupport
;
463 if (auto *Workspace
= O
->getObject("workspace")) {
464 if (auto *Symbol
= Workspace
->getObject("symbol")) {
465 if (auto *SymbolKind
= Symbol
->getObject("symbolKind")) {
466 if (auto *ValueSet
= SymbolKind
->get("valueSet")) {
467 R
.WorkspaceSymbolKinds
.emplace();
468 if (!fromJSON(*ValueSet
, *R
.WorkspaceSymbolKinds
,
477 if (auto *SemanticTokens
= Workspace
->getObject("semanticTokens")) {
478 if (auto RefreshSupport
= SemanticTokens
->getBoolean("refreshSupport"))
479 R
.SemanticTokenRefreshSupport
= *RefreshSupport
;
481 if (auto *WorkspaceEdit
= Workspace
->getObject("workspaceEdit")) {
482 if (auto DocumentChanges
= WorkspaceEdit
->getBoolean("documentChanges"))
483 R
.DocumentChanges
= *DocumentChanges
;
484 if (WorkspaceEdit
->getObject("changeAnnotationSupport")) {
485 R
.ChangeAnnotation
= true;
489 if (auto *Window
= O
->getObject("window")) {
490 if (auto WorkDoneProgress
= Window
->getBoolean("workDoneProgress"))
491 R
.WorkDoneProgress
= *WorkDoneProgress
;
492 if (auto Implicit
= Window
->getBoolean("implicitWorkDoneProgressCreate"))
493 R
.ImplicitProgressCreation
= *Implicit
;
495 if (auto *General
= O
->getObject("general")) {
496 if (auto *StaleRequestSupport
= General
->getObject("staleRequestSupport")) {
497 if (auto Cancel
= StaleRequestSupport
->getBoolean("cancel"))
498 R
.CancelsStaleRequests
= *Cancel
;
501 if (auto *OffsetEncoding
= O
->get("offsetEncoding")) {
502 R
.offsetEncoding
.emplace();
503 if (!fromJSON(*OffsetEncoding
, *R
.offsetEncoding
,
504 P
.field("offsetEncoding")))
510 bool fromJSON(const llvm::json::Value
&Params
, InitializeParams
&R
,
511 llvm::json::Path P
) {
512 llvm::json::ObjectMapper
O(Params
, P
);
515 // We deliberately don't fail if we can't parse individual fields.
516 // Failing to handle a slightly malformed initialize would be a disaster.
517 O
.map("processId", R
.processId
);
518 O
.map("rootUri", R
.rootUri
);
519 O
.map("rootPath", R
.rootPath
);
520 O
.map("capabilities", R
.capabilities
);
521 if (auto *RawCaps
= Params
.getAsObject()->getObject("capabilities"))
522 R
.rawCapabilities
= *RawCaps
;
523 O
.map("trace", R
.trace
);
524 O
.map("initializationOptions", R
.initializationOptions
);
528 llvm::json::Value
toJSON(const WorkDoneProgressCreateParams
&P
) {
529 return llvm::json::Object
{{"token", P
.token
}};
532 llvm::json::Value
toJSON(const WorkDoneProgressBegin
&P
) {
533 llvm::json::Object Result
{
538 Result
["cancellable"] = true;
540 Result
["percentage"] = 0;
542 // FIXME: workaround for older gcc/clang
543 return std::move(Result
);
546 llvm::json::Value
toJSON(const WorkDoneProgressReport
&P
) {
547 llvm::json::Object Result
{{"kind", "report"}};
549 Result
["cancellable"] = *P
.cancellable
;
551 Result
["message"] = *P
.message
;
553 Result
["percentage"] = *P
.percentage
;
554 // FIXME: workaround for older gcc/clang
555 return std::move(Result
);
558 llvm::json::Value
toJSON(const WorkDoneProgressEnd
&P
) {
559 llvm::json::Object Result
{{"kind", "end"}};
561 Result
["message"] = *P
.message
;
562 // FIXME: workaround for older gcc/clang
563 return std::move(Result
);
566 llvm::json::Value
toJSON(const MessageType
&R
) {
567 return static_cast<int64_t>(R
);
570 llvm::json::Value
toJSON(const ShowMessageParams
&R
) {
571 return llvm::json::Object
{{"type", R
.type
}, {"message", R
.message
}};
574 bool fromJSON(const llvm::json::Value
&Params
, DidOpenTextDocumentParams
&R
,
575 llvm::json::Path P
) {
576 llvm::json::ObjectMapper
O(Params
, P
);
577 return O
&& O
.map("textDocument", R
.textDocument
);
580 bool fromJSON(const llvm::json::Value
&Params
, DidCloseTextDocumentParams
&R
,
581 llvm::json::Path P
) {
582 llvm::json::ObjectMapper
O(Params
, P
);
583 return O
&& O
.map("textDocument", R
.textDocument
);
586 bool fromJSON(const llvm::json::Value
&Params
, DidSaveTextDocumentParams
&R
,
587 llvm::json::Path P
) {
588 llvm::json::ObjectMapper
O(Params
, P
);
589 return O
&& O
.map("textDocument", R
.textDocument
);
592 bool fromJSON(const llvm::json::Value
&Params
, DidChangeTextDocumentParams
&R
,
593 llvm::json::Path P
) {
594 llvm::json::ObjectMapper
O(Params
, P
);
595 return O
&& O
.map("textDocument", R
.textDocument
) &&
596 O
.map("contentChanges", R
.contentChanges
) &&
597 O
.map("wantDiagnostics", R
.wantDiagnostics
) &&
598 mapOptOrNull(Params
, "forceRebuild", R
.forceRebuild
, P
);
601 bool fromJSON(const llvm::json::Value
&E
, FileChangeType
&Out
,
602 llvm::json::Path P
) {
603 if (auto T
= E
.getAsInteger()) {
604 if (*T
< static_cast<int>(FileChangeType::Created
) ||
605 *T
> static_cast<int>(FileChangeType::Deleted
))
607 Out
= static_cast<FileChangeType
>(*T
);
613 bool fromJSON(const llvm::json::Value
&Params
, FileEvent
&R
,
614 llvm::json::Path P
) {
615 llvm::json::ObjectMapper
O(Params
, P
);
616 return O
&& O
.map("uri", R
.uri
) && O
.map("type", R
.type
);
619 bool fromJSON(const llvm::json::Value
&Params
, DidChangeWatchedFilesParams
&R
,
620 llvm::json::Path P
) {
621 llvm::json::ObjectMapper
O(Params
, P
);
622 return O
&& O
.map("changes", R
.changes
);
625 bool fromJSON(const llvm::json::Value
&Params
,
626 TextDocumentContentChangeEvent
&R
, llvm::json::Path P
) {
627 llvm::json::ObjectMapper
O(Params
, P
);
628 return O
&& O
.map("range", R
.range
) && O
.map("rangeLength", R
.rangeLength
) &&
629 O
.map("text", R
.text
);
632 bool fromJSON(const llvm::json::Value
&Params
, DocumentRangeFormattingParams
&R
,
633 llvm::json::Path P
) {
634 llvm::json::ObjectMapper
O(Params
, P
);
635 return O
&& O
.map("textDocument", R
.textDocument
) && O
.map("range", R
.range
);
638 bool fromJSON(const llvm::json::Value
&Params
,
639 DocumentOnTypeFormattingParams
&R
, llvm::json::Path P
) {
640 llvm::json::ObjectMapper
O(Params
, P
);
641 return O
&& O
.map("textDocument", R
.textDocument
) &&
642 O
.map("position", R
.position
) && O
.map("ch", R
.ch
);
645 bool fromJSON(const llvm::json::Value
&Params
, DocumentFormattingParams
&R
,
646 llvm::json::Path P
) {
647 llvm::json::ObjectMapper
O(Params
, P
);
648 return O
&& O
.map("textDocument", R
.textDocument
);
651 bool fromJSON(const llvm::json::Value
&Params
, DocumentSymbolParams
&R
,
652 llvm::json::Path P
) {
653 llvm::json::ObjectMapper
O(Params
, P
);
654 return O
&& O
.map("textDocument", R
.textDocument
);
657 llvm::json::Value
toJSON(const DiagnosticRelatedInformation
&DRI
) {
658 return llvm::json::Object
{
659 {"location", DRI
.location
},
660 {"message", DRI
.message
},
664 llvm::json::Value
toJSON(DiagnosticTag Tag
) { return static_cast<int>(Tag
); }
666 llvm::json::Value
toJSON(const CodeDescription
&D
) {
667 return llvm::json::Object
{{"href", D
.href
}};
670 llvm::json::Value
toJSON(const Diagnostic
&D
) {
671 llvm::json::Object Diag
{
673 {"severity", D
.severity
},
674 {"message", D
.message
},
677 Diag
["category"] = *D
.category
;
679 Diag
["codeActions"] = D
.codeActions
;
681 Diag
["code"] = D
.code
;
682 if (D
.codeDescription
)
683 Diag
["codeDescription"] = *D
.codeDescription
;
684 if (!D
.source
.empty())
685 Diag
["source"] = D
.source
;
686 if (D
.relatedInformation
)
687 Diag
["relatedInformation"] = *D
.relatedInformation
;
689 Diag
["data"] = llvm::json::Object(D
.data
);
691 Diag
["tags"] = llvm::json::Array
{D
.tags
};
692 // FIXME: workaround for older gcc/clang
693 return std::move(Diag
);
696 bool fromJSON(const llvm::json::Value
&Params
, Diagnostic
&R
,
697 llvm::json::Path P
) {
698 llvm::json::ObjectMapper
O(Params
, P
);
701 if (auto *Data
= Params
.getAsObject()->getObject("data"))
703 return O
.map("range", R
.range
) && O
.map("message", R
.message
) &&
704 mapOptOrNull(Params
, "severity", R
.severity
, P
) &&
705 mapOptOrNull(Params
, "category", R
.category
, P
) &&
706 mapOptOrNull(Params
, "code", R
.code
, P
) &&
707 mapOptOrNull(Params
, "source", R
.source
, P
);
710 llvm::json::Value
toJSON(const PublishDiagnosticsParams
&PDP
) {
711 llvm::json::Object Result
{
713 {"diagnostics", PDP
.diagnostics
},
716 Result
["version"] = PDP
.version
;
717 return std::move(Result
);
720 bool fromJSON(const llvm::json::Value
&Params
, CodeActionContext
&R
,
721 llvm::json::Path P
) {
722 llvm::json::ObjectMapper
O(Params
, P
);
723 if (!O
|| !O
.map("diagnostics", R
.diagnostics
))
725 O
.map("only", R
.only
);
729 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const Diagnostic
&D
) {
730 OS
<< D
.range
<< " [";
731 switch (D
.severity
) {
748 return OS
<< '(' << D
.severity
<< "): " << D
.message
<< "]";
751 bool fromJSON(const llvm::json::Value
&Params
, CodeActionParams
&R
,
752 llvm::json::Path P
) {
753 llvm::json::ObjectMapper
O(Params
, P
);
754 return O
&& O
.map("textDocument", R
.textDocument
) &&
755 O
.map("range", R
.range
) && O
.map("context", R
.context
);
758 bool fromJSON(const llvm::json::Value
&Params
, WorkspaceEdit
&R
,
759 llvm::json::Path P
) {
760 llvm::json::ObjectMapper
O(Params
, P
);
761 return O
&& O
.map("changes", R
.changes
) &&
762 O
.map("documentChanges", R
.documentChanges
) &&
763 O
.mapOptional("changeAnnotations", R
.changeAnnotations
);
766 bool fromJSON(const llvm::json::Value
&Params
, ExecuteCommandParams
&R
,
767 llvm::json::Path P
) {
768 llvm::json::ObjectMapper
O(Params
, P
);
769 if (!O
|| !O
.map("command", R
.command
))
772 const auto *Args
= Params
.getAsObject()->get("arguments");
774 return true; // Missing args is ok, argument is null.
775 const auto *ArgsArray
= Args
->getAsArray();
777 P
.field("arguments").report("expected array");
780 if (ArgsArray
->size() > 1) {
781 P
.field("arguments").report("Command should have 0 or 1 argument");
784 if (ArgsArray
->size() == 1) {
785 R
.argument
= ArgsArray
->front();
790 llvm::json::Value
toJSON(const SymbolInformation
&P
) {
791 llvm::json::Object O
{
793 {"kind", static_cast<int>(P
.kind
)},
794 {"location", P
.location
},
795 {"containerName", P
.containerName
},
798 O
["score"] = *P
.score
;
802 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
,
803 const SymbolInformation
&SI
) {
804 O
<< SI
.containerName
<< "::" << SI
.name
<< " - " << toJSON(SI
);
808 bool operator==(const SymbolDetails
&LHS
, const SymbolDetails
&RHS
) {
809 return LHS
.name
== RHS
.name
&& LHS
.containerName
== RHS
.containerName
&&
810 LHS
.USR
== RHS
.USR
&& LHS
.ID
== RHS
.ID
&&
811 LHS
.declarationRange
== RHS
.declarationRange
&&
812 LHS
.definitionRange
== RHS
.definitionRange
;
815 llvm::json::Value
toJSON(const SymbolDetails
&P
) {
816 llvm::json::Object Result
{{"name", llvm::json::Value(nullptr)},
817 {"containerName", llvm::json::Value(nullptr)},
818 {"usr", llvm::json::Value(nullptr)},
819 {"id", llvm::json::Value(nullptr)}};
822 Result
["name"] = P
.name
;
824 if (!P
.containerName
.empty())
825 Result
["containerName"] = P
.containerName
;
828 Result
["usr"] = P
.USR
;
831 Result
["id"] = P
.ID
.str();
833 if (P
.declarationRange
)
834 Result
["declarationRange"] = *P
.declarationRange
;
836 if (P
.definitionRange
)
837 Result
["definitionRange"] = *P
.definitionRange
;
839 // FIXME: workaround for older gcc/clang
840 return std::move(Result
);
843 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
, const SymbolDetails
&S
) {
844 if (!S
.containerName
.empty()) {
845 O
<< S
.containerName
;
846 llvm::StringRef ContNameRef
;
847 if (!ContNameRef
.endswith("::")) {
851 O
<< S
.name
<< " - " << toJSON(S
);
855 bool fromJSON(const llvm::json::Value
&Params
, WorkspaceSymbolParams
&R
,
856 llvm::json::Path P
) {
857 llvm::json::ObjectMapper
O(Params
, P
);
858 return O
&& O
.map("query", R
.query
) &&
859 mapOptOrNull(Params
, "limit", R
.limit
, P
);
862 llvm::json::Value
toJSON(const Command
&C
) {
863 auto Cmd
= llvm::json::Object
{{"title", C
.title
}, {"command", C
.command
}};
864 if (!C
.argument
.getAsNull())
865 Cmd
["arguments"] = llvm::json::Array
{C
.argument
};
866 return std::move(Cmd
);
869 const llvm::StringLiteral
CodeAction::QUICKFIX_KIND
= "quickfix";
870 const llvm::StringLiteral
CodeAction::REFACTOR_KIND
= "refactor";
871 const llvm::StringLiteral
CodeAction::INFO_KIND
= "info";
873 llvm::json::Value
toJSON(const CodeAction
&CA
) {
874 auto CodeAction
= llvm::json::Object
{{"title", CA
.title
}};
876 CodeAction
["kind"] = *CA
.kind
;
878 CodeAction
["diagnostics"] = llvm::json::Array(*CA
.diagnostics
);
880 CodeAction
["isPreferred"] = true;
882 CodeAction
["edit"] = *CA
.edit
;
884 CodeAction
["command"] = *CA
.command
;
885 return std::move(CodeAction
);
888 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
, const DocumentSymbol
&S
) {
889 return O
<< S
.name
<< " - " << toJSON(S
);
892 llvm::json::Value
toJSON(const DocumentSymbol
&S
) {
893 llvm::json::Object Result
{{"name", S
.name
},
894 {"kind", static_cast<int>(S
.kind
)},
896 {"selectionRange", S
.selectionRange
}};
898 if (!S
.detail
.empty())
899 Result
["detail"] = S
.detail
;
900 if (!S
.children
.empty())
901 Result
["children"] = S
.children
;
903 Result
["deprecated"] = true;
904 // FIXME: workaround for older gcc/clang
905 return std::move(Result
);
908 llvm::json::Value
toJSON(const WorkspaceEdit
&WE
) {
909 llvm::json::Object Result
;
911 llvm::json::Object FileChanges
;
912 for (auto &Change
: *WE
.changes
)
913 FileChanges
[Change
.first
] = llvm::json::Array(Change
.second
);
914 Result
["changes"] = std::move(FileChanges
);
916 if (WE
.documentChanges
)
917 Result
["documentChanges"] = *WE
.documentChanges
;
918 if (!WE
.changeAnnotations
.empty()) {
919 llvm::json::Object ChangeAnnotations
;
920 for (auto &Annotation
: WE
.changeAnnotations
)
921 ChangeAnnotations
[Annotation
.first
] = Annotation
.second
;
922 Result
["changeAnnotations"] = std::move(ChangeAnnotations
);
927 bool fromJSON(const llvm::json::Value
&Params
, TweakArgs
&A
,
928 llvm::json::Path P
) {
929 llvm::json::ObjectMapper
O(Params
, P
);
930 return O
&& O
.map("file", A
.file
) && O
.map("selection", A
.selection
) &&
931 O
.map("tweakID", A
.tweakID
);
934 llvm::json::Value
toJSON(const TweakArgs
&A
) {
935 return llvm::json::Object
{
936 {"tweakID", A
.tweakID
}, {"selection", A
.selection
}, {"file", A
.file
}};
939 llvm::json::Value
toJSON(const ApplyWorkspaceEditParams
&Params
) {
940 return llvm::json::Object
{{"edit", Params
.edit
}};
943 bool fromJSON(const llvm::json::Value
&Response
, ApplyWorkspaceEditResponse
&R
,
944 llvm::json::Path P
) {
945 llvm::json::ObjectMapper
O(Response
, P
);
946 return O
&& O
.map("applied", R
.applied
) &&
947 O
.map("failureReason", R
.failureReason
);
950 bool fromJSON(const llvm::json::Value
&Params
, TextDocumentPositionParams
&R
,
951 llvm::json::Path P
) {
952 llvm::json::ObjectMapper
O(Params
, P
);
953 return O
&& O
.map("textDocument", R
.textDocument
) &&
954 O
.map("position", R
.position
);
957 bool fromJSON(const llvm::json::Value
&Params
, CompletionContext
&R
,
958 llvm::json::Path P
) {
959 llvm::json::ObjectMapper
O(Params
, P
);
961 if (!O
|| !O
.map("triggerKind", TriggerKind
) ||
962 !mapOptOrNull(Params
, "triggerCharacter", R
.triggerCharacter
, P
))
964 R
.triggerKind
= static_cast<CompletionTriggerKind
>(TriggerKind
);
968 bool fromJSON(const llvm::json::Value
&Params
, CompletionParams
&R
,
969 llvm::json::Path P
) {
970 if (!fromJSON(Params
, static_cast<TextDocumentPositionParams
&>(R
), P
) ||
971 !mapOptOrNull(Params
, "limit", R
.limit
, P
))
973 if (auto *Context
= Params
.getAsObject()->get("context"))
974 return fromJSON(*Context
, R
.context
, P
.field("context"));
978 static llvm::StringRef
toTextKind(MarkupKind Kind
) {
980 case MarkupKind::PlainText
:
982 case MarkupKind::Markdown
:
985 llvm_unreachable("Invalid MarkupKind");
988 bool fromJSON(const llvm::json::Value
&V
, MarkupKind
&K
, llvm::json::Path P
) {
989 auto Str
= V
.getAsString();
991 P
.report("expected string");
994 if (*Str
== "plaintext")
995 K
= MarkupKind::PlainText
;
996 else if (*Str
== "markdown")
997 K
= MarkupKind::Markdown
;
999 P
.report("unknown markup kind");
1005 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, MarkupKind K
) {
1006 return OS
<< toTextKind(K
);
1009 llvm::json::Value
toJSON(const MarkupContent
&MC
) {
1010 if (MC
.value
.empty())
1013 return llvm::json::Object
{
1014 {"kind", toTextKind(MC
.kind
)},
1015 {"value", MC
.value
},
1019 llvm::json::Value
toJSON(const Hover
&H
) {
1020 llvm::json::Object Result
{{"contents", toJSON(H
.contents
)}};
1023 Result
["range"] = toJSON(*H
.range
);
1025 return std::move(Result
);
1028 bool fromJSON(const llvm::json::Value
&E
, CompletionItemKind
&Out
,
1029 llvm::json::Path P
) {
1030 if (auto T
= E
.getAsInteger()) {
1031 if (*T
< static_cast<int>(CompletionItemKind::Text
) ||
1032 *T
> static_cast<int>(CompletionItemKind::TypeParameter
))
1034 Out
= static_cast<CompletionItemKind
>(*T
);
1041 adjustKindToCapability(CompletionItemKind Kind
,
1042 CompletionItemKindBitset
&SupportedCompletionItemKinds
) {
1043 auto KindVal
= static_cast<size_t>(Kind
);
1044 if (KindVal
>= CompletionItemKindMin
&&
1045 KindVal
<= SupportedCompletionItemKinds
.size() &&
1046 SupportedCompletionItemKinds
[KindVal
])
1050 // Provide some fall backs for common kinds that are close enough.
1051 case CompletionItemKind::Folder
:
1052 return CompletionItemKind::File
;
1053 case CompletionItemKind::EnumMember
:
1054 return CompletionItemKind::Enum
;
1055 case CompletionItemKind::Struct
:
1056 return CompletionItemKind::Class
;
1058 return CompletionItemKind::Text
;
1062 bool fromJSON(const llvm::json::Value
&E
, CompletionItemKindBitset
&Out
,
1063 llvm::json::Path P
) {
1064 if (auto *A
= E
.getAsArray()) {
1065 for (size_t I
= 0; I
< A
->size(); ++I
) {
1066 CompletionItemKind KindOut
;
1067 if (fromJSON((*A
)[I
], KindOut
, P
.index(I
)))
1068 Out
.set(size_t(KindOut
));
1075 llvm::json::Value
toJSON(const CompletionItemLabelDetails
&CD
) {
1076 llvm::json::Object Result
;
1077 if (!CD
.detail
.empty())
1078 Result
["detail"] = CD
.detail
;
1079 if (!CD
.description
.empty())
1080 Result
["description"] = CD
.description
;
1084 void removeCompletionLabelDetails(CompletionItem
&C
) {
1085 if (!C
.labelDetails
)
1087 if (!C
.labelDetails
->detail
.empty())
1088 C
.label
+= C
.labelDetails
->detail
;
1089 if (!C
.labelDetails
->description
.empty())
1090 C
.label
= C
.labelDetails
->description
+ C
.label
;
1091 C
.labelDetails
.reset();
1094 llvm::json::Value
toJSON(const CompletionItem
&CI
) {
1095 assert(!CI
.label
.empty() && "completion item label is required");
1096 llvm::json::Object Result
{{"label", CI
.label
}};
1097 if (CI
.kind
!= CompletionItemKind::Missing
)
1098 Result
["kind"] = static_cast<int>(CI
.kind
);
1099 if (!CI
.detail
.empty())
1100 Result
["detail"] = CI
.detail
;
1101 if (CI
.labelDetails
)
1102 Result
["labelDetails"] = *CI
.labelDetails
;
1103 if (CI
.documentation
)
1104 Result
["documentation"] = CI
.documentation
;
1105 if (!CI
.sortText
.empty())
1106 Result
["sortText"] = CI
.sortText
;
1107 if (!CI
.filterText
.empty())
1108 Result
["filterText"] = CI
.filterText
;
1109 if (!CI
.insertText
.empty())
1110 Result
["insertText"] = CI
.insertText
;
1111 if (CI
.insertTextFormat
!= InsertTextFormat::Missing
)
1112 Result
["insertTextFormat"] = static_cast<int>(CI
.insertTextFormat
);
1114 Result
["textEdit"] = *CI
.textEdit
;
1115 if (!CI
.additionalTextEdits
.empty())
1116 Result
["additionalTextEdits"] = llvm::json::Array(CI
.additionalTextEdits
);
1118 Result
["deprecated"] = CI
.deprecated
;
1119 Result
["score"] = CI
.score
;
1120 return std::move(Result
);
1123 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
, const CompletionItem
&I
) {
1124 O
<< I
.label
<< " - " << toJSON(I
);
1128 bool operator<(const CompletionItem
&L
, const CompletionItem
&R
) {
1129 return (L
.sortText
.empty() ? L
.label
: L
.sortText
) <
1130 (R
.sortText
.empty() ? R
.label
: R
.sortText
);
1133 llvm::json::Value
toJSON(const CompletionList
&L
) {
1134 return llvm::json::Object
{
1135 {"isIncomplete", L
.isIncomplete
},
1136 {"items", llvm::json::Array(L
.items
)},
1140 llvm::json::Value
toJSON(const ParameterInformation
&PI
) {
1141 assert((PI
.labelOffsets
|| !PI
.labelString
.empty()) &&
1142 "parameter information label is required");
1143 llvm::json::Object Result
;
1144 if (PI
.labelOffsets
)
1146 llvm::json::Array({PI
.labelOffsets
->first
, PI
.labelOffsets
->second
});
1148 Result
["label"] = PI
.labelString
;
1149 if (!PI
.documentation
.empty())
1150 Result
["documentation"] = PI
.documentation
;
1151 return std::move(Result
);
1154 llvm::json::Value
toJSON(const SignatureInformation
&SI
) {
1155 assert(!SI
.label
.empty() && "signature information label is required");
1156 llvm::json::Object Result
{
1157 {"label", SI
.label
},
1158 {"parameters", llvm::json::Array(SI
.parameters
)},
1160 if (!SI
.documentation
.value
.empty())
1161 Result
["documentation"] = SI
.documentation
;
1162 return std::move(Result
);
1165 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
,
1166 const SignatureInformation
&I
) {
1167 O
<< I
.label
<< " - " << toJSON(I
);
1171 llvm::json::Value
toJSON(const SignatureHelp
&SH
) {
1172 assert(SH
.activeSignature
>= 0 &&
1173 "Unexpected negative value for number of active signatures.");
1174 assert(SH
.activeParameter
>= 0 &&
1175 "Unexpected negative value for active parameter index");
1176 return llvm::json::Object
{
1177 {"activeSignature", SH
.activeSignature
},
1178 {"activeParameter", SH
.activeParameter
},
1179 {"signatures", llvm::json::Array(SH
.signatures
)},
1183 bool fromJSON(const llvm::json::Value
&Params
, RenameParams
&R
,
1184 llvm::json::Path P
) {
1185 llvm::json::ObjectMapper
O(Params
, P
);
1186 return O
&& O
.map("textDocument", R
.textDocument
) &&
1187 O
.map("position", R
.position
) && O
.map("newName", R
.newName
);
1190 llvm::json::Value
toJSON(const DocumentHighlight
&DH
) {
1191 return llvm::json::Object
{
1192 {"range", toJSON(DH
.range
)},
1193 {"kind", static_cast<int>(DH
.kind
)},
1197 llvm::json::Value
toJSON(const FileStatus
&FStatus
) {
1198 return llvm::json::Object
{
1199 {"uri", FStatus
.uri
},
1200 {"state", FStatus
.state
},
1204 constexpr unsigned SemanticTokenEncodingSize
= 5;
1205 static llvm::json::Value
encodeTokens(llvm::ArrayRef
<SemanticToken
> Toks
) {
1206 llvm::json::Array Result
;
1207 Result
.reserve(SemanticTokenEncodingSize
* Toks
.size());
1208 for (const auto &Tok
: Toks
) {
1209 Result
.push_back(Tok
.deltaLine
);
1210 Result
.push_back(Tok
.deltaStart
);
1211 Result
.push_back(Tok
.length
);
1212 Result
.push_back(Tok
.tokenType
);
1213 Result
.push_back(Tok
.tokenModifiers
);
1215 assert(Result
.size() == SemanticTokenEncodingSize
* Toks
.size());
1216 return std::move(Result
);
1219 bool operator==(const SemanticToken
&L
, const SemanticToken
&R
) {
1220 return std::tie(L
.deltaLine
, L
.deltaStart
, L
.length
, L
.tokenType
,
1221 L
.tokenModifiers
) == std::tie(R
.deltaLine
, R
.deltaStart
,
1222 R
.length
, R
.tokenType
,
1226 llvm::json::Value
toJSON(const SemanticTokens
&Tokens
) {
1227 return llvm::json::Object
{{"resultId", Tokens
.resultId
},
1228 {"data", encodeTokens(Tokens
.tokens
)}};
1231 llvm::json::Value
toJSON(const SemanticTokensEdit
&Edit
) {
1232 return llvm::json::Object
{
1233 {"start", SemanticTokenEncodingSize
* Edit
.startToken
},
1234 {"deleteCount", SemanticTokenEncodingSize
* Edit
.deleteTokens
},
1235 {"data", encodeTokens(Edit
.tokens
)}};
1238 llvm::json::Value
toJSON(const SemanticTokensOrDelta
&TE
) {
1239 llvm::json::Object Result
{{"resultId", TE
.resultId
}};
1241 Result
["edits"] = *TE
.edits
;
1243 Result
["data"] = encodeTokens(*TE
.tokens
);
1244 return std::move(Result
);
1247 bool fromJSON(const llvm::json::Value
&Params
, SemanticTokensParams
&R
,
1248 llvm::json::Path P
) {
1249 llvm::json::ObjectMapper
O(Params
, P
);
1250 return O
&& O
.map("textDocument", R
.textDocument
);
1253 bool fromJSON(const llvm::json::Value
&Params
, SemanticTokensDeltaParams
&R
,
1254 llvm::json::Path P
) {
1255 llvm::json::ObjectMapper
O(Params
, P
);
1256 return O
&& O
.map("textDocument", R
.textDocument
) &&
1257 O
.map("previousResultId", R
.previousResultId
);
1260 llvm::json::Value
toJSON(const InactiveRegionsParams
&InactiveRegions
) {
1261 return llvm::json::Object
{
1262 {"textDocument", InactiveRegions
.TextDocument
},
1263 {"regions", std::move(InactiveRegions
.InactiveRegions
)}};
1266 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
,
1267 const DocumentHighlight
&V
) {
1269 if (V
.kind
== DocumentHighlightKind::Read
)
1271 if (V
.kind
== DocumentHighlightKind::Write
)
1276 bool fromJSON(const llvm::json::Value
&Params
,
1277 DidChangeConfigurationParams
&CCP
, llvm::json::Path P
) {
1278 llvm::json::ObjectMapper
O(Params
, P
);
1279 return O
&& O
.map("settings", CCP
.settings
);
1282 bool fromJSON(const llvm::json::Value
&Params
, ClangdCompileCommand
&CDbUpdate
,
1283 llvm::json::Path P
) {
1284 llvm::json::ObjectMapper
O(Params
, P
);
1285 return O
&& O
.map("workingDirectory", CDbUpdate
.workingDirectory
) &&
1286 O
.map("compilationCommand", CDbUpdate
.compilationCommand
);
1289 bool fromJSON(const llvm::json::Value
&Params
, ConfigurationSettings
&S
,
1290 llvm::json::Path P
) {
1291 llvm::json::ObjectMapper
O(Params
, P
);
1293 return true; // 'any' type in LSP.
1294 return mapOptOrNull(Params
, "compilationDatabaseChanges",
1295 S
.compilationDatabaseChanges
, P
);
1298 bool fromJSON(const llvm::json::Value
&Params
, InitializationOptions
&Opts
,
1299 llvm::json::Path P
) {
1300 llvm::json::ObjectMapper
O(Params
, P
);
1302 return true; // 'any' type in LSP.
1304 return fromJSON(Params
, Opts
.ConfigSettings
, P
) &&
1305 O
.map("compilationDatabasePath", Opts
.compilationDatabasePath
) &&
1306 mapOptOrNull(Params
, "fallbackFlags", Opts
.fallbackFlags
, P
) &&
1307 mapOptOrNull(Params
, "clangdFileStatus", Opts
.FileStatus
, P
);
1310 bool fromJSON(const llvm::json::Value
&E
, TypeHierarchyDirection
&Out
,
1311 llvm::json::Path P
) {
1312 auto T
= E
.getAsInteger();
1315 if (*T
< static_cast<int>(TypeHierarchyDirection::Children
) ||
1316 *T
> static_cast<int>(TypeHierarchyDirection::Both
))
1318 Out
= static_cast<TypeHierarchyDirection
>(*T
);
1322 bool fromJSON(const llvm::json::Value
&Params
, TypeHierarchyPrepareParams
&R
,
1323 llvm::json::Path P
) {
1324 llvm::json::ObjectMapper
O(Params
, P
);
1325 return O
&& O
.map("textDocument", R
.textDocument
) &&
1326 O
.map("position", R
.position
) &&
1327 mapOptOrNull(Params
, "resolve", R
.resolve
, P
) &&
1328 mapOptOrNull(Params
, "direction", R
.direction
, P
);
1331 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&O
,
1332 const TypeHierarchyItem
&I
) {
1333 return O
<< I
.name
<< " - " << toJSON(I
);
1336 llvm::json::Value
toJSON(const TypeHierarchyItem::ResolveParams
&RP
) {
1337 llvm::json::Object Result
{{"symbolID", RP
.symbolID
}};
1339 Result
["parents"] = RP
.parents
;
1340 return std::move(Result
);
1342 bool fromJSON(const llvm::json::Value
&Params
,
1343 TypeHierarchyItem::ResolveParams
&RP
, llvm::json::Path P
) {
1344 llvm::json::ObjectMapper
O(Params
, P
);
1345 return O
&& O
.map("symbolID", RP
.symbolID
) &&
1346 mapOptOrNull(Params
, "parents", RP
.parents
, P
);
1349 llvm::json::Value
toJSON(const TypeHierarchyItem
&I
) {
1350 llvm::json::Object Result
{
1351 {"name", I
.name
}, {"kind", static_cast<int>(I
.kind
)},
1352 {"range", I
.range
}, {"selectionRange", I
.selectionRange
},
1353 {"uri", I
.uri
}, {"data", I
.data
},
1357 Result
["detail"] = I
.detail
;
1358 return std::move(Result
);
1361 bool fromJSON(const llvm::json::Value
&Params
, TypeHierarchyItem
&I
,
1362 llvm::json::Path P
) {
1363 llvm::json::ObjectMapper
O(Params
, P
);
1366 return O
&& O
.map("name", I
.name
) && O
.map("kind", I
.kind
) &&
1367 O
.map("uri", I
.uri
) && O
.map("range", I
.range
) &&
1368 O
.map("selectionRange", I
.selectionRange
) &&
1369 mapOptOrNull(Params
, "detail", I
.detail
, P
) &&
1370 mapOptOrNull(Params
, "deprecated", I
.deprecated
, P
) &&
1371 mapOptOrNull(Params
, "parents", I
.parents
, P
) &&
1372 mapOptOrNull(Params
, "children", I
.children
, P
) &&
1373 mapOptOrNull(Params
, "data", I
.data
, P
);
1376 bool fromJSON(const llvm::json::Value
&Params
,
1377 ResolveTypeHierarchyItemParams
&R
, llvm::json::Path P
) {
1378 llvm::json::ObjectMapper
O(Params
, P
);
1379 return O
&& O
.map("item", R
.item
) &&
1380 mapOptOrNull(Params
, "resolve", R
.resolve
, P
) &&
1381 mapOptOrNull(Params
, "direction", R
.direction
, P
);
1384 bool fromJSON(const llvm::json::Value
&Params
, ReferenceContext
&R
,
1385 llvm::json::Path P
) {
1386 llvm::json::ObjectMapper
O(Params
, P
);
1387 return O
&& O
.mapOptional("includeDeclaration", R
.includeDeclaration
);
1390 bool fromJSON(const llvm::json::Value
&Params
, ReferenceParams
&R
,
1391 llvm::json::Path P
) {
1392 TextDocumentPositionParams
&Base
= R
;
1393 llvm::json::ObjectMapper
O(Params
, P
);
1394 return fromJSON(Params
, Base
, P
) && O
&& O
.mapOptional("context", R
.context
);
1397 llvm::json::Value
toJSON(SymbolTag Tag
) {
1398 return llvm::json::Value
{static_cast<int>(Tag
)};
1401 llvm::json::Value
toJSON(const CallHierarchyItem
&I
) {
1402 llvm::json::Object Result
{{"name", I
.name
},
1403 {"kind", static_cast<int>(I
.kind
)},
1405 {"selectionRange", I
.selectionRange
},
1407 if (!I
.tags
.empty())
1408 Result
["tags"] = I
.tags
;
1409 if (!I
.detail
.empty())
1410 Result
["detail"] = I
.detail
;
1411 if (!I
.data
.empty())
1412 Result
["data"] = I
.data
;
1413 return std::move(Result
);
1416 bool fromJSON(const llvm::json::Value
&Params
, CallHierarchyItem
&I
,
1417 llvm::json::Path P
) {
1418 llvm::json::ObjectMapper
O(Params
, P
);
1420 // Populate the required fields only. We don't care about the
1421 // optional fields `Tags` and `Detail` for the purpose of
1422 // client --> server communication.
1423 return O
&& O
.map("name", I
.name
) && O
.map("kind", I
.kind
) &&
1424 O
.map("uri", I
.uri
) && O
.map("range", I
.range
) &&
1425 O
.map("selectionRange", I
.selectionRange
) &&
1426 mapOptOrNull(Params
, "data", I
.data
, P
);
1429 bool fromJSON(const llvm::json::Value
&Params
,
1430 CallHierarchyIncomingCallsParams
&C
, llvm::json::Path P
) {
1431 llvm::json::ObjectMapper
O(Params
, P
);
1432 return O
.map("item", C
.item
);
1435 llvm::json::Value
toJSON(const CallHierarchyIncomingCall
&C
) {
1436 return llvm::json::Object
{{"from", C
.from
}, {"fromRanges", C
.fromRanges
}};
1439 bool fromJSON(const llvm::json::Value
&Params
,
1440 CallHierarchyOutgoingCallsParams
&C
, llvm::json::Path P
) {
1441 llvm::json::ObjectMapper
O(Params
, P
);
1442 return O
.map("item", C
.item
);
1445 llvm::json::Value
toJSON(const CallHierarchyOutgoingCall
&C
) {
1446 return llvm::json::Object
{{"to", C
.to
}, {"fromRanges", C
.fromRanges
}};
1449 bool fromJSON(const llvm::json::Value
&Params
, InlayHintsParams
&R
,
1450 llvm::json::Path P
) {
1451 llvm::json::ObjectMapper
O(Params
, P
);
1452 return O
&& O
.map("textDocument", R
.textDocument
) && O
.map("range", R
.range
);
1455 llvm::json::Value
toJSON(const InlayHintKind
&Kind
) {
1457 case InlayHintKind::Type
:
1459 case InlayHintKind::Parameter
:
1461 case InlayHintKind::Designator
:
1462 case InlayHintKind::BlockEnd
:
1463 // This is an extension, don't serialize.
1466 llvm_unreachable("Unknown clang.clangd.InlayHintKind");
1469 llvm::json::Value
toJSON(const InlayHint
&H
) {
1470 llvm::json::Object Result
{{"position", H
.position
},
1472 {"paddingLeft", H
.paddingLeft
},
1473 {"paddingRight", H
.paddingRight
}};
1474 auto K
= toJSON(H
.kind
);
1476 Result
["kind"] = std::move(K
);
1477 return std::move(Result
);
1479 bool operator==(const InlayHint
&A
, const InlayHint
&B
) {
1480 return std::tie(A
.position
, A
.range
, A
.kind
, A
.label
) ==
1481 std::tie(B
.position
, B
.range
, B
.kind
, B
.label
);
1483 bool operator<(const InlayHint
&A
, const InlayHint
&B
) {
1484 return std::tie(A
.position
, A
.range
, A
.kind
, A
.label
) <
1485 std::tie(B
.position
, B
.range
, B
.kind
, B
.label
);
1488 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, InlayHintKind Kind
) {
1489 auto ToString
= [](InlayHintKind K
) {
1491 case InlayHintKind::Parameter
:
1493 case InlayHintKind::Type
:
1495 case InlayHintKind::Designator
:
1496 return "designator";
1497 case InlayHintKind::BlockEnd
:
1500 llvm_unreachable("Unknown clang.clangd.InlayHintKind");
1502 return OS
<< ToString(Kind
);
1505 static const char *toString(OffsetEncoding OE
) {
1507 case OffsetEncoding::UTF8
:
1509 case OffsetEncoding::UTF16
:
1511 case OffsetEncoding::UTF32
:
1513 case OffsetEncoding::UnsupportedEncoding
:
1516 llvm_unreachable("Unknown clang.clangd.OffsetEncoding");
1518 llvm::json::Value
toJSON(const OffsetEncoding
&OE
) { return toString(OE
); }
1519 bool fromJSON(const llvm::json::Value
&V
, OffsetEncoding
&OE
,
1520 llvm::json::Path P
) {
1521 auto Str
= V
.getAsString();
1524 OE
= llvm::StringSwitch
<OffsetEncoding
>(*Str
)
1525 .Case("utf-8", OffsetEncoding::UTF8
)
1526 .Case("utf-16", OffsetEncoding::UTF16
)
1527 .Case("utf-32", OffsetEncoding::UTF32
)
1528 .Default(OffsetEncoding::UnsupportedEncoding
);
1531 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, OffsetEncoding Enc
) {
1532 return OS
<< toString(Enc
);
1535 bool fromJSON(const llvm::json::Value
&Params
, SelectionRangeParams
&S
,
1536 llvm::json::Path P
) {
1537 llvm::json::ObjectMapper
O(Params
, P
);
1538 return O
&& O
.map("textDocument", S
.textDocument
) &&
1539 O
.map("positions", S
.positions
);
1542 llvm::json::Value
toJSON(const SelectionRange
&Out
) {
1544 return llvm::json::Object
{{"range", Out
.range
},
1545 {"parent", toJSON(*Out
.parent
)}};
1547 return llvm::json::Object
{{"range", Out
.range
}};
1550 bool fromJSON(const llvm::json::Value
&Params
, DocumentLinkParams
&R
,
1551 llvm::json::Path P
) {
1552 llvm::json::ObjectMapper
O(Params
, P
);
1553 return O
&& O
.map("textDocument", R
.textDocument
);
1556 llvm::json::Value
toJSON(const DocumentLink
&DocumentLink
) {
1557 return llvm::json::Object
{
1558 {"range", DocumentLink
.range
},
1559 {"target", DocumentLink
.target
},
1563 bool fromJSON(const llvm::json::Value
&Params
, FoldingRangeParams
&R
,
1564 llvm::json::Path P
) {
1565 llvm::json::ObjectMapper
O(Params
, P
);
1566 return O
&& O
.map("textDocument", R
.textDocument
);
1569 const llvm::StringLiteral
FoldingRange::REGION_KIND
= "region";
1570 const llvm::StringLiteral
FoldingRange::COMMENT_KIND
= "comment";
1571 const llvm::StringLiteral
FoldingRange::IMPORT_KIND
= "import";
1573 llvm::json::Value
toJSON(const FoldingRange
&Range
) {
1574 llvm::json::Object Result
{
1575 {"startLine", Range
.startLine
},
1576 {"endLine", Range
.endLine
},
1578 if (Range
.startCharacter
)
1579 Result
["startCharacter"] = Range
.startCharacter
;
1580 if (Range
.endCharacter
)
1581 Result
["endCharacter"] = Range
.endCharacter
;
1582 if (!Range
.kind
.empty())
1583 Result
["kind"] = Range
.kind
;
1587 llvm::json::Value
toJSON(const MemoryTree
&MT
) {
1588 llvm::json::Object Out
;
1589 int64_t Total
= MT
.self();
1590 Out
["_self"] = Total
;
1591 for (const auto &Entry
: MT
.children()) {
1592 auto Child
= toJSON(Entry
.getSecond());
1593 Total
+= *Child
.getAsObject()->getInteger("_total");
1594 Out
[Entry
.first
] = std::move(Child
);
1596 Out
["_total"] = Total
;
1600 bool fromJSON(const llvm::json::Value
&Params
, ASTParams
&R
,
1601 llvm::json::Path P
) {
1602 llvm::json::ObjectMapper
O(Params
, P
);
1603 return O
&& O
.map("textDocument", R
.textDocument
) && O
.map("range", R
.range
);
1606 llvm::json::Value
toJSON(const ASTNode
&N
) {
1607 llvm::json::Object Result
{
1611 if (!N
.children
.empty())
1612 Result
["children"] = N
.children
;
1613 if (!N
.detail
.empty())
1614 Result
["detail"] = N
.detail
;
1615 if (!N
.arcana
.empty())
1616 Result
["arcana"] = N
.arcana
;
1618 Result
["range"] = *N
.range
;
1622 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const ASTNode
&Root
) {
1623 std::function
<void(const ASTNode
&, unsigned)> Print
= [&](const ASTNode
&N
,
1625 OS
.indent(2 * Level
) << N
.role
<< ": " << N
.kind
;
1626 if (!N
.detail
.empty())
1627 OS
<< " - " << N
.detail
;
1629 for (const ASTNode
&C
: N
.children
)
1630 Print(C
, Level
+ 1);
1636 bool fromJSON(const llvm::json::Value
&E
, SymbolID
&S
, llvm::json::Path P
) {
1637 auto Str
= E
.getAsString();
1639 P
.report("expected a string");
1642 auto ID
= SymbolID::fromStr(*Str
);
1644 elog("Malformed symbolid: {0}", ID
.takeError());
1645 P
.report("malformed symbolid");
1651 llvm::json::Value
toJSON(const SymbolID
&S
) { return S
.str(); }
1653 } // namespace clangd
1654 } // namespace clang