2089 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains structs based on the LSP specification at10// https://github.com/Microsoft/language-server-protocol/blob/main/protocol.md11//12// This is not meant to be a complete implementation, new interfaces are added13// when they're needed.14//15// Each struct has a toJSON and fromJSON function, that converts between16// the struct and a JSON representation. (See JSON.h)17//18// Some structs also have operator<< serialization. This is for debugging and19// tests, and is not generally machine-readable.20//21//===----------------------------------------------------------------------===//22 23#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H24#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H25 26#include "URI.h"27#include "index/SymbolID.h"28#include "support/MemoryTree.h"29#include "clang/Index/IndexSymbol.h"30#include "llvm/ADT/SmallVector.h"31#include "llvm/Support/JSON.h"32#include "llvm/Support/raw_ostream.h"33#include <bitset>34#include <memory>35#include <optional>36#include <string>37#include <vector>38 39// This file is using the LSP syntax for identifier names which is different40// from the LLVM coding standard. To avoid the clang-tidy warnings, we're41// disabling one check here.42// NOLINTBEGIN(readability-identifier-naming)43 44namespace clang {45namespace clangd {46 47enum class ErrorCode {48 // Defined by JSON RPC.49 ParseError = -32700,50 InvalidRequest = -32600,51 MethodNotFound = -32601,52 InvalidParams = -32602,53 InternalError = -32603,54 55 ServerNotInitialized = -32002,56 UnknownErrorCode = -32001,57 58 // Defined by the protocol.59 RequestCancelled = -32800,60 ContentModified = -32801,61};62// Models an LSP error as an llvm::Error.63class LSPError : public llvm::ErrorInfo<LSPError> {64public:65 std::string Message;66 ErrorCode Code;67 static char ID;68 69 LSPError(std::string Message, ErrorCode Code)70 : Message(std::move(Message)), Code(Code) {}71 72 void log(llvm::raw_ostream &OS) const override {73 OS << int(Code) << ": " << Message;74 }75 std::error_code convertToErrorCode() const override {76 return llvm::inconvertibleErrorCode();77 }78};79 80bool fromJSON(const llvm::json::Value &, SymbolID &, llvm::json::Path);81llvm::json::Value toJSON(const SymbolID &);82 83// URI in "file" scheme for a file.84struct URIForFile {85 URIForFile() = default;86 87 /// Canonicalizes \p AbsPath via URI.88 ///89 /// File paths in URIForFile can come from index or local AST. Path from90 /// index goes through URI transformation, and the final path is resolved by91 /// URI scheme and could potentially be different from the original path.92 /// Hence, we do the same transformation for all paths.93 ///94 /// Files can be referred to by several paths (e.g. in the presence of links).95 /// Which one we prefer may depend on where we're coming from. \p TUPath is a96 /// hint, and should usually be the main entrypoint file we're processing.97 static URIForFile canonicalize(llvm::StringRef AbsPath,98 llvm::StringRef TUPath);99 100 static llvm::Expected<URIForFile> fromURI(const URI &U,101 llvm::StringRef HintPath);102 103 /// Retrieves absolute path to the file.104 llvm::StringRef file() const { return File; }105 106 explicit operator bool() const { return !File.empty(); }107 std::string uri() const { return URI::createFile(File).toString(); }108 109 friend bool operator==(const URIForFile &LHS, const URIForFile &RHS) {110 return LHS.File == RHS.File;111 }112 113 friend bool operator!=(const URIForFile &LHS, const URIForFile &RHS) {114 return !(LHS == RHS);115 }116 117 friend bool operator<(const URIForFile &LHS, const URIForFile &RHS) {118 return LHS.File < RHS.File;119 }120 121private:122 explicit URIForFile(std::string &&File) : File(std::move(File)) {}123 124 std::string File;125};126 127/// Serialize/deserialize \p URIForFile to/from a string URI.128llvm::json::Value toJSON(const URIForFile &U);129bool fromJSON(const llvm::json::Value &, URIForFile &, llvm::json::Path);130 131struct TextDocumentIdentifier {132 /// The text document's URI.133 URIForFile uri;134};135llvm::json::Value toJSON(const TextDocumentIdentifier &);136bool fromJSON(const llvm::json::Value &, TextDocumentIdentifier &,137 llvm::json::Path);138 139struct VersionedTextDocumentIdentifier : public TextDocumentIdentifier {140 /// The version number of this document. If a versioned text document141 /// identifier is sent from the server to the client and the file is not open142 /// in the editor (the server has not received an open notification before)143 /// the server can send `null` to indicate that the version is known and the144 /// content on disk is the master (as speced with document content ownership).145 ///146 /// The version number of a document will increase after each change,147 /// including undo/redo. The number doesn't need to be consecutive.148 ///149 /// clangd extension: versions are optional, and synthesized if missing.150 std::optional<std::int64_t> version;151};152llvm::json::Value toJSON(const VersionedTextDocumentIdentifier &);153bool fromJSON(const llvm::json::Value &, VersionedTextDocumentIdentifier &,154 llvm::json::Path);155 156struct Position {157 /// Line position in a document (zero-based).158 int line = 0;159 160 /// Character offset on a line in a document (zero-based).161 /// WARNING: this is in UTF-16 codepoints, not bytes or characters!162 /// Use the functions in SourceCode.h to construct/interpret Positions.163 int character = 0;164 165 friend bool operator==(const Position &LHS, const Position &RHS) {166 return std::tie(LHS.line, LHS.character) ==167 std::tie(RHS.line, RHS.character);168 }169 friend bool operator!=(const Position &LHS, const Position &RHS) {170 return !(LHS == RHS);171 }172 friend bool operator<(const Position &LHS, const Position &RHS) {173 return std::tie(LHS.line, LHS.character) <174 std::tie(RHS.line, RHS.character);175 }176 friend bool operator<=(const Position &LHS, const Position &RHS) {177 return std::tie(LHS.line, LHS.character) <=178 std::tie(RHS.line, RHS.character);179 }180};181bool fromJSON(const llvm::json::Value &, Position &, llvm::json::Path);182llvm::json::Value toJSON(const Position &);183llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Position &);184 185struct Range {186 /// The range's start position.187 Position start;188 189 /// The range's end position.190 Position end;191 192 friend bool operator==(const Range &LHS, const Range &RHS) {193 return std::tie(LHS.start, LHS.end) == std::tie(RHS.start, RHS.end);194 }195 friend bool operator!=(const Range &LHS, const Range &RHS) {196 return !(LHS == RHS);197 }198 friend bool operator<(const Range &LHS, const Range &RHS) {199 return std::tie(LHS.start, LHS.end) < std::tie(RHS.start, RHS.end);200 }201 202 bool contains(Position Pos) const { return start <= Pos && Pos < end; }203 bool contains(Range Rng) const {204 return start <= Rng.start && Rng.end <= end;205 }206};207bool fromJSON(const llvm::json::Value &, Range &, llvm::json::Path);208llvm::json::Value toJSON(const Range &);209llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Range &);210 211struct Location {212 /// The text document's URI.213 URIForFile uri;214 Range range;215 216 friend bool operator==(const Location &LHS, const Location &RHS) {217 return LHS.uri == RHS.uri && LHS.range == RHS.range;218 }219 220 friend bool operator!=(const Location &LHS, const Location &RHS) {221 return !(LHS == RHS);222 }223 224 friend bool operator<(const Location &LHS, const Location &RHS) {225 return std::tie(LHS.uri, LHS.range) < std::tie(RHS.uri, RHS.range);226 }227};228llvm::json::Value toJSON(const Location &);229llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Location &);230 231/// Extends Locations returned by textDocument/references with extra info.232/// This is a clangd extension: LSP uses `Location`.233struct ReferenceLocation : Location {234 /// clangd extension: contains the name of the function or class in which the235 /// reference occurs236 std::optional<std::string> containerName;237};238llvm::json::Value toJSON(const ReferenceLocation &);239llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ReferenceLocation &);240 241using ChangeAnnotationIdentifier = std::string;242// A combination of a LSP standard TextEdit and AnnotatedTextEdit.243struct TextEdit {244 /// The range of the text document to be manipulated. To insert245 /// text into a document create a range where start === end.246 Range range;247 248 /// The string to be inserted. For delete operations use an249 /// empty string.250 std::string newText;251 252 /// The actual annotation identifier (optional)253 /// If empty, then this field is nullopt.254 ChangeAnnotationIdentifier annotationId = "";255};256inline bool operator==(const TextEdit &L, const TextEdit &R) {257 return std::tie(L.newText, L.range, L.annotationId) ==258 std::tie(R.newText, R.range, L.annotationId);259}260bool fromJSON(const llvm::json::Value &, TextEdit &, llvm::json::Path);261llvm::json::Value toJSON(const TextEdit &);262llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TextEdit &);263 264struct ChangeAnnotation {265 /// A human-readable string describing the actual change. The string266 /// is rendered prominent in the user interface.267 std::string label;268 269 /// A flag which indicates that user confirmation is needed270 /// before applying the change.271 std::optional<bool> needsConfirmation;272 273 /// A human-readable string which is rendered less prominent in274 /// the user interface.275 std::string description;276};277bool fromJSON(const llvm::json::Value &, ChangeAnnotation &, llvm::json::Path);278llvm::json::Value toJSON(const ChangeAnnotation &);279 280struct TextDocumentEdit {281 /// The text document to change.282 VersionedTextDocumentIdentifier textDocument;283 284 /// The edits to be applied.285 /// FIXME: support the AnnotatedTextEdit variant.286 std::vector<TextEdit> edits;287};288bool fromJSON(const llvm::json::Value &, TextDocumentEdit &, llvm::json::Path);289llvm::json::Value toJSON(const TextDocumentEdit &);290 291struct TextDocumentItem {292 /// The text document's URI.293 URIForFile uri;294 295 /// The text document's language identifier.296 std::string languageId;297 298 /// The version number of this document (it will strictly increase after each299 /// change, including undo/redo.300 ///301 /// clangd extension: versions are optional, and synthesized if missing.302 std::optional<int64_t> version;303 304 /// The content of the opened text document.305 std::string text;306};307bool fromJSON(const llvm::json::Value &, TextDocumentItem &, llvm::json::Path);308 309enum class TraceLevel {310 Off = 0,311 Messages = 1,312 Verbose = 2,313};314bool fromJSON(const llvm::json::Value &E, TraceLevel &Out, llvm::json::Path);315 316struct NoParams {};317inline llvm::json::Value toJSON(const NoParams &) { return nullptr; }318inline bool fromJSON(const llvm::json::Value &, NoParams &, llvm::json::Path) {319 return true;320}321using InitializedParams = NoParams;322 323/// Defines how the host (editor) should sync document changes to the language324/// server.325enum class TextDocumentSyncKind {326 /// Documents should not be synced at all.327 None = 0,328 329 /// Documents are synced by always sending the full content of the document.330 Full = 1,331 332 /// Documents are synced by sending the full content on open. After that333 /// only incremental updates to the document are send.334 Incremental = 2,335};336 337/// The kind of a completion entry.338enum class CompletionItemKind {339 Missing = 0,340 Text = 1,341 Method = 2,342 Function = 3,343 Constructor = 4,344 Field = 5,345 Variable = 6,346 Class = 7,347 Interface = 8,348 Module = 9,349 Property = 10,350 Unit = 11,351 Value = 12,352 Enum = 13,353 Keyword = 14,354 Snippet = 15,355 Color = 16,356 File = 17,357 Reference = 18,358 Folder = 19,359 EnumMember = 20,360 Constant = 21,361 Struct = 22,362 Event = 23,363 Operator = 24,364 TypeParameter = 25,365};366bool fromJSON(const llvm::json::Value &, CompletionItemKind &,367 llvm::json::Path);368constexpr auto CompletionItemKindMin =369 static_cast<size_t>(CompletionItemKind::Text);370constexpr auto CompletionItemKindMax =371 static_cast<size_t>(CompletionItemKind::TypeParameter);372using CompletionItemKindBitset = std::bitset<CompletionItemKindMax + 1>;373bool fromJSON(const llvm::json::Value &, CompletionItemKindBitset &,374 llvm::json::Path);375CompletionItemKind376adjustKindToCapability(CompletionItemKind Kind,377 CompletionItemKindBitset &SupportedCompletionItemKinds);378 379/// A symbol kind.380enum class SymbolKind {381 File = 1,382 Module = 2,383 Namespace = 3,384 Package = 4,385 Class = 5,386 Method = 6,387 Property = 7,388 Field = 8,389 Constructor = 9,390 Enum = 10,391 Interface = 11,392 Function = 12,393 Variable = 13,394 Constant = 14,395 String = 15,396 Number = 16,397 Boolean = 17,398 Array = 18,399 Object = 19,400 Key = 20,401 Null = 21,402 EnumMember = 22,403 Struct = 23,404 Event = 24,405 Operator = 25,406 TypeParameter = 26407};408bool fromJSON(const llvm::json::Value &, SymbolKind &, llvm::json::Path);409constexpr auto SymbolKindMin = static_cast<size_t>(SymbolKind::File);410constexpr auto SymbolKindMax = static_cast<size_t>(SymbolKind::TypeParameter);411using SymbolKindBitset = std::bitset<SymbolKindMax + 1>;412bool fromJSON(const llvm::json::Value &, SymbolKindBitset &, llvm::json::Path);413SymbolKind adjustKindToCapability(SymbolKind Kind,414 SymbolKindBitset &supportedSymbolKinds);415 416// Convert a index::SymbolKind to clangd::SymbolKind (LSP)417// Note, some are not perfect matches and should be improved when this LSP418// issue is addressed:419// https://github.com/Microsoft/language-server-protocol/issues/344420SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind);421 422// Determines the encoding used to measure offsets and lengths of source in LSP.423enum class OffsetEncoding {424 // Any string is legal on the wire. Unrecognized encodings parse as this.425 UnsupportedEncoding,426 // Length counts code units of UTF-16 encoded text. (Standard LSP behavior).427 UTF16,428 // Length counts bytes of UTF-8 encoded text. (Clangd extension).429 UTF8,430 // Length counts codepoints in unicode text. (Clangd extension).431 UTF32,432};433llvm::json::Value toJSON(const OffsetEncoding &);434bool fromJSON(const llvm::json::Value &, OffsetEncoding &, llvm::json::Path);435llvm::raw_ostream &operator<<(llvm::raw_ostream &, OffsetEncoding);436 437// Describes the content type that a client supports in various result literals438// like `Hover`, `ParameterInfo` or `CompletionItem`.439enum class MarkupKind {440 PlainText,441 Markdown,442};443bool fromJSON(const llvm::json::Value &, MarkupKind &, llvm::json::Path);444llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MarkupKind);445 446// This struct doesn't mirror LSP!447// The protocol defines deeply nested structures for client capabilities.448// Instead of mapping them all, this just parses out the bits we care about.449struct ClientCapabilities {450 /// The supported set of SymbolKinds for workspace/symbol.451 /// workspace.symbol.symbolKind.valueSet452 std::optional<SymbolKindBitset> WorkspaceSymbolKinds;453 454 /// Whether the client accepts diagnostics with codeActions attached inline.455 /// This is a clangd extension.456 /// textDocument.publishDiagnostics.codeActionsInline.457 bool DiagnosticFixes = false;458 459 /// Whether the client accepts diagnostics with related locations.460 /// textDocument.publishDiagnostics.relatedInformation.461 bool DiagnosticRelatedInformation = false;462 463 /// Whether the client accepts diagnostics with category attached to it464 /// using the "category" extension.465 /// textDocument.publishDiagnostics.categorySupport466 bool DiagnosticCategory = false;467 468 /// Client supports snippets as insert text.469 /// textDocument.completion.completionItem.snippetSupport470 bool CompletionSnippets = false;471 472 /// Client supports completions with additionalTextEdit near the cursor.473 /// This is a clangd extension. (LSP says this is for unrelated text only).474 /// textDocument.completion.editsNearCursor475 bool CompletionFixes = false;476 477 /// Client supports displaying a container string for results of478 /// textDocument/reference (clangd extension)479 /// textDocument.references.container480 bool ReferenceContainer = false;481 482 /// Client supports hierarchical document symbols.483 /// textDocument.documentSymbol.hierarchicalDocumentSymbolSupport484 bool HierarchicalDocumentSymbol = false;485 486 /// Client supports signature help.487 /// textDocument.signatureHelp488 bool HasSignatureHelp = false;489 490 /// Client signals that it only supports folding complete lines.491 /// Client will ignore specified `startCharacter` and `endCharacter`492 /// properties in a FoldingRange.493 /// textDocument.foldingRange.lineFoldingOnly494 bool LineFoldingOnly = false;495 496 /// Client supports processing label offsets instead of a simple label string.497 /// textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport498 bool OffsetsInSignatureHelp = false;499 500 /// The documentation format that should be used for501 /// textDocument/signatureHelp.502 /// textDocument.signatureHelp.signatureInformation.documentationFormat503 MarkupKind SignatureHelpDocumentationFormat = MarkupKind::PlainText;504 505 /// The supported set of CompletionItemKinds for textDocument/completion.506 /// textDocument.completion.completionItemKind.valueSet507 std::optional<CompletionItemKindBitset> CompletionItemKinds;508 509 /// The documentation format that should be used for textDocument/completion.510 /// textDocument.completion.completionItem.documentationFormat511 MarkupKind CompletionDocumentationFormat = MarkupKind::PlainText;512 513 /// The client has support for completion item label details.514 /// textDocument.completion.completionItem.labelDetailsSupport.515 bool CompletionLabelDetail = false;516 517 /// Client supports CodeAction return value for textDocument/codeAction.518 /// textDocument.codeAction.codeActionLiteralSupport.519 bool CodeActionStructure = false;520 521 /// Client advertises support for the semanticTokens feature.522 /// We support the textDocument/semanticTokens request in any case.523 /// textDocument.semanticTokens524 bool SemanticTokens = false;525 /// Client supports Theia semantic highlighting extension.526 /// https://github.com/microsoft/vscode-languageserver-node/pull/367527 /// clangd no longer supports this, we detect it just to log a warning.528 /// textDocument.semanticHighlightingCapabilities.semanticHighlighting529 bool TheiaSemanticHighlighting = false;530 531 /// Supported encodings for LSP character offsets.532 /// general.positionEncodings533 std::optional<std::vector<OffsetEncoding>> PositionEncodings;534 535 /// The content format that should be used for Hover requests.536 /// textDocument.hover.contentEncoding537 MarkupKind HoverContentFormat = MarkupKind::PlainText;538 539 /// The client supports testing for validity of rename operations540 /// before execution.541 bool RenamePrepareSupport = false;542 543 /// The client supports progress notifications.544 /// window.workDoneProgress545 bool WorkDoneProgress = false;546 547 /// The client supports implicit $/progress work-done progress streams,548 /// without a preceding window/workDoneProgress/create.549 /// This is a clangd extension.550 /// window.implicitWorkDoneProgressCreate551 bool ImplicitProgressCreation = false;552 553 /// Whether the client claims to cancel stale requests.554 /// general.staleRequestSupport.cancel555 bool CancelsStaleRequests = false;556 557 /// Whether the client implementation supports a refresh request sent from the558 /// server to the client.559 bool SemanticTokenRefreshSupport = false;560 561 /// The client supports versioned document changes for WorkspaceEdit.562 bool DocumentChanges = false;563 564 /// The client supports change annotations on text edits,565 bool ChangeAnnotation = false;566 567 /// Whether the client supports the textDocument/inactiveRegions568 /// notification. This is a clangd extension.569 /// textDocument.inactiveRegionsCapabilities.inactiveRegions570 bool InactiveRegions = false;571};572bool fromJSON(const llvm::json::Value &, ClientCapabilities &,573 llvm::json::Path);574 575/// Clangd extension that's used in the 'compilationDatabaseChanges' in576/// workspace/didChangeConfiguration to record updates to the in-memory577/// compilation database.578struct ClangdCompileCommand {579 std::string workingDirectory;580 std::vector<std::string> compilationCommand;581};582bool fromJSON(const llvm::json::Value &, ClangdCompileCommand &,583 llvm::json::Path);584 585/// Clangd extension: parameters configurable at any time, via the586/// `workspace/didChangeConfiguration` notification.587/// LSP defines this type as `any`.588struct ConfigurationSettings {589 // Changes to the in-memory compilation database.590 // The key of the map is a file name.591 std::map<std::string, ClangdCompileCommand> compilationDatabaseChanges;592};593bool fromJSON(const llvm::json::Value &, ConfigurationSettings &,594 llvm::json::Path);595 596/// Clangd extension: parameters configurable at `initialize` time.597/// LSP defines this type as `any`.598struct InitializationOptions {599 // What we can change through the didChangeConfiguration request, we can600 // also set through the initialize request (initializationOptions field).601 ConfigurationSettings ConfigSettings;602 603 std::optional<std::string> compilationDatabasePath;604 // Additional flags to be included in the "fallback command" used when605 // the compilation database doesn't describe an opened file.606 // The command used will be approximately `clang $FILE $fallbackFlags`.607 std::vector<std::string> fallbackFlags;608 609 /// Clients supports show file status for textDocument/clangd.fileStatus.610 bool FileStatus = false;611};612bool fromJSON(const llvm::json::Value &, InitializationOptions &,613 llvm::json::Path);614 615struct InitializeParams {616 /// The process Id of the parent process that started617 /// the server. Is null if the process has not been started by another618 /// process. If the parent process is not alive then the server should exit619 /// (see exit notification) its process.620 std::optional<int> processId;621 622 /// The rootPath of the workspace. Is null623 /// if no folder is open.624 ///625 /// @deprecated in favour of rootUri.626 std::optional<std::string> rootPath;627 628 /// The rootUri of the workspace. Is null if no629 /// folder is open. If both `rootPath` and `rootUri` are set630 /// `rootUri` wins.631 std::optional<URIForFile> rootUri;632 633 // User provided initialization options.634 // initializationOptions?: any;635 636 /// The capabilities provided by the client (editor or tool)637 ClientCapabilities capabilities;638 /// The same data as capabilities, but not parsed (to expose to modules).639 llvm::json::Object rawCapabilities;640 641 /// The initial trace setting. If omitted trace is disabled ('off').642 std::optional<TraceLevel> trace;643 644 /// User-provided initialization options.645 InitializationOptions initializationOptions;646};647bool fromJSON(const llvm::json::Value &, InitializeParams &, llvm::json::Path);648 649struct WorkDoneProgressCreateParams {650 /// The token to be used to report progress.651 llvm::json::Value token = nullptr;652};653llvm::json::Value toJSON(const WorkDoneProgressCreateParams &P);654 655template <typename T> struct ProgressParams {656 /// The progress token provided by the client or server.657 llvm::json::Value token = nullptr;658 659 /// The progress data.660 T value;661};662template <typename T> llvm::json::Value toJSON(const ProgressParams<T> &P) {663 return llvm::json::Object{{"token", P.token}, {"value", P.value}};664}665/// To start progress reporting a $/progress notification with the following666/// payload must be sent.667struct WorkDoneProgressBegin {668 /// Mandatory title of the progress operation. Used to briefly inform about669 /// the kind of operation being performed.670 ///671 /// Examples: "Indexing" or "Linking dependencies".672 std::string title;673 674 /// Controls if a cancel button should show to allow the user to cancel the675 /// long-running operation. Clients that don't support cancellation are676 /// allowed to ignore the setting.677 bool cancellable = false;678 679 /// Optional progress percentage to display (value 100 is considered 100%).680 /// If not provided infinite progress is assumed and clients are allowed681 /// to ignore the `percentage` value in subsequent in report notifications.682 ///683 /// The value should be steadily rising. Clients are free to ignore values684 /// that are not following this rule.685 ///686 /// Clangd implementation note: we only send nonzero percentages in687 /// the WorkProgressReport. 'true' here means percentages will be used.688 bool percentage = false;689};690llvm::json::Value toJSON(const WorkDoneProgressBegin &);691 692/// Reporting progress is done using the following payload.693struct WorkDoneProgressReport {694 /// Mandatory title of the progress operation. Used to briefly inform about695 /// the kind of operation being performed.696 ///697 /// Examples: "Indexing" or "Linking dependencies".698 std::string title;699 700 /// Controls enablement state of a cancel button. This property is only valid701 /// if a cancel button got requested in the `WorkDoneProgressStart` payload.702 ///703 /// Clients that don't support cancellation or don't support control704 /// the button's enablement state are allowed to ignore the setting.705 std::optional<bool> cancellable;706 707 /// Optional, more detailed associated progress message. Contains708 /// complementary information to the `title`.709 ///710 /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".711 /// If unset, the previous progress message (if any) is still valid.712 std::optional<std::string> message;713 714 /// Optional progress percentage to display (value 100 is considered 100%).715 /// If not provided infinite progress is assumed and clients are allowed716 /// to ignore the `percentage` value in subsequent in report notifications.717 ///718 /// The value should be steadily rising. Clients are free to ignore values719 /// that are not following this rule.720 std::optional<unsigned> percentage;721};722llvm::json::Value toJSON(const WorkDoneProgressReport &);723//724/// Signals the end of progress reporting.725struct WorkDoneProgressEnd {726 /// Optional, a final message indicating to for example indicate the outcome727 /// of the operation.728 std::optional<std::string> message;729};730llvm::json::Value toJSON(const WorkDoneProgressEnd &);731 732enum class MessageType {733 /// An error message.734 Error = 1,735 /// A warning message.736 Warning = 2,737 /// An information message.738 Info = 3,739 /// A log message.740 Log = 4,741};742llvm::json::Value toJSON(const MessageType &);743 744/// The show message notification is sent from a server to a client to ask the745/// client to display a particular message in the user interface.746struct ShowMessageParams {747 /// The message type.748 MessageType type = MessageType::Info;749 /// The actual message.750 std::string message;751};752llvm::json::Value toJSON(const ShowMessageParams &);753 754struct DidOpenTextDocumentParams {755 /// The document that was opened.756 TextDocumentItem textDocument;757};758bool fromJSON(const llvm::json::Value &, DidOpenTextDocumentParams &,759 llvm::json::Path);760 761struct DidCloseTextDocumentParams {762 /// The document that was closed.763 TextDocumentIdentifier textDocument;764};765bool fromJSON(const llvm::json::Value &, DidCloseTextDocumentParams &,766 llvm::json::Path);767 768struct DidSaveTextDocumentParams {769 /// The document that was saved.770 TextDocumentIdentifier textDocument;771};772bool fromJSON(const llvm::json::Value &, DidSaveTextDocumentParams &,773 llvm::json::Path);774 775struct TextDocumentContentChangeEvent {776 /// The range of the document that changed.777 std::optional<Range> range;778 779 /// The length of the range that got replaced.780 std::optional<int> rangeLength;781 782 /// The new text of the range/document.783 std::string text;784};785bool fromJSON(const llvm::json::Value &, TextDocumentContentChangeEvent &,786 llvm::json::Path);787 788struct DidChangeTextDocumentParams {789 /// The document that did change. The version number points790 /// to the version after all provided content changes have791 /// been applied.792 VersionedTextDocumentIdentifier textDocument;793 794 /// The actual content changes.795 std::vector<TextDocumentContentChangeEvent> contentChanges;796 797 /// Forces diagnostics to be generated, or to not be generated, for this798 /// version of the file. If not set, diagnostics are eventually consistent:799 /// either they will be provided for this version or some subsequent one.800 /// This is a clangd extension.801 std::optional<bool> wantDiagnostics;802 803 /// Force a complete rebuild of the file, ignoring all cached state. Slow!804 /// This is useful to defeat clangd's assumption that missing headers will805 /// stay missing.806 /// This is a clangd extension.807 bool forceRebuild = false;808};809bool fromJSON(const llvm::json::Value &, DidChangeTextDocumentParams &,810 llvm::json::Path);811 812enum class FileChangeType {813 /// The file got created.814 Created = 1,815 /// The file got changed.816 Changed = 2,817 /// The file got deleted.818 Deleted = 3819};820bool fromJSON(const llvm::json::Value &E, FileChangeType &Out,821 llvm::json::Path);822 823struct FileEvent {824 /// The file's URI.825 URIForFile uri;826 /// The change type.827 FileChangeType type = FileChangeType::Created;828};829bool fromJSON(const llvm::json::Value &, FileEvent &, llvm::json::Path);830 831struct DidChangeWatchedFilesParams {832 /// The actual file events.833 std::vector<FileEvent> changes;834};835bool fromJSON(const llvm::json::Value &, DidChangeWatchedFilesParams &,836 llvm::json::Path);837 838struct DidChangeConfigurationParams {839 ConfigurationSettings settings;840};841bool fromJSON(const llvm::json::Value &, DidChangeConfigurationParams &,842 llvm::json::Path);843 844// Note: we do not parse FormattingOptions for *FormattingParams.845// In general, we use a clang-format style detected from common mechanisms846// (.clang-format files and the -fallback-style flag).847// It would be possible to override these with FormatOptions, but:848// - the protocol makes FormatOptions mandatory, so many clients set them to849// useless values, and we can't tell when to respect them850// - we also format in other places, where FormatOptions aren't available.851 852struct DocumentRangeFormattingParams {853 /// The document to format.854 TextDocumentIdentifier textDocument;855 856 /// The range to format857 Range range;858};859bool fromJSON(const llvm::json::Value &, DocumentRangeFormattingParams &,860 llvm::json::Path);861 862struct DocumentRangesFormattingParams {863 /// The document to format.864 TextDocumentIdentifier textDocument;865 866 /// The list of ranges to format867 std::vector<Range> ranges;868};869bool fromJSON(const llvm::json::Value &, DocumentRangesFormattingParams &,870 llvm::json::Path);871 872struct DocumentOnTypeFormattingParams {873 /// The document to format.874 TextDocumentIdentifier textDocument;875 876 /// The position at which this request was sent.877 Position position;878 879 /// The character that has been typed.880 std::string ch;881};882bool fromJSON(const llvm::json::Value &, DocumentOnTypeFormattingParams &,883 llvm::json::Path);884 885struct DocumentFormattingParams {886 /// The document to format.887 TextDocumentIdentifier textDocument;888};889bool fromJSON(const llvm::json::Value &, DocumentFormattingParams &,890 llvm::json::Path);891 892struct DocumentSymbolParams {893 // The text document to find symbols in.894 TextDocumentIdentifier textDocument;895};896bool fromJSON(const llvm::json::Value &, DocumentSymbolParams &,897 llvm::json::Path);898 899/// Represents a related message and source code location for a diagnostic.900/// This should be used to point to code locations that cause or related to a901/// diagnostics, e.g when duplicating a symbol in a scope.902struct DiagnosticRelatedInformation {903 /// The location of this related diagnostic information.904 Location location;905 /// The message of this related diagnostic information.906 std::string message;907};908llvm::json::Value toJSON(const DiagnosticRelatedInformation &);909 910enum DiagnosticTag {911 /// Unused or unnecessary code.912 ///913 /// Clients are allowed to render diagnostics with this tag faded out instead914 /// of having an error squiggle.915 Unnecessary = 1,916 /// Deprecated or obsolete code.917 ///918 /// Clients are allowed to rendered diagnostics with this tag strike through.919 Deprecated = 2,920};921llvm::json::Value toJSON(DiagnosticTag Tag);922 923/// Structure to capture a description for an error code.924struct CodeDescription {925 /// An URI to open with more information about the diagnostic error.926 std::string href;927};928llvm::json::Value toJSON(const CodeDescription &);929 930struct CodeAction;931struct Diagnostic {932 /// The range at which the message applies.933 Range range;934 935 /// The diagnostic's severity. Can be omitted. If omitted it is up to the936 /// client to interpret diagnostics as error, warning, info or hint.937 int severity = 0;938 939 /// The diagnostic's code. Can be omitted.940 std::string code;941 942 /// An optional property to describe the error code.943 std::optional<CodeDescription> codeDescription;944 945 /// A human-readable string describing the source of this946 /// diagnostic, e.g. 'typescript' or 'super lint'.947 std::string source;948 949 /// The diagnostic's message.950 std::string message;951 952 /// Additional metadata about the diagnostic.953 llvm::SmallVector<DiagnosticTag, 1> tags;954 955 /// An array of related diagnostic information, e.g. when symbol-names within956 /// a scope collide all definitions can be marked via this property.957 std::optional<std::vector<DiagnosticRelatedInformation>> relatedInformation;958 959 /// The diagnostic's category. Can be omitted.960 /// An LSP extension that's used to send the name of the category over to the961 /// client. The category typically describes the compilation stage during962 /// which the issue was produced, e.g. "Semantic Issue" or "Parse Issue".963 std::optional<std::string> category;964 965 /// Clangd extension: code actions related to this diagnostic.966 /// Only with capability textDocument.publishDiagnostics.codeActionsInline.967 /// (These actions can also be obtained using textDocument/codeAction).968 std::optional<std::vector<CodeAction>> codeActions;969 970 /// A data entry field that is preserved between a971 /// `textDocument/publishDiagnostics` notification972 /// and `textDocument/codeAction` request.973 /// Mutating users should associate their data with a unique key they can use974 /// to retrieve later on.975 llvm::json::Object data;976};977llvm::json::Value toJSON(const Diagnostic &);978 979bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);980llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Diagnostic &);981 982struct PublishDiagnosticsParams {983 /// The URI for which diagnostic information is reported.984 URIForFile uri;985 /// An array of diagnostic information items.986 std::vector<Diagnostic> diagnostics;987 /// The version number of the document the diagnostics are published for.988 std::optional<int64_t> version;989};990llvm::json::Value toJSON(const PublishDiagnosticsParams &);991 992struct CodeActionContext {993 /// An array of diagnostics known on the client side overlapping the range994 /// provided to the `textDocument/codeAction` request. They are provided so995 /// that the server knows which errors are currently presented to the user for996 /// the given range. There is no guarantee that these accurately reflect the997 /// error state of the resource. The primary parameter to compute code actions998 /// is the provided range.999 std::vector<Diagnostic> diagnostics;1000 1001 /// Requested kind of actions to return.1002 ///1003 /// Actions not of this kind are filtered out by the client before being1004 /// shown. So servers can omit computing them.1005 std::vector<std::string> only;1006};1007bool fromJSON(const llvm::json::Value &, CodeActionContext &, llvm::json::Path);1008 1009struct CodeActionParams {1010 /// The document in which the command was invoked.1011 TextDocumentIdentifier textDocument;1012 1013 /// The range for which the command was invoked.1014 Range range;1015 1016 /// Context carrying additional information.1017 CodeActionContext context;1018};1019bool fromJSON(const llvm::json::Value &, CodeActionParams &, llvm::json::Path);1020 1021/// The edit should either provide changes or documentChanges. If the client1022/// can handle versioned document edits and if documentChanges are present,1023/// the latter are preferred over changes.1024struct WorkspaceEdit {1025 /// Holds changes to existing resources.1026 std::optional<std::map<std::string, std::vector<TextEdit>>> changes;1027 /// Versioned document edits.1028 ///1029 /// If a client neither supports `documentChanges` nor1030 /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s1031 /// using the `changes` property are supported.1032 std::optional<std::vector<TextDocumentEdit>> documentChanges;1033 1034 /// A map of change annotations that can be referenced in1035 /// AnnotatedTextEdit.1036 std::map<std::string, ChangeAnnotation> changeAnnotations;1037};1038bool fromJSON(const llvm::json::Value &, WorkspaceEdit &, llvm::json::Path);1039llvm::json::Value toJSON(const WorkspaceEdit &WE);1040 1041/// Arguments for the 'applyTweak' command. The server sends these commands as a1042/// response to the textDocument/codeAction request. The client can later send a1043/// command back to the server if the user requests to execute a particular code1044/// tweak.1045struct TweakArgs {1046 /// A file provided by the client on a textDocument/codeAction request.1047 URIForFile file;1048 /// A selection provided by the client on a textDocument/codeAction request.1049 Range selection;1050 /// ID of the tweak that should be executed. Corresponds to Tweak::id().1051 std::string tweakID;1052};1053bool fromJSON(const llvm::json::Value &, TweakArgs &, llvm::json::Path);1054llvm::json::Value toJSON(const TweakArgs &A);1055 1056struct ExecuteCommandParams {1057 /// The identifier of the actual command handler.1058 std::string command;1059 1060 // This is `arguments?: []any` in LSP.1061 // All clangd's commands accept a single argument (or none => null).1062 llvm::json::Value argument = nullptr;1063};1064bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &,1065 llvm::json::Path);1066 1067struct Command : public ExecuteCommandParams {1068 std::string title;1069};1070llvm::json::Value toJSON(const Command &C);1071 1072/// A code action represents a change that can be performed in code, e.g. to fix1073/// a problem or to refactor code.1074///1075/// A CodeAction must set either `edit` and/or a `command`. If both are1076/// supplied, the `edit` is applied first, then the `command` is executed.1077struct CodeAction {1078 /// A short, human-readable, title for this code action.1079 std::string title;1080 1081 /// The kind of the code action.1082 /// Used to filter code actions.1083 std::optional<std::string> kind;1084 const static llvm::StringLiteral QUICKFIX_KIND;1085 const static llvm::StringLiteral REFACTOR_KIND;1086 const static llvm::StringLiteral INFO_KIND;1087 1088 /// The diagnostics that this code action resolves.1089 std::optional<std::vector<Diagnostic>> diagnostics;1090 1091 /// Marks this as a preferred action. Preferred actions are used by the1092 /// `auto fix` command and can be targeted by keybindings.1093 /// A quick fix should be marked preferred if it properly addresses the1094 /// underlying error. A refactoring should be marked preferred if it is the1095 /// most reasonable choice of actions to take.1096 bool isPreferred = false;1097 1098 /// The workspace edit this code action performs.1099 std::optional<WorkspaceEdit> edit;1100 1101 /// A command this code action executes. If a code action provides an edit1102 /// and a command, first the edit is executed and then the command.1103 std::optional<Command> command;1104};1105llvm::json::Value toJSON(const CodeAction &);1106 1107/// Represents programming constructs like variables, classes, interfaces etc.1108/// that appear in a document. Document symbols can be hierarchical and they1109/// have two ranges: one that encloses its definition and one that points to its1110/// most interesting range, e.g. the range of an identifier.1111struct DocumentSymbol {1112 /// The name of this symbol.1113 std::string name;1114 1115 /// More detail for this symbol, e.g the signature of a function.1116 std::string detail;1117 1118 /// The kind of this symbol.1119 SymbolKind kind;1120 1121 /// Indicates if this symbol is deprecated.1122 bool deprecated = false;1123 1124 /// The range enclosing this symbol not including leading/trailing whitespace1125 /// but everything else like comments. This information is typically used to1126 /// determine if the clients cursor is inside the symbol to reveal in the1127 /// symbol in the UI.1128 Range range;1129 1130 /// The range that should be selected and revealed when this symbol is being1131 /// picked, e.g the name of a function. Must be contained by the `range`.1132 Range selectionRange;1133 1134 /// Children of this symbol, e.g. properties of a class.1135 std::vector<DocumentSymbol> children;1136};1137llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S);1138llvm::json::Value toJSON(const DocumentSymbol &S);1139 1140/// Represents information about programming constructs like variables, classes,1141/// interfaces etc.1142struct SymbolInformation {1143 /// The name of this symbol.1144 std::string name;1145 1146 /// The kind of this symbol.1147 SymbolKind kind;1148 1149 /// The location of this symbol.1150 Location location;1151 1152 /// The name of the symbol containing this symbol.1153 std::string containerName;1154 1155 /// The score that clangd calculates to rank the returned symbols.1156 /// This excludes the fuzzy-matching score between `name` and the query.1157 /// (Specifically, the last ::-separated component).1158 /// This can be used to re-rank results as the user types, using client-side1159 /// fuzzy-matching (that score should be multiplied with this one).1160 /// This is a clangd extension, set only for workspace/symbol responses.1161 std::optional<float> score;1162};1163llvm::json::Value toJSON(const SymbolInformation &);1164llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolInformation &);1165 1166/// Represents information about identifier.1167/// This is returned from textDocument/symbolInfo, which is a clangd extension.1168struct SymbolDetails {1169 std::string name;1170 1171 std::string containerName;1172 1173 /// Unified Symbol Resolution identifier1174 /// This is an opaque string uniquely identifying a symbol.1175 /// Unlike SymbolID, it is variable-length and somewhat human-readable.1176 /// It is a common representation across several clang tools.1177 /// (See USRGeneration.h)1178 std::string USR;1179 1180 SymbolID ID;1181 1182 std::optional<Location> declarationRange;1183 1184 std::optional<Location> definitionRange;1185};1186llvm::json::Value toJSON(const SymbolDetails &);1187llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolDetails &);1188bool operator==(const SymbolDetails &, const SymbolDetails &);1189 1190/// The parameters of a Workspace Symbol Request.1191struct WorkspaceSymbolParams {1192 /// A query string to filter symbols by.1193 /// Clients may send an empty string here to request all the symbols.1194 std::string query;1195 1196 /// Max results to return, overriding global default. 0 means no limit.1197 /// Clangd extension.1198 std::optional<int> limit;1199};1200bool fromJSON(const llvm::json::Value &, WorkspaceSymbolParams &,1201 llvm::json::Path);1202 1203struct ApplyWorkspaceEditParams {1204 WorkspaceEdit edit;1205};1206llvm::json::Value toJSON(const ApplyWorkspaceEditParams &);1207 1208struct ApplyWorkspaceEditResponse {1209 bool applied = true;1210 std::optional<std::string> failureReason;1211};1212bool fromJSON(const llvm::json::Value &, ApplyWorkspaceEditResponse &,1213 llvm::json::Path);1214 1215struct TextDocumentPositionParams {1216 /// The text document.1217 TextDocumentIdentifier textDocument;1218 1219 /// The position inside the text document.1220 Position position;1221};1222bool fromJSON(const llvm::json::Value &, TextDocumentPositionParams &,1223 llvm::json::Path);1224 1225enum class CompletionTriggerKind {1226 /// Completion was triggered by typing an identifier (24x7 code1227 /// complete), manual invocation (e.g Ctrl+Space) or via API.1228 Invoked = 1,1229 /// Completion was triggered by a trigger character specified by1230 /// the `triggerCharacters` properties of the `CompletionRegistrationOptions`.1231 TriggerCharacter = 2,1232 /// Completion was re-triggered as the current completion list is incomplete.1233 TriggerTriggerForIncompleteCompletions = 31234};1235 1236struct CompletionContext {1237 /// How the completion was triggered.1238 CompletionTriggerKind triggerKind = CompletionTriggerKind::Invoked;1239 /// The trigger character (a single character) that has trigger code complete.1240 /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`1241 std::string triggerCharacter;1242};1243bool fromJSON(const llvm::json::Value &, CompletionContext &, llvm::json::Path);1244 1245struct CompletionParams : TextDocumentPositionParams {1246 CompletionContext context;1247 1248 /// Max results to return, overriding global default. 0 means no limit.1249 /// Clangd extension.1250 std::optional<int> limit;1251};1252bool fromJSON(const llvm::json::Value &, CompletionParams &, llvm::json::Path);1253 1254struct MarkupContent {1255 MarkupKind kind = MarkupKind::PlainText;1256 std::string value;1257};1258llvm::json::Value toJSON(const MarkupContent &MC);1259 1260struct Hover {1261 /// The hover's content1262 MarkupContent contents;1263 1264 /// An optional range is a range inside a text document1265 /// that is used to visualize a hover, e.g. by changing the background color.1266 std::optional<Range> range;1267};1268llvm::json::Value toJSON(const Hover &H);1269 1270/// Defines whether the insert text in a completion item should be interpreted1271/// as plain text or a snippet.1272enum class InsertTextFormat {1273 Missing = 0,1274 /// The primary text to be inserted is treated as a plain string.1275 PlainText = 1,1276 /// The primary text to be inserted is treated as a snippet.1277 ///1278 /// A snippet can define tab stops and placeholders with `$1`, `$2`1279 /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to the end1280 /// of the snippet. Placeholders with equal identifiers are linked, that is1281 /// typing in one will update others too.1282 ///1283 /// See also:1284 /// https://github.com/Microsoft/vscode/blob/main/src/vs/editor/contrib/snippet/snippet.md1285 Snippet = 2,1286};1287 1288/// Additional details for a completion item label.1289struct CompletionItemLabelDetails {1290 /// An optional string which is rendered less prominently directly after label1291 /// without any spacing. Should be used for function signatures or type1292 /// annotations.1293 std::string detail;1294 1295 /// An optional string which is rendered less prominently after1296 /// CompletionItemLabelDetails.detail. Should be used for fully qualified1297 /// names or file path.1298 std::string description;1299};1300llvm::json::Value toJSON(const CompletionItemLabelDetails &);1301 1302struct CompletionItem {1303 /// The label of this completion item. By default also the text that is1304 /// inserted when selecting this completion.1305 std::string label;1306 1307 /// Additional details for the label.1308 std::optional<CompletionItemLabelDetails> labelDetails;1309 1310 /// The kind of this completion item. Based of the kind an icon is chosen by1311 /// the editor.1312 CompletionItemKind kind = CompletionItemKind::Missing;1313 1314 /// A human-readable string with additional information about this item, like1315 /// type or symbol information.1316 std::string detail;1317 1318 /// A human-readable string that represents a doc-comment.1319 std::optional<MarkupContent> documentation;1320 1321 /// A string that should be used when comparing this item with other items.1322 /// When `falsy` the label is used.1323 std::string sortText;1324 1325 /// A string that should be used when filtering a set of completion items.1326 /// When `falsy` the label is used.1327 std::string filterText;1328 1329 /// A string that should be inserted to a document when selecting this1330 /// completion. When `falsy` the label is used.1331 std::string insertText;1332 1333 /// The format of the insert text. The format applies to both the `insertText`1334 /// property and the `newText` property of a provided `textEdit`.1335 InsertTextFormat insertTextFormat = InsertTextFormat::Missing;1336 1337 /// An edit which is applied to a document when selecting this completion.1338 /// When an edit is provided `insertText` is ignored.1339 ///1340 /// Note: The range of the edit must be a single line range and it must1341 /// contain the position at which completion has been requested.1342 std::optional<TextEdit> textEdit;1343 1344 /// An optional array of additional text edits that are applied when selecting1345 /// this completion. Edits must not overlap with the main edit nor with1346 /// themselves.1347 std::vector<TextEdit> additionalTextEdits;1348 1349 /// Indicates if this item is deprecated.1350 bool deprecated = false;1351 1352 /// The score that clangd calculates to rank the returned completions.1353 /// This excludes the fuzzy-match between `filterText` and the partial word.1354 /// This can be used to re-rank results as the user types, using client-side1355 /// fuzzy-matching (that score should be multiplied with this one).1356 /// This is a clangd extension.1357 float score = 0.f;1358 1359 // TODO: Add custom commitCharacters for some of the completion items. For1360 // example, it makes sense to use () only for the functions.1361 // TODO(krasimir): The following optional fields defined by the language1362 // server protocol are unsupported:1363 //1364 // data?: any - A data entry field that is preserved on a completion item1365 // between a completion and a completion resolve request.1366};1367llvm::json::Value toJSON(const CompletionItem &);1368llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CompletionItem &);1369 1370/// Remove the labelDetails field (for clients that don't support it).1371/// Places the information into other fields of the completion item.1372void removeCompletionLabelDetails(CompletionItem &);1373 1374bool operator<(const CompletionItem &, const CompletionItem &);1375 1376/// Represents a collection of completion items to be presented in the editor.1377struct CompletionList {1378 /// The list is not complete. Further typing should result in recomputing the1379 /// list.1380 bool isIncomplete = false;1381 1382 /// The completion items.1383 std::vector<CompletionItem> items;1384};1385llvm::json::Value toJSON(const CompletionList &);1386 1387/// A single parameter of a particular signature.1388struct ParameterInformation {1389 1390 /// The label of this parameter. Ignored when labelOffsets is set.1391 std::string labelString;1392 1393 /// Inclusive start and exclusive end offsets withing the containing signature1394 /// label.1395 /// Offsets are computed by lspLength(), which counts UTF-16 code units by1396 /// default but that can be overriden, see its documentation for details.1397 std::optional<std::pair<unsigned, unsigned>> labelOffsets;1398 1399 /// The documentation of this parameter. Optional.1400 std::string documentation;1401};1402llvm::json::Value toJSON(const ParameterInformation &);1403 1404/// Represents the signature of something callable.1405struct SignatureInformation {1406 1407 /// The label of this signature. Mandatory.1408 std::string label;1409 1410 /// The documentation of this signature. Optional.1411 MarkupContent documentation;1412 1413 /// The parameters of this signature.1414 std::vector<ParameterInformation> parameters;1415};1416llvm::json::Value toJSON(const SignatureInformation &);1417llvm::raw_ostream &operator<<(llvm::raw_ostream &,1418 const SignatureInformation &);1419 1420/// Represents the signature of a callable.1421struct SignatureHelp {1422 1423 /// The resulting signatures.1424 std::vector<SignatureInformation> signatures;1425 1426 /// The active signature.1427 int activeSignature = 0;1428 1429 /// The active parameter of the active signature.1430 int activeParameter = 0;1431 1432 /// Position of the start of the argument list, including opening paren. e.g.1433 /// foo("first arg", "second arg",1434 /// ^-argListStart ^-cursor1435 /// This is a clangd-specific extension, it is only available via C++ API and1436 /// not currently serialized for the LSP.1437 Position argListStart;1438};1439llvm::json::Value toJSON(const SignatureHelp &);1440 1441struct RenameParams {1442 /// The document that was opened.1443 TextDocumentIdentifier textDocument;1444 1445 /// The position at which this request was sent.1446 Position position;1447 1448 /// The new name of the symbol.1449 std::string newName;1450};1451bool fromJSON(const llvm::json::Value &, RenameParams &, llvm::json::Path);1452llvm::json::Value toJSON(const RenameParams &);1453 1454struct PrepareRenameResult {1455 /// Range of the string to rename.1456 Range range;1457 /// Placeholder text to use in the editor if non-empty.1458 std::string placeholder;1459};1460llvm::json::Value toJSON(const PrepareRenameResult &PRR);1461 1462enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };1463 1464/// A document highlight is a range inside a text document which deserves1465/// special attention. Usually a document highlight is visualized by changing1466/// the background color of its range.1467 1468struct DocumentHighlight {1469 /// The range this highlight applies to.1470 Range range;1471 1472 /// The highlight kind, default is DocumentHighlightKind.Text.1473 DocumentHighlightKind kind = DocumentHighlightKind::Text;1474 1475 friend bool operator<(const DocumentHighlight &LHS,1476 const DocumentHighlight &RHS) {1477 int LHSKind = static_cast<int>(LHS.kind);1478 int RHSKind = static_cast<int>(RHS.kind);1479 return std::tie(LHS.range, LHSKind) < std::tie(RHS.range, RHSKind);1480 }1481 1482 friend bool operator==(const DocumentHighlight &LHS,1483 const DocumentHighlight &RHS) {1484 return LHS.kind == RHS.kind && LHS.range == RHS.range;1485 }1486};1487llvm::json::Value toJSON(const DocumentHighlight &DH);1488llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DocumentHighlight &);1489 1490enum class TypeHierarchyDirection { Children = 0, Parents = 1, Both = 2 };1491bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out,1492 llvm::json::Path);1493 1494/// The type hierarchy params is an extension of the1495/// `TextDocumentPositionsParams` with optional properties which can be used to1496/// eagerly resolve the item when requesting from the server.1497struct TypeHierarchyPrepareParams : public TextDocumentPositionParams {1498 /// The hierarchy levels to resolve. `0` indicates no level.1499 /// This is a clangd extension.1500 int resolve = 0;1501 1502 /// The direction of the hierarchy levels to resolve.1503 /// This is a clangd extension.1504 TypeHierarchyDirection direction = TypeHierarchyDirection::Parents;1505};1506bool fromJSON(const llvm::json::Value &, TypeHierarchyPrepareParams &,1507 llvm::json::Path);1508 1509struct TypeHierarchyItem {1510 /// The name of this item.1511 std::string name;1512 1513 /// The kind of this item.1514 SymbolKind kind;1515 1516 /// More detail for this item, e.g. the signature of a function.1517 std::optional<std::string> detail;1518 1519 /// The resource identifier of this item.1520 URIForFile uri;1521 1522 /// The range enclosing this symbol not including leading/trailing whitespace1523 /// but everything else, e.g. comments and code.1524 Range range;1525 1526 /// The range that should be selected and revealed when this symbol is being1527 /// picked, e.g. the name of a function. Must be contained by the `range`.1528 Range selectionRange;1529 1530 /// Used to resolve a client provided item back.1531 struct ResolveParams {1532 SymbolID symbolID;1533 /// std::nullopt means parents aren't resolved and empty is no parents.1534 std::optional<std::vector<ResolveParams>> parents;1535 };1536 /// A data entry field that is preserved between a type hierarchy prepare and1537 /// supertypes or subtypes requests. It could also be used to identify the1538 /// type hierarchy in the server, helping improve the performance on resolving1539 /// supertypes and subtypes.1540 ResolveParams data;1541 1542 /// `true` if the hierarchy item is deprecated. Otherwise, `false`.1543 /// This is a clangd exntesion.1544 bool deprecated = false;1545 1546 /// This is a clangd exntesion.1547 std::optional<std::vector<TypeHierarchyItem>> parents;1548 1549 /// If this type hierarchy item is resolved, it contains the direct children1550 /// of the current item. Could be empty if the item does not have any1551 /// descendants. If not defined, the children have not been resolved.1552 /// This is a clangd exntesion.1553 std::optional<std::vector<TypeHierarchyItem>> children;1554};1555llvm::json::Value toJSON(const TypeHierarchyItem::ResolveParams &);1556bool fromJSON(const TypeHierarchyItem::ResolveParams &);1557llvm::json::Value toJSON(const TypeHierarchyItem &);1558llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TypeHierarchyItem &);1559bool fromJSON(const llvm::json::Value &, TypeHierarchyItem &, llvm::json::Path);1560 1561/// Parameters for the `typeHierarchy/resolve` request.1562struct ResolveTypeHierarchyItemParams {1563 /// The item to resolve.1564 TypeHierarchyItem item;1565 1566 /// The hierarchy levels to resolve. `0` indicates no level.1567 int resolve;1568 1569 /// The direction of the hierarchy levels to resolve.1570 TypeHierarchyDirection direction;1571};1572bool fromJSON(const llvm::json::Value &, ResolveTypeHierarchyItemParams &,1573 llvm::json::Path);1574 1575enum class SymbolTag { Deprecated = 1 };1576llvm::json::Value toJSON(SymbolTag);1577 1578/// The parameter of a `textDocument/prepareCallHierarchy` request.1579struct CallHierarchyPrepareParams : public TextDocumentPositionParams {};1580 1581/// Represents programming constructs like functions or constructors1582/// in the context of call hierarchy.1583struct CallHierarchyItem {1584 /// The name of this item.1585 std::string name;1586 1587 /// The kind of this item.1588 SymbolKind kind;1589 1590 /// Tags for this item.1591 std::vector<SymbolTag> tags;1592 1593 /// More detaill for this item, e.g. the signature of a function.1594 std::string detail;1595 1596 /// The resource identifier of this item.1597 URIForFile uri;1598 1599 /// The range enclosing this symbol not including leading / trailing1600 /// whitespace but everything else, e.g. comments and code.1601 Range range;1602 1603 /// The range that should be selected and revealed when this symbol1604 /// is being picked, e.g. the name of a function.1605 /// Must be contained by `Rng`.1606 Range selectionRange;1607 1608 /// An optional 'data' field, which can be used to identify a call1609 /// hierarchy item in an incomingCalls or outgoingCalls request.1610 std::string data;1611};1612llvm::json::Value toJSON(const CallHierarchyItem &);1613bool fromJSON(const llvm::json::Value &, CallHierarchyItem &, llvm::json::Path);1614 1615/// The parameter of a `callHierarchy/incomingCalls` request.1616struct CallHierarchyIncomingCallsParams {1617 CallHierarchyItem item;1618};1619bool fromJSON(const llvm::json::Value &, CallHierarchyIncomingCallsParams &,1620 llvm::json::Path);1621 1622/// Represents an incoming call, e.g. a caller of a method or constructor.1623struct CallHierarchyIncomingCall {1624 /// The item that makes the call.1625 CallHierarchyItem from;1626 1627 /// The range at which the calls appear.1628 /// This is relative to the caller denoted by `From`.1629 std::vector<Range> fromRanges;1630 1631 /// For the case of being a virtual function we also return calls1632 /// to the base function. This caller might be a false positive.1633 /// We currently have no way of discerning this.1634 /// This is a clangd extension.1635 bool mightNeverCall = false;1636};1637llvm::json::Value toJSON(const CallHierarchyIncomingCall &);1638 1639/// The parameter of a `callHierarchy/outgoingCalls` request.1640struct CallHierarchyOutgoingCallsParams {1641 CallHierarchyItem item;1642};1643bool fromJSON(const llvm::json::Value &, CallHierarchyOutgoingCallsParams &,1644 llvm::json::Path);1645 1646/// Represents an outgoing call, e.g. calling a getter from a method or1647/// a method from a constructor etc.1648struct CallHierarchyOutgoingCall {1649 /// The item that is called.1650 CallHierarchyItem to;1651 1652 /// The range at which this item is called.1653 /// This is the range relative to the caller, and not `To`.1654 std::vector<Range> fromRanges;1655};1656llvm::json::Value toJSON(const CallHierarchyOutgoingCall &);1657 1658/// A parameter literal used in inlay hint requests.1659struct InlayHintsParams {1660 /// The text document.1661 TextDocumentIdentifier textDocument;1662 1663 /// The visible document range for which inlay hints should be computed.1664 ///1665 /// std::nullopt is a clangd extension, which hints for computing hints on the1666 /// whole file.1667 std::optional<Range> range;1668};1669bool fromJSON(const llvm::json::Value &, InlayHintsParams &, llvm::json::Path);1670 1671/// Inlay hint kinds.1672enum class InlayHintKind {1673 /// An inlay hint that for a type annotation.1674 ///1675 /// An example of a type hint is a hint in this position:1676 /// auto var ^ = expr;1677 /// which shows the deduced type of the variable.1678 Type = 1,1679 1680 /// An inlay hint that is for a parameter.1681 ///1682 /// An example of a parameter hint is a hint in this position:1683 /// func(^arg);1684 /// which shows the name of the corresponding parameter.1685 Parameter = 2,1686 1687 /// A hint before an element of an aggregate braced initializer list,1688 /// indicating what it is initializing.1689 /// Pair{^1, ^2};1690 /// Uses designator syntax, e.g. `.first:`.1691 /// This is a clangd extension.1692 Designator = 3,1693 1694 /// A hint after function, type or namespace definition, indicating the1695 /// defined symbol name of the definition.1696 ///1697 /// An example of a decl name hint in this position:1698 /// void func() {1699 /// } ^1700 /// Uses comment-like syntax like "// func".1701 /// This is a clangd extension.1702 BlockEnd = 4,1703 1704 /// An inlay hint that is for a default argument.1705 ///1706 /// An example of a parameter hint for a default argument:1707 /// void foo(bool A = true);1708 /// foo(^);1709 /// Adds an inlay hint "A: true".1710 /// This is a clangd extension.1711 DefaultArgument = 6,1712 1713 /// Other ideas for hints that are not currently implemented:1714 ///1715 /// * Chaining hints, showing the types of intermediate expressions1716 /// in a chain of function calls.1717 /// * Hints indicating implicit conversions or implicit constructor calls.1718};1719llvm::json::Value toJSON(const InlayHintKind &);1720 1721/// An inlay hint label part allows for interactive and composite labels1722/// of inlay hints.1723struct InlayHintLabelPart {1724 1725 InlayHintLabelPart() = default;1726 1727 InlayHintLabelPart(std::string value,1728 std::optional<Location> location = std::nullopt)1729 : value(std::move(value)), location(std::move(location)) {}1730 1731 /// The value of this label part.1732 std::string value;1733 1734 /// The tooltip text when you hover over this label part. Depending on1735 /// the client capability `inlayHint.resolveSupport`, clients might resolve1736 /// this property late using the resolve request.1737 std::optional<MarkupContent> tooltip;1738 1739 /// An optional source code location that represents this1740 /// label part.1741 ///1742 /// The editor will use this location for the hover and for code navigation1743 /// features: This part will become a clickable link that resolves to the1744 /// definition of the symbol at the given location (not necessarily the1745 /// location itself), it shows the hover that shows at the given location,1746 /// and it shows a context menu with further code navigation commands.1747 ///1748 /// Depending on the client capability `inlayHint.resolveSupport` clients1749 /// might resolve this property late using the resolve request.1750 std::optional<Location> location;1751 1752 /// An optional command for this label part.1753 ///1754 /// Depending on the client capability `inlayHint.resolveSupport` clients1755 /// might resolve this property late using the resolve request.1756 std::optional<Command> command;1757};1758llvm::json::Value toJSON(const InlayHintLabelPart &);1759bool operator==(const InlayHintLabelPart &, const InlayHintLabelPart &);1760bool operator<(const InlayHintLabelPart &, const InlayHintLabelPart &);1761llvm::raw_ostream &operator<<(llvm::raw_ostream &, const InlayHintLabelPart &);1762 1763/// Inlay hint information.1764struct InlayHint {1765 /// The position of this hint.1766 Position position;1767 1768 /// The label of this hint. A human readable string or an array of1769 /// InlayHintLabelPart label parts.1770 ///1771 /// *Note* that neither the string nor the label part can be empty.1772 std::vector<InlayHintLabelPart> label;1773 1774 /// The kind of this hint. Can be omitted in which case the client should fall1775 /// back to a reasonable default.1776 InlayHintKind kind;1777 1778 /// Render padding before the hint.1779 ///1780 /// Note: Padding should use the editor's background color, not the1781 /// background color of the hint itself. That means padding can be used1782 /// to visually align/separate an inlay hint.1783 bool paddingLeft = false;1784 1785 /// Render padding after the hint.1786 ///1787 /// Note: Padding should use the editor's background color, not the1788 /// background color of the hint itself. That means padding can be used1789 /// to visually align/separate an inlay hint.1790 bool paddingRight = false;1791 1792 /// The range of source code to which the hint applies.1793 ///1794 /// For example, a parameter hint may have the argument as its range.1795 /// The range allows clients more flexibility of when/how to display the hint.1796 /// This is an (unserialized) clangd extension.1797 Range range;1798 1799 /// Join the label[].value together.1800 std::string joinLabels() const;1801};1802llvm::json::Value toJSON(const InlayHint &);1803bool operator==(const InlayHint &, const InlayHint &);1804bool operator<(const InlayHint &, const InlayHint &);1805llvm::raw_ostream &operator<<(llvm::raw_ostream &, InlayHintKind);1806 1807struct ReferenceContext {1808 /// Include the declaration of the current symbol.1809 bool includeDeclaration = false;1810};1811 1812struct ReferenceParams : public TextDocumentPositionParams {1813 ReferenceContext context;1814};1815bool fromJSON(const llvm::json::Value &, ReferenceParams &, llvm::json::Path);1816 1817/// Clangd extension: indicates the current state of the file in clangd,1818/// sent from server via the `textDocument/clangd.fileStatus` notification.1819struct FileStatus {1820 /// The text document's URI.1821 URIForFile uri;1822 /// The human-readable string presents the current state of the file, can be1823 /// shown in the UI (e.g. status bar).1824 std::string state;1825 // FIXME: add detail messages.1826};1827llvm::json::Value toJSON(const FileStatus &);1828 1829/// Specifies a single semantic token in the document.1830/// This struct is not part of LSP, which just encodes lists of tokens as1831/// arrays of numbers directly.1832struct SemanticToken {1833 /// token line number, relative to the previous token1834 unsigned deltaLine = 0;1835 /// token start character, relative to the previous token1836 /// (relative to 0 or the previous token's start if they are on the same line)1837 unsigned deltaStart = 0;1838 /// the length of the token. A token cannot be multiline1839 unsigned length = 0;1840 /// will be looked up in `SemanticTokensLegend.tokenTypes`1841 unsigned tokenType = 0;1842 /// each set bit will be looked up in `SemanticTokensLegend.tokenModifiers`1843 unsigned tokenModifiers = 0;1844};1845bool operator==(const SemanticToken &, const SemanticToken &);1846 1847/// A versioned set of tokens.1848struct SemanticTokens {1849 // An optional result id. If provided and clients support delta updating1850 // the client will include the result id in the next semantic token request.1851 // A server can then instead of computing all semantic tokens again simply1852 // send a delta.1853 std::string resultId;1854 1855 /// The actual tokens.1856 std::vector<SemanticToken> tokens; // encoded as a flat integer array.1857};1858llvm::json::Value toJSON(const SemanticTokens &);1859 1860/// Body of textDocument/semanticTokens/full request.1861struct SemanticTokensParams {1862 /// The text document.1863 TextDocumentIdentifier textDocument;1864};1865bool fromJSON(const llvm::json::Value &, SemanticTokensParams &,1866 llvm::json::Path);1867 1868/// Body of textDocument/semanticTokens/full/delta request.1869/// Requests the changes in semantic tokens since a previous response.1870struct SemanticTokensDeltaParams {1871 /// The text document.1872 TextDocumentIdentifier textDocument;1873 /// The previous result id.1874 std::string previousResultId;1875};1876bool fromJSON(const llvm::json::Value &Params, SemanticTokensDeltaParams &R,1877 llvm::json::Path);1878 1879/// Describes a replacement of a contiguous range of semanticTokens.1880struct SemanticTokensEdit {1881 // LSP specifies `start` and `deleteCount` which are relative to the array1882 // encoding of the previous tokens.1883 // We use token counts instead, and translate when serializing this struct.1884 unsigned startToken = 0;1885 unsigned deleteTokens = 0;1886 std::vector<SemanticToken> tokens; // encoded as a flat integer array1887};1888llvm::json::Value toJSON(const SemanticTokensEdit &);1889 1890/// This models LSP SemanticTokensDelta | SemanticTokens, which is the result of1891/// textDocument/semanticTokens/full/delta.1892struct SemanticTokensOrDelta {1893 std::string resultId;1894 /// Set if we computed edits relative to a previous set of tokens.1895 std::optional<std::vector<SemanticTokensEdit>> edits;1896 /// Set if we computed a fresh set of tokens.1897 std::optional<std::vector<SemanticToken>> tokens; // encoded as integer array1898};1899llvm::json::Value toJSON(const SemanticTokensOrDelta &);1900 1901/// Parameters for the inactive regions (server-side) push notification.1902/// This is a clangd extension.1903struct InactiveRegionsParams {1904 /// The textdocument these inactive regions belong to.1905 TextDocumentIdentifier TextDocument;1906 /// The inactive regions that should be sent.1907 std::vector<Range> InactiveRegions;1908};1909llvm::json::Value toJSON(const InactiveRegionsParams &InactiveRegions);1910 1911struct SelectionRangeParams {1912 /// The text document.1913 TextDocumentIdentifier textDocument;1914 1915 /// The positions inside the text document.1916 std::vector<Position> positions;1917};1918bool fromJSON(const llvm::json::Value &, SelectionRangeParams &,1919 llvm::json::Path);1920 1921struct SelectionRange {1922 /**1923 * The range of this selection range.1924 */1925 Range range;1926 /**1927 * The parent selection range containing this range. Therefore `parent.range`1928 * must contain `this.range`.1929 */1930 std::unique_ptr<SelectionRange> parent;1931};1932llvm::json::Value toJSON(const SelectionRange &);1933 1934/// Parameters for the document link request.1935struct DocumentLinkParams {1936 /// The document to provide document links for.1937 TextDocumentIdentifier textDocument;1938};1939bool fromJSON(const llvm::json::Value &, DocumentLinkParams &,1940 llvm::json::Path);1941 1942/// A range in a text document that links to an internal or external resource,1943/// like another text document or a web site.1944struct DocumentLink {1945 /// The range this link applies to.1946 Range range;1947 1948 /// The uri this link points to. If missing a resolve request is sent later.1949 URIForFile target;1950 1951 // TODO(forster): The following optional fields defined by the language1952 // server protocol are unsupported:1953 //1954 // data?: any - A data entry field that is preserved on a document link1955 // between a DocumentLinkRequest and a1956 // DocumentLinkResolveRequest.1957 1958 friend bool operator==(const DocumentLink &LHS, const DocumentLink &RHS) {1959 return LHS.range == RHS.range && LHS.target == RHS.target;1960 }1961 1962 friend bool operator!=(const DocumentLink &LHS, const DocumentLink &RHS) {1963 return !(LHS == RHS);1964 }1965};1966llvm::json::Value toJSON(const DocumentLink &DocumentLink);1967 1968// FIXME(kirillbobyrev): Add FoldingRangeClientCapabilities so we can support1969// per-line-folding editors.1970struct FoldingRangeParams {1971 TextDocumentIdentifier textDocument;1972};1973bool fromJSON(const llvm::json::Value &, FoldingRangeParams &,1974 llvm::json::Path);1975 1976/// Stores information about a region of code that can be folded.1977struct FoldingRange {1978 unsigned startLine = 0;1979 unsigned startCharacter;1980 unsigned endLine = 0;1981 unsigned endCharacter;1982 1983 const static llvm::StringLiteral REGION_KIND;1984 const static llvm::StringLiteral COMMENT_KIND;1985 const static llvm::StringLiteral IMPORT_KIND;1986 std::string kind;1987};1988llvm::json::Value toJSON(const FoldingRange &Range);1989 1990/// Keys starting with an underscore(_) represent leaves, e.g. _total or _self1991/// for memory usage of whole subtree or only that specific node in bytes. All1992/// other keys represents children. An example:1993/// {1994/// "_self": 0,1995/// "_total": 8,1996/// "child1": {1997/// "_self": 4,1998/// "_total": 4,1999/// }2000/// "child2": {2001/// "_self": 2,2002/// "_total": 4,2003/// "child_deep": {2004/// "_self": 2,2005/// "_total": 2,2006/// }2007/// }2008/// }2009llvm::json::Value toJSON(const MemoryTree &MT);2010 2011/// Payload for textDocument/ast request.2012/// This request is a clangd extension.2013struct ASTParams {2014 /// The text document.2015 TextDocumentIdentifier textDocument;2016 2017 /// The position of the node to be dumped.2018 /// The highest-level node that entirely contains the range will be returned.2019 /// If no range is given, the root translation unit node will be returned.2020 std::optional<Range> range;2021};2022bool fromJSON(const llvm::json::Value &, ASTParams &, llvm::json::Path);2023 2024/// Simplified description of a clang AST node.2025/// This is clangd's internal representation of C++ code.2026struct ASTNode {2027 /// The general kind of node, such as "expression"2028 /// Corresponds to the base AST node type such as Expr.2029 std::string role;2030 /// The specific kind of node this is, such as "BinaryOperator".2031 /// This is usually a concrete node class (with Expr etc suffix dropped).2032 /// When there's no hierarchy (e.g. TemplateName), the variant (NameKind).2033 std::string kind;2034 /// Brief additional information, such as "||" for the particular operator.2035 /// The information included depends on the node kind, and may be empty.2036 std::string detail;2037 /// A one-line dump of detailed information about the node.2038 /// This includes role/kind/description information, but is rather cryptic.2039 /// It is similar to the output from `clang -Xclang -ast-dump`.2040 /// May be empty for certain types of nodes.2041 std::string arcana;2042 /// The range of the original source file covered by this node.2043 /// May be missing for implicit nodes, or those created by macro expansion.2044 std::optional<Range> range;2045 /// Nodes nested within this one, such as the operands of a BinaryOperator.2046 std::vector<ASTNode> children;2047};2048llvm::json::Value toJSON(const ASTNode &);2049llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ASTNode &);2050 2051} // namespace clangd2052} // namespace clang2053 2054namespace llvm {2055 2056template <> struct DenseMapInfo<clang::clangd::Range> {2057 using Range = clang::clangd::Range;2058 static inline Range getEmptyKey() {2059 static clang::clangd::Position Tomb{-1, -1};2060 static Range R{Tomb, Tomb};2061 return R;2062 }2063 static inline Range getTombstoneKey() {2064 static clang::clangd::Position Tomb{-2, -2};2065 static Range R{Tomb, Tomb};2066 return R;2067 }2068 static unsigned getHashValue(const Range &Val) {2069 return llvm::hash_combine(Val.start.line, Val.start.character, Val.end.line,2070 Val.end.character);2071 }2072 static bool isEqual(const Range &LHS, const Range &RHS) {2073 return std::tie(LHS.start, LHS.end) == std::tie(RHS.start, RHS.end);2074 }2075};2076 2077template <> struct format_provider<clang::clangd::Position> {2078 static void format(const clang::clangd::Position &Pos, raw_ostream &OS,2079 StringRef Style) {2080 assert(Style.empty() && "style modifiers for this type are not supported");2081 OS << Pos;2082 }2083};2084} // namespace llvm2085 2086// NOLINTEND(readability-identifier-naming)2087 2088#endif2089