Line data Source code
1 : //===--- Protocol.h - Language Server Protocol Implementation ---*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file contains structs based on the LSP specification at
11 : // https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md
12 : //
13 : // This is not meant to be a complete implementation, new interfaces are added
14 : // when they're needed.
15 : //
16 : // Each struct has a toJSON and fromJSON function, that converts between
17 : // the struct and a JSON representation. (See JSON.h)
18 : //
19 : // Some structs also have operator<< serialization. This is for debugging and
20 : // tests, and is not generally machine-readable.
21 : //
22 : //===----------------------------------------------------------------------===//
23 :
24 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
25 : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
26 :
27 : #include "URI.h"
28 : #include "llvm/ADT/Optional.h"
29 : #include "llvm/Support/JSON.h"
30 : #include <bitset>
31 : #include <string>
32 : #include <vector>
33 :
34 : namespace clang {
35 : namespace clangd {
36 :
37 : enum class ErrorCode {
38 : // Defined by JSON RPC.
39 : ParseError = -32700,
40 : InvalidRequest = -32600,
41 : MethodNotFound = -32601,
42 : InvalidParams = -32602,
43 : InternalError = -32603,
44 :
45 : ServerNotInitialized = -32002,
46 : UnknownErrorCode = -32001,
47 :
48 : // Defined by the protocol.
49 : RequestCancelled = -32800,
50 : };
51 : // Models an LSP error as an llvm::Error.
52 : class LSPError : public llvm::ErrorInfo<LSPError> {
53 : public:
54 : std::string Message;
55 : ErrorCode Code;
56 : static char ID;
57 :
58 : LSPError(std::string Message, ErrorCode Code)
59 0 : : Message(std::move(Message)), Code(Code) {}
60 :
61 0 : void log(llvm::raw_ostream &OS) const override {
62 0 : OS << int(Code) << ": " << Message;
63 0 : }
64 0 : std::error_code convertToErrorCode() const override {
65 0 : return llvm::inconvertibleErrorCode();
66 : }
67 : };
68 :
69 0 : struct URIForFile {
70 : URIForFile() = default;
71 : explicit URIForFile(std::string AbsPath);
72 :
73 : /// Retrieves absolute path to the file.
74 : llvm::StringRef file() const { return File; }
75 :
76 : explicit operator bool() const { return !File.empty(); }
77 : std::string uri() const { return URI::createFile(File).toString(); }
78 :
79 : friend bool operator==(const URIForFile &LHS, const URIForFile &RHS) {
80 0 : return LHS.File == RHS.File;
81 : }
82 :
83 : friend bool operator!=(const URIForFile &LHS, const URIForFile &RHS) {
84 : return !(LHS == RHS);
85 : }
86 :
87 : friend bool operator<(const URIForFile &LHS, const URIForFile &RHS) {
88 : return LHS.File < RHS.File;
89 : }
90 :
91 : private:
92 : std::string File;
93 : };
94 :
95 : /// Serialize/deserialize \p URIForFile to/from a string URI.
96 : llvm::json::Value toJSON(const URIForFile &U);
97 : bool fromJSON(const llvm::json::Value &, URIForFile &);
98 :
99 : struct TextDocumentIdentifier {
100 : /// The text document's URI.
101 : URIForFile uri;
102 : };
103 : llvm::json::Value toJSON(const TextDocumentIdentifier &);
104 : bool fromJSON(const llvm::json::Value &, TextDocumentIdentifier &);
105 :
106 0 : struct Position {
107 : /// Line position in a document (zero-based).
108 : int line = 0;
109 :
110 : /// Character offset on a line in a document (zero-based).
111 : /// WARNING: this is in UTF-16 codepoints, not bytes or characters!
112 : /// Use the functions in SourceCode.h to construct/interpret Positions.
113 : int character = 0;
114 :
115 : friend bool operator==(const Position &LHS, const Position &RHS) {
116 : return std::tie(LHS.line, LHS.character) ==
117 : std::tie(RHS.line, RHS.character);
118 : }
119 : friend bool operator!=(const Position &LHS, const Position &RHS) {
120 : return !(LHS == RHS);
121 : }
122 : friend bool operator<(const Position &LHS, const Position &RHS) {
123 : return std::tie(LHS.line, LHS.character) <
124 : std::tie(RHS.line, RHS.character);
125 : }
126 : friend bool operator<=(const Position &LHS, const Position &RHS) {
127 : return std::tie(LHS.line, LHS.character) <=
128 : std::tie(RHS.line, RHS.character);
129 : }
130 : };
131 : bool fromJSON(const llvm::json::Value &, Position &);
132 : llvm::json::Value toJSON(const Position &);
133 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Position &);
134 :
135 : struct Range {
136 : /// The range's start position.
137 : Position start;
138 :
139 : /// The range's end position.
140 : Position end;
141 :
142 : friend bool operator==(const Range &LHS, const Range &RHS) {
143 : return std::tie(LHS.start, LHS.end) == std::tie(RHS.start, RHS.end);
144 : }
145 : friend bool operator!=(const Range &LHS, const Range &RHS) {
146 : return !(LHS == RHS);
147 : }
148 : friend bool operator<(const Range &LHS, const Range &RHS) {
149 : return std::tie(LHS.start, LHS.end) < std::tie(RHS.start, RHS.end);
150 : }
151 :
152 : bool contains(Position Pos) const { return start <= Pos && Pos < end; }
153 : };
154 : bool fromJSON(const llvm::json::Value &, Range &);
155 : llvm::json::Value toJSON(const Range &);
156 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Range &);
157 :
158 0 : struct Location {
159 : /// The text document's URI.
160 : URIForFile uri;
161 : Range range;
162 :
163 0 : friend bool operator==(const Location &LHS, const Location &RHS) {
164 0 : return LHS.uri == RHS.uri && LHS.range == RHS.range;
165 : }
166 :
167 : friend bool operator!=(const Location &LHS, const Location &RHS) {
168 : return !(LHS == RHS);
169 : }
170 :
171 : friend bool operator<(const Location &LHS, const Location &RHS) {
172 : return std::tie(LHS.uri, LHS.range) < std::tie(RHS.uri, RHS.range);
173 : }
174 : };
175 : llvm::json::Value toJSON(const Location &);
176 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Location &);
177 :
178 : struct Metadata {
179 : std::vector<std::string> extraFlags;
180 : };
181 : bool fromJSON(const llvm::json::Value &, Metadata &);
182 :
183 0 : struct TextEdit {
184 : /// The range of the text document to be manipulated. To insert
185 : /// text into a document create a range where start === end.
186 : Range range;
187 :
188 : /// The string to be inserted. For delete operations use an
189 : /// empty string.
190 : std::string newText;
191 :
192 0 : bool operator==(const TextEdit &rhs) const {
193 0 : return newText == rhs.newText && range == rhs.range;
194 : }
195 : };
196 : bool fromJSON(const llvm::json::Value &, TextEdit &);
197 : llvm::json::Value toJSON(const TextEdit &);
198 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TextEdit &);
199 :
200 : struct TextDocumentItem {
201 : /// The text document's URI.
202 : URIForFile uri;
203 :
204 : /// The text document's language identifier.
205 : std::string languageId;
206 :
207 : /// The version number of this document (it will strictly increase after each
208 : int version = 0;
209 :
210 : /// The content of the opened text document.
211 : std::string text;
212 : };
213 : bool fromJSON(const llvm::json::Value &, TextDocumentItem &);
214 :
215 : enum class TraceLevel {
216 : Off = 0,
217 : Messages = 1,
218 : Verbose = 2,
219 : };
220 : bool fromJSON(const llvm::json::Value &E, TraceLevel &Out);
221 :
222 : struct NoParams {};
223 : inline bool fromJSON(const llvm::json::Value &, NoParams &) { return true; }
224 : using ShutdownParams = NoParams;
225 : using ExitParams = NoParams;
226 :
227 : /// Defines how the host (editor) should sync document changes to the language
228 : /// server.
229 : enum class TextDocumentSyncKind {
230 : /// Documents should not be synced at all.
231 : None = 0,
232 :
233 : /// Documents are synced by always sending the full content of the document.
234 : Full = 1,
235 :
236 : /// Documents are synced by sending the full content on open. After that
237 : /// only incremental updates to the document are send.
238 : Incremental = 2,
239 : };
240 :
241 : /// The kind of a completion entry.
242 : enum class CompletionItemKind {
243 : Missing = 0,
244 : Text = 1,
245 : Method = 2,
246 : Function = 3,
247 : Constructor = 4,
248 : Field = 5,
249 : Variable = 6,
250 : Class = 7,
251 : Interface = 8,
252 : Module = 9,
253 : Property = 10,
254 : Unit = 11,
255 : Value = 12,
256 : Enum = 13,
257 : Keyword = 14,
258 : Snippet = 15,
259 : Color = 16,
260 : File = 17,
261 : Reference = 18,
262 : Folder = 19,
263 : EnumMember = 20,
264 : Constant = 21,
265 : Struct = 22,
266 : Event = 23,
267 : Operator = 24,
268 : TypeParameter = 25,
269 : };
270 : bool fromJSON(const llvm::json::Value &, CompletionItemKind &);
271 : constexpr auto CompletionItemKindMin =
272 : static_cast<size_t>(CompletionItemKind::Text);
273 : constexpr auto CompletionItemKindMax =
274 : static_cast<size_t>(CompletionItemKind::TypeParameter);
275 : using CompletionItemKindBitset = std::bitset<CompletionItemKindMax + 1>;
276 : bool fromJSON(const llvm::json::Value &, CompletionItemKindBitset &);
277 : CompletionItemKind
278 : adjustKindToCapability(CompletionItemKind Kind,
279 : CompletionItemKindBitset &supportedCompletionItemKinds);
280 :
281 : /// A symbol kind.
282 : enum class SymbolKind {
283 : File = 1,
284 : Module = 2,
285 : Namespace = 3,
286 : Package = 4,
287 : Class = 5,
288 : Method = 6,
289 : Property = 7,
290 : Field = 8,
291 : Constructor = 9,
292 : Enum = 10,
293 : Interface = 11,
294 : Function = 12,
295 : Variable = 13,
296 : Constant = 14,
297 : String = 15,
298 : Number = 16,
299 : Boolean = 17,
300 : Array = 18,
301 : Object = 19,
302 : Key = 20,
303 : Null = 21,
304 : EnumMember = 22,
305 : Struct = 23,
306 : Event = 24,
307 : Operator = 25,
308 : TypeParameter = 26
309 : };
310 : bool fromJSON(const llvm::json::Value &, SymbolKind &);
311 : constexpr auto SymbolKindMin = static_cast<size_t>(SymbolKind::File);
312 : constexpr auto SymbolKindMax = static_cast<size_t>(SymbolKind::TypeParameter);
313 : using SymbolKindBitset = std::bitset<SymbolKindMax + 1>;
314 : bool fromJSON(const llvm::json::Value &, SymbolKindBitset &);
315 : SymbolKind adjustKindToCapability(SymbolKind Kind,
316 : SymbolKindBitset &supportedSymbolKinds);
317 :
318 : // This struct doesn't mirror LSP!
319 : // The protocol defines deeply nested structures for client capabilities.
320 : // Instead of mapping them all, this just parses out the bits we care about.
321 : struct ClientCapabilities {
322 : /// The supported set of SymbolKinds for workspace/symbol.
323 : /// workspace.symbol.symbolKind.valueSet
324 : llvm::Optional<SymbolKindBitset> WorkspaceSymbolKinds;
325 :
326 : /// Whether the client accepts diagnostics with fixes attached using the
327 : /// "clangd_fixes" extension.
328 : /// textDocument.publishDiagnostics.clangdFixSupport
329 : bool DiagnosticFixes = false;
330 :
331 : /// Whether the client accepts diagnostics with category attached to it
332 : /// using the "category" extension.
333 : /// textDocument.publishDiagnostics.categorySupport
334 : bool DiagnosticCategory = false;
335 :
336 : /// Client supports snippets as insert text.
337 : /// textDocument.completion.completionItem.snippetSupport
338 : bool CompletionSnippets = false;
339 :
340 : /// The supported set of CompletionItemKinds for textDocument/completion.
341 : /// textDocument.completion.completionItemKind.valueSet
342 : llvm::Optional<CompletionItemKindBitset> CompletionItemKinds;
343 :
344 : /// Client supports CodeAction return value for textDocument/codeAction.
345 : /// textDocument.codeAction.codeActionLiteralSupport.
346 : bool CodeActionStructure = false;
347 : };
348 : bool fromJSON(const llvm::json::Value &, ClientCapabilities &);
349 :
350 : /// Clangd extension that's used in the 'compilationDatabaseChanges' in
351 : /// workspace/didChangeConfiguration to record updates to the in-memory
352 : /// compilation database.
353 : struct ClangdCompileCommand {
354 : std::string workingDirectory;
355 : std::vector<std::string> compilationCommand;
356 : };
357 : bool fromJSON(const llvm::json::Value &, ClangdCompileCommand &);
358 :
359 : /// Clangd extension to set clangd-specific "initializationOptions" in the
360 : /// "initialize" request and for the "workspace/didChangeConfiguration"
361 : /// notification since the data received is described as 'any' type in LSP.
362 : struct ClangdConfigurationParamsChange {
363 : // The changes that happened to the compilation database.
364 : // The key of the map is a file name.
365 : llvm::Optional<std::map<std::string, ClangdCompileCommand>>
366 : compilationDatabaseChanges;
367 : };
368 : bool fromJSON(const llvm::json::Value &, ClangdConfigurationParamsChange &);
369 :
370 : struct ClangdInitializationOptions {
371 : // What we can change throught the didChangeConfiguration request, we can
372 : // also set through the initialize request (initializationOptions field).
373 : ClangdConfigurationParamsChange ParamsChange;
374 :
375 : llvm::Optional<std::string> compilationDatabasePath;
376 : };
377 : bool fromJSON(const llvm::json::Value &, ClangdInitializationOptions &);
378 :
379 : struct InitializeParams {
380 : /// The process Id of the parent process that started
381 : /// the server. Is null if the process has not been started by another
382 : /// process. If the parent process is not alive then the server should exit
383 : /// (see exit notification) its process.
384 : llvm::Optional<int> processId;
385 :
386 : /// The rootPath of the workspace. Is null
387 : /// if no folder is open.
388 : ///
389 : /// @deprecated in favour of rootUri.
390 : llvm::Optional<std::string> rootPath;
391 :
392 : /// The rootUri of the workspace. Is null if no
393 : /// folder is open. If both `rootPath` and `rootUri` are set
394 : /// `rootUri` wins.
395 : llvm::Optional<URIForFile> rootUri;
396 :
397 : // User provided initialization options.
398 : // initializationOptions?: any;
399 :
400 : /// The capabilities provided by the client (editor or tool)
401 : ClientCapabilities capabilities;
402 :
403 : /// The initial trace setting. If omitted trace is disabled ('off').
404 : llvm::Optional<TraceLevel> trace;
405 :
406 : // We use this predefined struct because it is easier to use
407 : // than the protocol specified type of 'any'.
408 : llvm::Optional<ClangdInitializationOptions> initializationOptions;
409 : };
410 : bool fromJSON(const llvm::json::Value &, InitializeParams &);
411 :
412 : struct DidOpenTextDocumentParams {
413 : /// The document that was opened.
414 : TextDocumentItem textDocument;
415 :
416 : /// Extension storing per-file metadata, such as compilation flags.
417 : llvm::Optional<Metadata> metadata;
418 : };
419 : bool fromJSON(const llvm::json::Value &, DidOpenTextDocumentParams &);
420 :
421 : struct DidCloseTextDocumentParams {
422 : /// The document that was closed.
423 : TextDocumentIdentifier textDocument;
424 : };
425 : bool fromJSON(const llvm::json::Value &, DidCloseTextDocumentParams &);
426 :
427 0 : struct TextDocumentContentChangeEvent {
428 : /// The range of the document that changed.
429 : llvm::Optional<Range> range;
430 :
431 : /// The length of the range that got replaced.
432 : llvm::Optional<int> rangeLength;
433 :
434 : /// The new text of the range/document.
435 : std::string text;
436 : };
437 : bool fromJSON(const llvm::json::Value &, TextDocumentContentChangeEvent &);
438 :
439 : struct DidChangeTextDocumentParams {
440 : /// The document that did change. The version number points
441 : /// to the version after all provided content changes have
442 : /// been applied.
443 : TextDocumentIdentifier textDocument;
444 :
445 : /// The actual content changes.
446 : std::vector<TextDocumentContentChangeEvent> contentChanges;
447 :
448 : /// Forces diagnostics to be generated, or to not be generated, for this
449 : /// version of the file. If not set, diagnostics are eventually consistent:
450 : /// either they will be provided for this version or some subsequent one.
451 : /// This is a clangd extension.
452 : llvm::Optional<bool> wantDiagnostics;
453 : };
454 : bool fromJSON(const llvm::json::Value &, DidChangeTextDocumentParams &);
455 :
456 : enum class FileChangeType {
457 : /// The file got created.
458 : Created = 1,
459 : /// The file got changed.
460 : Changed = 2,
461 : /// The file got deleted.
462 : Deleted = 3
463 : };
464 : bool fromJSON(const llvm::json::Value &E, FileChangeType &Out);
465 :
466 : struct FileEvent {
467 : /// The file's URI.
468 : URIForFile uri;
469 : /// The change type.
470 : FileChangeType type = FileChangeType::Created;
471 : };
472 : bool fromJSON(const llvm::json::Value &, FileEvent &);
473 :
474 : struct DidChangeWatchedFilesParams {
475 : /// The actual file events.
476 : std::vector<FileEvent> changes;
477 : };
478 : bool fromJSON(const llvm::json::Value &, DidChangeWatchedFilesParams &);
479 :
480 : struct DidChangeConfigurationParams {
481 : // We use this predefined struct because it is easier to use
482 : // than the protocol specified type of 'any'.
483 : ClangdConfigurationParamsChange settings;
484 : };
485 : bool fromJSON(const llvm::json::Value &, DidChangeConfigurationParams &);
486 :
487 : struct FormattingOptions {
488 : /// Size of a tab in spaces.
489 : int tabSize = 0;
490 :
491 : /// Prefer spaces over tabs.
492 : bool insertSpaces = false;
493 : };
494 : bool fromJSON(const llvm::json::Value &, FormattingOptions &);
495 : llvm::json::Value toJSON(const FormattingOptions &);
496 :
497 : struct DocumentRangeFormattingParams {
498 : /// The document to format.
499 : TextDocumentIdentifier textDocument;
500 :
501 : /// The range to format
502 : Range range;
503 :
504 : /// The format options
505 : FormattingOptions options;
506 : };
507 : bool fromJSON(const llvm::json::Value &, DocumentRangeFormattingParams &);
508 :
509 : struct DocumentOnTypeFormattingParams {
510 : /// The document to format.
511 : TextDocumentIdentifier textDocument;
512 :
513 : /// The position at which this request was sent.
514 : Position position;
515 :
516 : /// The character that has been typed.
517 : std::string ch;
518 :
519 : /// The format options.
520 : FormattingOptions options;
521 : };
522 : bool fromJSON(const llvm::json::Value &, DocumentOnTypeFormattingParams &);
523 :
524 : struct DocumentFormattingParams {
525 : /// The document to format.
526 : TextDocumentIdentifier textDocument;
527 :
528 : /// The format options
529 : FormattingOptions options;
530 : };
531 : bool fromJSON(const llvm::json::Value &, DocumentFormattingParams &);
532 :
533 : struct DocumentSymbolParams {
534 : // The text document to find symbols in.
535 : TextDocumentIdentifier textDocument;
536 : };
537 : bool fromJSON(const llvm::json::Value &, DocumentSymbolParams &);
538 :
539 : struct Diagnostic {
540 : /// The range at which the message applies.
541 : Range range;
542 :
543 : /// The diagnostic's severity. Can be omitted. If omitted it is up to the
544 : /// client to interpret diagnostics as error, warning, info or hint.
545 : int severity = 0;
546 :
547 : /// The diagnostic's code. Can be omitted.
548 : /// Note: Not currently used by clangd
549 : // std::string code;
550 :
551 : /// A human-readable string describing the source of this
552 : /// diagnostic, e.g. 'typescript' or 'super lint'.
553 : /// Note: Not currently used by clangd
554 : // std::string source;
555 :
556 : /// The diagnostic's message.
557 : std::string message;
558 :
559 : /// The diagnostic's category. Can be omitted.
560 : /// An LSP extension that's used to send the name of the category over to the
561 : /// client. The category typically describes the compilation stage during
562 : /// which the issue was produced, e.g. "Semantic Issue" or "Parse Issue".
563 : std::string category;
564 : };
565 : llvm::json::Value toJSON(const Diagnostic &);
566 :
567 : /// A LSP-specific comparator used to find diagnostic in a container like
568 : /// std:map.
569 : /// We only use the required fields of Diagnostic to do the comparsion to avoid
570 : /// any regression issues from LSP clients (e.g. VScode), see
571 : /// https://git.io/vbr29
572 : struct LSPDiagnosticCompare {
573 : bool operator()(const Diagnostic &LHS, const Diagnostic &RHS) const {
574 : return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
575 : }
576 : };
577 : bool fromJSON(const llvm::json::Value &, Diagnostic &);
578 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Diagnostic &);
579 :
580 : struct CodeActionContext {
581 : /// An array of diagnostics.
582 : std::vector<Diagnostic> diagnostics;
583 : };
584 : bool fromJSON(const llvm::json::Value &, CodeActionContext &);
585 :
586 : struct CodeActionParams {
587 : /// The document in which the command was invoked.
588 : TextDocumentIdentifier textDocument;
589 :
590 : /// The range for which the command was invoked.
591 : Range range;
592 :
593 : /// Context carrying additional information.
594 : CodeActionContext context;
595 : };
596 : bool fromJSON(const llvm::json::Value &, CodeActionParams &);
597 :
598 : struct WorkspaceEdit {
599 : /// Holds changes to existing resources.
600 : llvm::Optional<std::map<std::string, std::vector<TextEdit>>> changes;
601 :
602 : /// Note: "documentChanges" is not currently used because currently there is
603 : /// no support for versioned edits.
604 : };
605 : bool fromJSON(const llvm::json::Value &, WorkspaceEdit &);
606 : llvm::json::Value toJSON(const WorkspaceEdit &WE);
607 :
608 : /// Exact commands are not specified in the protocol so we define the
609 : /// ones supported by Clangd here. The protocol specifies the command arguments
610 : /// to be "any[]" but to make this safer and more manageable, each command we
611 : /// handle maps to a certain llvm::Optional of some struct to contain its
612 : /// arguments. Different commands could reuse the same llvm::Optional as
613 : /// arguments but a command that needs different arguments would simply add a
614 : /// new llvm::Optional and not use any other ones. In practice this means only
615 : /// one argument type will be parsed and set.
616 : struct ExecuteCommandParams {
617 : // Command to apply fix-its. Uses WorkspaceEdit as argument.
618 : const static llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND;
619 :
620 : /// The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND
621 : std::string command;
622 :
623 : // Arguments
624 : llvm::Optional<WorkspaceEdit> workspaceEdit;
625 : };
626 : bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &);
627 :
628 : struct Command : public ExecuteCommandParams {
629 : std::string title;
630 : };
631 : llvm::json::Value toJSON(const Command &C);
632 :
633 : /// A code action represents a change that can be performed in code, e.g. to fix
634 : /// a problem or to refactor code.
635 : ///
636 : /// A CodeAction must set either `edit` and/or a `command`. If both are
637 : /// supplied, the `edit` is applied first, then the `command` is executed.
638 : struct CodeAction {
639 : /// A short, human-readable, title for this code action.
640 : std::string title;
641 :
642 : /// The kind of the code action.
643 : /// Used to filter code actions.
644 : llvm::Optional<std::string> kind;
645 : const static llvm::StringLiteral QUICKFIX_KIND;
646 :
647 : /// The diagnostics that this code action resolves.
648 : llvm::Optional<std::vector<Diagnostic>> diagnostics;
649 :
650 : /// The workspace edit this code action performs.
651 : llvm::Optional<WorkspaceEdit> edit;
652 :
653 : /// A command this code action executes. If a code action provides an edit
654 : /// and a command, first the edit is executed and then the command.
655 : llvm::Optional<Command> command;
656 : };
657 : llvm::json::Value toJSON(const CodeAction &);
658 :
659 : /// Represents information about programming constructs like variables, classes,
660 : /// interfaces etc.
661 : struct SymbolInformation {
662 : /// The name of this symbol.
663 : std::string name;
664 :
665 : /// The kind of this symbol.
666 : SymbolKind kind;
667 :
668 : /// The location of this symbol.
669 : Location location;
670 :
671 : /// The name of the symbol containing this symbol.
672 : std::string containerName;
673 : };
674 : llvm::json::Value toJSON(const SymbolInformation &);
675 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolInformation &);
676 :
677 : /// The parameters of a Workspace Symbol Request.
678 : struct WorkspaceSymbolParams {
679 : /// A non-empty query string
680 : std::string query;
681 : };
682 : bool fromJSON(const llvm::json::Value &, WorkspaceSymbolParams &);
683 :
684 : struct ApplyWorkspaceEditParams {
685 : WorkspaceEdit edit;
686 : };
687 : llvm::json::Value toJSON(const ApplyWorkspaceEditParams &);
688 :
689 : struct TextDocumentPositionParams {
690 : /// The text document.
691 : TextDocumentIdentifier textDocument;
692 :
693 : /// The position inside the text document.
694 : Position position;
695 : };
696 : bool fromJSON(const llvm::json::Value &, TextDocumentPositionParams &);
697 :
698 : enum class MarkupKind {
699 : PlainText,
700 : Markdown,
701 : };
702 :
703 : struct MarkupContent {
704 : MarkupKind kind = MarkupKind::PlainText;
705 : std::string value;
706 : };
707 : llvm::json::Value toJSON(const MarkupContent &MC);
708 :
709 : struct Hover {
710 : /// The hover's content
711 : MarkupContent contents;
712 :
713 : /// An optional range is a range inside a text document
714 : /// that is used to visualize a hover, e.g. by changing the background color.
715 : llvm::Optional<Range> range;
716 : };
717 : llvm::json::Value toJSON(const Hover &H);
718 :
719 : /// Defines whether the insert text in a completion item should be interpreted
720 : /// as plain text or a snippet.
721 : enum class InsertTextFormat {
722 : Missing = 0,
723 : /// The primary text to be inserted is treated as a plain string.
724 : PlainText = 1,
725 : /// The primary text to be inserted is treated as a snippet.
726 : ///
727 : /// A snippet can define tab stops and placeholders with `$1`, `$2`
728 : /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to the end
729 : /// of the snippet. Placeholders with equal identifiers are linked, that is
730 : /// typing in one will update others too.
731 : ///
732 : /// See also:
733 : /// https//github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
734 : Snippet = 2,
735 : };
736 :
737 : struct CompletionItem {
738 : /// The label of this completion item. By default also the text that is
739 : /// inserted when selecting this completion.
740 : std::string label;
741 :
742 : /// The kind of this completion item. Based of the kind an icon is chosen by
743 : /// the editor.
744 : CompletionItemKind kind = CompletionItemKind::Missing;
745 :
746 : /// A human-readable string with additional information about this item, like
747 : /// type or symbol information.
748 : std::string detail;
749 :
750 : /// A human-readable string that represents a doc-comment.
751 : std::string documentation;
752 :
753 : /// A string that should be used when comparing this item with other items.
754 : /// When `falsy` the label is used.
755 : std::string sortText;
756 :
757 : /// A string that should be used when filtering a set of completion items.
758 : /// When `falsy` the label is used.
759 : std::string filterText;
760 :
761 : /// A string that should be inserted to a document when selecting this
762 : /// completion. When `falsy` the label is used.
763 : std::string insertText;
764 :
765 : /// The format of the insert text. The format applies to both the `insertText`
766 : /// property and the `newText` property of a provided `textEdit`.
767 : InsertTextFormat insertTextFormat = InsertTextFormat::Missing;
768 :
769 : /// An edit which is applied to a document when selecting this completion.
770 : /// When an edit is provided `insertText` is ignored.
771 : ///
772 : /// Note: The range of the edit must be a single line range and it must
773 : /// contain the position at which completion has been requested.
774 : llvm::Optional<TextEdit> textEdit;
775 :
776 : /// An optional array of additional text edits that are applied when selecting
777 : /// this completion. Edits must not overlap with the main edit nor with
778 : /// themselves.
779 : std::vector<TextEdit> additionalTextEdits;
780 :
781 : /// Indicates if this item is deprecated.
782 : bool deprecated = false;
783 :
784 : // TODO(krasimir): The following optional fields defined by the language
785 : // server protocol are unsupported:
786 : //
787 : // data?: any - A data entry field that is preserved on a completion item
788 : // between a completion and a completion resolve request.
789 : };
790 : llvm::json::Value toJSON(const CompletionItem &);
791 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CompletionItem &);
792 :
793 : bool operator<(const CompletionItem &, const CompletionItem &);
794 :
795 : /// Represents a collection of completion items to be presented in the editor.
796 : struct CompletionList {
797 : /// The list is not complete. Further typing should result in recomputing the
798 : /// list.
799 : bool isIncomplete = false;
800 :
801 : /// The completion items.
802 : std::vector<CompletionItem> items;
803 : };
804 : llvm::json::Value toJSON(const CompletionList &);
805 :
806 : /// A single parameter of a particular signature.
807 : struct ParameterInformation {
808 :
809 : /// The label of this parameter. Mandatory.
810 : std::string label;
811 :
812 : /// The documentation of this parameter. Optional.
813 : std::string documentation;
814 : };
815 : llvm::json::Value toJSON(const ParameterInformation &);
816 :
817 : /// Represents the signature of something callable.
818 : struct SignatureInformation {
819 :
820 : /// The label of this signature. Mandatory.
821 : std::string label;
822 :
823 : /// The documentation of this signature. Optional.
824 : std::string documentation;
825 :
826 : /// The parameters of this signature.
827 : std::vector<ParameterInformation> parameters;
828 : };
829 : llvm::json::Value toJSON(const SignatureInformation &);
830 : llvm::raw_ostream &operator<<(llvm::raw_ostream &,
831 : const SignatureInformation &);
832 :
833 : /// Represents the signature of a callable.
834 0 : struct SignatureHelp {
835 :
836 : /// The resulting signatures.
837 : std::vector<SignatureInformation> signatures;
838 :
839 : /// The active signature.
840 : int activeSignature = 0;
841 :
842 : /// The active parameter of the active signature.
843 : int activeParameter = 0;
844 :
845 : /// Position of the start of the argument list, including opening paren. e.g.
846 : /// foo("first arg", "second arg",
847 : /// ^-argListStart ^-cursor
848 : /// This is a clangd-specific extension, it is only available via C++ API and
849 : /// not currently serialized for the LSP.
850 : Position argListStart;
851 : };
852 : llvm::json::Value toJSON(const SignatureHelp &);
853 :
854 : struct RenameParams {
855 : /// The document that was opened.
856 : TextDocumentIdentifier textDocument;
857 :
858 : /// The position at which this request was sent.
859 : Position position;
860 :
861 : /// The new name of the symbol.
862 : std::string newName;
863 : };
864 : bool fromJSON(const llvm::json::Value &, RenameParams &);
865 :
866 : enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };
867 :
868 : /// A document highlight is a range inside a text document which deserves
869 : /// special attention. Usually a document highlight is visualized by changing
870 : /// the background color of its range.
871 :
872 0 : struct DocumentHighlight {
873 : /// The range this highlight applies to.
874 : Range range;
875 :
876 : /// The highlight kind, default is DocumentHighlightKind.Text.
877 : DocumentHighlightKind kind = DocumentHighlightKind::Text;
878 :
879 : friend bool operator<(const DocumentHighlight &LHS,
880 : const DocumentHighlight &RHS) {
881 : int LHSKind = static_cast<int>(LHS.kind);
882 : int RHSKind = static_cast<int>(RHS.kind);
883 : return std::tie(LHS.range, LHSKind) < std::tie(RHS.range, RHSKind);
884 : }
885 :
886 : friend bool operator==(const DocumentHighlight &LHS,
887 : const DocumentHighlight &RHS) {
888 0 : return LHS.kind == RHS.kind && LHS.range == RHS.range;
889 : }
890 : };
891 : llvm::json::Value toJSON(const DocumentHighlight &DH);
892 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DocumentHighlight &);
893 :
894 : struct ReferenceParams : public TextDocumentPositionParams {
895 : // For now, no options like context.includeDeclaration are supported.
896 : };
897 : bool fromJSON(const llvm::json::Value &, ReferenceParams &);
898 :
899 : } // namespace clangd
900 : } // namespace clang
901 :
902 : namespace llvm {
903 : template <> struct format_provider<clang::clangd::Position> {
904 : static void format(const clang::clangd::Position &Pos, raw_ostream &OS,
905 : StringRef Style) {
906 : assert(Style.empty() && "style modifiers for this type are not supported");
907 : OS << Pos;
908 : }
909 : };
910 : } // namespace llvm
911 :
912 : #endif
|