llvm-project
1702 строки · 54.5 Кб
1//===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the serialization code for the LSP structs.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Protocol.h"14#include "URI.h"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"25
26namespace clang {27namespace clangd {28namespace {29
30// Helper that doesn't treat `null` and absent fields as failures.
31template <typename T>32bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop,33T &Out, llvm::json::Path P) {34auto *O = Params.getAsObject();35assert(O);36auto *V = O->get(Prop);37// Field is missing or null.38if (!V || V->getAsNull())39return true;40return fromJSON(*V, Out, P.field(Prop));41}
42} // namespace43
44char LSPError::ID;45
46URIForFile URIForFile::canonicalize(llvm::StringRef AbsPath,47llvm::StringRef TUPath) {48assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");49auto Resolved = URI::resolvePath(AbsPath, TUPath);50if (!Resolved) {51elog("URIForFile: failed to resolve path {0} with TU path {1}: "52"{2}.\nUsing unresolved path.",53AbsPath, TUPath, Resolved.takeError());54return URIForFile(std::string(AbsPath));55}56return URIForFile(std::move(*Resolved));57}
58
59llvm::Expected<URIForFile> URIForFile::fromURI(const URI &U,60llvm::StringRef HintPath) {61auto Resolved = URI::resolve(U, HintPath);62if (!Resolved)63return Resolved.takeError();64return URIForFile(std::move(*Resolved));65}
66
67bool fromJSON(const llvm::json::Value &E, URIForFile &R, llvm::json::Path P) {68if (auto S = E.getAsString()) {69auto Parsed = URI::parse(*S);70if (!Parsed) {71consumeError(Parsed.takeError());72P.report("failed to parse URI");73return false;74}75if (Parsed->scheme() != "file" && Parsed->scheme() != "test") {76P.report("clangd only supports 'file' URI scheme for workspace files");77return false;78}79// "file" and "test" schemes do not require hint path.80auto U = URIForFile::fromURI(*Parsed, /*HintPath=*/"");81if (!U) {82P.report("unresolvable URI");83consumeError(U.takeError());84return false;85}86R = std::move(*U);87return true;88}89return false;90}
91
92llvm::json::Value toJSON(const URIForFile &U) { return U.uri(); }93
94llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {95return OS << U.uri();96}
97
98llvm::json::Value toJSON(const TextDocumentIdentifier &R) {99return llvm::json::Object{{"uri", R.uri}};100}
101
102bool fromJSON(const llvm::json::Value &Params, TextDocumentIdentifier &R,103llvm::json::Path P) {104llvm::json::ObjectMapper O(Params, P);105return O && O.map("uri", R.uri);106}
107
108llvm::json::Value toJSON(const VersionedTextDocumentIdentifier &R) {109auto Result = toJSON(static_cast<const TextDocumentIdentifier &>(R));110Result.getAsObject()->try_emplace("version", R.version);111return Result;112}
113
114bool fromJSON(const llvm::json::Value &Params,115VersionedTextDocumentIdentifier &R, llvm::json::Path P) {116llvm::json::ObjectMapper O(Params, P);117return fromJSON(Params, static_cast<TextDocumentIdentifier &>(R), P) && O &&118O.map("version", R.version);119}
120
121bool fromJSON(const llvm::json::Value &Params, Position &R,122llvm::json::Path P) {123llvm::json::ObjectMapper O(Params, P);124return O && O.map("line", R.line) && O.map("character", R.character);125}
126
127llvm::json::Value toJSON(const Position &P) {128return llvm::json::Object{129{"line", P.line},130{"character", P.character},131};132}
133
134llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) {135return OS << P.line << ':' << P.character;136}
137
138bool fromJSON(const llvm::json::Value &Params, Range &R, llvm::json::Path P) {139llvm::json::ObjectMapper O(Params, P);140return O && O.map("start", R.start) && O.map("end", R.end);141}
142
143llvm::json::Value toJSON(const Range &P) {144return llvm::json::Object{145{"start", P.start},146{"end", P.end},147};148}
149
150llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) {151return OS << R.start << '-' << R.end;152}
153
154llvm::json::Value toJSON(const Location &P) {155return llvm::json::Object{156{"uri", P.uri},157{"range", P.range},158};159}
160
161llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) {162return OS << L.range << '@' << L.uri;163}
164
165llvm::json::Value toJSON(const ReferenceLocation &P) {166llvm::json::Object Result{167{"uri", P.uri},168{"range", P.range},169};170if (P.containerName)171Result.insert({"containerName", P.containerName});172return Result;173}
174
175llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,176const ReferenceLocation &L) {177return OS << L.range << '@' << L.uri << " (container: " << L.containerName178<< ")";179}
180
181bool fromJSON(const llvm::json::Value &Params, TextDocumentItem &R,182llvm::json::Path P) {183llvm::json::ObjectMapper O(Params, P);184return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&185O.map("version", R.version) && O.map("text", R.text);186}
187
188bool fromJSON(const llvm::json::Value &Params, TextEdit &R,189llvm::json::Path P) {190llvm::json::ObjectMapper O(Params, P);191return O && O.map("range", R.range) && O.map("newText", R.newText) &&192O.mapOptional("annotationId", R.annotationId);193}
194
195llvm::json::Value toJSON(const TextEdit &P) {196llvm::json::Object Result{197{"range", P.range},198{"newText", P.newText},199};200if (!P.annotationId.empty())201Result["annotationId"] = P.annotationId;202return Result;203}
204
205bool fromJSON(const llvm::json::Value &Params, ChangeAnnotation &R,206llvm::json::Path P) {207llvm::json::ObjectMapper O(Params, P);208return O && O.map("label", R.label) &&209O.map("needsConfirmation", R.needsConfirmation) &&210O.mapOptional("description", R.description);211}
212llvm::json::Value toJSON(const ChangeAnnotation & CA) {213llvm::json::Object Result{{"label", CA.label}};214if (CA.needsConfirmation)215Result["needsConfirmation"] = *CA.needsConfirmation;216if (!CA.description.empty())217Result["description"] = CA.description;218return Result;219}
220
221bool fromJSON(const llvm::json::Value &Params, TextDocumentEdit &R,222llvm::json::Path P) {223llvm::json::ObjectMapper O(Params, P);224return O && O.map("textDocument", R.textDocument) && O.map("edits", R.edits);225}
226llvm::json::Value toJSON(const TextDocumentEdit &P) {227llvm::json::Object Result{{"textDocument", P.textDocument},228{"edits", P.edits}};229return Result;230}
231
232llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) {233OS << TE.range << " => \"";234llvm::printEscapedString(TE.newText, OS);235return OS << '"';236}
237
238bool fromJSON(const llvm::json::Value &E, TraceLevel &Out, llvm::json::Path P) {239if (auto S = E.getAsString()) {240if (*S == "off") {241Out = TraceLevel::Off;242return true;243}244if (*S == "messages") {245Out = TraceLevel::Messages;246return true;247}248if (*S == "verbose") {249Out = TraceLevel::Verbose;250return true;251}252}253return false;254}
255
256bool fromJSON(const llvm::json::Value &E, SymbolKind &Out, llvm::json::Path P) {257if (auto T = E.getAsInteger()) {258if (*T < static_cast<int>(SymbolKind::File) ||259*T > static_cast<int>(SymbolKind::TypeParameter))260return false;261Out = static_cast<SymbolKind>(*T);262return true;263}264return false;265}
266
267bool fromJSON(const llvm::json::Value &E, SymbolKindBitset &Out,268llvm::json::Path P) {269if (auto *A = E.getAsArray()) {270for (size_t I = 0; I < A->size(); ++I) {271SymbolKind KindOut;272if (fromJSON((*A)[I], KindOut, P.index(I)))273Out.set(size_t(KindOut));274}275return true;276}277return false;278}
279
280SymbolKind adjustKindToCapability(SymbolKind Kind,281SymbolKindBitset &SupportedSymbolKinds) {282auto KindVal = static_cast<size_t>(Kind);283if (KindVal >= SymbolKindMin && KindVal <= SupportedSymbolKinds.size() &&284SupportedSymbolKinds[KindVal])285return Kind;286
287switch (Kind) {288// Provide some fall backs for common kinds that are close enough.289case SymbolKind::Struct:290return SymbolKind::Class;291case SymbolKind::EnumMember:292return SymbolKind::Enum;293default:294return SymbolKind::String;295}296}
297
298SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {299switch (Kind) {300case index::SymbolKind::Unknown:301return SymbolKind::Variable;302case index::SymbolKind::Module:303return SymbolKind::Module;304case index::SymbolKind::Namespace:305return SymbolKind::Namespace;306case index::SymbolKind::NamespaceAlias:307return SymbolKind::Namespace;308case index::SymbolKind::Macro:309return SymbolKind::String;310case index::SymbolKind::Enum:311return SymbolKind::Enum;312case index::SymbolKind::Struct:313return SymbolKind::Struct;314case index::SymbolKind::Class:315return SymbolKind::Class;316case index::SymbolKind::Protocol:317return SymbolKind::Interface;318case index::SymbolKind::Extension:319return SymbolKind::Interface;320case index::SymbolKind::Union:321return SymbolKind::Class;322case index::SymbolKind::TypeAlias:323return SymbolKind::Class;324case index::SymbolKind::Function:325return SymbolKind::Function;326case index::SymbolKind::Variable:327return SymbolKind::Variable;328case index::SymbolKind::Field:329return SymbolKind::Field;330case index::SymbolKind::EnumConstant:331return SymbolKind::EnumMember;332case index::SymbolKind::InstanceMethod:333case index::SymbolKind::ClassMethod:334case index::SymbolKind::StaticMethod:335return SymbolKind::Method;336case index::SymbolKind::InstanceProperty:337case index::SymbolKind::ClassProperty:338case index::SymbolKind::StaticProperty:339return SymbolKind::Property;340case index::SymbolKind::Constructor:341case index::SymbolKind::Destructor:342return SymbolKind::Constructor;343case index::SymbolKind::ConversionFunction:344return SymbolKind::Function;345case index::SymbolKind::Parameter:346case index::SymbolKind::NonTypeTemplateParm:347return SymbolKind::Variable;348case index::SymbolKind::Using:349return SymbolKind::Namespace;350case index::SymbolKind::TemplateTemplateParm:351case index::SymbolKind::TemplateTypeParm:352return SymbolKind::TypeParameter;353case index::SymbolKind::Concept:354return SymbolKind::Interface;355}356llvm_unreachable("invalid symbol kind");357}
358
359bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,360llvm::json::Path P) {361const llvm::json::Object *O = Params.getAsObject();362if (!O) {363P.report("expected object");364return false;365}366if (auto *TextDocument = O->getObject("textDocument")) {367if (auto *SemanticHighlighting =368TextDocument->getObject("semanticHighlightingCapabilities")) {369if (auto SemanticHighlightingSupport =370SemanticHighlighting->getBoolean("semanticHighlighting"))371R.TheiaSemanticHighlighting = *SemanticHighlightingSupport;372}373if (auto *InactiveRegions =374TextDocument->getObject("inactiveRegionsCapabilities")) {375if (auto InactiveRegionsSupport =376InactiveRegions->getBoolean("inactiveRegions")) {377R.InactiveRegions = *InactiveRegionsSupport;378}379}380if (TextDocument->getObject("semanticTokens"))381R.SemanticTokens = true;382if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {383if (auto CategorySupport = Diagnostics->getBoolean("categorySupport"))384R.DiagnosticCategory = *CategorySupport;385if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline"))386R.DiagnosticFixes = *CodeActions;387if (auto RelatedInfo = Diagnostics->getBoolean("relatedInformation"))388R.DiagnosticRelatedInformation = *RelatedInfo;389}390if (auto *References = TextDocument->getObject("references"))391if (auto ContainerSupport = References->getBoolean("container"))392R.ReferenceContainer = *ContainerSupport;393if (auto *Completion = TextDocument->getObject("completion")) {394if (auto *Item = Completion->getObject("completionItem")) {395if (auto SnippetSupport = Item->getBoolean("snippetSupport"))396R.CompletionSnippets = *SnippetSupport;397if (auto LabelDetailsSupport = Item->getBoolean("labelDetailsSupport"))398R.CompletionLabelDetail = *LabelDetailsSupport;399if (const auto *DocumentationFormat =400Item->getArray("documentationFormat")) {401for (const auto &Format : *DocumentationFormat) {402if (fromJSON(Format, R.CompletionDocumentationFormat, P))403break;404}405}406}407if (auto *ItemKind = Completion->getObject("completionItemKind")) {408if (auto *ValueSet = ItemKind->get("valueSet")) {409R.CompletionItemKinds.emplace();410if (!fromJSON(*ValueSet, *R.CompletionItemKinds,411P.field("textDocument")412.field("completion")413.field("completionItemKind")414.field("valueSet")))415return false;416}417}418if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor"))419R.CompletionFixes = *EditsNearCursor;420}421if (auto *CodeAction = TextDocument->getObject("codeAction")) {422if (CodeAction->getObject("codeActionLiteralSupport"))423R.CodeActionStructure = true;424}425if (auto *DocumentSymbol = TextDocument->getObject("documentSymbol")) {426if (auto HierarchicalSupport =427DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))428R.HierarchicalDocumentSymbol = *HierarchicalSupport;429}430if (auto *Hover = TextDocument->getObject("hover")) {431if (auto *ContentFormat = Hover->getArray("contentFormat")) {432for (const auto &Format : *ContentFormat) {433if (fromJSON(Format, R.HoverContentFormat, P))434break;435}436}437}438if (auto *Help = TextDocument->getObject("signatureHelp")) {439R.HasSignatureHelp = true;440if (auto *Info = Help->getObject("signatureInformation")) {441if (auto *Parameter = Info->getObject("parameterInformation")) {442if (auto OffsetSupport = Parameter->getBoolean("labelOffsetSupport"))443R.OffsetsInSignatureHelp = *OffsetSupport;444}445if (const auto *DocumentationFormat =446Info->getArray("documentationFormat")) {447for (const auto &Format : *DocumentationFormat) {448if (fromJSON(Format, R.SignatureHelpDocumentationFormat, P))449break;450}451}452}453}454if (auto *Folding = TextDocument->getObject("foldingRange")) {455if (auto LineFolding = Folding->getBoolean("lineFoldingOnly"))456R.LineFoldingOnly = *LineFolding;457}458if (auto *Rename = TextDocument->getObject("rename")) {459if (auto RenameSupport = Rename->getBoolean("prepareSupport"))460R.RenamePrepareSupport = *RenameSupport;461}462}463if (auto *Workspace = O->getObject("workspace")) {464if (auto *Symbol = Workspace->getObject("symbol")) {465if (auto *SymbolKind = Symbol->getObject("symbolKind")) {466if (auto *ValueSet = SymbolKind->get("valueSet")) {467R.WorkspaceSymbolKinds.emplace();468if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds,469P.field("workspace")470.field("symbol")471.field("symbolKind")472.field("valueSet")))473return false;474}475}476}477if (auto *SemanticTokens = Workspace->getObject("semanticTokens")) {478if (auto RefreshSupport = SemanticTokens->getBoolean("refreshSupport"))479R.SemanticTokenRefreshSupport = *RefreshSupport;480}481if (auto *WorkspaceEdit = Workspace->getObject("workspaceEdit")) {482if (auto DocumentChanges = WorkspaceEdit->getBoolean("documentChanges"))483R.DocumentChanges = *DocumentChanges;484if (WorkspaceEdit->getObject("changeAnnotationSupport")) {485R.ChangeAnnotation = true;486}487}488}489if (auto *Window = O->getObject("window")) {490if (auto WorkDoneProgress = Window->getBoolean("workDoneProgress"))491R.WorkDoneProgress = *WorkDoneProgress;492if (auto Implicit = Window->getBoolean("implicitWorkDoneProgressCreate"))493R.ImplicitProgressCreation = *Implicit;494}495if (auto *General = O->getObject("general")) {496if (auto *StaleRequestSupport = General->getObject("staleRequestSupport")) {497if (auto Cancel = StaleRequestSupport->getBoolean("cancel"))498R.CancelsStaleRequests = *Cancel;499}500}501if (auto *OffsetEncoding = O->get("offsetEncoding")) {502R.offsetEncoding.emplace();503if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,504P.field("offsetEncoding")))505return false;506}507return true;508}
509
510bool fromJSON(const llvm::json::Value &Params, InitializeParams &R,511llvm::json::Path P) {512llvm::json::ObjectMapper O(Params, P);513if (!O)514return false;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.517O.map("processId", R.processId);518O.map("rootUri", R.rootUri);519O.map("rootPath", R.rootPath);520O.map("capabilities", R.capabilities);521if (auto *RawCaps = Params.getAsObject()->getObject("capabilities"))522R.rawCapabilities = *RawCaps;523O.map("trace", R.trace);524O.map("initializationOptions", R.initializationOptions);525return true;526}
527
528llvm::json::Value toJSON(const WorkDoneProgressCreateParams &P) {529return llvm::json::Object{{"token", P.token}};530}
531
532llvm::json::Value toJSON(const WorkDoneProgressBegin &P) {533llvm::json::Object Result{534{"kind", "begin"},535{"title", P.title},536};537if (P.cancellable)538Result["cancellable"] = true;539if (P.percentage)540Result["percentage"] = 0;541
542// FIXME: workaround for older gcc/clang543return std::move(Result);544}
545
546llvm::json::Value toJSON(const WorkDoneProgressReport &P) {547llvm::json::Object Result{{"kind", "report"}};548if (P.cancellable)549Result["cancellable"] = *P.cancellable;550if (P.message)551Result["message"] = *P.message;552if (P.percentage)553Result["percentage"] = *P.percentage;554// FIXME: workaround for older gcc/clang555return std::move(Result);556}
557
558llvm::json::Value toJSON(const WorkDoneProgressEnd &P) {559llvm::json::Object Result{{"kind", "end"}};560if (P.message)561Result["message"] = *P.message;562// FIXME: workaround for older gcc/clang563return std::move(Result);564}
565
566llvm::json::Value toJSON(const MessageType &R) {567return static_cast<int64_t>(R);568}
569
570llvm::json::Value toJSON(const ShowMessageParams &R) {571return llvm::json::Object{{"type", R.type}, {"message", R.message}};572}
573
574bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R,575llvm::json::Path P) {576llvm::json::ObjectMapper O(Params, P);577return O && O.map("textDocument", R.textDocument);578}
579
580bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R,581llvm::json::Path P) {582llvm::json::ObjectMapper O(Params, P);583return O && O.map("textDocument", R.textDocument);584}
585
586bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R,587llvm::json::Path P) {588llvm::json::ObjectMapper O(Params, P);589return O && O.map("textDocument", R.textDocument);590}
591
592bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R,593llvm::json::Path P) {594llvm::json::ObjectMapper O(Params, P);595return O && O.map("textDocument", R.textDocument) &&596O.map("contentChanges", R.contentChanges) &&597O.map("wantDiagnostics", R.wantDiagnostics) &&598mapOptOrNull(Params, "forceRebuild", R.forceRebuild, P);599}
600
601bool fromJSON(const llvm::json::Value &E, FileChangeType &Out,602llvm::json::Path P) {603if (auto T = E.getAsInteger()) {604if (*T < static_cast<int>(FileChangeType::Created) ||605*T > static_cast<int>(FileChangeType::Deleted))606return false;607Out = static_cast<FileChangeType>(*T);608return true;609}610return false;611}
612
613bool fromJSON(const llvm::json::Value &Params, FileEvent &R,614llvm::json::Path P) {615llvm::json::ObjectMapper O(Params, P);616return O && O.map("uri", R.uri) && O.map("type", R.type);617}
618
619bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R,620llvm::json::Path P) {621llvm::json::ObjectMapper O(Params, P);622return O && O.map("changes", R.changes);623}
624
625bool fromJSON(const llvm::json::Value &Params,626TextDocumentContentChangeEvent &R, llvm::json::Path P) {627llvm::json::ObjectMapper O(Params, P);628return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&629O.map("text", R.text);630}
631
632bool fromJSON(const llvm::json::Value &Params, DocumentRangeFormattingParams &R,633llvm::json::Path P) {634llvm::json::ObjectMapper O(Params, P);635return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);636}
637
638bool fromJSON(const llvm::json::Value &Params,639DocumentOnTypeFormattingParams &R, llvm::json::Path P) {640llvm::json::ObjectMapper O(Params, P);641return O && O.map("textDocument", R.textDocument) &&642O.map("position", R.position) && O.map("ch", R.ch);643}
644
645bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R,646llvm::json::Path P) {647llvm::json::ObjectMapper O(Params, P);648return O && O.map("textDocument", R.textDocument);649}
650
651bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R,652llvm::json::Path P) {653llvm::json::ObjectMapper O(Params, P);654return O && O.map("textDocument", R.textDocument);655}
656
657llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) {658return llvm::json::Object{659{"location", DRI.location},660{"message", DRI.message},661};662}
663
664llvm::json::Value toJSON(DiagnosticTag Tag) { return static_cast<int>(Tag); }665
666llvm::json::Value toJSON(const CodeDescription &D) {667return llvm::json::Object{{"href", D.href}};668}
669
670llvm::json::Value toJSON(const Diagnostic &D) {671llvm::json::Object Diag{672{"range", D.range},673{"severity", D.severity},674{"message", D.message},675};676if (D.category)677Diag["category"] = *D.category;678if (D.codeActions)679Diag["codeActions"] = D.codeActions;680if (!D.code.empty())681Diag["code"] = D.code;682if (D.codeDescription)683Diag["codeDescription"] = *D.codeDescription;684if (!D.source.empty())685Diag["source"] = D.source;686if (D.relatedInformation)687Diag["relatedInformation"] = *D.relatedInformation;688if (!D.data.empty())689Diag["data"] = llvm::json::Object(D.data);690if (!D.tags.empty())691Diag["tags"] = llvm::json::Array{D.tags};692// FIXME: workaround for older gcc/clang693return std::move(Diag);694}
695
696bool fromJSON(const llvm::json::Value &Params, Diagnostic &R,697llvm::json::Path P) {698llvm::json::ObjectMapper O(Params, P);699if (!O)700return false;701if (auto *Data = Params.getAsObject()->getObject("data"))702R.data = *Data;703return O.map("range", R.range) && O.map("message", R.message) &&704mapOptOrNull(Params, "severity", R.severity, P) &&705mapOptOrNull(Params, "category", R.category, P) &&706mapOptOrNull(Params, "code", R.code, P) &&707mapOptOrNull(Params, "source", R.source, P);708}
709
710llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) {711llvm::json::Object Result{712{"uri", PDP.uri},713{"diagnostics", PDP.diagnostics},714};715if (PDP.version)716Result["version"] = PDP.version;717return std::move(Result);718}
719
720bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R,721llvm::json::Path P) {722llvm::json::ObjectMapper O(Params, P);723if (!O || !O.map("diagnostics", R.diagnostics))724return false;725O.map("only", R.only);726return true;727}
728
729llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {730OS << D.range << " [";731switch (D.severity) {732case 1:733OS << "error";734break;735case 2:736OS << "warning";737break;738case 3:739OS << "note";740break;741case 4:742OS << "remark";743break;744default:745OS << "diagnostic";746break;747}748return OS << '(' << D.severity << "): " << D.message << "]";749}
750
751bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R,752llvm::json::Path P) {753llvm::json::ObjectMapper O(Params, P);754return O && O.map("textDocument", R.textDocument) &&755O.map("range", R.range) && O.map("context", R.context);756}
757
758bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R,759llvm::json::Path P) {760llvm::json::ObjectMapper O(Params, P);761return O && O.map("changes", R.changes) &&762O.map("documentChanges", R.documentChanges) &&763O.mapOptional("changeAnnotations", R.changeAnnotations);764}
765
766bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R,767llvm::json::Path P) {768llvm::json::ObjectMapper O(Params, P);769if (!O || !O.map("command", R.command))770return false;771
772const auto *Args = Params.getAsObject()->get("arguments");773if (!Args)774return true; // Missing args is ok, argument is null.775const auto *ArgsArray = Args->getAsArray();776if (!ArgsArray) {777P.field("arguments").report("expected array");778return false;779}780if (ArgsArray->size() > 1) {781P.field("arguments").report("Command should have 0 or 1 argument");782return false;783}784if (ArgsArray->size() == 1) {785R.argument = ArgsArray->front();786}787return true;788}
789
790llvm::json::Value toJSON(const SymbolInformation &P) {791llvm::json::Object O{792{"name", P.name},793{"kind", static_cast<int>(P.kind)},794{"location", P.location},795{"containerName", P.containerName},796};797if (P.score)798O["score"] = *P.score;799return std::move(O);800}
801
802llvm::raw_ostream &operator<<(llvm::raw_ostream &O,803const SymbolInformation &SI) {804O << SI.containerName << "::" << SI.name << " - " << toJSON(SI);805return O;806}
807
808bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {809return LHS.name == RHS.name && LHS.containerName == RHS.containerName &&810LHS.USR == RHS.USR && LHS.ID == RHS.ID &&811LHS.declarationRange == RHS.declarationRange &&812LHS.definitionRange == RHS.definitionRange;813}
814
815llvm::json::Value toJSON(const SymbolDetails &P) {816llvm::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)}};820
821if (!P.name.empty())822Result["name"] = P.name;823
824if (!P.containerName.empty())825Result["containerName"] = P.containerName;826
827if (!P.USR.empty())828Result["usr"] = P.USR;829
830if (P.ID)831Result["id"] = P.ID.str();832
833if (P.declarationRange)834Result["declarationRange"] = *P.declarationRange;835
836if (P.definitionRange)837Result["definitionRange"] = *P.definitionRange;838
839// FIXME: workaround for older gcc/clang840return std::move(Result);841}
842
843llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {844if (!S.containerName.empty()) {845O << S.containerName;846llvm::StringRef ContNameRef;847if (!ContNameRef.ends_with("::")) {848O << " ";849}850}851O << S.name << " - " << toJSON(S);852return O;853}
854
855bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R,856llvm::json::Path P) {857llvm::json::ObjectMapper O(Params, P);858return O && O.map("query", R.query) &&859mapOptOrNull(Params, "limit", R.limit, P);860}
861
862llvm::json::Value toJSON(const Command &C) {863auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};864if (!C.argument.getAsNull())865Cmd["arguments"] = llvm::json::Array{C.argument};866return std::move(Cmd);867}
868
869const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";870const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor";871const llvm::StringLiteral CodeAction::INFO_KIND = "info";872
873llvm::json::Value toJSON(const CodeAction &CA) {874auto CodeAction = llvm::json::Object{{"title", CA.title}};875if (CA.kind)876CodeAction["kind"] = *CA.kind;877if (CA.diagnostics)878CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics);879if (CA.isPreferred)880CodeAction["isPreferred"] = true;881if (CA.edit)882CodeAction["edit"] = *CA.edit;883if (CA.command)884CodeAction["command"] = *CA.command;885return std::move(CodeAction);886}
887
888llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) {889return O << S.name << " - " << toJSON(S);890}
891
892llvm::json::Value toJSON(const DocumentSymbol &S) {893llvm::json::Object Result{{"name", S.name},894{"kind", static_cast<int>(S.kind)},895{"range", S.range},896{"selectionRange", S.selectionRange}};897
898if (!S.detail.empty())899Result["detail"] = S.detail;900if (!S.children.empty())901Result["children"] = S.children;902if (S.deprecated)903Result["deprecated"] = true;904// FIXME: workaround for older gcc/clang905return std::move(Result);906}
907
908llvm::json::Value toJSON(const WorkspaceEdit &WE) {909llvm::json::Object Result;910if (WE.changes) {911llvm::json::Object FileChanges;912for (auto &Change : *WE.changes)913FileChanges[Change.first] = llvm::json::Array(Change.second);914Result["changes"] = std::move(FileChanges);915}916if (WE.documentChanges)917Result["documentChanges"] = *WE.documentChanges;918if (!WE.changeAnnotations.empty()) {919llvm::json::Object ChangeAnnotations;920for (auto &Annotation : WE.changeAnnotations)921ChangeAnnotations[Annotation.first] = Annotation.second;922Result["changeAnnotations"] = std::move(ChangeAnnotations);923}924return Result;925}
926
927bool fromJSON(const llvm::json::Value &Params, TweakArgs &A,928llvm::json::Path P) {929llvm::json::ObjectMapper O(Params, P);930return O && O.map("file", A.file) && O.map("selection", A.selection) &&931O.map("tweakID", A.tweakID);932}
933
934llvm::json::Value toJSON(const TweakArgs &A) {935return llvm::json::Object{936{"tweakID", A.tweakID}, {"selection", A.selection}, {"file", A.file}};937}
938
939llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) {940return llvm::json::Object{{"edit", Params.edit}};941}
942
943bool fromJSON(const llvm::json::Value &Response, ApplyWorkspaceEditResponse &R,944llvm::json::Path P) {945llvm::json::ObjectMapper O(Response, P);946return O && O.map("applied", R.applied) &&947O.map("failureReason", R.failureReason);948}
949
950bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R,951llvm::json::Path P) {952llvm::json::ObjectMapper O(Params, P);953return O && O.map("textDocument", R.textDocument) &&954O.map("position", R.position);955}
956
957bool fromJSON(const llvm::json::Value &Params, CompletionContext &R,958llvm::json::Path P) {959llvm::json::ObjectMapper O(Params, P);960int TriggerKind;961if (!O || !O.map("triggerKind", TriggerKind) ||962!mapOptOrNull(Params, "triggerCharacter", R.triggerCharacter, P))963return false;964R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind);965return true;966}
967
968bool fromJSON(const llvm::json::Value &Params, CompletionParams &R,969llvm::json::Path P) {970if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R), P) ||971!mapOptOrNull(Params, "limit", R.limit, P))972return false;973if (auto *Context = Params.getAsObject()->get("context"))974return fromJSON(*Context, R.context, P.field("context"));975return true;976}
977
978static llvm::StringRef toTextKind(MarkupKind Kind) {979switch (Kind) {980case MarkupKind::PlainText:981return "plaintext";982case MarkupKind::Markdown:983return "markdown";984}985llvm_unreachable("Invalid MarkupKind");986}
987
988bool fromJSON(const llvm::json::Value &V, MarkupKind &K, llvm::json::Path P) {989auto Str = V.getAsString();990if (!Str) {991P.report("expected string");992return false;993}994if (*Str == "plaintext")995K = MarkupKind::PlainText;996else if (*Str == "markdown")997K = MarkupKind::Markdown;998else {999P.report("unknown markup kind");1000return false;1001}1002return true;1003}
1004
1005llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MarkupKind K) {1006return OS << toTextKind(K);1007}
1008
1009llvm::json::Value toJSON(const MarkupContent &MC) {1010if (MC.value.empty())1011return nullptr;1012
1013return llvm::json::Object{1014{"kind", toTextKind(MC.kind)},1015{"value", MC.value},1016};1017}
1018
1019llvm::json::Value toJSON(const Hover &H) {1020llvm::json::Object Result{{"contents", toJSON(H.contents)}};1021
1022if (H.range)1023Result["range"] = toJSON(*H.range);1024
1025return std::move(Result);1026}
1027
1028bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out,1029llvm::json::Path P) {1030if (auto T = E.getAsInteger()) {1031if (*T < static_cast<int>(CompletionItemKind::Text) ||1032*T > static_cast<int>(CompletionItemKind::TypeParameter))1033return false;1034Out = static_cast<CompletionItemKind>(*T);1035return true;1036}1037return false;1038}
1039
1040CompletionItemKind
1041adjustKindToCapability(CompletionItemKind Kind,1042CompletionItemKindBitset &SupportedCompletionItemKinds) {1043auto KindVal = static_cast<size_t>(Kind);1044if (KindVal >= CompletionItemKindMin &&1045KindVal <= SupportedCompletionItemKinds.size() &&1046SupportedCompletionItemKinds[KindVal])1047return Kind;1048
1049switch (Kind) {1050// Provide some fall backs for common kinds that are close enough.1051case CompletionItemKind::Folder:1052return CompletionItemKind::File;1053case CompletionItemKind::EnumMember:1054return CompletionItemKind::Enum;1055case CompletionItemKind::Struct:1056return CompletionItemKind::Class;1057default:1058return CompletionItemKind::Text;1059}1060}
1061
1062bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out,1063llvm::json::Path P) {1064if (auto *A = E.getAsArray()) {1065for (size_t I = 0; I < A->size(); ++I) {1066CompletionItemKind KindOut;1067if (fromJSON((*A)[I], KindOut, P.index(I)))1068Out.set(size_t(KindOut));1069}1070return true;1071}1072return false;1073}
1074
1075llvm::json::Value toJSON(const CompletionItemLabelDetails &CD) {1076llvm::json::Object Result;1077if (!CD.detail.empty())1078Result["detail"] = CD.detail;1079if (!CD.description.empty())1080Result["description"] = CD.description;1081return Result;1082}
1083
1084void removeCompletionLabelDetails(CompletionItem &C) {1085if (!C.labelDetails)1086return;1087if (!C.labelDetails->detail.empty())1088C.label += C.labelDetails->detail;1089if (!C.labelDetails->description.empty())1090C.label = C.labelDetails->description + C.label;1091C.labelDetails.reset();1092}
1093
1094llvm::json::Value toJSON(const CompletionItem &CI) {1095assert(!CI.label.empty() && "completion item label is required");1096llvm::json::Object Result{{"label", CI.label}};1097if (CI.kind != CompletionItemKind::Missing)1098Result["kind"] = static_cast<int>(CI.kind);1099if (!CI.detail.empty())1100Result["detail"] = CI.detail;1101if (CI.labelDetails)1102Result["labelDetails"] = *CI.labelDetails;1103if (CI.documentation)1104Result["documentation"] = CI.documentation;1105if (!CI.sortText.empty())1106Result["sortText"] = CI.sortText;1107if (!CI.filterText.empty())1108Result["filterText"] = CI.filterText;1109if (!CI.insertText.empty())1110Result["insertText"] = CI.insertText;1111if (CI.insertTextFormat != InsertTextFormat::Missing)1112Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);1113if (CI.textEdit)1114Result["textEdit"] = *CI.textEdit;1115if (!CI.additionalTextEdits.empty())1116Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits);1117if (CI.deprecated)1118Result["deprecated"] = CI.deprecated;1119Result["score"] = CI.score;1120return std::move(Result);1121}
1122
1123llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {1124O << I.label << " - " << toJSON(I);1125return O;1126}
1127
1128bool operator<(const CompletionItem &L, const CompletionItem &R) {1129return (L.sortText.empty() ? L.label : L.sortText) <1130(R.sortText.empty() ? R.label : R.sortText);1131}
1132
1133llvm::json::Value toJSON(const CompletionList &L) {1134return llvm::json::Object{1135{"isIncomplete", L.isIncomplete},1136{"items", llvm::json::Array(L.items)},1137};1138}
1139
1140llvm::json::Value toJSON(const ParameterInformation &PI) {1141assert((PI.labelOffsets || !PI.labelString.empty()) &&1142"parameter information label is required");1143llvm::json::Object Result;1144if (PI.labelOffsets)1145Result["label"] =1146llvm::json::Array({PI.labelOffsets->first, PI.labelOffsets->second});1147else1148Result["label"] = PI.labelString;1149if (!PI.documentation.empty())1150Result["documentation"] = PI.documentation;1151return std::move(Result);1152}
1153
1154llvm::json::Value toJSON(const SignatureInformation &SI) {1155assert(!SI.label.empty() && "signature information label is required");1156llvm::json::Object Result{1157{"label", SI.label},1158{"parameters", llvm::json::Array(SI.parameters)},1159};1160if (!SI.documentation.value.empty())1161Result["documentation"] = SI.documentation;1162return std::move(Result);1163}
1164
1165llvm::raw_ostream &operator<<(llvm::raw_ostream &O,1166const SignatureInformation &I) {1167O << I.label << " - " << toJSON(I);1168return O;1169}
1170
1171llvm::json::Value toJSON(const SignatureHelp &SH) {1172assert(SH.activeSignature >= 0 &&1173"Unexpected negative value for number of active signatures.");1174assert(SH.activeParameter >= 0 &&1175"Unexpected negative value for active parameter index");1176return llvm::json::Object{1177{"activeSignature", SH.activeSignature},1178{"activeParameter", SH.activeParameter},1179{"signatures", llvm::json::Array(SH.signatures)},1180};1181}
1182
1183bool fromJSON(const llvm::json::Value &Params, RenameParams &R,1184llvm::json::Path P) {1185llvm::json::ObjectMapper O(Params, P);1186return O && O.map("textDocument", R.textDocument) &&1187O.map("position", R.position) && O.map("newName", R.newName);1188}
1189
1190llvm::json::Value toJSON(const RenameParams &R) {1191return llvm::json::Object{1192{"textDocument", R.textDocument},1193{"position", R.position},1194{"newName", R.newName},1195};1196}
1197
1198llvm::json::Value toJSON(const PrepareRenameResult &PRR) {1199if (PRR.placeholder.empty())1200return toJSON(PRR.range);1201return llvm::json::Object{1202{"range", toJSON(PRR.range)},1203{"placeholder", PRR.placeholder},1204};1205}
1206
1207llvm::json::Value toJSON(const DocumentHighlight &DH) {1208return llvm::json::Object{1209{"range", toJSON(DH.range)},1210{"kind", static_cast<int>(DH.kind)},1211};1212}
1213
1214llvm::json::Value toJSON(const FileStatus &FStatus) {1215return llvm::json::Object{1216{"uri", FStatus.uri},1217{"state", FStatus.state},1218};1219}
1220
1221constexpr unsigned SemanticTokenEncodingSize = 5;1222static llvm::json::Value encodeTokens(llvm::ArrayRef<SemanticToken> Toks) {1223llvm::json::Array Result;1224Result.reserve(SemanticTokenEncodingSize * Toks.size());1225for (const auto &Tok : Toks) {1226Result.push_back(Tok.deltaLine);1227Result.push_back(Tok.deltaStart);1228Result.push_back(Tok.length);1229Result.push_back(Tok.tokenType);1230Result.push_back(Tok.tokenModifiers);1231}1232assert(Result.size() == SemanticTokenEncodingSize * Toks.size());1233return std::move(Result);1234}
1235
1236bool operator==(const SemanticToken &L, const SemanticToken &R) {1237return std::tie(L.deltaLine, L.deltaStart, L.length, L.tokenType,1238L.tokenModifiers) == std::tie(R.deltaLine, R.deltaStart,1239R.length, R.tokenType,1240R.tokenModifiers);1241}
1242
1243llvm::json::Value toJSON(const SemanticTokens &Tokens) {1244return llvm::json::Object{{"resultId", Tokens.resultId},1245{"data", encodeTokens(Tokens.tokens)}};1246}
1247
1248llvm::json::Value toJSON(const SemanticTokensEdit &Edit) {1249return llvm::json::Object{1250{"start", SemanticTokenEncodingSize * Edit.startToken},1251{"deleteCount", SemanticTokenEncodingSize * Edit.deleteTokens},1252{"data", encodeTokens(Edit.tokens)}};1253}
1254
1255llvm::json::Value toJSON(const SemanticTokensOrDelta &TE) {1256llvm::json::Object Result{{"resultId", TE.resultId}};1257if (TE.edits)1258Result["edits"] = *TE.edits;1259if (TE.tokens)1260Result["data"] = encodeTokens(*TE.tokens);1261return std::move(Result);1262}
1263
1264bool fromJSON(const llvm::json::Value &Params, SemanticTokensParams &R,1265llvm::json::Path P) {1266llvm::json::ObjectMapper O(Params, P);1267return O && O.map("textDocument", R.textDocument);1268}
1269
1270bool fromJSON(const llvm::json::Value &Params, SemanticTokensDeltaParams &R,1271llvm::json::Path P) {1272llvm::json::ObjectMapper O(Params, P);1273return O && O.map("textDocument", R.textDocument) &&1274O.map("previousResultId", R.previousResultId);1275}
1276
1277llvm::json::Value toJSON(const InactiveRegionsParams &InactiveRegions) {1278return llvm::json::Object{1279{"textDocument", InactiveRegions.TextDocument},1280{"regions", std::move(InactiveRegions.InactiveRegions)}};1281}
1282
1283llvm::raw_ostream &operator<<(llvm::raw_ostream &O,1284const DocumentHighlight &V) {1285O << V.range;1286if (V.kind == DocumentHighlightKind::Read)1287O << "(r)";1288if (V.kind == DocumentHighlightKind::Write)1289O << "(w)";1290return O;1291}
1292
1293bool fromJSON(const llvm::json::Value &Params,1294DidChangeConfigurationParams &CCP, llvm::json::Path P) {1295llvm::json::ObjectMapper O(Params, P);1296return O && O.map("settings", CCP.settings);1297}
1298
1299bool fromJSON(const llvm::json::Value &Params, ClangdCompileCommand &CDbUpdate,1300llvm::json::Path P) {1301llvm::json::ObjectMapper O(Params, P);1302return O && O.map("workingDirectory", CDbUpdate.workingDirectory) &&1303O.map("compilationCommand", CDbUpdate.compilationCommand);1304}
1305
1306bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S,1307llvm::json::Path P) {1308llvm::json::ObjectMapper O(Params, P);1309if (!O)1310return true; // 'any' type in LSP.1311return mapOptOrNull(Params, "compilationDatabaseChanges",1312S.compilationDatabaseChanges, P);1313}
1314
1315bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts,1316llvm::json::Path P) {1317llvm::json::ObjectMapper O(Params, P);1318if (!O)1319return true; // 'any' type in LSP.1320
1321return fromJSON(Params, Opts.ConfigSettings, P) &&1322O.map("compilationDatabasePath", Opts.compilationDatabasePath) &&1323mapOptOrNull(Params, "fallbackFlags", Opts.fallbackFlags, P) &&1324mapOptOrNull(Params, "clangdFileStatus", Opts.FileStatus, P);1325}
1326
1327bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out,1328llvm::json::Path P) {1329auto T = E.getAsInteger();1330if (!T)1331return false;1332if (*T < static_cast<int>(TypeHierarchyDirection::Children) ||1333*T > static_cast<int>(TypeHierarchyDirection::Both))1334return false;1335Out = static_cast<TypeHierarchyDirection>(*T);1336return true;1337}
1338
1339bool fromJSON(const llvm::json::Value &Params, TypeHierarchyPrepareParams &R,1340llvm::json::Path P) {1341llvm::json::ObjectMapper O(Params, P);1342return O && O.map("textDocument", R.textDocument) &&1343O.map("position", R.position) &&1344mapOptOrNull(Params, "resolve", R.resolve, P) &&1345mapOptOrNull(Params, "direction", R.direction, P);1346}
1347
1348llvm::raw_ostream &operator<<(llvm::raw_ostream &O,1349const TypeHierarchyItem &I) {1350return O << I.name << " - " << toJSON(I);1351}
1352
1353llvm::json::Value toJSON(const TypeHierarchyItem::ResolveParams &RP) {1354llvm::json::Object Result{{"symbolID", RP.symbolID}};1355if (RP.parents)1356Result["parents"] = RP.parents;1357return std::move(Result);1358}
1359bool fromJSON(const llvm::json::Value &Params,1360TypeHierarchyItem::ResolveParams &RP, llvm::json::Path P) {1361llvm::json::ObjectMapper O(Params, P);1362return O && O.map("symbolID", RP.symbolID) &&1363mapOptOrNull(Params, "parents", RP.parents, P);1364}
1365
1366llvm::json::Value toJSON(const TypeHierarchyItem &I) {1367llvm::json::Object Result{1368{"name", I.name}, {"kind", static_cast<int>(I.kind)},1369{"range", I.range}, {"selectionRange", I.selectionRange},1370{"uri", I.uri}, {"data", I.data},1371};1372
1373if (I.detail)1374Result["detail"] = I.detail;1375return std::move(Result);1376}
1377
1378bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I,1379llvm::json::Path P) {1380llvm::json::ObjectMapper O(Params, P);1381
1382// Required fields.1383return O && O.map("name", I.name) && O.map("kind", I.kind) &&1384O.map("uri", I.uri) && O.map("range", I.range) &&1385O.map("selectionRange", I.selectionRange) &&1386mapOptOrNull(Params, "detail", I.detail, P) &&1387mapOptOrNull(Params, "deprecated", I.deprecated, P) &&1388mapOptOrNull(Params, "parents", I.parents, P) &&1389mapOptOrNull(Params, "children", I.children, P) &&1390mapOptOrNull(Params, "data", I.data, P);1391}
1392
1393bool fromJSON(const llvm::json::Value &Params,1394ResolveTypeHierarchyItemParams &R, llvm::json::Path P) {1395llvm::json::ObjectMapper O(Params, P);1396return O && O.map("item", R.item) &&1397mapOptOrNull(Params, "resolve", R.resolve, P) &&1398mapOptOrNull(Params, "direction", R.direction, P);1399}
1400
1401bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R,1402llvm::json::Path P) {1403llvm::json::ObjectMapper O(Params, P);1404return O && O.mapOptional("includeDeclaration", R.includeDeclaration);1405}
1406
1407bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R,1408llvm::json::Path P) {1409TextDocumentPositionParams &Base = R;1410llvm::json::ObjectMapper O(Params, P);1411return fromJSON(Params, Base, P) && O && O.mapOptional("context", R.context);1412}
1413
1414llvm::json::Value toJSON(SymbolTag Tag) {1415return llvm::json::Value(static_cast<int>(Tag));1416}
1417
1418llvm::json::Value toJSON(const CallHierarchyItem &I) {1419llvm::json::Object Result{{"name", I.name},1420{"kind", static_cast<int>(I.kind)},1421{"range", I.range},1422{"selectionRange", I.selectionRange},1423{"uri", I.uri}};1424if (!I.tags.empty())1425Result["tags"] = I.tags;1426if (!I.detail.empty())1427Result["detail"] = I.detail;1428if (!I.data.empty())1429Result["data"] = I.data;1430return std::move(Result);1431}
1432
1433bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I,1434llvm::json::Path P) {1435llvm::json::ObjectMapper O(Params, P);1436
1437// Populate the required fields only. We don't care about the1438// optional fields `Tags` and `Detail` for the purpose of1439// client --> server communication.1440return O && O.map("name", I.name) && O.map("kind", I.kind) &&1441O.map("uri", I.uri) && O.map("range", I.range) &&1442O.map("selectionRange", I.selectionRange) &&1443mapOptOrNull(Params, "data", I.data, P);1444}
1445
1446bool fromJSON(const llvm::json::Value &Params,1447CallHierarchyIncomingCallsParams &C, llvm::json::Path P) {1448llvm::json::ObjectMapper O(Params, P);1449return O.map("item", C.item);1450}
1451
1452llvm::json::Value toJSON(const CallHierarchyIncomingCall &C) {1453return llvm::json::Object{{"from", C.from}, {"fromRanges", C.fromRanges}};1454}
1455
1456bool fromJSON(const llvm::json::Value &Params,1457CallHierarchyOutgoingCallsParams &C, llvm::json::Path P) {1458llvm::json::ObjectMapper O(Params, P);1459return O.map("item", C.item);1460}
1461
1462llvm::json::Value toJSON(const CallHierarchyOutgoingCall &C) {1463return llvm::json::Object{{"to", C.to}, {"fromRanges", C.fromRanges}};1464}
1465
1466bool fromJSON(const llvm::json::Value &Params, InlayHintsParams &R,1467llvm::json::Path P) {1468llvm::json::ObjectMapper O(Params, P);1469return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);1470}
1471
1472llvm::json::Value toJSON(const InlayHintKind &Kind) {1473switch (Kind) {1474case InlayHintKind::Type:1475return 1;1476case InlayHintKind::Parameter:1477return 2;1478case InlayHintKind::Designator:1479case InlayHintKind::BlockEnd:1480// This is an extension, don't serialize.1481return nullptr;1482}1483llvm_unreachable("Unknown clang.clangd.InlayHintKind");1484}
1485
1486llvm::json::Value toJSON(const InlayHint &H) {1487llvm::json::Object Result{{"position", H.position},1488{"label", H.label},1489{"paddingLeft", H.paddingLeft},1490{"paddingRight", H.paddingRight}};1491auto K = toJSON(H.kind);1492if (!K.getAsNull())1493Result["kind"] = std::move(K);1494return std::move(Result);1495}
1496bool operator==(const InlayHint &A, const InlayHint &B) {1497return std::tie(A.position, A.range, A.kind, A.label) ==1498std::tie(B.position, B.range, B.kind, B.label);1499}
1500bool operator<(const InlayHint &A, const InlayHint &B) {1501return std::tie(A.position, A.range, A.kind, A.label) <1502std::tie(B.position, B.range, B.kind, B.label);1503}
1504std::string InlayHint::joinLabels() const {1505return llvm::join(llvm::map_range(label, [](auto &L) { return L.value; }),1506"");1507}
1508
1509llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) {1510auto ToString = [](InlayHintKind K) {1511switch (K) {1512case InlayHintKind::Parameter:1513return "parameter";1514case InlayHintKind::Type:1515return "type";1516case InlayHintKind::Designator:1517return "designator";1518case InlayHintKind::BlockEnd:1519return "block-end";1520}1521llvm_unreachable("Unknown clang.clangd.InlayHintKind");1522};1523return OS << ToString(Kind);1524}
1525
1526llvm::json::Value toJSON(const InlayHintLabelPart &L) {1527llvm::json::Object Result{{"value", L.value}};1528if (L.tooltip)1529Result["tooltip"] = *L.tooltip;1530if (L.location)1531Result["location"] = *L.location;1532if (L.command)1533Result["command"] = *L.command;1534return Result;1535}
1536
1537bool operator==(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) {1538return std::tie(LHS.value, LHS.location) == std::tie(RHS.value, RHS.location);1539}
1540
1541bool operator<(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) {1542return std::tie(LHS.value, LHS.location) < std::tie(RHS.value, RHS.location);1543}
1544
1545llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,1546const InlayHintLabelPart &L) {1547OS << L.value;1548if (L.location)1549OS << " (" << L.location << ")";1550return OS;1551}
1552
1553static const char *toString(OffsetEncoding OE) {1554switch (OE) {1555case OffsetEncoding::UTF8:1556return "utf-8";1557case OffsetEncoding::UTF16:1558return "utf-16";1559case OffsetEncoding::UTF32:1560return "utf-32";1561case OffsetEncoding::UnsupportedEncoding:1562return "unknown";1563}1564llvm_unreachable("Unknown clang.clangd.OffsetEncoding");1565}
1566llvm::json::Value toJSON(const OffsetEncoding &OE) { return toString(OE); }1567bool fromJSON(const llvm::json::Value &V, OffsetEncoding &OE,1568llvm::json::Path P) {1569auto Str = V.getAsString();1570if (!Str)1571return false;1572OE = llvm::StringSwitch<OffsetEncoding>(*Str)1573.Case("utf-8", OffsetEncoding::UTF8)1574.Case("utf-16", OffsetEncoding::UTF16)1575.Case("utf-32", OffsetEncoding::UTF32)1576.Default(OffsetEncoding::UnsupportedEncoding);1577return true;1578}
1579llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) {1580return OS << toString(Enc);1581}
1582
1583bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &S,1584llvm::json::Path P) {1585llvm::json::ObjectMapper O(Params, P);1586return O && O.map("textDocument", S.textDocument) &&1587O.map("positions", S.positions);1588}
1589
1590llvm::json::Value toJSON(const SelectionRange &Out) {1591if (Out.parent) {1592return llvm::json::Object{{"range", Out.range},1593{"parent", toJSON(*Out.parent)}};1594}1595return llvm::json::Object{{"range", Out.range}};1596}
1597
1598bool fromJSON(const llvm::json::Value &Params, DocumentLinkParams &R,1599llvm::json::Path P) {1600llvm::json::ObjectMapper O(Params, P);1601return O && O.map("textDocument", R.textDocument);1602}
1603
1604llvm::json::Value toJSON(const DocumentLink &DocumentLink) {1605return llvm::json::Object{1606{"range", DocumentLink.range},1607{"target", DocumentLink.target},1608};1609}
1610
1611bool fromJSON(const llvm::json::Value &Params, FoldingRangeParams &R,1612llvm::json::Path P) {1613llvm::json::ObjectMapper O(Params, P);1614return O && O.map("textDocument", R.textDocument);1615}
1616
1617const llvm::StringLiteral FoldingRange::REGION_KIND = "region";1618const llvm::StringLiteral FoldingRange::COMMENT_KIND = "comment";1619const llvm::StringLiteral FoldingRange::IMPORT_KIND = "import";1620
1621llvm::json::Value toJSON(const FoldingRange &Range) {1622llvm::json::Object Result{1623{"startLine", Range.startLine},1624{"endLine", Range.endLine},1625};1626if (Range.startCharacter)1627Result["startCharacter"] = Range.startCharacter;1628if (Range.endCharacter)1629Result["endCharacter"] = Range.endCharacter;1630if (!Range.kind.empty())1631Result["kind"] = Range.kind;1632return Result;1633}
1634
1635llvm::json::Value toJSON(const MemoryTree &MT) {1636llvm::json::Object Out;1637int64_t Total = MT.self();1638Out["_self"] = Total;1639for (const auto &Entry : MT.children()) {1640auto Child = toJSON(Entry.getSecond());1641Total += *Child.getAsObject()->getInteger("_total");1642Out[Entry.first] = std::move(Child);1643}1644Out["_total"] = Total;1645return Out;1646}
1647
1648bool fromJSON(const llvm::json::Value &Params, ASTParams &R,1649llvm::json::Path P) {1650llvm::json::ObjectMapper O(Params, P);1651return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);1652}
1653
1654llvm::json::Value toJSON(const ASTNode &N) {1655llvm::json::Object Result{1656{"role", N.role},1657{"kind", N.kind},1658};1659if (!N.children.empty())1660Result["children"] = N.children;1661if (!N.detail.empty())1662Result["detail"] = N.detail;1663if (!N.arcana.empty())1664Result["arcana"] = N.arcana;1665if (N.range)1666Result["range"] = *N.range;1667return Result;1668}
1669
1670llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ASTNode &Root) {1671std::function<void(const ASTNode &, unsigned)> Print = [&](const ASTNode &N,1672unsigned Level) {1673OS.indent(2 * Level) << N.role << ": " << N.kind;1674if (!N.detail.empty())1675OS << " - " << N.detail;1676OS << "\n";1677for (const ASTNode &C : N.children)1678Print(C, Level + 1);1679};1680Print(Root, 0);1681return OS;1682}
1683
1684bool fromJSON(const llvm::json::Value &E, SymbolID &S, llvm::json::Path P) {1685auto Str = E.getAsString();1686if (!Str) {1687P.report("expected a string");1688return false;1689}1690auto ID = SymbolID::fromStr(*Str);1691if (!ID) {1692elog("Malformed symbolid: {0}", ID.takeError());1693P.report("malformed symbolid");1694return false;1695}1696S = *ID;1697return true;1698}
1699llvm::json::Value toJSON(const SymbolID &S) { return S.str(); }1700
1701} // namespace clangd1702} // namespace clang1703