blob: 1e71c2ab37f5e998d8da65cd9b97473b3f99e638 [file] [log] [blame]
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +00001//===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the serialization code for the LSP structs.
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000010//
11//===----------------------------------------------------------------------===//
12
13#include "Protocol.h"
Eric Liu78ed91a72018-01-29 15:37:46 +000014#include "Logger.h"
Ilya Biryukov7d60d202018-02-16 12:20:47 +000015#include "URI.h"
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000016#include "clang/Basic/LLVM.h"
Jan Korousb4067012018-11-27 16:40:46 +000017#include "llvm/ADT/Hashing.h"
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000018#include "llvm/ADT/SmallString.h"
Sam McCalla69698f2019-03-27 17:47:49 +000019#include "llvm/ADT/StringSwitch.h"
Kadir Cetinkayac6578ee2019-05-28 10:29:58 +000020#include "llvm/Support/ErrorHandling.h"
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000021#include "llvm/Support/Format.h"
Marc-Andre Laperle85dcce42017-09-18 15:02:59 +000022#include "llvm/Support/FormatVariadic.h"
Ilya Biryukov19d75602018-11-23 15:21:19 +000023#include "llvm/Support/JSON.h"
Krasimir Georgiev50117372017-04-07 11:03:26 +000024#include "llvm/Support/Path.h"
Ilya Biryukov574b7532017-08-02 09:08:39 +000025#include "llvm/Support/raw_ostream.h"
Ilya Biryukove5128f72017-09-20 07:24:15 +000026
Sam McCallff8b8742017-11-30 21:32:29 +000027namespace clang {
28namespace clangd {
Sam McCall38a04912017-11-29 11:36:46 +000029
Sam McCalldc8f3cf2018-10-17 07:32:05 +000030char LSPError::ID;
31
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000032URIForFile URIForFile::canonicalize(llvm::StringRef AbsPath,
33 llvm::StringRef TUPath) {
34 assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
Eric Liu4d814a92018-11-28 10:30:42 +000035 auto Resolved = URI::resolvePath(AbsPath, TUPath);
36 if (!Resolved) {
37 elog("URIForFile: failed to resolve path {0} with TU path {1}: "
38 "{2}.\nUsing unresolved path.",
39 AbsPath, TUPath, Resolved.takeError());
Benjamin Krameradcd0262020-01-28 20:23:46 +010040 return URIForFile(std::string(AbsPath));
Eric Liu4d814a92018-11-28 10:30:42 +000041 }
42 return URIForFile(std::move(*Resolved));
43}
44
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000045llvm::Expected<URIForFile> URIForFile::fromURI(const URI &U,
46 llvm::StringRef HintPath) {
Eric Liu4d814a92018-11-28 10:30:42 +000047 auto Resolved = URI::resolve(U, HintPath);
48 if (!Resolved)
49 return Resolved.takeError();
50 return URIForFile(std::move(*Resolved));
Ilya Biryukov7d60d202018-02-16 12:20:47 +000051}
52
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000053bool fromJSON(const llvm::json::Value &E, URIForFile &R) {
Sam McCalld20d7982018-07-09 14:25:59 +000054 if (auto S = E.getAsString()) {
Eric Liu4d814a92018-11-28 10:30:42 +000055 auto Parsed = URI::parse(*S);
56 if (!Parsed) {
57 elog("Failed to parse URI {0}: {1}", *S, Parsed.takeError());
Eric Liu78ed91a72018-01-29 15:37:46 +000058 return false;
59 }
Eric Liu4d814a92018-11-28 10:30:42 +000060 if (Parsed->scheme() != "file" && Parsed->scheme() != "test") {
Sam McCallbed58852018-07-11 10:35:11 +000061 elog("Clangd only supports 'file' URI scheme for workspace files: {0}",
62 *S);
Eric Liu78ed91a72018-01-29 15:37:46 +000063 return false;
64 }
Eric Liu4d814a92018-11-28 10:30:42 +000065 // "file" and "test" schemes do not require hint path.
66 auto U = URIForFile::fromURI(*Parsed, /*HintPath=*/"");
67 if (!U) {
68 elog("{0}", U.takeError());
Sam McCall41d21522018-01-30 11:23:11 +000069 return false;
70 }
Eric Liu4d814a92018-11-28 10:30:42 +000071 R = std::move(*U);
Sam McCallff8b8742017-11-30 21:32:29 +000072 return true;
73 }
74 return false;
Sam McCall38a04912017-11-29 11:36:46 +000075}
76
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000077llvm::json::Value toJSON(const URIForFile &U) { return U.uri(); }
Krasimir Georgiev50117372017-04-07 11:03:26 +000078
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000079llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {
Eric Liu78ed91a72018-01-29 15:37:46 +000080 return OS << U.uri();
Sam McCallfffa8222017-12-20 10:26:53 +000081}
82
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000083llvm::json::Value toJSON(const TextDocumentIdentifier &R) {
84 return llvm::json::Object{{"uri", R.uri}};
Eric Liuc5105f92018-02-16 14:15:55 +000085}
86
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000087bool fromJSON(const llvm::json::Value &Params, TextDocumentIdentifier &R) {
88 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +000089 return O && O.map("uri", R.uri);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000090}
91
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000092bool fromJSON(const llvm::json::Value &Params, Position &R) {
93 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +000094 return O && O.map("line", R.line) && O.map("character", R.character);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000095}
96
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000097llvm::json::Value toJSON(const Position &P) {
98 return llvm::json::Object{
Sam McCalldd0566b2017-11-06 15:40:30 +000099 {"line", P.line},
100 {"character", P.character},
101 };
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000102}
103
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000104llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) {
Sam McCallfffa8222017-12-20 10:26:53 +0000105 return OS << P.line << ':' << P.character;
106}
107
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000108bool fromJSON(const llvm::json::Value &Params, Range &R) {
109 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000110 return O && O.map("start", R.start) && O.map("end", R.end);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000111}
112
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000113llvm::json::Value toJSON(const Range &P) {
114 return llvm::json::Object{
Sam McCalldd0566b2017-11-06 15:40:30 +0000115 {"start", P.start},
116 {"end", P.end},
117 };
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000118}
119
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000120llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) {
Sam McCallfffa8222017-12-20 10:26:53 +0000121 return OS << R.start << '-' << R.end;
122}
123
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000124llvm::json::Value toJSON(const Location &P) {
125 return llvm::json::Object{
Sam McCalldd0566b2017-11-06 15:40:30 +0000126 {"uri", P.uri},
127 {"range", P.range},
128 };
Marc-Andre Laperle2cbf0372017-06-28 16:12:10 +0000129}
130
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000131llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) {
Sam McCallfffa8222017-12-20 10:26:53 +0000132 return OS << L.range << '@' << L.uri;
133}
134
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000135bool fromJSON(const llvm::json::Value &Params, TextDocumentItem &R) {
136 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000137 return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&
138 O.map("version", R.version) && O.map("text", R.text);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000139}
140
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000141bool fromJSON(const llvm::json::Value &Params, TextEdit &R) {
142 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000143 return O && O.map("range", R.range) && O.map("newText", R.newText);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000144}
145
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000146llvm::json::Value toJSON(const TextEdit &P) {
147 return llvm::json::Object{
Sam McCalldd0566b2017-11-06 15:40:30 +0000148 {"range", P.range},
149 {"newText", P.newText},
150 };
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000151}
152
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000153llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) {
Sam McCall034e11a2018-01-25 17:29:17 +0000154 OS << TE.range << " => \"";
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000155 llvm::printEscapedString(TE.newText, OS);
Sam McCall034e11a2018-01-25 17:29:17 +0000156 return OS << '"';
157}
158
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000159bool fromJSON(const llvm::json::Value &E, TraceLevel &Out) {
Sam McCalld20d7982018-07-09 14:25:59 +0000160 if (auto S = E.getAsString()) {
Sam McCallff8b8742017-11-30 21:32:29 +0000161 if (*S == "off") {
162 Out = TraceLevel::Off;
163 return true;
164 } else if (*S == "messages") {
165 Out = TraceLevel::Messages;
166 return true;
167 } else if (*S == "verbose") {
168 Out = TraceLevel::Verbose;
169 return true;
170 }
171 }
172 return false;
173}
174
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000175bool fromJSON(const llvm::json::Value &E, SymbolKind &Out) {
Sam McCalld20d7982018-07-09 14:25:59 +0000176 if (auto T = E.getAsInteger()) {
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000177 if (*T < static_cast<int>(SymbolKind::File) ||
178 *T > static_cast<int>(SymbolKind::TypeParameter))
179 return false;
180 Out = static_cast<SymbolKind>(*T);
181 return true;
182 }
183 return false;
184}
185
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000186bool fromJSON(const llvm::json::Value &E, SymbolKindBitset &Out) {
Sam McCalld20d7982018-07-09 14:25:59 +0000187 if (auto *A = E.getAsArray()) {
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000188 for (size_t I = 0; I < A->size(); ++I) {
189 SymbolKind KindOut;
190 if (fromJSON((*A)[I], KindOut))
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000191 Out.set(size_t(KindOut));
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000192 }
193 return true;
194 }
195 return false;
196}
197
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000198SymbolKind adjustKindToCapability(SymbolKind Kind,
Ilya Biryukov74f26552018-07-26 12:05:31 +0000199 SymbolKindBitset &SupportedSymbolKinds) {
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000200 auto KindVal = static_cast<size_t>(Kind);
Ilya Biryukov74f26552018-07-26 12:05:31 +0000201 if (KindVal >= SymbolKindMin && KindVal <= SupportedSymbolKinds.size() &&
202 SupportedSymbolKinds[KindVal])
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000203 return Kind;
204
205 switch (Kind) {
206 // Provide some fall backs for common kinds that are close enough.
207 case SymbolKind::Struct:
208 return SymbolKind::Class;
209 case SymbolKind::EnumMember:
210 return SymbolKind::Enum;
211 default:
212 return SymbolKind::String;
213 }
214}
215
Kadir Cetinkaya86658022019-03-19 09:27:04 +0000216SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
217 switch (Kind) {
218 case index::SymbolKind::Unknown:
219 return SymbolKind::Variable;
220 case index::SymbolKind::Module:
221 return SymbolKind::Module;
222 case index::SymbolKind::Namespace:
223 return SymbolKind::Namespace;
224 case index::SymbolKind::NamespaceAlias:
225 return SymbolKind::Namespace;
226 case index::SymbolKind::Macro:
227 return SymbolKind::String;
228 case index::SymbolKind::Enum:
229 return SymbolKind::Enum;
230 case index::SymbolKind::Struct:
231 return SymbolKind::Struct;
232 case index::SymbolKind::Class:
233 return SymbolKind::Class;
234 case index::SymbolKind::Protocol:
235 return SymbolKind::Interface;
236 case index::SymbolKind::Extension:
237 return SymbolKind::Interface;
238 case index::SymbolKind::Union:
239 return SymbolKind::Class;
240 case index::SymbolKind::TypeAlias:
241 return SymbolKind::Class;
242 case index::SymbolKind::Function:
243 return SymbolKind::Function;
244 case index::SymbolKind::Variable:
245 return SymbolKind::Variable;
246 case index::SymbolKind::Field:
247 return SymbolKind::Field;
248 case index::SymbolKind::EnumConstant:
249 return SymbolKind::EnumMember;
250 case index::SymbolKind::InstanceMethod:
251 case index::SymbolKind::ClassMethod:
252 case index::SymbolKind::StaticMethod:
253 return SymbolKind::Method;
254 case index::SymbolKind::InstanceProperty:
255 case index::SymbolKind::ClassProperty:
256 case index::SymbolKind::StaticProperty:
257 return SymbolKind::Property;
258 case index::SymbolKind::Constructor:
259 case index::SymbolKind::Destructor:
Sam McCallc9081962019-11-15 15:46:17 +0100260 return SymbolKind::Constructor;
Kadir Cetinkaya86658022019-03-19 09:27:04 +0000261 case index::SymbolKind::ConversionFunction:
262 return SymbolKind::Function;
263 case index::SymbolKind::Parameter:
264 return SymbolKind::Variable;
265 case index::SymbolKind::Using:
266 return SymbolKind::Namespace;
267 }
268 llvm_unreachable("invalid symbol kind");
269}
270
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000271bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R) {
272 const llvm::json::Object *O = Params.getAsObject();
Ilya Biryukov23bc73b2018-02-15 14:32:57 +0000273 if (!O)
274 return false;
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000275 if (auto *TextDocument = O->getObject("textDocument")) {
Johan Vikstroma848dab2019-07-04 07:53:12 +0000276 if (auto *SemanticHighlighting =
277 TextDocument->getObject("semanticHighlightingCapabilities")) {
278 if (auto SemanticHighlightingSupport =
279 SemanticHighlighting->getBoolean("semanticHighlighting"))
280 R.SemanticHighlighting = *SemanticHighlightingSupport;
281 }
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000282 if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {
283 if (auto CategorySupport = Diagnostics->getBoolean("categorySupport"))
284 R.DiagnosticCategory = *CategorySupport;
Sam McCall16e70702018-10-24 07:59:38 +0000285 if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline"))
286 R.DiagnosticFixes = *CodeActions;
Sam McCallc9e4ee92019-04-18 15:17:07 +0000287 if (auto RelatedInfo = Diagnostics->getBoolean("relatedInformation"))
288 R.DiagnosticRelatedInformation = *RelatedInfo;
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000289 }
290 if (auto *Completion = TextDocument->getObject("completion")) {
291 if (auto *Item = Completion->getObject("completionItem")) {
292 if (auto SnippetSupport = Item->getBoolean("snippetSupport"))
293 R.CompletionSnippets = *SnippetSupport;
294 }
295 if (auto *ItemKind = Completion->getObject("completionItemKind")) {
296 if (auto *ValueSet = ItemKind->get("valueSet")) {
297 R.CompletionItemKinds.emplace();
298 if (!fromJSON(*ValueSet, *R.CompletionItemKinds))
299 return false;
300 }
301 }
Sam McCall8d412942019-06-18 11:57:26 +0000302 if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor"))
303 R.CompletionFixes = *EditsNearCursor;
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000304 }
305 if (auto *CodeAction = TextDocument->getObject("codeAction")) {
306 if (CodeAction->getObject("codeActionLiteralSupport"))
307 R.CodeActionStructure = true;
308 }
Ilya Biryukov19d75602018-11-23 15:21:19 +0000309 if (auto *DocumentSymbol = TextDocument->getObject("documentSymbol")) {
310 if (auto HierarchicalSupport =
311 DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
312 R.HierarchicalDocumentSymbol = *HierarchicalSupport;
313 }
Ilya Biryukovf9169d02019-05-29 10:01:00 +0000314 if (auto *Hover = TextDocument->getObject("hover")) {
315 if (auto *ContentFormat = Hover->getArray("contentFormat")) {
316 for (const auto &Format : *ContentFormat) {
317 MarkupKind K = MarkupKind::PlainText;
318 if (fromJSON(Format, K)) {
319 R.HoverContentFormat = K;
320 break;
321 }
322 }
323 }
324 }
Ilya Biryukov4ef0f822019-06-04 09:36:59 +0000325 if (auto *Help = TextDocument->getObject("signatureHelp")) {
Sam McCall5f092e32019-07-08 17:27:15 +0000326 R.HasSignatureHelp = true;
Ilya Biryukov4ef0f822019-06-04 09:36:59 +0000327 if (auto *Info = Help->getObject("signatureInformation")) {
328 if (auto *Parameter = Info->getObject("parameterInformation")) {
329 if (auto OffsetSupport = Parameter->getBoolean("labelOffsetSupport"))
330 R.OffsetsInSignatureHelp = *OffsetSupport;
331 }
332 }
333 }
Haojian Wuf429ab62019-07-24 07:49:23 +0000334 if (auto *Rename = TextDocument->getObject("rename")) {
335 if (auto RenameSupport = Rename->getBoolean("prepareSupport"))
336 R.RenamePrepareSupport = *RenameSupport;
337 }
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000338 }
339 if (auto *Workspace = O->getObject("workspace")) {
340 if (auto *Symbol = Workspace->getObject("symbol")) {
341 if (auto *SymbolKind = Symbol->getObject("symbolKind")) {
342 if (auto *ValueSet = SymbolKind->get("valueSet")) {
343 R.WorkspaceSymbolKinds.emplace();
344 if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds))
345 return false;
346 }
347 }
348 }
349 }
Sam McCall7d20e802020-01-22 19:41:45 +0100350 if (auto *Window = O->getObject("window")) {
351 if (auto WorkDoneProgress = Window->getBoolean("workDoneProgress"))
352 R.WorkDoneProgress = *WorkDoneProgress;
353 if (auto Implicit = Window->getBoolean("implicitWorkDoneProgressCreate"))
354 R.ImplicitProgressCreation = *Implicit;
355 }
Sam McCalla69698f2019-03-27 17:47:49 +0000356 if (auto *OffsetEncoding = O->get("offsetEncoding")) {
357 R.offsetEncoding.emplace();
358 if (!fromJSON(*OffsetEncoding, *R.offsetEncoding))
359 return false;
360 }
Ilya Biryukov23bc73b2018-02-15 14:32:57 +0000361 return true;
362}
363
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000364bool fromJSON(const llvm::json::Value &Params, InitializeParams &R) {
365 llvm::json::ObjectMapper O(Params);
Sam McCallec109022017-11-28 09:37:43 +0000366 if (!O)
Sam McCallff8b8742017-11-30 21:32:29 +0000367 return false;
Sam McCall38a04912017-11-29 11:36:46 +0000368 // We deliberately don't fail if we can't parse individual fields.
369 // Failing to handle a slightly malformed initialize would be a disaster.
Sam McCallff8b8742017-11-30 21:32:29 +0000370 O.map("processId", R.processId);
371 O.map("rootUri", R.rootUri);
372 O.map("rootPath", R.rootPath);
Ilya Biryukov23bc73b2018-02-15 14:32:57 +0000373 O.map("capabilities", R.capabilities);
Sam McCallff8b8742017-11-30 21:32:29 +0000374 O.map("trace", R.trace);
Simon Marchi88016782018-08-01 11:28:49 +0000375 O.map("initializationOptions", R.initializationOptions);
Sam McCallff8b8742017-11-30 21:32:29 +0000376 return true;
Marc-Andre Laperle37de9712017-09-27 15:31:17 +0000377}
378
Sam McCall7d20e802020-01-22 19:41:45 +0100379llvm::json::Value toJSON(const WorkDoneProgressCreateParams &P) {
380 return llvm::json::Object{{"token", P.token}};
381}
382
383llvm::json::Value toJSON(const WorkDoneProgressBegin &P) {
384 llvm::json::Object Result{
385 {"kind", "begin"},
386 {"title", P.title},
387 };
388 if (P.cancellable)
389 Result["cancellable"] = true;
390 if (P.percentage)
391 Result["percentage"] = 0;
392 return Result;
393}
394
395llvm::json::Value toJSON(const WorkDoneProgressReport &P) {
396 llvm::json::Object Result{{"kind", "report"}};
397 if (P.cancellable)
398 Result["cancellable"] = *P.cancellable;
399 if (P.message)
400 Result["message"] = *P.message;
401 if (P.percentage)
402 Result["percentage"] = *P.percentage;
403 return Result;
404}
405
406llvm::json::Value toJSON(const WorkDoneProgressEnd &P) {
407 llvm::json::Object Result{{"kind", "end"}};
408 if (P.message)
409 Result["message"] = *P.message;
410 return Result;
411}
412
Sam McCall395fde72019-06-18 13:37:54 +0000413llvm::json::Value toJSON(const MessageType &R) {
414 return static_cast<int64_t>(R);
415}
416
417llvm::json::Value toJSON(const ShowMessageParams &R) {
418 return llvm::json::Object{{"type", R.type}, {"message", R.message}};
419}
420
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000421bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R) {
422 llvm::json::ObjectMapper O(Params);
Sam McCall2eb6b402018-11-02 13:06:55 +0000423 return O && O.map("textDocument", R.textDocument);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000424}
425
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000426bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R) {
427 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000428 return O && O.map("textDocument", R.textDocument);
Krasimir Georgiev561ba5e2017-04-10 13:31:39 +0000429}
430
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000431bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R) {
432 llvm::json::ObjectMapper O(Params);
David Goldman6ff02282020-02-03 15:14:49 -0500433 if (!O)
434 return false;
435 O.map("forceRebuild", R.forceRebuild); // Optional clangd extension.
436 return O.map("textDocument", R.textDocument) &&
Eric Liu51fed182018-02-22 18:40:39 +0000437 O.map("contentChanges", R.contentChanges) &&
438 O.map("wantDiagnostics", R.wantDiagnostics);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000439}
440
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000441bool fromJSON(const llvm::json::Value &E, FileChangeType &Out) {
Sam McCalld20d7982018-07-09 14:25:59 +0000442 if (auto T = E.getAsInteger()) {
Sam McCallff8b8742017-11-30 21:32:29 +0000443 if (*T < static_cast<int>(FileChangeType::Created) ||
444 *T > static_cast<int>(FileChangeType::Deleted))
445 return false;
446 Out = static_cast<FileChangeType>(*T);
447 return true;
448 }
449 return false;
Marc-Andre Laperlebf114242017-10-02 18:00:37 +0000450}
451
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000452bool fromJSON(const llvm::json::Value &Params, FileEvent &R) {
453 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000454 return O && O.map("uri", R.uri) && O.map("type", R.type);
Marc-Andre Laperlebf114242017-10-02 18:00:37 +0000455}
456
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000457bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R) {
458 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000459 return O && O.map("changes", R.changes);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000460}
461
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000462bool fromJSON(const llvm::json::Value &Params,
463 TextDocumentContentChangeEvent &R) {
464 llvm::json::ObjectMapper O(Params);
Simon Marchi98082622018-03-26 14:41:40 +0000465 return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&
466 O.map("text", R.text);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000467}
468
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000469bool fromJSON(const llvm::json::Value &Params,
470 DocumentRangeFormattingParams &R) {
471 llvm::json::ObjectMapper O(Params);
Nathan Ridge087b0442019-07-13 03:24:48 +0000472 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000473}
474
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000475bool fromJSON(const llvm::json::Value &Params,
476 DocumentOnTypeFormattingParams &R) {
477 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000478 return O && O.map("textDocument", R.textDocument) &&
Sam McCall149786d2019-06-10 13:01:49 +0000479 O.map("position", R.position) && O.map("ch", R.ch);
Krasimir Georgiev1b8bfd42017-02-16 10:49:46 +0000480}
481
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000482bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R) {
483 llvm::json::ObjectMapper O(Params);
Sam McCall149786d2019-06-10 13:01:49 +0000484 return O && O.map("textDocument", R.textDocument);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000485}
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000486
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000487bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R) {
488 llvm::json::ObjectMapper O(Params);
Marc-Andre Laperle1be69702018-07-05 19:35:01 +0000489 return O && O.map("textDocument", R.textDocument);
490}
491
Sam McCallc9e4ee92019-04-18 15:17:07 +0000492llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) {
493 return llvm::json::Object{
Nathan Ridge087b0442019-07-13 03:24:48 +0000494 {"location", DRI.location},
495 {"message", DRI.message},
Sam McCallc9e4ee92019-04-18 15:17:07 +0000496 };
497}
498
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000499llvm::json::Value toJSON(const Diagnostic &D) {
500 llvm::json::Object Diag{
Sam McCall20841d42018-10-16 16:29:41 +0000501 {"range", D.range},
502 {"severity", D.severity},
503 {"message", D.message},
504 };
Sam McCall16e70702018-10-24 07:59:38 +0000505 if (D.category)
506 Diag["category"] = *D.category;
507 if (D.codeActions)
508 Diag["codeActions"] = D.codeActions;
Sam McCall641caa52019-04-17 12:35:16 +0000509 if (!D.code.empty())
510 Diag["code"] = D.code;
511 if (!D.source.empty())
512 Diag["source"] = D.source;
Sam McCallc9e4ee92019-04-18 15:17:07 +0000513 if (D.relatedInformation)
514 Diag["relatedInformation"] = *D.relatedInformation;
Sam McCall20841d42018-10-16 16:29:41 +0000515 return std::move(Diag);
516}
517
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000518bool fromJSON(const llvm::json::Value &Params, Diagnostic &R) {
519 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000520 if (!O || !O.map("range", R.range) || !O.map("message", R.message))
521 return false;
522 O.map("severity", R.severity);
Sam McCall16e70702018-10-24 07:59:38 +0000523 O.map("category", R.category);
Sam McCall641caa52019-04-17 12:35:16 +0000524 O.map("code", R.code);
525 O.map("source", R.source);
Sam McCallff8b8742017-11-30 21:32:29 +0000526 return true;
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000527}
528
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000529bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R) {
530 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000531 return O && O.map("diagnostics", R.diagnostics);
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000532}
533
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000534llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {
Sam McCall034e11a2018-01-25 17:29:17 +0000535 OS << D.range << " [";
536 switch (D.severity) {
Ilya Biryukov22fa4652019-01-03 13:28:05 +0000537 case 1:
538 OS << "error";
539 break;
540 case 2:
541 OS << "warning";
542 break;
543 case 3:
544 OS << "note";
545 break;
546 case 4:
547 OS << "remark";
548 break;
549 default:
550 OS << "diagnostic";
551 break;
Sam McCall034e11a2018-01-25 17:29:17 +0000552 }
553 return OS << '(' << D.severity << "): " << D.message << "]";
554}
555
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000556bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R) {
557 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000558 return O && O.map("textDocument", R.textDocument) &&
559 O.map("range", R.range) && O.map("context", R.context);
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000560}
561
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000562bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R) {
563 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000564 return O && O.map("changes", R.changes);
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000565}
566
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000567const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000568 "clangd.applyFix";
Ilya Biryukovcce67a32019-01-29 14:17:36 +0000569const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_TWEAK =
570 "clangd.applyTweak";
571
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000572bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R) {
573 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000574 if (!O || !O.map("command", R.command))
575 return false;
Sam McCallec109022017-11-28 09:37:43 +0000576
Sam McCalld20d7982018-07-09 14:25:59 +0000577 auto Args = Params.getAsObject()->getArray("arguments");
Sam McCallff8b8742017-11-30 21:32:29 +0000578 if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) {
579 return Args && Args->size() == 1 &&
580 fromJSON(Args->front(), R.workspaceEdit);
581 }
Ilya Biryukovcce67a32019-01-29 14:17:36 +0000582 if (R.command == ExecuteCommandParams::CLANGD_APPLY_TWEAK)
583 return Args && Args->size() == 1 && fromJSON(Args->front(), R.tweakArgs);
Sam McCallff8b8742017-11-30 21:32:29 +0000584 return false; // Unrecognized command.
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000585}
586
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000587llvm::json::Value toJSON(const SymbolInformation &P) {
588 return llvm::json::Object{
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000589 {"name", P.name},
590 {"kind", static_cast<int>(P.kind)},
591 {"location", P.location},
592 {"containerName", P.containerName},
593 };
594}
595
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000596llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
597 const SymbolInformation &SI) {
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000598 O << SI.containerName << "::" << SI.name << " - " << toJSON(SI);
599 return O;
600}
601
Jan Korousb4067012018-11-27 16:40:46 +0000602bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {
603 return LHS.name == RHS.name && LHS.containerName == RHS.containerName &&
604 LHS.USR == RHS.USR && LHS.ID == RHS.ID;
605}
606
607llvm::json::Value toJSON(const SymbolDetails &P) {
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000608 llvm::json::Object Result{{"name", llvm::json::Value(nullptr)},
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000609 {"containerName", llvm::json::Value(nullptr)},
610 {"usr", llvm::json::Value(nullptr)},
611 {"id", llvm::json::Value(nullptr)}};
Jan Korousb4067012018-11-27 16:40:46 +0000612
613 if (!P.name.empty())
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000614 Result["name"] = P.name;
Jan Korousb4067012018-11-27 16:40:46 +0000615
616 if (!P.containerName.empty())
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000617 Result["containerName"] = P.containerName;
Jan Korousb4067012018-11-27 16:40:46 +0000618
619 if (!P.USR.empty())
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000620 Result["usr"] = P.USR;
Jan Korousb4067012018-11-27 16:40:46 +0000621
622 if (P.ID.hasValue())
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000623 Result["id"] = P.ID.getValue().str();
Jan Korousb4067012018-11-27 16:40:46 +0000624
Jan Korous613c80d2018-11-28 10:24:07 +0000625 // Older clang cannot compile 'return Result', even though it is legal.
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000626 return llvm::json::Value(std::move(Result));
Jan Korousb4067012018-11-27 16:40:46 +0000627}
628
629llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
630 if (!S.containerName.empty()) {
631 O << S.containerName;
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000632 llvm::StringRef ContNameRef;
Jan Korousb4067012018-11-27 16:40:46 +0000633 if (!ContNameRef.endswith("::")) {
634 O << " ";
635 }
636 }
637 O << S.name << " - " << toJSON(S);
638 return O;
639}
640
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000641bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R) {
642 llvm::json::ObjectMapper O(Params);
Marc-Andre Laperleb387b6e2018-04-23 20:00:52 +0000643 return O && O.map("query", R.query);
644}
645
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000646llvm::json::Value toJSON(const Command &C) {
647 auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};
Eric Liuc5105f92018-02-16 14:15:55 +0000648 if (C.workspaceEdit)
649 Cmd["arguments"] = {*C.workspaceEdit};
Ilya Biryukovcce67a32019-01-29 14:17:36 +0000650 if (C.tweakArgs)
651 Cmd["arguments"] = {*C.tweakArgs};
Eric Liuc5105f92018-02-16 14:15:55 +0000652 return std::move(Cmd);
653}
654
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000655const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
Ilya Biryukovcce67a32019-01-29 14:17:36 +0000656const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor";
Sam McCall395fde72019-06-18 13:37:54 +0000657const llvm::StringLiteral CodeAction::INFO_KIND = "info";
Sam McCall20841d42018-10-16 16:29:41 +0000658
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000659llvm::json::Value toJSON(const CodeAction &CA) {
660 auto CodeAction = llvm::json::Object{{"title", CA.title}};
Sam McCall20841d42018-10-16 16:29:41 +0000661 if (CA.kind)
662 CodeAction["kind"] = *CA.kind;
663 if (CA.diagnostics)
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000664 CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics);
Sam McCall20841d42018-10-16 16:29:41 +0000665 if (CA.edit)
666 CodeAction["edit"] = *CA.edit;
667 if (CA.command)
668 CodeAction["command"] = *CA.command;
669 return std::move(CodeAction);
670}
671
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000672llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) {
Ilya Biryukov19d75602018-11-23 15:21:19 +0000673 return O << S.name << " - " << toJSON(S);
674}
675
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000676llvm::json::Value toJSON(const DocumentSymbol &S) {
677 llvm::json::Object Result{{"name", S.name},
678 {"kind", static_cast<int>(S.kind)},
679 {"range", S.range},
680 {"selectionRange", S.selectionRange}};
Ilya Biryukov19d75602018-11-23 15:21:19 +0000681
682 if (!S.detail.empty())
683 Result["detail"] = S.detail;
684 if (!S.children.empty())
685 Result["children"] = S.children;
686 if (S.deprecated)
687 Result["deprecated"] = true;
Ilya Biryukov4174d092018-11-26 09:57:41 +0000688 // Older gcc cannot compile 'return Result', even though it is legal.
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000689 return llvm::json::Value(std::move(Result));
Ilya Biryukov19d75602018-11-23 15:21:19 +0000690}
691
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000692llvm::json::Value toJSON(const WorkspaceEdit &WE) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000693 if (!WE.changes)
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000694 return llvm::json::Object{};
695 llvm::json::Object FileChanges;
Sam McCalldd0566b2017-11-06 15:40:30 +0000696 for (auto &Change : *WE.changes)
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000697 FileChanges[Change.first] = llvm::json::Array(Change.second);
698 return llvm::json::Object{{"changes", std::move(FileChanges)}};
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000699}
700
Ilya Biryukovcce67a32019-01-29 14:17:36 +0000701bool fromJSON(const llvm::json::Value &Params, TweakArgs &A) {
702 llvm::json::ObjectMapper O(Params);
703 return O && O.map("file", A.file) && O.map("selection", A.selection) &&
704 O.map("tweakID", A.tweakID);
705}
706
707llvm::json::Value toJSON(const TweakArgs &A) {
708 return llvm::json::Object{
709 {"tweakID", A.tweakID}, {"selection", A.selection}, {"file", A.file}};
710}
711
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000712llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
713 return llvm::json::Object{{"edit", Params.edit}};
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000714}
715
Haojian Wuf2516342019-08-05 12:48:09 +0000716bool fromJSON(const llvm::json::Value &Response,
717 ApplyWorkspaceEditResponse &R) {
718 llvm::json::ObjectMapper O(Response);
719 if (!O || !O.map("applied", R.applied))
720 return false;
721 O.map("failureReason", R.failureReason);
722 return true;
723}
724
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000725bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R) {
726 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000727 return O && O.map("textDocument", R.textDocument) &&
728 O.map("position", R.position);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000729}
730
Ilya Biryukovb0826bd2019-01-03 13:37:12 +0000731bool fromJSON(const llvm::json::Value &Params, CompletionContext &R) {
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000732 llvm::json::ObjectMapper O(Params);
Ilya Biryukovb0826bd2019-01-03 13:37:12 +0000733 if (!O)
734 return false;
735
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000736 int TriggerKind;
737 if (!O.map("triggerKind", TriggerKind))
Ilya Biryukovb0826bd2019-01-03 13:37:12 +0000738 return false;
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000739 R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind);
Ilya Biryukovb0826bd2019-01-03 13:37:12 +0000740
741 if (auto *TC = Params.getAsObject()->get("triggerCharacter"))
742 return fromJSON(*TC, R.triggerCharacter);
743 return true;
744}
745
746bool fromJSON(const llvm::json::Value &Params, CompletionParams &R) {
747 if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R)))
748 return false;
749 if (auto *Context = Params.getAsObject()->get("context"))
750 return fromJSON(*Context, R.context);
751 return true;
752}
753
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000754static llvm::StringRef toTextKind(MarkupKind Kind) {
Marc-Andre Laperle3e618ed2018-02-16 21:38:15 +0000755 switch (Kind) {
756 case MarkupKind::PlainText:
757 return "plaintext";
758 case MarkupKind::Markdown:
759 return "markdown";
760 }
761 llvm_unreachable("Invalid MarkupKind");
762}
763
Ilya Biryukovf9169d02019-05-29 10:01:00 +0000764bool fromJSON(const llvm::json::Value &V, MarkupKind &K) {
765 auto Str = V.getAsString();
766 if (!Str) {
767 elog("Failed to parse markup kind: expected a string");
768 return false;
769 }
770 if (*Str == "plaintext")
771 K = MarkupKind::PlainText;
772 else if (*Str == "markdown")
773 K = MarkupKind::Markdown;
774 else {
775 elog("Unknown markup kind: {0}", *Str);
776 return false;
777 }
778 return true;
779}
780
781llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MarkupKind K) {
782 return OS << toTextKind(K);
783}
784
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000785llvm::json::Value toJSON(const MarkupContent &MC) {
Marc-Andre Laperle373e30a2018-02-16 23:12:26 +0000786 if (MC.value.empty())
Marc-Andre Laperle3e618ed2018-02-16 21:38:15 +0000787 return nullptr;
788
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000789 return llvm::json::Object{
Marc-Andre Laperle373e30a2018-02-16 23:12:26 +0000790 {"kind", toTextKind(MC.kind)},
791 {"value", MC.value},
Marc-Andre Laperle3e618ed2018-02-16 21:38:15 +0000792 };
793}
794
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000795llvm::json::Value toJSON(const Hover &H) {
796 llvm::json::Object Result{{"contents", toJSON(H.contents)}};
Marc-Andre Laperle3e618ed2018-02-16 21:38:15 +0000797
Marc-Andre Laperle373e30a2018-02-16 23:12:26 +0000798 if (H.range.hasValue())
799 Result["range"] = toJSON(*H.range);
Marc-Andre Laperle3e618ed2018-02-16 21:38:15 +0000800
801 return std::move(Result);
802}
803
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000804bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out) {
Kadir Cetinkaya133d46f2018-09-27 17:13:07 +0000805 if (auto T = E.getAsInteger()) {
806 if (*T < static_cast<int>(CompletionItemKind::Text) ||
807 *T > static_cast<int>(CompletionItemKind::TypeParameter))
808 return false;
809 Out = static_cast<CompletionItemKind>(*T);
810 return true;
811 }
812 return false;
813}
814
815CompletionItemKind
816adjustKindToCapability(CompletionItemKind Kind,
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000817 CompletionItemKindBitset &SupportedCompletionItemKinds) {
Kadir Cetinkaya133d46f2018-09-27 17:13:07 +0000818 auto KindVal = static_cast<size_t>(Kind);
819 if (KindVal >= CompletionItemKindMin &&
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000820 KindVal <= SupportedCompletionItemKinds.size() &&
821 SupportedCompletionItemKinds[KindVal])
Kadir Cetinkaya133d46f2018-09-27 17:13:07 +0000822 return Kind;
823
824 switch (Kind) {
825 // Provide some fall backs for common kinds that are close enough.
826 case CompletionItemKind::Folder:
827 return CompletionItemKind::File;
828 case CompletionItemKind::EnumMember:
829 return CompletionItemKind::Enum;
830 case CompletionItemKind::Struct:
831 return CompletionItemKind::Class;
832 default:
833 return CompletionItemKind::Text;
834 }
835}
836
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000837bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out) {
Kadir Cetinkaya133d46f2018-09-27 17:13:07 +0000838 if (auto *A = E.getAsArray()) {
Kadir Cetinkaya133d46f2018-09-27 17:13:07 +0000839 for (size_t I = 0; I < A->size(); ++I) {
840 CompletionItemKind KindOut;
841 if (fromJSON((*A)[I], KindOut))
Sam McCallbf6a2fc2018-10-17 07:33:42 +0000842 Out.set(size_t(KindOut));
Kadir Cetinkaya133d46f2018-09-27 17:13:07 +0000843 }
844 return true;
845 }
846 return false;
847}
848
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000849llvm::json::Value toJSON(const CompletionItem &CI) {
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000850 assert(!CI.label.empty() && "completion item label is required");
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000851 llvm::json::Object Result{{"label", CI.label}};
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000852 if (CI.kind != CompletionItemKind::Missing)
Sam McCalldd0566b2017-11-06 15:40:30 +0000853 Result["kind"] = static_cast<int>(CI.kind);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000854 if (!CI.detail.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000855 Result["detail"] = CI.detail;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000856 if (!CI.documentation.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000857 Result["documentation"] = CI.documentation;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000858 if (!CI.sortText.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000859 Result["sortText"] = CI.sortText;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000860 if (!CI.filterText.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000861 Result["filterText"] = CI.filterText;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000862 if (!CI.insertText.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000863 Result["insertText"] = CI.insertText;
864 if (CI.insertTextFormat != InsertTextFormat::Missing)
865 Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000866 if (CI.textEdit)
Sam McCalldd0566b2017-11-06 15:40:30 +0000867 Result["textEdit"] = *CI.textEdit;
868 if (!CI.additionalTextEdits.empty())
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000869 Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits);
Eric Liu6df66002018-09-06 18:52:26 +0000870 if (CI.deprecated)
871 Result["deprecated"] = CI.deprecated;
Kirill Bobyrevff7b5ba2020-02-13 14:17:30 +0100872 Result["score"] = CI.score;
Sam McCalldd0566b2017-11-06 15:40:30 +0000873 return std::move(Result);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000874}
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000875
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000876llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {
Marc-Andre Laperle90a937e2018-04-10 17:34:46 +0000877 O << I.label << " - " << toJSON(I);
878 return O;
879}
880
Sam McCallff8b8742017-11-30 21:32:29 +0000881bool operator<(const CompletionItem &L, const CompletionItem &R) {
Sam McCallc78ccbd2017-11-08 07:44:12 +0000882 return (L.sortText.empty() ? L.label : L.sortText) <
883 (R.sortText.empty() ? R.label : R.sortText);
884}
885
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000886llvm::json::Value toJSON(const CompletionList &L) {
887 return llvm::json::Object{
Sam McCalla40371b2017-11-15 09:16:29 +0000888 {"isIncomplete", L.isIncomplete},
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000889 {"items", llvm::json::Array(L.items)},
Sam McCalla40371b2017-11-15 09:16:29 +0000890 };
891}
892
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000893llvm::json::Value toJSON(const ParameterInformation &PI) {
Simon Pilgrim5b41fe52019-06-04 11:31:45 +0000894 assert((PI.labelOffsets.hasValue() || !PI.labelString.empty()) &&
895 "parameter information label is required");
Ilya Biryukov4ef0f822019-06-04 09:36:59 +0000896 llvm::json::Object Result;
897 if (PI.labelOffsets)
898 Result["label"] =
899 llvm::json::Array({PI.labelOffsets->first, PI.labelOffsets->second});
900 else
901 Result["label"] = PI.labelString;
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000902 if (!PI.documentation.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000903 Result["documentation"] = PI.documentation;
904 return std::move(Result);
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000905}
906
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000907llvm::json::Value toJSON(const SignatureInformation &SI) {
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000908 assert(!SI.label.empty() && "signature information label is required");
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000909 llvm::json::Object Result{
Sam McCalldd0566b2017-11-06 15:40:30 +0000910 {"label", SI.label},
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000911 {"parameters", llvm::json::Array(SI.parameters)},
Sam McCalldd0566b2017-11-06 15:40:30 +0000912 };
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000913 if (!SI.documentation.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000914 Result["documentation"] = SI.documentation;
915 return std::move(Result);
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000916}
917
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000918llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
919 const SignatureInformation &I) {
Marc-Andre Laperle90a937e2018-04-10 17:34:46 +0000920 O << I.label << " - " << toJSON(I);
921 return O;
922}
923
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000924llvm::json::Value toJSON(const SignatureHelp &SH) {
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000925 assert(SH.activeSignature >= 0 &&
926 "Unexpected negative value for number of active signatures.");
927 assert(SH.activeParameter >= 0 &&
928 "Unexpected negative value for active parameter index");
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000929 return llvm::json::Object{
Sam McCalldd0566b2017-11-06 15:40:30 +0000930 {"activeSignature", SH.activeSignature},
931 {"activeParameter", SH.activeParameter},
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000932 {"signatures", llvm::json::Array(SH.signatures)},
Sam McCalldd0566b2017-11-06 15:40:30 +0000933 };
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000934}
Haojian Wu345099c2017-11-09 11:30:04 +0000935
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000936bool fromJSON(const llvm::json::Value &Params, RenameParams &R) {
937 llvm::json::ObjectMapper O(Params);
Sam McCallff8b8742017-11-30 21:32:29 +0000938 return O && O.map("textDocument", R.textDocument) &&
939 O.map("position", R.position) && O.map("newName", R.newName);
Haojian Wu345099c2017-11-09 11:30:04 +0000940}
Sam McCallff8b8742017-11-30 21:32:29 +0000941
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000942llvm::json::Value toJSON(const DocumentHighlight &DH) {
943 return llvm::json::Object{
Ilya Biryukov0e6a51f2017-12-12 12:27:47 +0000944 {"range", toJSON(DH.range)},
945 {"kind", static_cast<int>(DH.kind)},
946 };
947}
948
Haojian Wub6188492018-12-20 15:39:12 +0000949llvm::json::Value toJSON(const FileStatus &FStatus) {
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000950 return llvm::json::Object{
Ilya Biryukov22fa4652019-01-03 13:28:05 +0000951 {"uri", FStatus.uri},
952 {"state", FStatus.state},
Haojian Wub6188492018-12-20 15:39:12 +0000953 };
954}
955
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000956llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
957 const DocumentHighlight &V) {
Marc-Andre Laperle90a937e2018-04-10 17:34:46 +0000958 O << V.range;
959 if (V.kind == DocumentHighlightKind::Read)
960 O << "(r)";
961 if (V.kind == DocumentHighlightKind::Write)
962 O << "(w)";
963 return O;
964}
965
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000966bool fromJSON(const llvm::json::Value &Params,
967 DidChangeConfigurationParams &CCP) {
968 llvm::json::ObjectMapper O(Params);
Simon Marchi5178f922018-02-22 14:00:39 +0000969 return O && O.map("settings", CCP.settings);
970}
971
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000972bool fromJSON(const llvm::json::Value &Params,
973 ClangdCompileCommand &CDbUpdate) {
974 llvm::json::ObjectMapper O(Params);
Alex Lorenzf8087862018-08-01 17:39:29 +0000975 return O && O.map("workingDirectory", CDbUpdate.workingDirectory) &&
976 O.map("compilationCommand", CDbUpdate.compilationCommand);
977}
978
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000979bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S) {
980 llvm::json::ObjectMapper O(Params);
Sam McCallbc904612018-10-25 04:22:52 +0000981 if (!O)
982 return true; // 'any' type in LSP.
983 O.map("compilationDatabaseChanges", S.compilationDatabaseChanges);
984 return true;
Simon Marchi5178f922018-02-22 14:00:39 +0000985}
986
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000987bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts) {
988 llvm::json::ObjectMapper O(Params);
Sam McCallbc904612018-10-25 04:22:52 +0000989 if (!O)
990 return true; // 'any' type in LSP.
991
992 fromJSON(Params, Opts.ConfigSettings);
993 O.map("compilationDatabasePath", Opts.compilationDatabasePath);
Sam McCall6980edb2018-11-02 14:07:51 +0000994 O.map("fallbackFlags", Opts.fallbackFlags);
Haojian Wub6188492018-12-20 15:39:12 +0000995 O.map("clangdFileStatus", Opts.FileStatus);
Sam McCallbc904612018-10-25 04:22:52 +0000996 return true;
Simon Marchiabeed662018-10-16 15:55:03 +0000997}
998
Kadir Cetinkaya86658022019-03-19 09:27:04 +0000999bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out) {
1000 auto T = E.getAsInteger();
1001 if (!T)
1002 return false;
1003 if (*T < static_cast<int>(TypeHierarchyDirection::Children) ||
1004 *T > static_cast<int>(TypeHierarchyDirection::Both))
1005 return false;
1006 Out = static_cast<TypeHierarchyDirection>(*T);
1007 return true;
1008}
1009
1010bool fromJSON(const llvm::json::Value &Params, TypeHierarchyParams &R) {
1011 llvm::json::ObjectMapper O(Params);
1012 return O && O.map("textDocument", R.textDocument) &&
1013 O.map("position", R.position) && O.map("resolve", R.resolve) &&
1014 O.map("direction", R.direction);
1015}
1016
1017llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
1018 const TypeHierarchyItem &I) {
1019 return O << I.name << " - " << toJSON(I);
1020}
1021
1022llvm::json::Value toJSON(const TypeHierarchyItem &I) {
1023 llvm::json::Object Result{{"name", I.name},
1024 {"kind", static_cast<int>(I.kind)},
1025 {"range", I.range},
1026 {"selectionRange", I.selectionRange},
1027 {"uri", I.uri}};
1028
1029 if (I.detail)
1030 Result["detail"] = I.detail;
1031 if (I.deprecated)
1032 Result["deprecated"] = I.deprecated;
1033 if (I.parents)
1034 Result["parents"] = I.parents;
1035 if (I.children)
1036 Result["children"] = I.children;
Nathan Ridge087b0442019-07-13 03:24:48 +00001037 if (I.data)
1038 Result["data"] = I.data;
Kadir Cetinkaya86658022019-03-19 09:27:04 +00001039 return std::move(Result);
1040}
1041
1042bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I) {
1043 llvm::json::ObjectMapper O(Params);
1044
1045 // Required fields.
1046 if (!(O && O.map("name", I.name) && O.map("kind", I.kind) &&
1047 O.map("uri", I.uri) && O.map("range", I.range) &&
1048 O.map("selectionRange", I.selectionRange))) {
1049 return false;
1050 }
1051
1052 // Optional fields.
1053 O.map("detail", I.detail);
1054 O.map("deprecated", I.deprecated);
1055 O.map("parents", I.parents);
1056 O.map("children", I.children);
Nathan Ridge087b0442019-07-13 03:24:48 +00001057 O.map("data", I.data);
Kadir Cetinkaya86658022019-03-19 09:27:04 +00001058
1059 return true;
1060}
1061
Nathan Ridge087b0442019-07-13 03:24:48 +00001062bool fromJSON(const llvm::json::Value &Params,
1063 ResolveTypeHierarchyItemParams &P) {
1064 llvm::json::ObjectMapper O(Params);
1065 return O && O.map("item", P.item) && O.map("resolve", P.resolve) &&
1066 O.map("direction", P.direction);
1067}
1068
Ilya Biryukovf2001aa2019-01-07 15:45:19 +00001069bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R) {
Sam McCall1ad142f2018-09-05 11:53:07 +00001070 TextDocumentPositionParams &Base = R;
1071 return fromJSON(Params, Base);
1072}
1073
Sam McCall8b25d222019-03-28 14:37:51 +00001074static const char *toString(OffsetEncoding OE) {
Sam McCalla69698f2019-03-27 17:47:49 +00001075 switch (OE) {
Sam McCall8b25d222019-03-28 14:37:51 +00001076 case OffsetEncoding::UTF8:
1077 return "utf-8";
1078 case OffsetEncoding::UTF16:
1079 return "utf-16";
1080 case OffsetEncoding::UTF32:
1081 return "utf-32";
1082 case OffsetEncoding::UnsupportedEncoding:
1083 return "unknown";
Sam McCalla69698f2019-03-27 17:47:49 +00001084 }
Simon Pilgrim945db0b2019-03-29 13:43:00 +00001085 llvm_unreachable("Unknown clang.clangd.OffsetEncoding");
Sam McCalla69698f2019-03-27 17:47:49 +00001086}
Sam McCall8b25d222019-03-28 14:37:51 +00001087llvm::json::Value toJSON(const OffsetEncoding &OE) { return toString(OE); }
Sam McCalla69698f2019-03-27 17:47:49 +00001088bool fromJSON(const llvm::json::Value &V, OffsetEncoding &OE) {
1089 auto Str = V.getAsString();
1090 if (!Str)
1091 return false;
1092 OE = llvm::StringSwitch<OffsetEncoding>(*Str)
1093 .Case("utf-8", OffsetEncoding::UTF8)
1094 .Case("utf-16", OffsetEncoding::UTF16)
Sam McCall8b25d222019-03-28 14:37:51 +00001095 .Case("utf-32", OffsetEncoding::UTF32)
Sam McCalla69698f2019-03-27 17:47:49 +00001096 .Default(OffsetEncoding::UnsupportedEncoding);
1097 return true;
1098}
Sam McCall8b25d222019-03-28 14:37:51 +00001099llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) {
1100 return OS << toString(Enc);
1101}
Sam McCalla69698f2019-03-27 17:47:49 +00001102
Johan Vikstroma848dab2019-07-04 07:53:12 +00001103bool operator==(const SemanticHighlightingInformation &Lhs,
1104 const SemanticHighlightingInformation &Rhs) {
1105 return Lhs.Line == Rhs.Line && Lhs.Tokens == Rhs.Tokens;
1106}
1107
1108llvm::json::Value toJSON(const SemanticHighlightingInformation &Highlighting) {
1109 return llvm::json::Object{{"line", Highlighting.Line},
Nathan Ridgeb2e6c2b2019-09-24 18:17:55 -04001110 {"tokens", Highlighting.Tokens},
1111 {"isInactive", Highlighting.IsInactive}};
Johan Vikstroma848dab2019-07-04 07:53:12 +00001112}
1113
1114llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting) {
1115 return llvm::json::Object{
1116 {"textDocument", Highlighting.TextDocument},
1117 {"lines", std::move(Highlighting.Lines)},
1118 };
1119}
1120
Utkarsh Saxena55925da2019-09-24 13:38:33 +00001121bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &P) {
1122 llvm::json::ObjectMapper O(Params);
1123 return O && O.map("textDocument", P.textDocument) &&
1124 O.map("positions", P.positions);
1125}
1126
1127llvm::json::Value toJSON(const SelectionRange &Out) {
1128 if (Out.parent) {
1129 return llvm::json::Object{{"range", Out.range},
1130 {"parent", toJSON(*Out.parent)}};
1131 }
1132 return llvm::json::Object{{"range", Out.range}};
1133}
Sam McCall8d7ecc12019-12-16 19:08:51 +01001134
1135bool fromJSON(const llvm::json::Value &Params, DocumentLinkParams &R) {
1136 llvm::json::ObjectMapper O(Params);
1137 return O && O.map("textDocument", R.textDocument);
1138}
1139
1140llvm::json::Value toJSON(const DocumentLink &DocumentLink) {
1141 return llvm::json::Object{
1142 {"range", DocumentLink.range},
1143 {"target", DocumentLink.target},
1144 };
1145}
1146
Sam McCallff8b8742017-11-30 21:32:29 +00001147} // namespace clangd
1148} // namespace clang