1 //===--- Protocol.h - Language Server Protocol Implementation ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains structs based on the LSP specification at
10 // https://microsoft.github.io/language-server-protocol/specification
11 //
12 // This is not meant to be a complete implementation, new interfaces are added
13 // when they're needed.
14 //
15 // Each struct has a toJSON and fromJSON function, that converts between
16 // the struct and a JSON representation. (See JSON.h)
17 //
18 // Some structs also have operator<< serialization. This is for debugging and
19 // tests, and is not generally machine-readable.
20 //
21 //===----------------------------------------------------------------------===//
22
23 #ifndef LIB_MLIR_TOOLS_LSPSERVERSUPPORT_PROTOCOL_H_
24 #define LIB_MLIR_TOOLS_LSPSERVERSUPPORT_PROTOCOL_H_
25
26 #include "mlir/Support/LLVM.h"
27 #include "llvm/ADT/Optional.h"
28 #include "llvm/Support/JSON.h"
29 #include "llvm/Support/SourceMgr.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include <bitset>
32 #include <memory>
33 #include <string>
34 #include <utility>
35 #include <vector>
36
37 namespace mlir {
38 struct LogicalResult;
39
40 namespace lsp {
41
42 enum class ErrorCode {
43 // Defined by JSON RPC.
44 ParseError = -32700,
45 InvalidRequest = -32600,
46 MethodNotFound = -32601,
47 InvalidParams = -32602,
48 InternalError = -32603,
49
50 ServerNotInitialized = -32002,
51 UnknownErrorCode = -32001,
52
53 // Defined by the protocol.
54 RequestCancelled = -32800,
55 ContentModified = -32801,
56 };
57
58 /// Defines how the host (editor) should sync document changes to the language
59 /// server.
60 enum class TextDocumentSyncKind {
61 /// Documents should not be synced at all.
62 None = 0,
63
64 /// Documents are synced by always sending the full content of the document.
65 Full = 1,
66
67 /// Documents are synced by sending the full content on open. After that only
68 /// incremental updates to the document are sent.
69 Incremental = 2,
70 };
71
72 //===----------------------------------------------------------------------===//
73 // LSPError
74 //===----------------------------------------------------------------------===//
75
76 /// This class models an LSP error as an llvm::Error.
77 class LSPError : public llvm::ErrorInfo<LSPError> {
78 public:
79 std::string message;
80 ErrorCode code;
81 static char ID;
82
LSPError(std::string message,ErrorCode code)83 LSPError(std::string message, ErrorCode code)
84 : message(std::move(message)), code(code) {}
85
log(raw_ostream & os)86 void log(raw_ostream &os) const override {
87 os << int(code) << ": " << message;
88 }
convertToErrorCode()89 std::error_code convertToErrorCode() const override {
90 return llvm::inconvertibleErrorCode();
91 }
92 };
93
94 //===----------------------------------------------------------------------===//
95 // URIForFile
96 //===----------------------------------------------------------------------===//
97
98 /// URI in "file" scheme for a file.
99 class URIForFile {
100 public:
101 URIForFile() = default;
102
103 /// Try to build a URIForFile from the given URI string.
104 static llvm::Expected<URIForFile> fromURI(StringRef uri);
105
106 /// Try to build a URIForFile from the given absolute file path.
107 static llvm::Expected<URIForFile> fromFile(StringRef absoluteFilepath);
108
109 /// Returns the absolute path to the file.
file()110 StringRef file() const { return filePath; }
111
112 /// Returns the original uri of the file.
uri()113 StringRef uri() const { return uriStr; }
114
115 explicit operator bool() const { return !filePath.empty(); }
116
117 friend bool operator==(const URIForFile &lhs, const URIForFile &rhs) {
118 return lhs.filePath == rhs.filePath;
119 }
120 friend bool operator!=(const URIForFile &lhs, const URIForFile &rhs) {
121 return !(lhs == rhs);
122 }
123 friend bool operator<(const URIForFile &lhs, const URIForFile &rhs) {
124 return lhs.filePath < rhs.filePath;
125 }
126
127 private:
URIForFile(std::string && filePath,std::string && uriStr)128 explicit URIForFile(std::string &&filePath, std::string &&uriStr)
129 : filePath(std::move(filePath)), uriStr(uriStr) {}
130
131 std::string filePath;
132 std::string uriStr;
133 };
134
135 /// Add support for JSON serialization.
136 llvm::json::Value toJSON(const URIForFile &value);
137 bool fromJSON(const llvm::json::Value &value, URIForFile &result,
138 llvm::json::Path path);
139 raw_ostream &operator<<(raw_ostream &os, const URIForFile &value);
140
141 //===----------------------------------------------------------------------===//
142 // ClientCapabilities
143 //===----------------------------------------------------------------------===//
144
145 struct ClientCapabilities {
146 /// Client supports hierarchical document symbols.
147 /// textDocument.documentSymbol.hierarchicalDocumentSymbolSupport
148 bool hierarchicalDocumentSymbol = false;
149
150 /// Client supports CodeAction return value for textDocument/codeAction.
151 /// textDocument.codeAction.codeActionLiteralSupport.
152 bool codeActionStructure = false;
153 };
154
155 /// Add support for JSON serialization.
156 bool fromJSON(const llvm::json::Value &value, ClientCapabilities &result,
157 llvm::json::Path path);
158
159 //===----------------------------------------------------------------------===//
160 // InitializeParams
161 //===----------------------------------------------------------------------===//
162
163 enum class TraceLevel {
164 Off = 0,
165 Messages = 1,
166 Verbose = 2,
167 };
168
169 /// Add support for JSON serialization.
170 bool fromJSON(const llvm::json::Value &value, TraceLevel &result,
171 llvm::json::Path path);
172
173 struct InitializeParams {
174 /// The capabilities provided by the client (editor or tool).
175 ClientCapabilities capabilities;
176
177 /// The initial trace setting. If omitted trace is disabled ('off').
178 Optional<TraceLevel> trace;
179 };
180
181 /// Add support for JSON serialization.
182 bool fromJSON(const llvm::json::Value &value, InitializeParams &result,
183 llvm::json::Path path);
184
185 //===----------------------------------------------------------------------===//
186 // InitializedParams
187 //===----------------------------------------------------------------------===//
188
189 struct NoParams {};
fromJSON(const llvm::json::Value &,NoParams &,llvm::json::Path)190 inline bool fromJSON(const llvm::json::Value &, NoParams &, llvm::json::Path) {
191 return true;
192 }
193 using InitializedParams = NoParams;
194
195 //===----------------------------------------------------------------------===//
196 // TextDocumentItem
197 //===----------------------------------------------------------------------===//
198
199 struct TextDocumentItem {
200 /// The text document's URI.
201 URIForFile uri;
202
203 /// The text document's language identifier.
204 std::string languageId;
205
206 /// The content of the opened text document.
207 std::string text;
208
209 /// The version number of this document.
210 int64_t version;
211 };
212
213 /// Add support for JSON serialization.
214 bool fromJSON(const llvm::json::Value &value, TextDocumentItem &result,
215 llvm::json::Path path);
216
217 //===----------------------------------------------------------------------===//
218 // TextDocumentIdentifier
219 //===----------------------------------------------------------------------===//
220
221 struct TextDocumentIdentifier {
222 /// The text document's URI.
223 URIForFile uri;
224 };
225
226 /// Add support for JSON serialization.
227 llvm::json::Value toJSON(const TextDocumentIdentifier &value);
228 bool fromJSON(const llvm::json::Value &value, TextDocumentIdentifier &result,
229 llvm::json::Path path);
230
231 //===----------------------------------------------------------------------===//
232 // VersionedTextDocumentIdentifier
233 //===----------------------------------------------------------------------===//
234
235 struct VersionedTextDocumentIdentifier {
236 /// The text document's URI.
237 URIForFile uri;
238 /// The version number of this document.
239 int64_t version;
240 };
241
242 /// Add support for JSON serialization.
243 llvm::json::Value toJSON(const VersionedTextDocumentIdentifier &value);
244 bool fromJSON(const llvm::json::Value &value,
245 VersionedTextDocumentIdentifier &result, llvm::json::Path path);
246
247 //===----------------------------------------------------------------------===//
248 // Position
249 //===----------------------------------------------------------------------===//
250
251 struct Position {
252 Position(int line = 0, int character = 0)
linePosition253 : line(line), character(character) {}
254
255 /// Construct a position from the given source location.
PositionPosition256 Position(llvm::SourceMgr &mgr, SMLoc loc) {
257 std::pair<unsigned, unsigned> lineAndCol = mgr.getLineAndColumn(loc);
258 line = lineAndCol.first - 1;
259 character = lineAndCol.second - 1;
260 }
261
262 /// Line position in a document (zero-based).
263 int line = 0;
264
265 /// Character offset on a line in a document (zero-based).
266 int character = 0;
267
268 friend bool operator==(const Position &lhs, const Position &rhs) {
269 return std::tie(lhs.line, lhs.character) ==
270 std::tie(rhs.line, rhs.character);
271 }
272 friend bool operator!=(const Position &lhs, const Position &rhs) {
273 return !(lhs == rhs);
274 }
275 friend bool operator<(const Position &lhs, const Position &rhs) {
276 return std::tie(lhs.line, lhs.character) <
277 std::tie(rhs.line, rhs.character);
278 }
279 friend bool operator<=(const Position &lhs, const Position &rhs) {
280 return std::tie(lhs.line, lhs.character) <=
281 std::tie(rhs.line, rhs.character);
282 }
283
284 /// Convert this position into a source location in the main file of the given
285 /// source manager.
getAsSMLocPosition286 SMLoc getAsSMLoc(llvm::SourceMgr &mgr) const {
287 return mgr.FindLocForLineAndColumn(mgr.getMainFileID(), line + 1,
288 character + 1);
289 }
290 };
291
292 /// Add support for JSON serialization.
293 bool fromJSON(const llvm::json::Value &value, Position &result,
294 llvm::json::Path path);
295 llvm::json::Value toJSON(const Position &value);
296 raw_ostream &operator<<(raw_ostream &os, const Position &value);
297
298 //===----------------------------------------------------------------------===//
299 // Range
300 //===----------------------------------------------------------------------===//
301
302 struct Range {
303 Range() = default;
RangeRange304 Range(Position start, Position end) : start(start), end(end) {}
RangeRange305 Range(Position loc) : Range(loc, loc) {}
306
307 /// Construct a range from the given source range.
RangeRange308 Range(llvm::SourceMgr &mgr, SMRange range)
309 : Range(Position(mgr, range.Start), Position(mgr, range.End)) {}
310
311 /// The range's start position.
312 Position start;
313
314 /// The range's end position.
315 Position end;
316
317 friend bool operator==(const Range &lhs, const Range &rhs) {
318 return std::tie(lhs.start, lhs.end) == std::tie(rhs.start, rhs.end);
319 }
320 friend bool operator!=(const Range &lhs, const Range &rhs) {
321 return !(lhs == rhs);
322 }
323 friend bool operator<(const Range &lhs, const Range &rhs) {
324 return std::tie(lhs.start, lhs.end) < std::tie(rhs.start, rhs.end);
325 }
326
containsRange327 bool contains(Position pos) const { return start <= pos && pos < end; }
containsRange328 bool contains(Range range) const {
329 return start <= range.start && range.end <= end;
330 }
331
332 /// Convert this range into a source range in the main file of the given
333 /// source manager.
getAsSMRangeRange334 SMRange getAsSMRange(llvm::SourceMgr &mgr) const {
335 SMLoc startLoc = start.getAsSMLoc(mgr);
336 SMLoc endLoc = end.getAsSMLoc(mgr);
337 // Check that the start and end locations are valid.
338 if (!startLoc.isValid() || !endLoc.isValid() ||
339 startLoc.getPointer() > endLoc.getPointer())
340 return SMRange();
341 return SMRange(startLoc, endLoc);
342 }
343 };
344
345 /// Add support for JSON serialization.
346 bool fromJSON(const llvm::json::Value &value, Range &result,
347 llvm::json::Path path);
348 llvm::json::Value toJSON(const Range &value);
349 raw_ostream &operator<<(raw_ostream &os, const Range &value);
350
351 //===----------------------------------------------------------------------===//
352 // Location
353 //===----------------------------------------------------------------------===//
354
355 struct Location {
356 Location() = default;
LocationLocation357 Location(const URIForFile &uri, Range range) : uri(uri), range(range) {}
358
359 /// Construct a Location from the given source range.
LocationLocation360 Location(const URIForFile &uri, llvm::SourceMgr &mgr, SMRange range)
361 : Location(uri, Range(mgr, range)) {}
362
363 /// The text document's URI.
364 URIForFile uri;
365 Range range;
366
367 friend bool operator==(const Location &lhs, const Location &rhs) {
368 return lhs.uri == rhs.uri && lhs.range == rhs.range;
369 }
370
371 friend bool operator!=(const Location &lhs, const Location &rhs) {
372 return !(lhs == rhs);
373 }
374
375 friend bool operator<(const Location &lhs, const Location &rhs) {
376 return std::tie(lhs.uri, lhs.range) < std::tie(rhs.uri, rhs.range);
377 }
378 };
379
380 /// Add support for JSON serialization.
381 bool fromJSON(const llvm::json::Value &value, Location &result,
382 llvm::json::Path path);
383 llvm::json::Value toJSON(const Location &value);
384 raw_ostream &operator<<(raw_ostream &os, const Location &value);
385
386 //===----------------------------------------------------------------------===//
387 // TextDocumentPositionParams
388 //===----------------------------------------------------------------------===//
389
390 struct TextDocumentPositionParams {
391 /// The text document.
392 TextDocumentIdentifier textDocument;
393
394 /// The position inside the text document.
395 Position position;
396 };
397
398 /// Add support for JSON serialization.
399 bool fromJSON(const llvm::json::Value &value,
400 TextDocumentPositionParams &result, llvm::json::Path path);
401
402 //===----------------------------------------------------------------------===//
403 // ReferenceParams
404 //===----------------------------------------------------------------------===//
405
406 struct ReferenceContext {
407 /// Include the declaration of the current symbol.
408 bool includeDeclaration = false;
409 };
410
411 /// Add support for JSON serialization.
412 bool fromJSON(const llvm::json::Value &value, ReferenceContext &result,
413 llvm::json::Path path);
414
415 struct ReferenceParams : public TextDocumentPositionParams {
416 ReferenceContext context;
417 };
418
419 /// Add support for JSON serialization.
420 bool fromJSON(const llvm::json::Value &value, ReferenceParams &result,
421 llvm::json::Path path);
422
423 //===----------------------------------------------------------------------===//
424 // DidOpenTextDocumentParams
425 //===----------------------------------------------------------------------===//
426
427 struct DidOpenTextDocumentParams {
428 /// The document that was opened.
429 TextDocumentItem textDocument;
430 };
431
432 /// Add support for JSON serialization.
433 bool fromJSON(const llvm::json::Value &value, DidOpenTextDocumentParams &result,
434 llvm::json::Path path);
435
436 //===----------------------------------------------------------------------===//
437 // DidCloseTextDocumentParams
438 //===----------------------------------------------------------------------===//
439
440 struct DidCloseTextDocumentParams {
441 /// The document that was closed.
442 TextDocumentIdentifier textDocument;
443 };
444
445 /// Add support for JSON serialization.
446 bool fromJSON(const llvm::json::Value &value,
447 DidCloseTextDocumentParams &result, llvm::json::Path path);
448
449 //===----------------------------------------------------------------------===//
450 // DidChangeTextDocumentParams
451 //===----------------------------------------------------------------------===//
452
453 struct TextDocumentContentChangeEvent {
454 /// Try to apply this change to the given contents string.
455 LogicalResult applyTo(std::string &contents) const;
456 /// Try to apply a set of changes to the given contents string.
457 static LogicalResult applyTo(ArrayRef<TextDocumentContentChangeEvent> changes,
458 std::string &contents);
459
460 /// The range of the document that changed.
461 Optional<Range> range;
462
463 /// The length of the range that got replaced.
464 Optional<int> rangeLength;
465
466 /// The new text of the range/document.
467 std::string text;
468 };
469
470 /// Add support for JSON serialization.
471 bool fromJSON(const llvm::json::Value &value,
472 TextDocumentContentChangeEvent &result, llvm::json::Path path);
473
474 struct DidChangeTextDocumentParams {
475 /// The document that changed.
476 VersionedTextDocumentIdentifier textDocument;
477
478 /// The actual content changes.
479 std::vector<TextDocumentContentChangeEvent> contentChanges;
480 };
481
482 /// Add support for JSON serialization.
483 bool fromJSON(const llvm::json::Value &value,
484 DidChangeTextDocumentParams &result, llvm::json::Path path);
485
486 //===----------------------------------------------------------------------===//
487 // MarkupContent
488 //===----------------------------------------------------------------------===//
489
490 /// Describes the content type that a client supports in various result literals
491 /// like `Hover`.
492 enum class MarkupKind {
493 PlainText,
494 Markdown,
495 };
496 raw_ostream &operator<<(raw_ostream &os, MarkupKind kind);
497
498 struct MarkupContent {
499 MarkupKind kind = MarkupKind::PlainText;
500 std::string value;
501 };
502
503 /// Add support for JSON serialization.
504 llvm::json::Value toJSON(const MarkupContent &mc);
505
506 //===----------------------------------------------------------------------===//
507 // Hover
508 //===----------------------------------------------------------------------===//
509
510 struct Hover {
511 /// Construct a default hover with the given range that uses Markdown content.
HoverHover512 Hover(Range range) : contents{MarkupKind::Markdown, ""}, range(range) {}
513
514 /// The hover's content.
515 MarkupContent contents;
516
517 /// An optional range is a range inside a text document that is used to
518 /// visualize a hover, e.g. by changing the background color.
519 Optional<Range> range;
520 };
521
522 /// Add support for JSON serialization.
523 llvm::json::Value toJSON(const Hover &hover);
524
525 //===----------------------------------------------------------------------===//
526 // SymbolKind
527 //===----------------------------------------------------------------------===//
528
529 enum class SymbolKind {
530 File = 1,
531 Module = 2,
532 Namespace = 3,
533 Package = 4,
534 Class = 5,
535 Method = 6,
536 Property = 7,
537 Field = 8,
538 Constructor = 9,
539 Enum = 10,
540 Interface = 11,
541 Function = 12,
542 Variable = 13,
543 Constant = 14,
544 String = 15,
545 Number = 16,
546 Boolean = 17,
547 Array = 18,
548 Object = 19,
549 Key = 20,
550 Null = 21,
551 EnumMember = 22,
552 Struct = 23,
553 Event = 24,
554 Operator = 25,
555 TypeParameter = 26
556 };
557
558 //===----------------------------------------------------------------------===//
559 // DocumentSymbol
560 //===----------------------------------------------------------------------===//
561
562 /// Represents programming constructs like variables, classes, interfaces etc.
563 /// that appear in a document. Document symbols can be hierarchical and they
564 /// have two ranges: one that encloses its definition and one that points to its
565 /// most interesting range, e.g. the range of an identifier.
566 struct DocumentSymbol {
567 DocumentSymbol() = default;
568 DocumentSymbol(DocumentSymbol &&) = default;
DocumentSymbolDocumentSymbol569 DocumentSymbol(const Twine &name, SymbolKind kind, Range range,
570 Range selectionRange)
571 : name(name.str()), kind(kind), range(range),
572 selectionRange(selectionRange) {}
573
574 /// The name of this symbol.
575 std::string name;
576
577 /// More detail for this symbol, e.g the signature of a function.
578 std::string detail;
579
580 /// The kind of this symbol.
581 SymbolKind kind;
582
583 /// The range enclosing this symbol not including leading/trailing whitespace
584 /// but everything else like comments. This information is typically used to
585 /// determine if the clients cursor is inside the symbol to reveal in the
586 /// symbol in the UI.
587 Range range;
588
589 /// The range that should be selected and revealed when this symbol is being
590 /// picked, e.g the name of a function. Must be contained by the `range`.
591 Range selectionRange;
592
593 /// Children of this symbol, e.g. properties of a class.
594 std::vector<DocumentSymbol> children;
595 };
596
597 /// Add support for JSON serialization.
598 llvm::json::Value toJSON(const DocumentSymbol &symbol);
599
600 //===----------------------------------------------------------------------===//
601 // DocumentSymbolParams
602 //===----------------------------------------------------------------------===//
603
604 struct DocumentSymbolParams {
605 // The text document to find symbols in.
606 TextDocumentIdentifier textDocument;
607 };
608
609 /// Add support for JSON serialization.
610 bool fromJSON(const llvm::json::Value &value, DocumentSymbolParams &result,
611 llvm::json::Path path);
612
613 //===----------------------------------------------------------------------===//
614 // DiagnosticRelatedInformation
615 //===----------------------------------------------------------------------===//
616
617 /// Represents a related message and source code location for a diagnostic.
618 /// This should be used to point to code locations that cause or related to a
619 /// diagnostics, e.g. when duplicating a symbol in a scope.
620 struct DiagnosticRelatedInformation {
621 DiagnosticRelatedInformation() = default;
DiagnosticRelatedInformationDiagnosticRelatedInformation622 DiagnosticRelatedInformation(Location location, std::string message)
623 : location(std::move(location)), message(std::move(message)) {}
624
625 /// The location of this related diagnostic information.
626 Location location;
627 /// The message of this related diagnostic information.
628 std::string message;
629 };
630
631 /// Add support for JSON serialization.
632 bool fromJSON(const llvm::json::Value &value,
633 DiagnosticRelatedInformation &result, llvm::json::Path path);
634 llvm::json::Value toJSON(const DiagnosticRelatedInformation &info);
635
636 //===----------------------------------------------------------------------===//
637 // Diagnostic
638 //===----------------------------------------------------------------------===//
639
640 enum class DiagnosticSeverity {
641 /// It is up to the client to interpret diagnostics as error, warning, info or
642 /// hint.
643 Undetermined = 0,
644 Error = 1,
645 Warning = 2,
646 Information = 3,
647 Hint = 4
648 };
649
650 struct Diagnostic {
651 /// The source range where the message applies.
652 Range range;
653
654 /// The diagnostic's severity. Can be omitted. If omitted it is up to the
655 /// client to interpret diagnostics as error, warning, info or hint.
656 DiagnosticSeverity severity = DiagnosticSeverity::Undetermined;
657
658 /// A human-readable string describing the source of this diagnostic, e.g.
659 /// 'typescript' or 'super lint'.
660 std::string source;
661
662 /// The diagnostic's message.
663 std::string message;
664
665 /// An array of related diagnostic information, e.g. when symbol-names within
666 /// a scope collide all definitions can be marked via this property.
667 Optional<std::vector<DiagnosticRelatedInformation>> relatedInformation;
668
669 /// The diagnostic's category. Can be omitted.
670 /// An LSP extension that's used to send the name of the category over to the
671 /// client. The category typically describes the compilation stage during
672 /// which the issue was produced, e.g. "Semantic Issue" or "Parse Issue".
673 Optional<std::string> category;
674 };
675
676 /// Add support for JSON serialization.
677 llvm::json::Value toJSON(const Diagnostic &diag);
678 bool fromJSON(const llvm::json::Value &value, Diagnostic &result,
679 llvm::json::Path path);
680
681 //===----------------------------------------------------------------------===//
682 // PublishDiagnosticsParams
683 //===----------------------------------------------------------------------===//
684
685 struct PublishDiagnosticsParams {
PublishDiagnosticsParamsPublishDiagnosticsParams686 PublishDiagnosticsParams(URIForFile uri, int64_t version)
687 : uri(std::move(uri)), version(version) {}
688
689 /// The URI for which diagnostic information is reported.
690 URIForFile uri;
691 /// The list of reported diagnostics.
692 std::vector<Diagnostic> diagnostics;
693 /// The version number of the document the diagnostics are published for.
694 int64_t version;
695 };
696
697 /// Add support for JSON serialization.
698 llvm::json::Value toJSON(const PublishDiagnosticsParams ¶ms);
699
700 //===----------------------------------------------------------------------===//
701 // TextEdit
702 //===----------------------------------------------------------------------===//
703
704 struct TextEdit {
705 /// The range of the text document to be manipulated. To insert
706 /// text into a document create a range where start === end.
707 Range range;
708
709 /// The string to be inserted. For delete operations use an
710 /// empty string.
711 std::string newText;
712 };
713
714 inline bool operator==(const TextEdit &lhs, const TextEdit &rhs) {
715 return std::tie(lhs.newText, lhs.range) == std::tie(rhs.newText, rhs.range);
716 }
717
718 bool fromJSON(const llvm::json::Value &value, TextEdit &result,
719 llvm::json::Path path);
720 llvm::json::Value toJSON(const TextEdit &value);
721 raw_ostream &operator<<(raw_ostream &os, const TextEdit &value);
722
723 //===----------------------------------------------------------------------===//
724 // CompletionItemKind
725 //===----------------------------------------------------------------------===//
726
727 /// The kind of a completion entry.
728 enum class CompletionItemKind {
729 Missing = 0,
730 Text = 1,
731 Method = 2,
732 Function = 3,
733 Constructor = 4,
734 Field = 5,
735 Variable = 6,
736 Class = 7,
737 Interface = 8,
738 Module = 9,
739 Property = 10,
740 Unit = 11,
741 Value = 12,
742 Enum = 13,
743 Keyword = 14,
744 Snippet = 15,
745 Color = 16,
746 File = 17,
747 Reference = 18,
748 Folder = 19,
749 EnumMember = 20,
750 Constant = 21,
751 Struct = 22,
752 Event = 23,
753 Operator = 24,
754 TypeParameter = 25,
755 };
756 bool fromJSON(const llvm::json::Value &value, CompletionItemKind &result,
757 llvm::json::Path path);
758
759 constexpr auto kCompletionItemKindMin =
760 static_cast<size_t>(CompletionItemKind::Text);
761 constexpr auto kCompletionItemKindMax =
762 static_cast<size_t>(CompletionItemKind::TypeParameter);
763 using CompletionItemKindBitset = std::bitset<kCompletionItemKindMax + 1>;
764 bool fromJSON(const llvm::json::Value &value, CompletionItemKindBitset &result,
765 llvm::json::Path path);
766
767 CompletionItemKind
768 adjustKindToCapability(CompletionItemKind kind,
769 CompletionItemKindBitset &supportedCompletionItemKinds);
770
771 //===----------------------------------------------------------------------===//
772 // CompletionItem
773 //===----------------------------------------------------------------------===//
774
775 /// Defines whether the insert text in a completion item should be interpreted
776 /// as plain text or a snippet.
777 enum class InsertTextFormat {
778 Missing = 0,
779 /// The primary text to be inserted is treated as a plain string.
780 PlainText = 1,
781 /// The primary text to be inserted is treated as a snippet.
782 ///
783 /// A snippet can define tab stops and placeholders with `$1`, `$2`
784 /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to the end
785 /// of the snippet. Placeholders with equal identifiers are linked, that is
786 /// typing in one will update others too.
787 ///
788 /// See also:
789 /// https//github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
790 Snippet = 2,
791 };
792
793 struct CompletionItem {
794 CompletionItem() = default;
795 CompletionItem(const Twine &label, CompletionItemKind kind,
796 StringRef sortText = "")
797 : label(label.str()), kind(kind), sortText(sortText.str()),
798 insertTextFormat(InsertTextFormat::PlainText) {}
799
800 /// The label of this completion item. By default also the text that is
801 /// inserted when selecting this completion.
802 std::string label;
803
804 /// The kind of this completion item. Based of the kind an icon is chosen by
805 /// the editor.
806 CompletionItemKind kind = CompletionItemKind::Missing;
807
808 /// A human-readable string with additional information about this item, like
809 /// type or symbol information.
810 std::string detail;
811
812 /// A human-readable string that represents a doc-comment.
813 Optional<MarkupContent> documentation;
814
815 /// A string that should be used when comparing this item with other items.
816 /// When `falsy` the label is used.
817 std::string sortText;
818
819 /// A string that should be used when filtering a set of completion items.
820 /// When `falsy` the label is used.
821 std::string filterText;
822
823 /// A string that should be inserted to a document when selecting this
824 /// completion. When `falsy` the label is used.
825 std::string insertText;
826
827 /// The format of the insert text. The format applies to both the `insertText`
828 /// property and the `newText` property of a provided `textEdit`.
829 InsertTextFormat insertTextFormat = InsertTextFormat::Missing;
830
831 /// An edit which is applied to a document when selecting this completion.
832 /// When an edit is provided `insertText` is ignored.
833 ///
834 /// Note: The range of the edit must be a single line range and it must
835 /// contain the position at which completion has been requested.
836 Optional<TextEdit> textEdit;
837
838 /// An optional array of additional text edits that are applied when selecting
839 /// this completion. Edits must not overlap with the main edit nor with
840 /// themselves.
841 std::vector<TextEdit> additionalTextEdits;
842
843 /// Indicates if this item is deprecated.
844 bool deprecated = false;
845 };
846
847 /// Add support for JSON serialization.
848 llvm::json::Value toJSON(const CompletionItem &value);
849 raw_ostream &operator<<(raw_ostream &os, const CompletionItem &value);
850 bool operator<(const CompletionItem &lhs, const CompletionItem &rhs);
851
852 //===----------------------------------------------------------------------===//
853 // CompletionList
854 //===----------------------------------------------------------------------===//
855
856 /// Represents a collection of completion items to be presented in the editor.
857 struct CompletionList {
858 /// The list is not complete. Further typing should result in recomputing the
859 /// list.
860 bool isIncomplete = false;
861
862 /// The completion items.
863 std::vector<CompletionItem> items;
864 };
865
866 /// Add support for JSON serialization.
867 llvm::json::Value toJSON(const CompletionList &value);
868
869 //===----------------------------------------------------------------------===//
870 // CompletionContext
871 //===----------------------------------------------------------------------===//
872
873 enum class CompletionTriggerKind {
874 /// Completion was triggered by typing an identifier (24x7 code
875 /// complete), manual invocation (e.g Ctrl+Space) or via API.
876 Invoked = 1,
877
878 /// Completion was triggered by a trigger character specified by
879 /// the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
880 TriggerCharacter = 2,
881
882 /// Completion was re-triggered as the current completion list is incomplete.
883 TriggerTriggerForIncompleteCompletions = 3
884 };
885
886 struct CompletionContext {
887 /// How the completion was triggered.
888 CompletionTriggerKind triggerKind = CompletionTriggerKind::Invoked;
889
890 /// The trigger character (a single character) that has trigger code complete.
891 /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
892 std::string triggerCharacter;
893 };
894
895 /// Add support for JSON serialization.
896 bool fromJSON(const llvm::json::Value &value, CompletionContext &result,
897 llvm::json::Path path);
898
899 //===----------------------------------------------------------------------===//
900 // CompletionParams
901 //===----------------------------------------------------------------------===//
902
903 struct CompletionParams : TextDocumentPositionParams {
904 CompletionContext context;
905 };
906
907 /// Add support for JSON serialization.
908 bool fromJSON(const llvm::json::Value &value, CompletionParams &result,
909 llvm::json::Path path);
910
911 //===----------------------------------------------------------------------===//
912 // ParameterInformation
913 //===----------------------------------------------------------------------===//
914
915 /// A single parameter of a particular signature.
916 struct ParameterInformation {
917 /// The label of this parameter. Ignored when labelOffsets is set.
918 std::string labelString;
919
920 /// Inclusive start and exclusive end offsets withing the containing signature
921 /// label.
922 Optional<std::pair<unsigned, unsigned>> labelOffsets;
923
924 /// The documentation of this parameter. Optional.
925 std::string documentation;
926 };
927
928 /// Add support for JSON serialization.
929 llvm::json::Value toJSON(const ParameterInformation &value);
930
931 //===----------------------------------------------------------------------===//
932 // SignatureInformation
933 //===----------------------------------------------------------------------===//
934
935 /// Represents the signature of something callable.
936 struct SignatureInformation {
937 /// The label of this signature. Mandatory.
938 std::string label;
939
940 /// The documentation of this signature. Optional.
941 std::string documentation;
942
943 /// The parameters of this signature.
944 std::vector<ParameterInformation> parameters;
945 };
946
947 /// Add support for JSON serialization.
948 llvm::json::Value toJSON(const SignatureInformation &value);
949 raw_ostream &operator<<(raw_ostream &os, const SignatureInformation &value);
950
951 //===----------------------------------------------------------------------===//
952 // SignatureHelp
953 //===----------------------------------------------------------------------===//
954
955 /// Represents the signature of a callable.
956 struct SignatureHelp {
957 /// The resulting signatures.
958 std::vector<SignatureInformation> signatures;
959
960 /// The active signature.
961 int activeSignature = 0;
962
963 /// The active parameter of the active signature.
964 int activeParameter = 0;
965 };
966
967 /// Add support for JSON serialization.
968 llvm::json::Value toJSON(const SignatureHelp &value);
969
970 //===----------------------------------------------------------------------===//
971 // DocumentLinkParams
972 //===----------------------------------------------------------------------===//
973
974 /// Parameters for the document link request.
975 struct DocumentLinkParams {
976 /// The document to provide document links for.
977 TextDocumentIdentifier textDocument;
978 };
979
980 /// Add support for JSON serialization.
981 bool fromJSON(const llvm::json::Value &value, DocumentLinkParams &result,
982 llvm::json::Path path);
983
984 //===----------------------------------------------------------------------===//
985 // DocumentLink
986 //===----------------------------------------------------------------------===//
987
988 /// A range in a text document that links to an internal or external resource,
989 /// like another text document or a web site.
990 struct DocumentLink {
991 DocumentLink() = default;
DocumentLinkDocumentLink992 DocumentLink(Range range, URIForFile target)
993 : range(range), target(std::move(target)) {}
994
995 /// The range this link applies to.
996 Range range;
997
998 /// The uri this link points to. If missing a resolve request is sent later.
999 URIForFile target;
1000
1001 // TODO: The following optional fields defined by the language server protocol
1002 // are unsupported:
1003 //
1004 // data?: any - A data entry field that is preserved on a document link
1005 // between a DocumentLinkRequest and a
1006 // DocumentLinkResolveRequest.
1007
1008 friend bool operator==(const DocumentLink &lhs, const DocumentLink &rhs) {
1009 return lhs.range == rhs.range && lhs.target == rhs.target;
1010 }
1011
1012 friend bool operator!=(const DocumentLink &lhs, const DocumentLink &rhs) {
1013 return !(lhs == rhs);
1014 }
1015 };
1016
1017 /// Add support for JSON serialization.
1018 llvm::json::Value toJSON(const DocumentLink &value);
1019
1020 //===----------------------------------------------------------------------===//
1021 // InlayHintsParams
1022 //===----------------------------------------------------------------------===//
1023
1024 /// A parameter literal used in inlay hint requests.
1025 struct InlayHintsParams {
1026 /// The text document.
1027 TextDocumentIdentifier textDocument;
1028
1029 /// The visible document range for which inlay hints should be computed.
1030 Range range;
1031 };
1032
1033 /// Add support for JSON serialization.
1034 bool fromJSON(const llvm::json::Value &value, InlayHintsParams &result,
1035 llvm::json::Path path);
1036
1037 //===----------------------------------------------------------------------===//
1038 // InlayHintKind
1039 //===----------------------------------------------------------------------===//
1040
1041 /// Inlay hint kinds.
1042 enum class InlayHintKind {
1043 /// An inlay hint that for a type annotation.
1044 ///
1045 /// An example of a type hint is a hint in this position:
1046 /// auto var ^ = expr;
1047 /// which shows the deduced type of the variable.
1048 Type = 1,
1049
1050 /// An inlay hint that is for a parameter.
1051 ///
1052 /// An example of a parameter hint is a hint in this position:
1053 /// func(^arg);
1054 /// which shows the name of the corresponding parameter.
1055 Parameter = 2,
1056 };
1057
1058 //===----------------------------------------------------------------------===//
1059 // InlayHint
1060 //===----------------------------------------------------------------------===//
1061
1062 /// Inlay hint information.
1063 struct InlayHint {
InlayHintInlayHint1064 InlayHint(InlayHintKind kind, Position pos) : position(pos), kind(kind) {}
1065
1066 /// The position of this hint.
1067 Position position;
1068
1069 /// The label of this hint. A human readable string or an array of
1070 /// InlayHintLabelPart label parts.
1071 ///
1072 /// *Note* that neither the string nor the label part can be empty.
1073 std::string label;
1074
1075 /// The kind of this hint. Can be omitted in which case the client should fall
1076 /// back to a reasonable default.
1077 InlayHintKind kind;
1078
1079 /// Render padding before the hint.
1080 ///
1081 /// Note: Padding should use the editor's background color, not the
1082 /// background color of the hint itself. That means padding can be used
1083 /// to visually align/separate an inlay hint.
1084 bool paddingLeft = false;
1085
1086 /// Render padding after the hint.
1087 ///
1088 /// Note: Padding should use the editor's background color, not the
1089 /// background color of the hint itself. That means padding can be used
1090 /// to visually align/separate an inlay hint.
1091 bool paddingRight = false;
1092 };
1093
1094 /// Add support for JSON serialization.
1095 llvm::json::Value toJSON(const InlayHint &);
1096 bool operator==(const InlayHint &lhs, const InlayHint &rhs);
1097 bool operator<(const InlayHint &lhs, const InlayHint &rhs);
1098 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, InlayHintKind value);
1099
1100 //===----------------------------------------------------------------------===//
1101 // CodeActionContext
1102 //===----------------------------------------------------------------------===//
1103
1104 struct CodeActionContext {
1105 /// An array of diagnostics known on the client side overlapping the range
1106 /// provided to the `textDocument/codeAction` request. They are provided so
1107 /// that the server knows which errors are currently presented to the user for
1108 /// the given range. There is no guarantee that these accurately reflect the
1109 /// error state of the resource. The primary parameter to compute code actions
1110 /// is the provided range.
1111 std::vector<Diagnostic> diagnostics;
1112
1113 /// Requested kind of actions to return.
1114 ///
1115 /// Actions not of this kind are filtered out by the client before being
1116 /// shown. So servers can omit computing them.
1117 std::vector<std::string> only;
1118 };
1119
1120 /// Add support for JSON serialization.
1121 bool fromJSON(const llvm::json::Value &value, CodeActionContext &result,
1122 llvm::json::Path path);
1123
1124 //===----------------------------------------------------------------------===//
1125 // CodeActionParams
1126 //===----------------------------------------------------------------------===//
1127
1128 struct CodeActionParams {
1129 /// The document in which the command was invoked.
1130 TextDocumentIdentifier textDocument;
1131
1132 /// The range for which the command was invoked.
1133 Range range;
1134
1135 /// Context carrying additional information.
1136 CodeActionContext context;
1137 };
1138
1139 /// Add support for JSON serialization.
1140 bool fromJSON(const llvm::json::Value &value, CodeActionParams &result,
1141 llvm::json::Path path);
1142
1143 //===----------------------------------------------------------------------===//
1144 // WorkspaceEdit
1145 //===----------------------------------------------------------------------===//
1146
1147 struct WorkspaceEdit {
1148 /// Holds changes to existing resources.
1149 std::map<std::string, std::vector<TextEdit>> changes;
1150
1151 /// Note: "documentChanges" is not currently used because currently there is
1152 /// no support for versioned edits.
1153 };
1154
1155 /// Add support for JSON serialization.
1156 bool fromJSON(const llvm::json::Value &value, WorkspaceEdit &result,
1157 llvm::json::Path path);
1158 llvm::json::Value toJSON(const WorkspaceEdit &value);
1159
1160 //===----------------------------------------------------------------------===//
1161 // CodeAction
1162 //===----------------------------------------------------------------------===//
1163
1164 /// A code action represents a change that can be performed in code, e.g. to fix
1165 /// a problem or to refactor code.
1166 ///
1167 /// A CodeAction must set either `edit` and/or a `command`. If both are
1168 /// supplied, the `edit` is applied first, then the `command` is executed.
1169 struct CodeAction {
1170 /// A short, human-readable, title for this code action.
1171 std::string title;
1172
1173 /// The kind of the code action.
1174 /// Used to filter code actions.
1175 Optional<std::string> kind;
1176 const static llvm::StringLiteral kQuickFix;
1177 const static llvm::StringLiteral kRefactor;
1178 const static llvm::StringLiteral kInfo;
1179
1180 /// The diagnostics that this code action resolves.
1181 Optional<std::vector<Diagnostic>> diagnostics;
1182
1183 /// Marks this as a preferred action. Preferred actions are used by the
1184 /// `auto fix` command and can be targeted by keybindings.
1185 /// A quick fix should be marked preferred if it properly addresses the
1186 /// underlying error. A refactoring should be marked preferred if it is the
1187 /// most reasonable choice of actions to take.
1188 bool isPreferred = false;
1189
1190 /// The workspace edit this code action performs.
1191 Optional<WorkspaceEdit> edit;
1192 };
1193
1194 /// Add support for JSON serialization.
1195 llvm::json::Value toJSON(const CodeAction &);
1196
1197 } // namespace lsp
1198 } // namespace mlir
1199
1200 namespace llvm {
1201 template <>
1202 struct format_provider<mlir::lsp::Position> {
1203 static void format(const mlir::lsp::Position &pos, raw_ostream &os,
1204 StringRef style) {
1205 assert(style.empty() && "style modifiers for this type are not supported");
1206 os << pos;
1207 }
1208 };
1209 } // namespace llvm
1210
1211 #endif
1212