blob: a884a0c4841d8818e4325aa8c7601ce57a0c2e26 [file] [log] [blame]
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +00001//===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the serialization code for the LSP structs.
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "Protocol.h"
Eric Liu78ed91a72018-01-29 15:37:46 +000015#include "Logger.h"
Ilya Biryukov7d60d202018-02-16 12:20:47 +000016#include "URI.h"
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000017#include "clang/Basic/LLVM.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/Support/Format.h"
Marc-Andre Laperle85dcce42017-09-18 15:02:59 +000020#include "llvm/Support/FormatVariadic.h"
Krasimir Georgiev50117372017-04-07 11:03:26 +000021#include "llvm/Support/Path.h"
Ilya Biryukov574b7532017-08-02 09:08:39 +000022#include "llvm/Support/raw_ostream.h"
Ilya Biryukove5128f72017-09-20 07:24:15 +000023
Sam McCallff8b8742017-11-30 21:32:29 +000024namespace clang {
25namespace clangd {
Sam McCall38a04912017-11-29 11:36:46 +000026
Ilya Biryukov7d60d202018-02-16 12:20:47 +000027URIForFile::URIForFile(std::string AbsPath) {
28 assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
29 File = std::move(AbsPath);
30}
31
Eric Liu78ed91a72018-01-29 15:37:46 +000032bool fromJSON(const json::Expr &E, URIForFile &R) {
Sam McCallff8b8742017-11-30 21:32:29 +000033 if (auto S = E.asString()) {
Eric Liu78ed91a72018-01-29 15:37:46 +000034 auto U = URI::parse(*S);
35 if (!U) {
Sam McCalld1a7a372018-01-31 13:40:48 +000036 log("Failed to parse URI " + *S + ": " + llvm::toString(U.takeError()));
Eric Liu78ed91a72018-01-29 15:37:46 +000037 return false;
38 }
Eric Liu5740ff52018-01-31 16:26:27 +000039 if (U->scheme() != "file" && U->scheme() != "test") {
Sam McCalld1a7a372018-01-31 13:40:48 +000040 log("Clangd only supports 'file' URI scheme for workspace files: " + *S);
Eric Liu78ed91a72018-01-29 15:37:46 +000041 return false;
42 }
Sam McCall41d21522018-01-30 11:23:11 +000043 auto Path = URI::resolve(*U);
44 if (!Path) {
Sam McCalld1a7a372018-01-31 13:40:48 +000045 log(llvm::toString(Path.takeError()));
Sam McCall41d21522018-01-30 11:23:11 +000046 return false;
47 }
Ilya Biryukov7d60d202018-02-16 12:20:47 +000048 R = URIForFile(*Path);
Sam McCallff8b8742017-11-30 21:32:29 +000049 return true;
50 }
51 return false;
Sam McCall38a04912017-11-29 11:36:46 +000052}
53
Ilya Biryukov7d60d202018-02-16 12:20:47 +000054json::Expr toJSON(const URIForFile &U) { return U.uri(); }
Krasimir Georgiev50117372017-04-07 11:03:26 +000055
Eric Liu78ed91a72018-01-29 15:37:46 +000056llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {
57 return OS << U.uri();
Sam McCallfffa8222017-12-20 10:26:53 +000058}
59
Sam McCallff8b8742017-11-30 21:32:29 +000060bool fromJSON(const json::Expr &Params, TextDocumentIdentifier &R) {
61 json::ObjectMapper O(Params);
62 return O && O.map("uri", R.uri);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000063}
64
Sam McCallff8b8742017-11-30 21:32:29 +000065bool fromJSON(const json::Expr &Params, Position &R) {
66 json::ObjectMapper O(Params);
67 return O && O.map("line", R.line) && O.map("character", R.character);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000068}
69
Sam McCallff8b8742017-11-30 21:32:29 +000070json::Expr toJSON(const Position &P) {
Sam McCalldd0566b2017-11-06 15:40:30 +000071 return json::obj{
72 {"line", P.line},
73 {"character", P.character},
74 };
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000075}
76
Sam McCallfffa8222017-12-20 10:26:53 +000077llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) {
78 return OS << P.line << ':' << P.character;
79}
80
Sam McCallff8b8742017-11-30 21:32:29 +000081bool fromJSON(const json::Expr &Params, Range &R) {
82 json::ObjectMapper O(Params);
83 return O && O.map("start", R.start) && O.map("end", R.end);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000084}
85
Sam McCallff8b8742017-11-30 21:32:29 +000086json::Expr toJSON(const Range &P) {
Sam McCalldd0566b2017-11-06 15:40:30 +000087 return json::obj{
88 {"start", P.start},
89 {"end", P.end},
90 };
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +000091}
92
Sam McCallfffa8222017-12-20 10:26:53 +000093llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) {
94 return OS << R.start << '-' << R.end;
95}
96
Sam McCallff8b8742017-11-30 21:32:29 +000097json::Expr toJSON(const Location &P) {
Sam McCalldd0566b2017-11-06 15:40:30 +000098 return json::obj{
99 {"uri", P.uri},
100 {"range", P.range},
101 };
Marc-Andre Laperle2cbf0372017-06-28 16:12:10 +0000102}
103
Sam McCallfffa8222017-12-20 10:26:53 +0000104llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) {
105 return OS << L.range << '@' << L.uri;
106}
107
Sam McCallff8b8742017-11-30 21:32:29 +0000108bool fromJSON(const json::Expr &Params, TextDocumentItem &R) {
109 json::ObjectMapper O(Params);
110 return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&
111 O.map("version", R.version) && O.map("text", R.text);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000112}
113
Sam McCallff8b8742017-11-30 21:32:29 +0000114bool fromJSON(const json::Expr &Params, Metadata &R) {
115 json::ObjectMapper O(Params);
Sam McCallec109022017-11-28 09:37:43 +0000116 if (!O)
Sam McCallff8b8742017-11-30 21:32:29 +0000117 return false;
118 O.map("extraFlags", R.extraFlags);
119 return true;
Krasimir Georgievc2a16a32017-07-06 08:44:54 +0000120}
121
Sam McCallff8b8742017-11-30 21:32:29 +0000122bool fromJSON(const json::Expr &Params, TextEdit &R) {
123 json::ObjectMapper O(Params);
124 return O && O.map("range", R.range) && O.map("newText", R.newText);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000125}
126
Sam McCallff8b8742017-11-30 21:32:29 +0000127json::Expr toJSON(const TextEdit &P) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000128 return json::obj{
129 {"range", P.range},
130 {"newText", P.newText},
131 };
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000132}
133
Sam McCall034e11a2018-01-25 17:29:17 +0000134llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) {
135 OS << TE.range << " => \"";
136 PrintEscapedString(TE.newText, OS);
137 return OS << '"';
138}
139
Sam McCallff8b8742017-11-30 21:32:29 +0000140bool fromJSON(const json::Expr &E, TraceLevel &Out) {
141 if (auto S = E.asString()) {
142 if (*S == "off") {
143 Out = TraceLevel::Off;
144 return true;
145 } else if (*S == "messages") {
146 Out = TraceLevel::Messages;
147 return true;
148 } else if (*S == "verbose") {
149 Out = TraceLevel::Verbose;
150 return true;
151 }
152 }
153 return false;
154}
155
Ilya Biryukov23bc73b2018-02-15 14:32:57 +0000156bool fromJSON(const json::Expr &Params, CompletionItemClientCapabilities &R) {
157 json::ObjectMapper O(Params);
158 if (!O)
159 return false;
160 O.map("snippetSupport", R.snippetSupport);
161 O.map("commitCharacterSupport", R.commitCharacterSupport);
162 return true;
163}
164
165bool fromJSON(const json::Expr &Params, CompletionClientCapabilities &R) {
166 json::ObjectMapper O(Params);
167 if (!O)
168 return false;
169 O.map("dynamicRegistration", R.dynamicRegistration);
170 O.map("completionItem", R.completionItem);
171 O.map("contextSupport", R.contextSupport);
172 return true;
173}
174
175bool fromJSON(const json::Expr &Params, TextDocumentClientCapabilities &R) {
176 json::ObjectMapper O(Params);
177 if (!O)
178 return false;
179 O.map("completion", R.completion);
180 return true;
181}
182
183bool fromJSON(const json::Expr &Params, ClientCapabilities &R) {
184 json::ObjectMapper O(Params);
185 if (!O)
186 return false;
187 O.map("textDocument", R.textDocument);
188 return true;
189}
190
Sam McCallff8b8742017-11-30 21:32:29 +0000191bool fromJSON(const json::Expr &Params, InitializeParams &R) {
192 json::ObjectMapper O(Params);
Sam McCallec109022017-11-28 09:37:43 +0000193 if (!O)
Sam McCallff8b8742017-11-30 21:32:29 +0000194 return false;
Sam McCall38a04912017-11-29 11:36:46 +0000195 // We deliberately don't fail if we can't parse individual fields.
196 // Failing to handle a slightly malformed initialize would be a disaster.
Sam McCallff8b8742017-11-30 21:32:29 +0000197 O.map("processId", R.processId);
198 O.map("rootUri", R.rootUri);
199 O.map("rootPath", R.rootPath);
Ilya Biryukov23bc73b2018-02-15 14:32:57 +0000200 O.map("capabilities", R.capabilities);
Sam McCallff8b8742017-11-30 21:32:29 +0000201 O.map("trace", R.trace);
Sam McCallec109022017-11-28 09:37:43 +0000202 // initializationOptions, capabilities unused
Sam McCallff8b8742017-11-30 21:32:29 +0000203 return true;
Marc-Andre Laperle37de9712017-09-27 15:31:17 +0000204}
205
Sam McCallff8b8742017-11-30 21:32:29 +0000206bool fromJSON(const json::Expr &Params, DidOpenTextDocumentParams &R) {
207 json::ObjectMapper O(Params);
208 return O && O.map("textDocument", R.textDocument) &&
209 O.map("metadata", R.metadata);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000210}
211
Sam McCallff8b8742017-11-30 21:32:29 +0000212bool fromJSON(const json::Expr &Params, DidCloseTextDocumentParams &R) {
213 json::ObjectMapper O(Params);
214 return O && O.map("textDocument", R.textDocument);
Krasimir Georgiev561ba5e2017-04-10 13:31:39 +0000215}
216
Sam McCallff8b8742017-11-30 21:32:29 +0000217bool fromJSON(const json::Expr &Params, DidChangeTextDocumentParams &R) {
218 json::ObjectMapper O(Params);
219 return O && O.map("textDocument", R.textDocument) &&
220 O.map("contentChanges", R.contentChanges);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000221}
222
Sam McCallff8b8742017-11-30 21:32:29 +0000223bool fromJSON(const json::Expr &E, FileChangeType &Out) {
224 if (auto T = E.asInteger()) {
225 if (*T < static_cast<int>(FileChangeType::Created) ||
226 *T > static_cast<int>(FileChangeType::Deleted))
227 return false;
228 Out = static_cast<FileChangeType>(*T);
229 return true;
230 }
231 return false;
Marc-Andre Laperlebf114242017-10-02 18:00:37 +0000232}
233
Sam McCallff8b8742017-11-30 21:32:29 +0000234bool fromJSON(const json::Expr &Params, FileEvent &R) {
235 json::ObjectMapper O(Params);
236 return O && O.map("uri", R.uri) && O.map("type", R.type);
Marc-Andre Laperlebf114242017-10-02 18:00:37 +0000237}
238
Sam McCallff8b8742017-11-30 21:32:29 +0000239bool fromJSON(const json::Expr &Params, DidChangeWatchedFilesParams &R) {
240 json::ObjectMapper O(Params);
241 return O && O.map("changes", R.changes);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000242}
243
Sam McCallff8b8742017-11-30 21:32:29 +0000244bool fromJSON(const json::Expr &Params, TextDocumentContentChangeEvent &R) {
245 json::ObjectMapper O(Params);
246 return O && O.map("text", R.text);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000247}
248
Sam McCallff8b8742017-11-30 21:32:29 +0000249bool fromJSON(const json::Expr &Params, FormattingOptions &R) {
250 json::ObjectMapper O(Params);
251 return O && O.map("tabSize", R.tabSize) &&
252 O.map("insertSpaces", R.insertSpaces);
253}
254
255json::Expr toJSON(const FormattingOptions &P) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000256 return json::obj{
257 {"tabSize", P.tabSize},
258 {"insertSpaces", P.insertSpaces},
259 };
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000260}
261
Sam McCallff8b8742017-11-30 21:32:29 +0000262bool fromJSON(const json::Expr &Params, DocumentRangeFormattingParams &R) {
263 json::ObjectMapper O(Params);
264 return O && O.map("textDocument", R.textDocument) &&
265 O.map("range", R.range) && O.map("options", R.options);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000266}
267
Sam McCallff8b8742017-11-30 21:32:29 +0000268bool fromJSON(const json::Expr &Params, DocumentOnTypeFormattingParams &R) {
269 json::ObjectMapper O(Params);
270 return O && O.map("textDocument", R.textDocument) &&
271 O.map("position", R.position) && O.map("ch", R.ch) &&
272 O.map("options", R.options);
Krasimir Georgiev1b8bfd42017-02-16 10:49:46 +0000273}
274
Sam McCallff8b8742017-11-30 21:32:29 +0000275bool fromJSON(const json::Expr &Params, DocumentFormattingParams &R) {
276 json::ObjectMapper O(Params);
277 return O && O.map("textDocument", R.textDocument) &&
278 O.map("options", R.options);
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000279}
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000280
Sam McCallff8b8742017-11-30 21:32:29 +0000281bool fromJSON(const json::Expr &Params, Diagnostic &R) {
282 json::ObjectMapper O(Params);
283 if (!O || !O.map("range", R.range) || !O.map("message", R.message))
284 return false;
285 O.map("severity", R.severity);
286 return true;
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000287}
288
Sam McCallff8b8742017-11-30 21:32:29 +0000289bool fromJSON(const json::Expr &Params, CodeActionContext &R) {
290 json::ObjectMapper O(Params);
291 return O && O.map("diagnostics", R.diagnostics);
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000292}
293
Sam McCall034e11a2018-01-25 17:29:17 +0000294llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {
295 OS << D.range << " [";
296 switch (D.severity) {
297 case 1:
298 OS << "error";
299 break;
300 case 2:
301 OS << "warning";
302 break;
303 case 3:
304 OS << "note";
305 break;
306 case 4:
307 OS << "remark";
308 break;
309 default:
310 OS << "diagnostic";
311 break;
312 }
313 return OS << '(' << D.severity << "): " << D.message << "]";
314}
315
Sam McCallff8b8742017-11-30 21:32:29 +0000316bool fromJSON(const json::Expr &Params, CodeActionParams &R) {
317 json::ObjectMapper O(Params);
318 return O && O.map("textDocument", R.textDocument) &&
319 O.map("range", R.range) && O.map("context", R.context);
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000320}
321
Sam McCallff8b8742017-11-30 21:32:29 +0000322bool fromJSON(const json::Expr &Params, WorkspaceEdit &R) {
323 json::ObjectMapper O(Params);
324 return O && O.map("changes", R.changes);
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000325}
326
Benjamin Kramerb4c5c2d2017-12-28 15:03:02 +0000327const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000328 "clangd.applyFix";
329
Sam McCallff8b8742017-11-30 21:32:29 +0000330bool fromJSON(const json::Expr &Params, ExecuteCommandParams &R) {
331 json::ObjectMapper O(Params);
332 if (!O || !O.map("command", R.command))
333 return false;
Sam McCallec109022017-11-28 09:37:43 +0000334
Sam McCallff8b8742017-11-30 21:32:29 +0000335 auto Args = Params.asObject()->getArray("arguments");
336 if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) {
337 return Args && Args->size() == 1 &&
338 fromJSON(Args->front(), R.workspaceEdit);
339 }
340 return false; // Unrecognized command.
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000341}
342
Sam McCallff8b8742017-11-30 21:32:29 +0000343json::Expr toJSON(const WorkspaceEdit &WE) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000344 if (!WE.changes)
345 return json::obj{};
346 json::obj FileChanges;
347 for (auto &Change : *WE.changes)
348 FileChanges[Change.first] = json::ary(Change.second);
349 return json::obj{{"changes", std::move(FileChanges)}};
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000350}
351
Sam McCallff8b8742017-11-30 21:32:29 +0000352json::Expr toJSON(const ApplyWorkspaceEditParams &Params) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000353 return json::obj{{"edit", Params.edit}};
Marc-Andre Laperlee7ec16a2017-11-03 13:39:15 +0000354}
355
Sam McCallff8b8742017-11-30 21:32:29 +0000356bool fromJSON(const json::Expr &Params, TextDocumentPositionParams &R) {
357 json::ObjectMapper O(Params);
358 return O && O.map("textDocument", R.textDocument) &&
359 O.map("position", R.position);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000360}
361
Sam McCallff8b8742017-11-30 21:32:29 +0000362json::Expr toJSON(const CompletionItem &CI) {
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000363 assert(!CI.label.empty() && "completion item label is required");
Sam McCalldd0566b2017-11-06 15:40:30 +0000364 json::obj Result{{"label", CI.label}};
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000365 if (CI.kind != CompletionItemKind::Missing)
Sam McCalldd0566b2017-11-06 15:40:30 +0000366 Result["kind"] = static_cast<int>(CI.kind);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000367 if (!CI.detail.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000368 Result["detail"] = CI.detail;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000369 if (!CI.documentation.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000370 Result["documentation"] = CI.documentation;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000371 if (!CI.sortText.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000372 Result["sortText"] = CI.sortText;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000373 if (!CI.filterText.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000374 Result["filterText"] = CI.filterText;
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000375 if (!CI.insertText.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000376 Result["insertText"] = CI.insertText;
377 if (CI.insertTextFormat != InsertTextFormat::Missing)
378 Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000379 if (CI.textEdit)
Sam McCalldd0566b2017-11-06 15:40:30 +0000380 Result["textEdit"] = *CI.textEdit;
381 if (!CI.additionalTextEdits.empty())
382 Result["additionalTextEdits"] = json::ary(CI.additionalTextEdits);
383 return std::move(Result);
Krasimir Georgiev6d2131a2017-04-04 09:46:39 +0000384}
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000385
Sam McCallff8b8742017-11-30 21:32:29 +0000386bool operator<(const CompletionItem &L, const CompletionItem &R) {
Sam McCallc78ccbd2017-11-08 07:44:12 +0000387 return (L.sortText.empty() ? L.label : L.sortText) <
388 (R.sortText.empty() ? R.label : R.sortText);
389}
390
Sam McCallff8b8742017-11-30 21:32:29 +0000391json::Expr toJSON(const CompletionList &L) {
Sam McCalla40371b2017-11-15 09:16:29 +0000392 return json::obj{
393 {"isIncomplete", L.isIncomplete},
394 {"items", json::ary(L.items)},
395 };
396}
397
Sam McCallff8b8742017-11-30 21:32:29 +0000398json::Expr toJSON(const ParameterInformation &PI) {
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000399 assert(!PI.label.empty() && "parameter information label is required");
Sam McCalldd0566b2017-11-06 15:40:30 +0000400 json::obj Result{{"label", PI.label}};
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000401 if (!PI.documentation.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000402 Result["documentation"] = PI.documentation;
403 return std::move(Result);
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000404}
405
Sam McCallff8b8742017-11-30 21:32:29 +0000406json::Expr toJSON(const SignatureInformation &SI) {
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000407 assert(!SI.label.empty() && "signature information label is required");
Sam McCalldd0566b2017-11-06 15:40:30 +0000408 json::obj Result{
409 {"label", SI.label},
410 {"parameters", json::ary(SI.parameters)},
411 };
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000412 if (!SI.documentation.empty())
Sam McCalldd0566b2017-11-06 15:40:30 +0000413 Result["documentation"] = SI.documentation;
414 return std::move(Result);
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000415}
416
Sam McCallff8b8742017-11-30 21:32:29 +0000417json::Expr toJSON(const SignatureHelp &SH) {
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000418 assert(SH.activeSignature >= 0 &&
419 "Unexpected negative value for number of active signatures.");
420 assert(SH.activeParameter >= 0 &&
421 "Unexpected negative value for active parameter index");
Sam McCalldd0566b2017-11-06 15:40:30 +0000422 return json::obj{
423 {"activeSignature", SH.activeSignature},
424 {"activeParameter", SH.activeParameter},
425 {"signatures", json::ary(SH.signatures)},
426 };
Ilya Biryukovd9bdfe02017-10-06 11:54:17 +0000427}
Haojian Wu345099c2017-11-09 11:30:04 +0000428
Sam McCallff8b8742017-11-30 21:32:29 +0000429bool fromJSON(const json::Expr &Params, RenameParams &R) {
430 json::ObjectMapper O(Params);
431 return O && O.map("textDocument", R.textDocument) &&
432 O.map("position", R.position) && O.map("newName", R.newName);
Haojian Wu345099c2017-11-09 11:30:04 +0000433}
Sam McCallff8b8742017-11-30 21:32:29 +0000434
Ilya Biryukov0e6a51f2017-12-12 12:27:47 +0000435json::Expr toJSON(const DocumentHighlight &DH) {
436 return json::obj{
437 {"range", toJSON(DH.range)},
438 {"kind", static_cast<int>(DH.kind)},
439 };
440}
441
Sam McCallff8b8742017-11-30 21:32:29 +0000442} // namespace clangd
443} // namespace clang