brintos

brintos / llvm-project-archived public Read only

0
0
Text · 73.2 KiB · 2248572 Raw
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