clang-tools  7.0.0
ClangdLSPServer.cpp
Go to the documentation of this file.
1 //===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===---------------------------------------------------------------------===//
9 
10 #include "ClangdLSPServer.h"
11 #include "Diagnostics.h"
12 #include "JSONRPCDispatcher.h"
13 #include "SourceCode.h"
14 #include "URI.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/FormatVariadic.h"
17 #include "llvm/Support/Path.h"
18 
19 using namespace clang::clangd;
20 using namespace clang;
21 using namespace llvm;
22 
23 namespace {
24 
25 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
26 /// The path in a test URI will be combined with a platform-specific fake
27 /// directory to form an absolute path. For example, test:///a.cpp is resolved
28 /// C:\clangd-test\a.cpp on Windows and /clangd-test/a.cpp on Unix.
29 class TestScheme : public URIScheme {
30 public:
31  llvm::Expected<std::string>
32  getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
33  llvm::StringRef /*HintPath*/) const override {
34  using namespace llvm::sys;
35  // Still require "/" in body to mimic file scheme, as we want lengths of an
36  // equivalent URI in both schemes to be the same.
37  if (!Body.startswith("/"))
38  return llvm::make_error<llvm::StringError>(
39  "Expect URI body to be an absolute path starting with '/': " + Body,
40  llvm::inconvertibleErrorCode());
41  Body = Body.ltrim('/');
42 #ifdef _WIN32
43  constexpr char TestDir[] = "C:\\clangd-test";
44 #else
45  constexpr char TestDir[] = "/clangd-test";
46 #endif
47  llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
48  path::native(Path);
49  auto Err = fs::make_absolute(TestDir, Path);
50  if (Err)
51  llvm_unreachable("Failed to make absolute path in test scheme.");
52  return std::string(Path.begin(), Path.end());
53  }
54 
55  llvm::Expected<URI>
56  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
57  llvm_unreachable("Clangd must never create a test URI.");
58  }
59 };
60 
61 static URISchemeRegistry::Add<TestScheme>
62  X("test", "Test scheme for clangd lit tests.");
63 
64 SymbolKindBitset defaultSymbolKinds() {
65  SymbolKindBitset Defaults;
66  for (size_t I = SymbolKindMin; I <= static_cast<size_t>(SymbolKind::Array);
67  ++I)
68  Defaults.set(I);
69  return Defaults;
70 }
71 
72 } // namespace
73 
74 void ClangdLSPServer::onInitialize(InitializeParams &Params) {
75  if (Params.initializationOptions)
76  applyConfiguration(*Params.initializationOptions);
77 
78  if (Params.rootUri && *Params.rootUri)
79  Server.setRootPath(Params.rootUri->file());
80  else if (Params.rootPath && !Params.rootPath->empty())
81  Server.setRootPath(*Params.rootPath);
82 
83  CCOpts.EnableSnippets =
85 
86  if (Params.capabilities.workspace && Params.capabilities.workspace->symbol &&
87  Params.capabilities.workspace->symbol->symbolKind) {
88  for (SymbolKind Kind :
89  *Params.capabilities.workspace->symbol->symbolKind->valueSet) {
90  SupportedSymbolKinds.set(static_cast<size_t>(Kind));
91  }
92  }
93 
95  {{"capabilities",
97  {"textDocumentSync", (int)TextDocumentSyncKind::Incremental},
98  {"documentFormattingProvider", true},
99  {"documentRangeFormattingProvider", true},
100  {"documentOnTypeFormattingProvider",
101  json::Object{
102  {"firstTriggerCharacter", "}"},
103  {"moreTriggerCharacter", {}},
104  }},
105  {"codeActionProvider", true},
106  {"completionProvider",
107  json::Object{
108  {"resolveProvider", false},
109  {"triggerCharacters", {".", ">", ":"}},
110  }},
111  {"signatureHelpProvider",
112  json::Object{
113  {"triggerCharacters", {"(", ","}},
114  }},
115  {"definitionProvider", true},
116  {"documentHighlightProvider", true},
117  {"hoverProvider", true},
118  {"renameProvider", true},
119  {"documentSymbolProvider", true},
120  {"workspaceSymbolProvider", true},
121  {"executeCommandProvider",
122  json::Object{
124  }},
125  }}}});
126 }
127 
128 void ClangdLSPServer::onShutdown(ShutdownParams &Params) {
129  // Do essentially nothing, just say we're ready to exit.
130  ShutdownRequestReceived = true;
131  reply(nullptr);
132 }
133 
134 void ClangdLSPServer::onExit(ExitParams &Params) { IsDone = true; }
135 
136 void ClangdLSPServer::onDocumentDidOpen(DidOpenTextDocumentParams &Params) {
137  PathRef File = Params.textDocument.uri.file();
138  if (Params.metadata && !Params.metadata->extraFlags.empty()) {
139  NonCachedCDB.setExtraFlagsForFile(File,
140  std::move(Params.metadata->extraFlags));
141  CDB.invalidate(File);
142  }
143 
144  std::string &Contents = Params.textDocument.text;
145 
146  DraftMgr.addDraft(File, Contents);
147  Server.addDocument(File, Contents, WantDiagnostics::Yes);
148 }
149 
150 void ClangdLSPServer::onDocumentDidChange(DidChangeTextDocumentParams &Params) {
151  auto WantDiags = WantDiagnostics::Auto;
152  if (Params.wantDiagnostics.hasValue())
153  WantDiags = Params.wantDiagnostics.getValue() ? WantDiagnostics::Yes
155 
156  PathRef File = Params.textDocument.uri.file();
157  llvm::Expected<std::string> Contents =
158  DraftMgr.updateDraft(File, Params.contentChanges);
159  if (!Contents) {
160  // If this fails, we are most likely going to be not in sync anymore with
161  // the client. It is better to remove the draft and let further operations
162  // fail rather than giving wrong results.
163  DraftMgr.removeDraft(File);
164  Server.removeDocument(File);
165  CDB.invalidate(File);
166  elog("Failed to update {0}: {1}", File, Contents.takeError());
167  return;
168  }
169 
170  Server.addDocument(File, *Contents, WantDiags);
171 }
172 
173 void ClangdLSPServer::onFileEvent(DidChangeWatchedFilesParams &Params) {
174  Server.onFileEvent(Params);
175 }
176 
177 void ClangdLSPServer::onCommand(ExecuteCommandParams &Params) {
178  auto ApplyEdit = [](WorkspaceEdit WE) {
180  Edit.edit = std::move(WE);
181  // We don't need the response so id == 1 is OK.
182  // Ideally, we would wait for the response and if there is no error, we
183  // would reply success/failure to the original RPC.
184  call("workspace/applyEdit", Edit);
185  };
187  Params.workspaceEdit) {
188  // The flow for "apply-fix" :
189  // 1. We publish a diagnostic, including fixits
190  // 2. The user clicks on the diagnostic, the editor asks us for code actions
191  // 3. We send code actions, with the fixit embedded as context
192  // 4. The user selects the fixit, the editor asks us to apply it
193  // 5. We unwrap the changes and send them back to the editor
194  // 6. The editor applies the changes (applyEdit), and sends us a reply (but
195  // we ignore it)
196 
197  reply("Fix applied.");
198  ApplyEdit(*Params.workspaceEdit);
199  } else {
200  // We should not get here because ExecuteCommandParams would not have
201  // parsed in the first place and this handler should not be called. But if
202  // more commands are added, this will be here has a safe guard.
203  replyError(
205  llvm::formatv("Unsupported command \"{0}\".", Params.command).str());
206  }
207 }
208 
209 void ClangdLSPServer::onWorkspaceSymbol(WorkspaceSymbolParams &Params) {
210  Server.workspaceSymbols(
211  Params.query, CCOpts.Limit,
212  [this](llvm::Expected<std::vector<SymbolInformation>> Items) {
213  if (!Items)
214  return replyError(ErrorCode::InternalError,
215  llvm::toString(Items.takeError()));
216  for (auto &Sym : *Items)
217  Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
218 
219  reply(json::Array(*Items));
220  });
221 }
222 
223 void ClangdLSPServer::onRename(RenameParams &Params) {
224  Path File = Params.textDocument.uri.file();
225  llvm::Optional<std::string> Code = DraftMgr.getDraft(File);
226  if (!Code)
228  "onRename called for non-added file");
229 
230  Server.rename(
231  File, Params.position, Params.newName,
232  [File, Code,
233  Params](llvm::Expected<std::vector<tooling::Replacement>> Replacements) {
234  if (!Replacements)
235  return replyError(ErrorCode::InternalError,
236  llvm::toString(Replacements.takeError()));
237 
238  // Turn the replacements into the format specified by the Language
239  // Server Protocol. Fuse them into one big JSON array.
240  std::vector<TextEdit> Edits;
241  for (const auto &R : *Replacements)
242  Edits.push_back(replacementToEdit(*Code, R));
243  WorkspaceEdit WE;
244  WE.changes = {{Params.textDocument.uri.uri(), Edits}};
245  reply(WE);
246  });
247 }
248 
249 void ClangdLSPServer::onDocumentDidClose(DidCloseTextDocumentParams &Params) {
250  PathRef File = Params.textDocument.uri.file();
251  DraftMgr.removeDraft(File);
252  Server.removeDocument(File);
253 }
254 
255 void ClangdLSPServer::onDocumentOnTypeFormatting(
257  auto File = Params.textDocument.uri.file();
258  auto Code = DraftMgr.getDraft(File);
259  if (!Code)
261  "onDocumentOnTypeFormatting called for non-added file");
262 
263  auto ReplacementsOrError = Server.formatOnType(*Code, File, Params.position);
264  if (ReplacementsOrError)
265  reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
266  else
268  llvm::toString(ReplacementsOrError.takeError()));
269 }
270 
271 void ClangdLSPServer::onDocumentRangeFormatting(
273  auto File = Params.textDocument.uri.file();
274  auto Code = DraftMgr.getDraft(File);
275  if (!Code)
277  "onDocumentRangeFormatting called for non-added file");
278 
279  auto ReplacementsOrError = Server.formatRange(*Code, File, Params.range);
280  if (ReplacementsOrError)
281  reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
282  else
284  llvm::toString(ReplacementsOrError.takeError()));
285 }
286 
287 void ClangdLSPServer::onDocumentFormatting(DocumentFormattingParams &Params) {
288  auto File = Params.textDocument.uri.file();
289  auto Code = DraftMgr.getDraft(File);
290  if (!Code)
292  "onDocumentFormatting called for non-added file");
293 
294  auto ReplacementsOrError = Server.formatFile(*Code, File);
295  if (ReplacementsOrError)
296  reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
297  else
299  llvm::toString(ReplacementsOrError.takeError()));
300 }
301 
302 void ClangdLSPServer::onDocumentSymbol(DocumentSymbolParams &Params) {
303  Server.documentSymbols(
304  Params.textDocument.uri.file(),
305  [this](llvm::Expected<std::vector<SymbolInformation>> Items) {
306  if (!Items)
308  llvm::toString(Items.takeError()));
309  for (auto &Sym : *Items)
310  Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
311  reply(json::Array(*Items));
312  });
313 }
314 
315 void ClangdLSPServer::onCodeAction(CodeActionParams &Params) {
316  // We provide a code action for each diagnostic at the requested location
317  // which has FixIts available.
318  auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
319  if (!Code)
321  "onCodeAction called for non-added file");
322 
324  for (Diagnostic &D : Params.context.diagnostics) {
325  for (auto &F : getFixes(Params.textDocument.uri.file(), D)) {
326  WorkspaceEdit WE;
327  std::vector<TextEdit> Edits(F.Edits.begin(), F.Edits.end());
328  WE.changes = {{Params.textDocument.uri.uri(), std::move(Edits)}};
329  Commands.push_back(json::Object{
330  {"title", llvm::formatv("Apply fix: {0}", F.Message)},
332  {"arguments", {WE}},
333  });
334  }
335  }
336  reply(std::move(Commands));
337 }
338 
339 void ClangdLSPServer::onCompletion(TextDocumentPositionParams &Params) {
340  Server.codeComplete(Params.textDocument.uri.file(), Params.position, CCOpts,
341  [this](llvm::Expected<CodeCompleteResult> List) {
342  if (!List)
344  llvm::toString(List.takeError()));
345  CompletionList LSPList;
346  LSPList.isIncomplete = List->HasMore;
347  for (const auto &R : List->Completions)
348  LSPList.items.push_back(R.render(CCOpts));
349  reply(std::move(LSPList));
350  });
351 }
352 
353 void ClangdLSPServer::onSignatureHelp(TextDocumentPositionParams &Params) {
354  Server.signatureHelp(Params.textDocument.uri.file(), Params.position,
355  [](llvm::Expected<SignatureHelp> SignatureHelp) {
356  if (!SignatureHelp)
357  return replyError(
359  llvm::toString(SignatureHelp.takeError()));
361  });
362 }
363 
364 void ClangdLSPServer::onGoToDefinition(TextDocumentPositionParams &Params) {
365  Server.findDefinitions(
366  Params.textDocument.uri.file(), Params.position,
367  [](llvm::Expected<std::vector<Location>> Items) {
368  if (!Items)
370  llvm::toString(Items.takeError()));
371  reply(json::Array(*Items));
372  });
373 }
374 
375 void ClangdLSPServer::onSwitchSourceHeader(TextDocumentIdentifier &Params) {
376  llvm::Optional<Path> Result = Server.switchSourceHeader(Params.uri.file());
377  reply(Result ? URI::createFile(*Result).toString() : "");
378 }
379 
380 void ClangdLSPServer::onDocumentHighlight(TextDocumentPositionParams &Params) {
381  Server.findDocumentHighlights(
382  Params.textDocument.uri.file(), Params.position,
383  [](llvm::Expected<std::vector<DocumentHighlight>> Highlights) {
384  if (!Highlights)
386  llvm::toString(Highlights.takeError()));
387  reply(json::Array(*Highlights));
388  });
389 }
390 
391 void ClangdLSPServer::onHover(TextDocumentPositionParams &Params) {
392  Server.findHover(Params.textDocument.uri.file(), Params.position,
393  [](llvm::Expected<llvm::Optional<Hover>> H) {
394  if (!H) {
396  llvm::toString(H.takeError()));
397  return;
398  }
399 
400  reply(*H);
401  });
402 }
403 
404 void ClangdLSPServer::applyConfiguration(
405  const ClangdConfigurationParamsChange &Settings) {
406  // Compilation database change.
407  if (Settings.compilationDatabasePath.hasValue()) {
408  NonCachedCDB.setCompileCommandsDir(
409  Settings.compilationDatabasePath.getValue());
410  CDB.clear();
411 
412  reparseOpenedFiles();
413  }
414 }
415 
416 // FIXME: This function needs to be properly tested.
417 void ClangdLSPServer::onChangeConfiguration(
419  applyConfiguration(Params.settings);
420 }
421 
423  const clangd::CodeCompleteOptions &CCOpts,
424  llvm::Optional<Path> CompileCommandsDir,
425  const ClangdServer::Options &Opts)
426  : Out(Out), NonCachedCDB(std::move(CompileCommandsDir)), CDB(NonCachedCDB),
427  CCOpts(CCOpts), SupportedSymbolKinds(defaultSymbolKinds()),
428  Server(CDB, FSProvider, /*DiagConsumer=*/*this, Opts) {}
429 
431  assert(!IsDone && "Run was called before");
432 
433  // Set up JSONRPCDispatcher.
434  JSONRPCDispatcher Dispatcher([](const json::Value &Params) {
435  replyError(ErrorCode::MethodNotFound, "method not found");
436  });
437  registerCallbackHandlers(Dispatcher, /*Callbacks=*/*this);
438 
439  // Run the Language Server loop.
440  runLanguageServerLoop(In, Out, InputStyle, Dispatcher, IsDone);
441 
442  // Make sure IsDone is set to true after this method exits to ensure assertion
443  // at the start of the method fires if it's ever executed again.
444  IsDone = true;
445 
446  return ShutdownRequestReceived;
447 }
448 
449 std::vector<Fix> ClangdLSPServer::getFixes(StringRef File,
450  const clangd::Diagnostic &D) {
451  std::lock_guard<std::mutex> Lock(FixItsMutex);
452  auto DiagToFixItsIter = FixItsMap.find(File);
453  if (DiagToFixItsIter == FixItsMap.end())
454  return {};
455 
456  const auto &DiagToFixItsMap = DiagToFixItsIter->second;
457  auto FixItsIter = DiagToFixItsMap.find(D);
458  if (FixItsIter == DiagToFixItsMap.end())
459  return {};
460 
461  return FixItsIter->second;
462 }
463 
464 void ClangdLSPServer::onDiagnosticsReady(PathRef File,
465  std::vector<Diag> Diagnostics) {
466  json::Array DiagnosticsJSON;
467 
468  DiagnosticToReplacementMap LocalFixIts; // Temporary storage
469  for (auto &Diag : Diagnostics) {
470  toLSPDiags(Diag, [&](clangd::Diagnostic Diag, llvm::ArrayRef<Fix> Fixes) {
471  DiagnosticsJSON.push_back(json::Object{
472  {"range", Diag.range},
473  {"severity", Diag.severity},
474  {"message", Diag.message},
475  });
476 
477  auto &FixItsForDiagnostic = LocalFixIts[Diag];
478  std::copy(Fixes.begin(), Fixes.end(),
479  std::back_inserter(FixItsForDiagnostic));
480  });
481  }
482 
483  // Cache FixIts
484  {
485  // FIXME(ibiryukov): should be deleted when documents are removed
486  std::lock_guard<std::mutex> Lock(FixItsMutex);
487  FixItsMap[File] = LocalFixIts;
488  }
489 
490  // Publish diagnostics.
492  {"jsonrpc", "2.0"},
493  {"method", "textDocument/publishDiagnostics"},
494  {"params",
495  json::Object{
496  {"uri", URIForFile{File}},
497  {"diagnostics", std::move(DiagnosticsJSON)},
498  }},
499  });
500 }
501 
502 void ClangdLSPServer::reparseOpenedFiles() {
503  for (const Path &FilePath : DraftMgr.getActiveFiles())
504  Server.addDocument(FilePath, *DraftMgr.getDraft(FilePath),
506 }
Range range
The range to format.
Definition: Protocol.h:458
TextDocumentIdentifier textDocument
The document to format.
Definition: Protocol.h:482
JSONStreamStyle
Controls the way JSON-RPC messages are encoded (both input and output).
CompletionClientCapabilities completion
Capabilities specific to the textDocument/completion
Definition: Protocol.h:311
Encapsulates output and logs streams and provides thread-safe access to them.
Exact commands are not specified in the protocol so we define the ones supported by Clangd here...
Definition: Protocol.h:565
TextDocumentIdentifier textDocument
The document to format.
Definition: Protocol.h:467
Some operations such as code completion produce a set of candidates.
llvm::Optional< URIForFile > rootUri
The rootUri of the workspace.
Definition: Protocol.h:351
Represents a collection of completion items to be presented in the editor.
Definition: Protocol.h:740
Diagnostics must be generated for this snapshot.
llvm::Optional< bool > wantDiagnostics
Forces diagnostics to be generated, or to not be generated, for this version of the file...
Definition: Protocol.h:408
CodeActionContext context
Context carrying additional information.
Definition: Protocol.h:543
static const llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND
Definition: Protocol.h:567
Clangd extension to set clangd-specific "initializationOptions" in the "initialize" request and for t...
Definition: Protocol.h:328
ClangdLSPServer(JSONOutput &Out, const clangd::CodeCompleteOptions &CCOpts, llvm::Optional< Path > CompileCommandsDir, const ClangdServer::Options &Opts)
If CompileCommandsDir has a value, compile_commands.json will be loaded only from CompileCommandsDir...
std::vector< CompletionItem > items
The completion items.
Definition: Protocol.h:746
void toLSPDiags(const Diag &D, llvm::function_ref< void(clangd::Diagnostic, llvm::ArrayRef< Fix >)> OutFn)
Conversion to LSP diagnostics.
Documents are synced by sending the full content on open.
bool snippetSupport
Client supports snippets as insert text.
Definition: Protocol.h:222
llvm::Optional< std::map< std::string, std::vector< TextEdit > > > changes
Holds changes to existing resources.
Definition: Protocol.h:549
static cl::list< std::string > Commands("c", cl::desc("Specify command to run"), cl::value_desc("command"), cl::cat(ClangQueryCategory))
URIScheme is an extension point for teaching clangd to recognize a custom URI scheme.
Definition: URI.h:94
TextDocumentIdentifier textDocument
The document that was closed.
Definition: Protocol.h:379
llvm::Optional< ClangdInitializationOptions > initializationOptions
Definition: Protocol.h:364
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:24
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
llvm::Optional< WorkspaceClientCapabilities > workspace
Definition: Protocol.h:317
bool run(std::FILE *In, JSONStreamStyle InputStyle=JSONStreamStyle::Standard)
Run LSP server loop, receiving input for it from In.
constexpr auto SymbolKindMin
Definition: Protocol.h:276
def make_absolute(f, directory)
bool isIncomplete
The list is not complete.
Definition: Protocol.h:743
llvm::Optional< Metadata > metadata
Extension storing per-file metadata, such as compilation flags.
Definition: Protocol.h:373
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
StringRef Contents
static ClangTidyModuleRegistry::Add< AbseilModule > X("abseil-module", "Add Abseil checks.")
A top-level diagnostic that may have Notes and Fixes.
Definition: Diagnostics.h:54
std::string uri() const
Definition: Protocol.h:60
BindArgumentKind Kind
void addDocument(PathRef File, StringRef Contents, WantDiagnostics WD=WantDiagnostics::Auto)
Add a File to the list of tracked C++ files or update the contents if File is already tracked...
TextDocumentClientCapabilities textDocument
Definition: Protocol.h:320
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:181
static URI createFile(llvm::StringRef AbsolutePath)
This creates a file:// URI for AbsolutePath. The path must be absolute.
Definition: URI.cpp:184
TextDocumentIdentifier textDocument
The document that was opened.
Definition: Protocol.h:793
void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, ProtocolCallbacks &Callbacks)
void replyError(ErrorCode Code, const llvm::StringRef &Message)
Sends an error response to the client, and logs it.
std::string newName
The new name of the symbol.
Definition: Protocol.h:799
std::string command
The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND.
Definition: Protocol.h:570
TextDocumentIdentifier textDocument
Definition: Protocol.h:491
llvm::Optional< std::string > getDraft(PathRef File) const
Definition: DraftStore.cpp:17
TextDocumentIdentifier textDocument
The document in which the command was invoked.
Definition: Protocol.h:537
CompletionItemClientCapabilities completionItem
The client supports the following CompletionItem specific capabilities.
Definition: Protocol.h:236
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
static llvm::cl::opt< Path > CompileCommandsDir("compile-commands-dir", llvm::cl::desc("Specify a path to look for compile_commands.json. If path " "is invalid, clangd will look in the current directory and " "parent paths of each source file."))
Position position
The position inside the text document.
Definition: Protocol.h:618
Main JSONRPC entry point.
ClientCapabilities capabilities
The capabilities provided by the client (editor or tool)
Definition: Protocol.h:357
TextDocumentItem textDocument
The document that was opened.
Definition: Protocol.h:370
std::vector< TextEdit > replacementsToEdits(StringRef Code, const tooling::Replacements &Repls)
Definition: SourceCode.cpp:180
TextDocumentIdentifier textDocument
The document that did change.
Definition: Protocol.h:399
std::vector< Path > getActiveFiles() const
Definition: DraftStore.cpp:27
llvm::Optional< std::string > rootPath
The rootPath of the workspace.
Definition: Protocol.h:346
Position position
The position at which this request was sent.
Definition: Protocol.h:470
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
Definition: Protocol.h:402
Represents the signature of a callable.
Definition: Protocol.h:778
std::string query
A non-empty query string.
Definition: Protocol.h:604
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::bitset< SymbolKindMax+1 > SymbolKindBitset
Definition: Protocol.h:278
SymbolKind
A symbol kind.
Definition: Protocol.h:247
std::string message
The diagnostic&#39;s code.
Definition: Protocol.h:513
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:615
SymbolKind adjustKindToCapability(SymbolKind Kind, SymbolKindBitset &SupportedSymbolKinds)
Definition: Protocol.cpp:210
std::vector< Diagnostic > diagnostics
An array of diagnostics.
Definition: Protocol.h:531
int severity
The diagnostic&#39;s severity.
Definition: Protocol.h:501
The parameters of a Workspace Symbol Request.
Definition: Protocol.h:602
std::string text
The content of the opened text document.
Definition: Protocol.h:190
void call(llvm::StringRef Method, llvm::json::Value &&Params)
Sends a request to the client.
Position position
The position at which this request was sent.
Definition: Protocol.h:796
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:84
void writeMessage(const llvm::json::Value &Result)
Emit a JSONRPC message.
Range range
The range at which the message applies.
Definition: Protocol.h:497
TextDocumentIdentifier textDocument
The document to format.
Definition: Protocol.h:455
llvm::Optional< WorkspaceEdit > workspaceEdit
Definition: Protocol.h:573
std::string toString() const
Returns a string URI with all components percent-encoded.
Definition: URI.cpp:141
ClangdConfigurationParamsChange settings
Definition: Protocol.h:439
void reply(llvm::json::Value &&Result)
Sends a successful reply.
Diagnostics must not be generated for this snapshot.
llvm::Optional< std::string > compilationDatabasePath
Definition: Protocol.h:329
void runLanguageServerLoop(std::FILE *In, JSONOutput &Out, JSONStreamStyle InputStyle, JSONRPCDispatcher &Dispatcher, bool &IsDone)
Parses input queries from LSP client (coming from In) and runs call method of Dispatcher for each que...
static llvm::cl::opt< JSONStreamStyle > InputStyle("input-style", llvm::cl::desc("Input JSON stream encoding"), llvm::cl::values(clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"), clEnumValN(JSONStreamStyle::Delimited, "delimited", "messages delimited by --- lines, with # comment support")), llvm::cl::init(JSONStreamStyle::Standard))
llvm::StringRef file() const
Retrieves absolute path to the file.
Definition: Protocol.h:57