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