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