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 &params);
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