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