blob: 2814a5417a91fa51b19984aca6f4a414aeebdca8 [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.
11// FIXME: This is extremely repetetive and ugly. Is there a better way?
12//
13//===----------------------------------------------------------------------===//
14
15#include "Protocol.h"
16#include "clang/Basic/LLVM.h"
17#include "llvm/ADT/SmallString.h"
18#include "llvm/Support/Format.h"
19#include "llvm/Support/raw_ostream.h"
20using namespace clang::clangd;
21
22llvm::Optional<TextDocumentIdentifier>
23TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params) {
24 TextDocumentIdentifier Result;
25 for (auto &NextKeyValue : *Params) {
26 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
27 if (!KeyString)
28 return llvm::None;
29
30 llvm::SmallString<10> KeyStorage;
31 StringRef KeyValue = KeyString->getValue(KeyStorage);
32 auto *Value =
33 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
34 if (!Value)
35 return llvm::None;
36
37 llvm::SmallString<10> Storage;
38 if (KeyValue == "uri") {
39 Result.uri = Value->getValue(Storage);
40 } else if (KeyValue == "version") {
41 // FIXME: parse version, but only for VersionedTextDocumentIdentifiers.
42 } else {
43 return llvm::None;
44 }
45 }
46 return Result;
47}
48
49llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params) {
50 Position Result;
51 for (auto &NextKeyValue : *Params) {
52 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
53 if (!KeyString)
54 return llvm::None;
55
56 llvm::SmallString<10> KeyStorage;
57 StringRef KeyValue = KeyString->getValue(KeyStorage);
58 auto *Value =
59 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
60 if (!Value)
61 return llvm::None;
62
63 llvm::SmallString<10> Storage;
64 if (KeyValue == "line") {
65 long long Val;
66 if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
67 return llvm::None;
68 Result.line = Val;
69 } else if (KeyValue == "character") {
70 long long Val;
71 if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
72 return llvm::None;
73 Result.character = Val;
74 } else {
75 return llvm::None;
76 }
77 }
78 return Result;
79}
80
81std::string Position::unparse(const Position &P) {
82 std::string Result;
83 llvm::raw_string_ostream(Result)
84 << llvm::format(R"({"line": %d, "character": %d})", P.line, P.character);
85 return Result;
86}
87
88llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params) {
89 Range Result;
90 for (auto &NextKeyValue : *Params) {
91 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
92 if (!KeyString)
93 return llvm::None;
94
95 llvm::SmallString<10> KeyStorage;
96 StringRef KeyValue = KeyString->getValue(KeyStorage);
97 auto *Value =
98 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
99 if (!Value)
100 return llvm::None;
101
102 llvm::SmallString<10> Storage;
103 if (KeyValue == "start") {
104 auto Parsed = Position::parse(Value);
105 if (!Parsed)
106 return llvm::None;
107 Result.start = std::move(*Parsed);
108 } else if (KeyValue == "end") {
109 auto Parsed = Position::parse(Value);
110 if (!Parsed)
111 return llvm::None;
112 Result.end = std::move(*Parsed);
113 } else {
114 return llvm::None;
115 }
116 }
117 return Result;
118}
119
120std::string Range::unparse(const Range &P) {
121 std::string Result;
122 llvm::raw_string_ostream(Result) << llvm::format(
123 R"({"start": %s, "end": %s})", Position::unparse(P.start).c_str(),
124 Position::unparse(P.end).c_str());
125 return Result;
126}
127
128llvm::Optional<TextDocumentItem>
129TextDocumentItem::parse(llvm::yaml::MappingNode *Params) {
130 TextDocumentItem Result;
131 for (auto &NextKeyValue : *Params) {
132 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
133 if (!KeyString)
134 return llvm::None;
135
136 llvm::SmallString<10> KeyStorage;
137 StringRef KeyValue = KeyString->getValue(KeyStorage);
138 auto *Value =
139 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
140 if (!Value)
141 return llvm::None;
142
143 llvm::SmallString<10> Storage;
144 if (KeyValue == "uri") {
145 Result.uri = Value->getValue(Storage);
146 } else if (KeyValue == "languageId") {
147 Result.languageId = Value->getValue(Storage);
148 } else if (KeyValue == "version") {
149 long long Val;
150 if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
151 return llvm::None;
152 Result.version = Val;
153 } else if (KeyValue == "text") {
154 Result.text = Value->getValue(Storage);
155 } else {
156 return llvm::None;
157 }
158 }
159 return Result;
160}
161
162llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params) {
163 TextEdit Result;
164 for (auto &NextKeyValue : *Params) {
165 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
166 if (!KeyString)
167 return llvm::None;
168
169 llvm::SmallString<10> KeyStorage;
170 StringRef KeyValue = KeyString->getValue(KeyStorage);
171 auto *Value = NextKeyValue.getValue();
172
173 llvm::SmallString<10> Storage;
174 if (KeyValue == "range") {
175 auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
176 if (!Map)
177 return llvm::None;
178 auto Parsed = Range::parse(Map);
179 if (!Parsed)
180 return llvm::None;
181 Result.range = std::move(*Parsed);
182 } else if (KeyValue == "newText") {
183 auto *Node = dyn_cast<llvm::yaml::ScalarNode>(Value);
184 if (!Node)
185 return llvm::None;
186 Result.newText = Node->getValue(Storage);
187 } else {
188 return llvm::None;
189 }
190 }
191 return Result;
192}
193
194std::string TextEdit::unparse(const TextEdit &P) {
195 std::string Result;
196 llvm::raw_string_ostream(Result) << llvm::format(
197 R"({"range": %s, "newText": "%s"})", Range::unparse(P.range).c_str(),
198 llvm::yaml::escape(P.newText).c_str());
199 return Result;
200}
201
202llvm::Optional<DidOpenTextDocumentParams>
203DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
204 DidOpenTextDocumentParams Result;
205 for (auto &NextKeyValue : *Params) {
206 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
207 if (!KeyString)
208 return llvm::None;
209
210 llvm::SmallString<10> KeyStorage;
211 StringRef KeyValue = KeyString->getValue(KeyStorage);
212 auto *Value =
213 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
214 if (!Value)
215 return llvm::None;
216
217 llvm::SmallString<10> Storage;
218 if (KeyValue == "textDocument") {
219 auto Parsed = TextDocumentItem::parse(Value);
220 if (!Parsed)
221 return llvm::None;
222 Result.textDocument = std::move(*Parsed);
223 } else {
224 return llvm::None;
225 }
226 }
227 return Result;
228}
229
230llvm::Optional<DidChangeTextDocumentParams>
231DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
232 DidChangeTextDocumentParams Result;
233 for (auto &NextKeyValue : *Params) {
234 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
235 if (!KeyString)
236 return llvm::None;
237
238 llvm::SmallString<10> KeyStorage;
239 StringRef KeyValue = KeyString->getValue(KeyStorage);
240 auto *Value = NextKeyValue.getValue();
241
242 llvm::SmallString<10> Storage;
243 if (KeyValue == "textDocument") {
244 auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
245 if (!Map)
246 return llvm::None;
247 auto Parsed = TextDocumentIdentifier::parse(Map);
248 if (!Parsed)
249 return llvm::None;
250 Result.textDocument = std::move(*Parsed);
251 } else if (KeyValue == "contentChanges") {
252 auto *Seq = dyn_cast<llvm::yaml::SequenceNode>(Value);
253 if (!Seq)
254 return llvm::None;
255 for (auto &Item : *Seq) {
256 auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
257 if (!I)
258 return llvm::None;
259 auto Parsed = TextDocumentContentChangeEvent::parse(I);
260 if (!Parsed)
261 return llvm::None;
262 Result.contentChanges.push_back(std::move(*Parsed));
263 }
264 } else {
265 return llvm::None;
266 }
267 }
268 return Result;
269}
270
271llvm::Optional<TextDocumentContentChangeEvent>
272TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params) {
273 TextDocumentContentChangeEvent Result;
274 for (auto &NextKeyValue : *Params) {
275 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
276 if (!KeyString)
277 return llvm::None;
278
279 llvm::SmallString<10> KeyStorage;
280 StringRef KeyValue = KeyString->getValue(KeyStorage);
281 auto *Value =
282 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
283 if (!Value)
284 return llvm::None;
285
286 llvm::SmallString<10> Storage;
287 if (KeyValue == "text") {
288 Result.text = Value->getValue(Storage);
289 } else {
290 return llvm::None;
291 }
292 }
293 return Result;
294}
295
296llvm::Optional<FormattingOptions>
297FormattingOptions::parse(llvm::yaml::MappingNode *Params) {
298 FormattingOptions Result;
299 for (auto &NextKeyValue : *Params) {
300 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
301 if (!KeyString)
302 return llvm::None;
303
304 llvm::SmallString<10> KeyStorage;
305 StringRef KeyValue = KeyString->getValue(KeyStorage);
306 auto *Value =
307 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
308 if (!Value)
309 return llvm::None;
310
311 llvm::SmallString<10> Storage;
312 if (KeyValue == "tabSize") {
313 long long Val;
314 if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
315 return llvm::None;
316 Result.tabSize = Val;
317 } else if (KeyValue == "insertSpaces") {
318 long long Val;
319 StringRef Str = Value->getValue(Storage);
320 if (llvm::getAsSignedInteger(Str, 0, Val)) {
321 if (Str == "true")
322 Val = 1;
323 else if (Str == "false")
324 Val = 0;
325 else
326 return llvm::None;
327 }
328 Result.insertSpaces = Val;
329 } else {
330 return llvm::None;
331 }
332 }
333 return Result;
334}
335
336std::string FormattingOptions::unparse(const FormattingOptions &P) {
337 std::string Result;
338 llvm::raw_string_ostream(Result) << llvm::format(
339 R"({"tabSize": %d, "insertSpaces": %d})", P.tabSize, P.insertSpaces);
340 return Result;
341}
342
343llvm::Optional<DocumentRangeFormattingParams>
344DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
345 DocumentRangeFormattingParams Result;
346 for (auto &NextKeyValue : *Params) {
347 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
348 if (!KeyString)
349 return llvm::None;
350
351 llvm::SmallString<10> KeyStorage;
352 StringRef KeyValue = KeyString->getValue(KeyStorage);
353 auto *Value =
354 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
355 if (!Value)
356 return llvm::None;
357
358 llvm::SmallString<10> Storage;
359 if (KeyValue == "textDocument") {
360 auto Parsed = TextDocumentIdentifier::parse(Value);
361 if (!Parsed)
362 return llvm::None;
363 Result.textDocument = std::move(*Parsed);
364 } else if (KeyValue == "range") {
365 auto Parsed = Range::parse(Value);
366 if (!Parsed)
367 return llvm::None;
368 Result.range = std::move(*Parsed);
369 } else if (KeyValue == "options") {
370 auto Parsed = FormattingOptions::parse(Value);
371 if (!Parsed)
372 return llvm::None;
373 Result.options = std::move(*Parsed);
374 } else {
375 return llvm::None;
376 }
377 }
378 return Result;
379}
380
Krasimir Georgiev1b8bfd42017-02-16 10:49:46 +0000381llvm::Optional<DocumentOnTypeFormattingParams>
382DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
383 DocumentOnTypeFormattingParams Result;
384 for (auto &NextKeyValue : *Params) {
385 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
386 if (!KeyString)
387 return llvm::None;
388
389 llvm::SmallString<10> KeyStorage;
390 StringRef KeyValue = KeyString->getValue(KeyStorage);
391
392 if (KeyValue == "ch") {
393 auto *ScalarValue =
394 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
395 if (!ScalarValue)
396 return llvm::None;
397 llvm::SmallString<10> Storage;
398 Result.ch = ScalarValue->getValue(Storage);
399 continue;
400 }
401
402 auto *Value =
403 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
404 if (!Value)
405 return llvm::None;
406 if (KeyValue == "textDocument") {
407 auto Parsed = TextDocumentIdentifier::parse(Value);
408 if (!Parsed)
409 return llvm::None;
410 Result.textDocument = std::move(*Parsed);
411 } else if (KeyValue == "position") {
412 auto Parsed = Position::parse(Value);
413 if (!Parsed)
414 return llvm::None;
415 Result.position = std::move(*Parsed);
416 } else if (KeyValue == "options") {
417 auto Parsed = FormattingOptions::parse(Value);
418 if (!Parsed)
419 return llvm::None;
420 Result.options = std::move(*Parsed);
421 } else {
422 return llvm::None;
423 }
424 }
425 return Result;
426}
427
Benjamin Kramerbb1cdb62017-02-07 10:28:20 +0000428llvm::Optional<DocumentFormattingParams>
429DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params) {
430 DocumentFormattingParams Result;
431 for (auto &NextKeyValue : *Params) {
432 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
433 if (!KeyString)
434 return llvm::None;
435
436 llvm::SmallString<10> KeyStorage;
437 StringRef KeyValue = KeyString->getValue(KeyStorage);
438 auto *Value =
439 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
440 if (!Value)
441 return llvm::None;
442
443 llvm::SmallString<10> Storage;
444 if (KeyValue == "textDocument") {
445 auto Parsed = TextDocumentIdentifier::parse(Value);
446 if (!Parsed)
447 return llvm::None;
448 Result.textDocument = std::move(*Parsed);
449 } else if (KeyValue == "options") {
450 auto Parsed = FormattingOptions::parse(Value);
451 if (!Parsed)
452 return llvm::None;
453 Result.options = std::move(*Parsed);
454 } else {
455 return llvm::None;
456 }
457 }
458 return Result;
459}
Benjamin Kramerf0af3e62017-03-01 16:16:29 +0000460
461llvm::Optional<Diagnostic> Diagnostic::parse(llvm::yaml::MappingNode *Params) {
462 Diagnostic Result;
463 for (auto &NextKeyValue : *Params) {
464 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
465 if (!KeyString)
466 return llvm::None;
467
468 llvm::SmallString<10> KeyStorage;
469 StringRef KeyValue = KeyString->getValue(KeyStorage);
470
471 llvm::SmallString<10> Storage;
472 if (KeyValue == "range") {
473 auto *Value =
474 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
475 if (!Value)
476 return llvm::None;
477 auto Parsed = Range::parse(Value);
478 if (!Parsed)
479 return llvm::None;
480 Result.range = std::move(*Parsed);
481 } else if (KeyValue == "severity") {
482 auto *Value =
483 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
484 if (!Value)
485 return llvm::None;
486 long long Val;
487 if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
488 return llvm::None;
489 Result.severity = Val;
490 } else if (KeyValue == "message") {
491 auto *Value =
492 dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
493 if (!Value)
494 return llvm::None;
495 Result.message = Value->getValue(Storage);
496 } else {
497 return llvm::None;
498 }
499 }
500 return Result;
501}
502
503llvm::Optional<CodeActionContext>
504CodeActionContext::parse(llvm::yaml::MappingNode *Params) {
505 CodeActionContext Result;
506 for (auto &NextKeyValue : *Params) {
507 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
508 if (!KeyString)
509 return llvm::None;
510
511 llvm::SmallString<10> KeyStorage;
512 StringRef KeyValue = KeyString->getValue(KeyStorage);
513 auto *Value = NextKeyValue.getValue();
514
515 llvm::SmallString<10> Storage;
516 if (KeyValue == "diagnostics") {
517 auto *Seq = dyn_cast<llvm::yaml::SequenceNode>(Value);
518 if (!Seq)
519 return llvm::None;
520 for (auto &Item : *Seq) {
521 auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
522 if (!I)
523 return llvm::None;
524 auto Parsed = Diagnostic::parse(I);
525 if (!Parsed)
526 return llvm::None;
527 Result.diagnostics.push_back(std::move(*Parsed));
528 }
529 } else {
530 return llvm::None;
531 }
532 }
533 return Result;
534}
535
536llvm::Optional<CodeActionParams>
537CodeActionParams::parse(llvm::yaml::MappingNode *Params) {
538 CodeActionParams Result;
539 for (auto &NextKeyValue : *Params) {
540 auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
541 if (!KeyString)
542 return llvm::None;
543
544 llvm::SmallString<10> KeyStorage;
545 StringRef KeyValue = KeyString->getValue(KeyStorage);
546 auto *Value =
547 dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
548 if (!Value)
549 return llvm::None;
550
551 llvm::SmallString<10> Storage;
552 if (KeyValue == "textDocument") {
553 auto Parsed = TextDocumentIdentifier::parse(Value);
554 if (!Parsed)
555 return llvm::None;
556 Result.textDocument = std::move(*Parsed);
557 } else if (KeyValue == "range") {
558 auto Parsed = Range::parse(Value);
559 if (!Parsed)
560 return llvm::None;
561 Result.range = std::move(*Parsed);
562 } else if (KeyValue == "context") {
563 auto Parsed = CodeActionContext::parse(Value);
564 if (!Parsed)
565 return llvm::None;
566 Result.context = std::move(*Parsed);
567 } else {
568 return llvm::None;
569 }
570 }
571 return Result;
572}