clang-tools  11.0.0
ClangdMain.cpp
Go to the documentation of this file.
1 //===--- ClangdMain.cpp - clangd server loop ------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ClangdLSPServer.h"
10 #include "CodeComplete.h"
11 #include "Features.inc"
12 #include "PathMapping.h"
13 #include "Protocol.h"
14 #include "Transport.h"
15 #include "index/Background.h"
16 #include "index/Serialization.h"
17 #include "refactor/Rename.h"
18 #include "support/Path.h"
19 #include "support/Shutdown.h"
20 #include "support/ThreadsafeFS.h"
21 #include "support/Trace.h"
22 #include "clang/Basic/Version.h"
23 #include "clang/Format/Format.h"
24 #include "llvm/ADT/Optional.h"
25 #include "llvm/ADT/SmallString.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/FileSystem.h"
29 #include "llvm/Support/Path.h"
30 #include "llvm/Support/Process.h"
31 #include "llvm/Support/Program.h"
32 #include "llvm/Support/Signals.h"
33 #include "llvm/Support/TargetSelect.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <chrono>
36 #include <cstdlib>
37 #include <iostream>
38 #include <memory>
39 #include <mutex>
40 #include <string>
41 #include <thread>
42 
43 #ifndef _WIN32
44 #include <unistd.h>
45 #endif
46 
47 namespace clang {
48 namespace clangd {
49 namespace {
50 
51 using llvm::cl::cat;
52 using llvm::cl::CommaSeparated;
53 using llvm::cl::desc;
54 using llvm::cl::Hidden;
55 using llvm::cl::init;
56 using llvm::cl::list;
57 using llvm::cl::opt;
58 using llvm::cl::OptionCategory;
59 using llvm::cl::values;
60 
61 // All flags must be placed in a category, or they will be shown neither in
62 // --help, nor --help-hidden!
63 OptionCategory CompileCommands("clangd compilation flags options");
64 OptionCategory Features("clangd feature options");
65 OptionCategory Misc("clangd miscellaneous options");
66 OptionCategory Protocol("clangd protocol and logging options");
67 const OptionCategory *ClangdCategories[] = {&Features, &Protocol,
68  &CompileCommands, &Misc};
69 
70 enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs };
71 opt<CompileArgsFrom> CompileArgsFrom{
72  "compile_args_from",
73  cat(CompileCommands),
74  desc("The source of compile commands"),
75  values(clEnumValN(LSPCompileArgs, "lsp",
76  "All compile commands come from LSP and "
77  "'compile_commands.json' files are ignored"),
78  clEnumValN(FilesystemCompileArgs, "filesystem",
79  "All compile commands come from the "
80  "'compile_commands.json' files")),
81  init(FilesystemCompileArgs),
82  Hidden,
83 };
84 
85 opt<Path> CompileCommandsDir{
86  "compile-commands-dir",
87  cat(CompileCommands),
88  desc("Specify a path to look for compile_commands.json. If path "
89  "is invalid, clangd will look in the current directory and "
90  "parent paths of each source file"),
91 };
92 
93 opt<Path> ResourceDir{
94  "resource-dir",
95  cat(CompileCommands),
96  desc("Directory for system clang headers"),
97  init(""),
98  Hidden,
99 };
100 
101 list<std::string> QueryDriverGlobs{
102  "query-driver",
103  cat(CompileCommands),
104  desc(
105  "Comma separated list of globs for white-listing gcc-compatible "
106  "drivers that are safe to execute. Drivers matching any of these globs "
107  "will be used to extract system includes. e.g. "
108  "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
109  CommaSeparated,
110 };
111 
112 // FIXME: Flags are the wrong mechanism for user preferences.
113 // We should probably read a dotfile or similar.
114 opt<bool> AllScopesCompletion{
115  "all-scopes-completion",
116  cat(Features),
117  desc("If set to true, code completion will include index symbols that are "
118  "not defined in the scopes (e.g. "
119  "namespaces) visible from the code completion point. Such completions "
120  "can insert scope qualifiers"),
121  init(true),
122 };
123 
124 opt<bool> ShowOrigins{
125  "debug-origin",
126  cat(Features),
127  desc("Show origins of completion items"),
128  init(CodeCompleteOptions().ShowOrigins),
129  Hidden,
130 };
131 
132 opt<bool> EnableBackgroundIndex{
133  "background-index",
134  cat(Features),
135  desc("Index project code in the background and persist index on disk."),
136  init(true),
137 };
138 
139 opt<bool> EnableClangTidy{
140  "clang-tidy",
141  cat(Features),
142  desc("Enable clang-tidy diagnostics"),
143  init(true),
144 };
145 
146 opt<std::string> ClangTidyChecks{
147  "clang-tidy-checks",
148  cat(Features),
149  desc("List of clang-tidy checks to run (this will override "
150  ".clang-tidy files). Only meaningful when -clang-tidy flag is on"),
151  init(""),
152 };
153 
154 opt<CodeCompleteOptions::CodeCompletionParse> CodeCompletionParse{
155  "completion-parse",
156  cat(Features),
157  desc("Whether the clang-parser is used for code-completion"),
158  values(clEnumValN(CodeCompleteOptions::AlwaysParse, "always",
159  "Block until the parser can be used"),
160  clEnumValN(CodeCompleteOptions::ParseIfReady, "auto",
161  "Use text-based completion if the parser "
162  "is not ready"),
163  clEnumValN(CodeCompleteOptions::NeverParse, "never",
164  "Always used text-based completion")),
165  init(CodeCompleteOptions().RunParser),
166  Hidden,
167 };
168 
169 // FIXME: also support "plain" style where signatures are always omitted.
170 enum CompletionStyleFlag { Detailed, Bundled };
171 opt<CompletionStyleFlag> CompletionStyle{
172  "completion-style",
173  cat(Features),
174  desc("Granularity of code completion suggestions"),
175  values(clEnumValN(Detailed, "detailed",
176  "One completion item for each semantically distinct "
177  "completion, with full type information"),
178  clEnumValN(Bundled, "bundled",
179  "Similar completion items (e.g. function overloads) are "
180  "combined. Type information shown where possible")),
181 };
182 
183 opt<std::string> FallbackStyle{
184  "fallback-style",
185  cat(Features),
186  desc("clang-format style to apply by default when "
187  "no .clang-format file is found"),
188  init(clang::format::DefaultFallbackStyle),
189 };
190 
191 opt<bool> EnableFunctionArgSnippets{
192  "function-arg-placeholders",
193  cat(Features),
194  desc("When disabled, completions contain only parentheses for "
195  "function calls. When enabled, completions also contain "
196  "placeholders for method parameters"),
197  init(CodeCompleteOptions().EnableFunctionArgSnippets),
198  Hidden,
199 };
200 
201 opt<CodeCompleteOptions::IncludeInsertion> HeaderInsertion{
202  "header-insertion",
203  cat(Features),
204  desc("Add #include directives when accepting code completions"),
205  init(CodeCompleteOptions().InsertIncludes),
206  values(
207  clEnumValN(CodeCompleteOptions::IWYU, "iwyu",
208  "Include what you use. "
209  "Insert the owning header for top-level symbols, unless the "
210  "header is already directly included or the symbol is "
211  "forward-declared"),
212  clEnumValN(
214  "Never insert #include directives as part of code completion")),
215 };
216 
217 opt<bool> HeaderInsertionDecorators{
218  "header-insertion-decorators",
219  cat(Features),
220  desc("Prepend a circular dot or space before the completion "
221  "label, depending on whether "
222  "an include line will be inserted or not"),
223  init(true),
224 };
225 
226 opt<bool> HiddenFeatures{
227  "hidden-features",
228  cat(Features),
229  desc("Enable hidden features mostly useful to clangd developers"),
230  init(false),
231  Hidden,
232 };
233 
234 opt<bool> IncludeIneligibleResults{
235  "include-ineligible-results",
236  cat(Features),
237  desc("Include ineligible completion results (e.g. private members)"),
238  init(CodeCompleteOptions().IncludeIneligibleResults),
239  Hidden,
240 };
241 
242 opt<bool> EnableIndex{
243  "index",
244  cat(Features),
245  desc("Enable index-based features. By default, clangd maintains an index "
246  "built from symbols in opened files. Global index support needs to "
247  "enabled separatedly"),
248  init(true),
249  Hidden,
250 };
251 
252 opt<int> LimitResults{
253  "limit-results",
254  cat(Features),
255  desc("Limit the number of results returned by clangd. "
256  "0 means no limit (default=100)"),
257  init(100),
258 };
259 
260 opt<bool> SuggestMissingIncludes{
261  "suggest-missing-includes",
262  cat(Features),
263  desc("Attempts to fix diagnostic errors caused by missing "
264  "includes using index"),
265  init(true),
266 };
267 
268 list<std::string> TweakList{
269  "tweaks",
270  cat(Features),
271  desc("Specify a list of Tweaks to enable (only for clangd developers)."),
272  Hidden,
273  CommaSeparated,
274 };
275 
276 opt<bool> CrossFileRename{
277  "cross-file-rename",
278  cat(Features),
279  desc("Enable cross-file rename feature."),
280  init(true),
281 };
282 
283 opt<bool> RecoveryAST{
284  "recovery-ast",
285  cat(Features),
286  desc("Preserve expressions in AST for broken code (C++ only)."),
287  init(ClangdServer::Options().BuildRecoveryAST),
288 };
289 
290 opt<bool> RecoveryASTType{
291  "recovery-ast-type",
292  cat(Features),
293  desc("Preserve the type for recovery AST. Note that "
294  "this feature is experimental and may lead to crashes"),
295  init(false),
296  Hidden,
297 };
298 
299 opt<bool> FoldingRanges{
300  "folding-ranges",
301  cat(Features),
302  desc("Enable preview of FoldingRanges feature"),
303  init(false),
304  Hidden,
305 };
306 
307 opt<unsigned> WorkerThreadsCount{
308  "j",
309  cat(Misc),
310  desc("Number of async workers used by clangd. Background index also "
311  "uses this many workers."),
313 };
314 
315 opt<Path> IndexFile{
316  "index-file",
317  cat(Misc),
318  desc(
319  "Index file to build the static index. The file must have been created "
320  "by a compatible clangd-indexer\n"
321  "WARNING: This option is experimental only, and will be removed "
322  "eventually. Don't rely on it"),
323  init(""),
324  Hidden,
325 };
326 
327 opt<bool> Test{
328  "lit-test",
329  cat(Misc),
330  desc("Abbreviation for -input-style=delimited -pretty -sync "
331  "-enable-test-scheme -enable-config=0 -log=verbose. "
332  "Intended to simplify lit tests"),
333  init(false),
334  Hidden,
335 };
336 
337 enum PCHStorageFlag { Disk, Memory };
338 opt<PCHStorageFlag> PCHStorage{
339  "pch-storage",
340  cat(Misc),
341  desc("Storing PCHs in memory increases memory usages, but may "
342  "improve performance"),
343  values(
344  clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"),
345  clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")),
346  init(PCHStorageFlag::Disk),
347 };
348 
349 opt<bool> Sync{
350  "sync",
351  cat(Misc),
352  desc("Handle client requests on main thread. Background index still uses "
353  "its own thread."),
354  init(false),
355  Hidden,
356 };
357 
358 opt<JSONStreamStyle> InputStyle{
359  "input-style",
360  cat(Protocol),
361  desc("Input JSON stream encoding"),
362  values(
363  clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"),
364  clEnumValN(JSONStreamStyle::Delimited, "delimited",
365  "messages delimited by --- lines, with # comment support")),
367  Hidden,
368 };
369 
370 opt<bool> EnableTestScheme{
371  "enable-test-uri-scheme",
372  cat(Protocol),
373  desc("Enable 'test:' URI scheme. Only use in lit tests"),
374  init(false),
375  Hidden,
376 };
377 
378 opt<std::string> PathMappingsArg{
379  "path-mappings",
380  cat(Protocol),
381  desc(
382  "Translates between client paths (as seen by a remote editor) and "
383  "server paths (where clangd sees files on disk). "
384  "Comma separated list of '<client_path>=<server_path>' pairs, the "
385  "first entry matching a given path is used. "
386  "e.g. /home/project/incl=/opt/include,/home/project=/workarea/project"),
387  init(""),
388 };
389 
390 opt<Path> InputMirrorFile{
391  "input-mirror-file",
392  cat(Protocol),
393  desc("Mirror all LSP input to the specified file. Useful for debugging"),
394  init(""),
395  Hidden,
396 };
397 
398 opt<Logger::Level> LogLevel{
399  "log",
400  cat(Protocol),
401  desc("Verbosity of log messages written to stderr"),
402  values(clEnumValN(Logger::Error, "error", "Error messages only"),
403  clEnumValN(Logger::Info, "info", "High level execution tracing"),
404  clEnumValN(Logger::Debug, "verbose", "Low level details")),
405  init(Logger::Info),
406 };
407 
408 opt<OffsetEncoding> ForceOffsetEncoding{
409  "offset-encoding",
410  cat(Protocol),
411  desc("Force the offsetEncoding used for character positions. "
412  "This bypasses negotiation via client capabilities"),
413  values(
414  clEnumValN(OffsetEncoding::UTF8, "utf-8", "Offsets are in UTF-8 bytes"),
415  clEnumValN(OffsetEncoding::UTF16, "utf-16",
416  "Offsets are in UTF-16 code units"),
417  clEnumValN(OffsetEncoding::UTF32, "utf-32",
418  "Offsets are in unicode codepoints")),
420 };
421 
422 opt<bool> PrettyPrint{
423  "pretty",
424  cat(Protocol),
425  desc("Pretty-print JSON output"),
426  init(false),
427 };
428 
429 opt<bool> AsyncPreamble{
430  "async-preamble",
431  cat(Misc),
432  desc("Reuse even stale preambles, and rebuild them in the background. This "
433  "improves latency at the cost of accuracy."),
434  init(ClangdServer::Options().AsyncPreambleBuilds),
435  Hidden,
436 };
437 
438 opt<bool> EnableConfig{
439  "enable-config",
440  cat(Misc),
441  desc(
442  "Read user and project configuration from YAML files.\n"
443  "Project config is from a .clangd file in the project directory.\n"
444  "User config is from clangd/config.yaml in the following directories:\n"
445  "\tWindows: %USERPROFILE%\\AppData\\Local\n"
446  "\tMac OS: ~/Library/Preferences/\n"
447  "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n"
448  "Configuration is documented at https://clangd.llvm.org/config.html"),
449  init(true),
450 };
451 
452 /// Supports a test URI scheme with relaxed constraints for lit tests.
453 /// The path in a test URI will be combined with a platform-specific fake
454 /// directory to form an absolute path. For example, test:///a.cpp is resolved
455 /// C:\clangd-test\a.cpp on Windows and /clangd-test/a.cpp on Unix.
456 class TestScheme : public URIScheme {
457 public:
458  llvm::Expected<std::string>
459  getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
460  llvm::StringRef /*HintPath*/) const override {
461  using namespace llvm::sys;
462  // Still require "/" in body to mimic file scheme, as we want lengths of an
463  // equivalent URI in both schemes to be the same.
464  if (!Body.startswith("/"))
465  return llvm::make_error<llvm::StringError>(
466  "Expect URI body to be an absolute path starting with '/': " + Body,
467  llvm::inconvertibleErrorCode());
468  Body = Body.ltrim('/');
469  llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
470  path::native(Path);
471  fs::make_absolute(TestScheme::TestDir, Path);
472  return std::string(Path.begin(), Path.end());
473  }
474 
475  llvm::Expected<URI>
476  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
477  llvm::StringRef Body = AbsolutePath;
478  if (!Body.consume_front(TestScheme::TestDir)) {
479  return llvm::make_error<llvm::StringError>(
480  "Path " + AbsolutePath + " doesn't start with root " + TestDir,
481  llvm::inconvertibleErrorCode());
482  }
483 
484  return URI("test", /*Authority=*/"",
485  llvm::sys::path::convert_to_slash(Body));
486  }
487 
488 private:
489  const static char TestDir[];
490 };
491 
492 #ifdef _WIN32
493 const char TestScheme::TestDir[] = "C:\\clangd-test";
494 #else
495 const char TestScheme::TestDir[] = "/clangd-test";
496 #endif
497 
498 } // namespace
499 } // namespace clangd
500 } // namespace clang
501 
502 enum class ErrorResultCode : int {
503  NoShutdownRequest = 1,
505 };
506 
507 int main(int argc, char *argv[]) {
508  using namespace clang;
509  using namespace clang::clangd;
510 
511  llvm::InitializeAllTargetInfos();
512  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
513  llvm::sys::SetInterruptFunction(&requestShutdown);
514  llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
515  OS << clang::getClangToolFullVersion("clangd") << "\n";
516  });
517  const char *FlagsEnvVar = "CLANGD_FLAGS";
518  const char *Overview =
519  R"(clangd is a language server that provides IDE-like features to editors.
520 
521 It should be used via an editor plugin rather than invoked directly. For more information, see:
522  https://clangd.llvm.org/
523  https://microsoft.github.io/language-server-protocol/
524 
525 clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.
526 )";
527  llvm::cl::HideUnrelatedOptions(ClangdCategories);
528  llvm::cl::ParseCommandLineOptions(argc, argv, Overview,
529  /*Errs=*/nullptr, FlagsEnvVar);
530  if (Test) {
531  Sync = true;
532  InputStyle = JSONStreamStyle::Delimited;
533  LogLevel = Logger::Verbose;
534  PrettyPrint = true;
535  // Disable config system by default to avoid external reads.
536  if (!EnableConfig.getNumOccurrences())
537  EnableConfig = false;
538  // Disable background index on lit tests by default to prevent disk writes.
539  if (!EnableBackgroundIndex.getNumOccurrences())
540  EnableBackgroundIndex = false;
541  // Ensure background index makes progress.
542  else if (EnableBackgroundIndex)
544  }
545  if (Test || EnableTestScheme) {
546  static URISchemeRegistry::Add<TestScheme> X(
547  "test", "Test scheme for clangd lit tests.");
548  }
549 
550  if (!Sync && WorkerThreadsCount == 0) {
551  llvm::errs() << "A number of worker threads cannot be 0. Did you mean to "
552  "specify -sync?";
553  return 1;
554  }
555 
556  if (Sync) {
557  if (WorkerThreadsCount.getNumOccurrences())
558  llvm::errs() << "Ignoring -j because -sync is set.\n";
559  WorkerThreadsCount = 0;
560  }
561  if (FallbackStyle.getNumOccurrences())
562  clang::format::DefaultFallbackStyle = FallbackStyle.c_str();
563 
564  // Validate command line arguments.
565  llvm::Optional<llvm::raw_fd_ostream> InputMirrorStream;
566  if (!InputMirrorFile.empty()) {
567  std::error_code EC;
568  InputMirrorStream.emplace(InputMirrorFile, /*ref*/ EC,
569  llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
570  if (EC) {
571  InputMirrorStream.reset();
572  llvm::errs() << "Error while opening an input mirror file: "
573  << EC.message();
574  } else {
575  InputMirrorStream->SetUnbuffered();
576  }
577  }
578 
579  // Setup tracing facilities if CLANGD_TRACE is set. In practice enabling a
580  // trace flag in your editor's config is annoying, launching with
581  // `CLANGD_TRACE=trace.json vim` is easier.
582  llvm::Optional<llvm::raw_fd_ostream> TracerStream;
583  std::unique_ptr<trace::EventTracer> Tracer;
584  const char *JSONTraceFile = getenv("CLANGD_TRACE");
585  const char *MetricsCSVFile = getenv("CLANGD_METRICS");
586  const char *TracerFile = JSONTraceFile ? JSONTraceFile : MetricsCSVFile;
587  if (TracerFile) {
588  std::error_code EC;
589  TracerStream.emplace(TracerFile, /*ref*/ EC,
590  llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
591  if (EC) {
592  TracerStream.reset();
593  llvm::errs() << "Error while opening trace file " << TracerFile << ": "
594  << EC.message();
595  } else {
596  Tracer = (TracerFile == JSONTraceFile)
597  ? trace::createJSONTracer(*TracerStream, PrettyPrint)
598  : trace::createCSVMetricTracer(*TracerStream);
599  }
600  }
601 
602  llvm::Optional<trace::Session> TracingSession;
603  if (Tracer)
604  TracingSession.emplace(*Tracer);
605 
606  // If a user ran `clangd` in a terminal without redirecting anything,
607  // it's somewhat likely they're confused about how to use clangd.
608  // Show them the help overview, which explains.
609  if (llvm::outs().is_displayed() && llvm::errs().is_displayed())
610  llvm::errs() << Overview << "\n";
611  // Use buffered stream to stderr (we still flush each log message). Unbuffered
612  // stream can cause significant (non-deterministic) latency for the logger.
613  llvm::errs().SetBuffered();
614  // Don't flush stdout when logging, this would be both slow and racy!
615  llvm::errs().tie(nullptr);
616  StreamLogger Logger(llvm::errs(), LogLevel);
618  // Write some initial logs before we start doing any real work.
619  log("{0}", clang::getClangToolFullVersion("clangd"));
620  log("PID: {0}", llvm::sys::Process::getProcessId());
621  {
622  SmallString<128> CWD;
623  if (auto Err = llvm::sys::fs::current_path(CWD))
624  log("Working directory unknown: {0}", Err.message());
625  else
626  log("Working directory: {0}", CWD);
627  }
628  for (int I = 0; I < argc; ++I)
629  log("argv[{0}]: {1}", I, argv[I]);
630  if (auto EnvFlags = llvm::sys::Process::GetEnv(FlagsEnvVar))
631  log("{0}: {1}", FlagsEnvVar, *EnvFlags);
632 
633  // If --compile-commands-dir arg was invoked, check value and override default
634  // path.
635  llvm::Optional<Path> CompileCommandsDirPath;
636  if (!CompileCommandsDir.empty()) {
637  if (llvm::sys::fs::exists(CompileCommandsDir)) {
638  // We support passing both relative and absolute paths to the
639  // --compile-commands-dir argument, but we assume the path is absolute in
640  // the rest of clangd so we make sure the path is absolute before
641  // continuing.
642  llvm::SmallString<128> Path(CompileCommandsDir);
643  if (std::error_code EC = llvm::sys::fs::make_absolute(Path)) {
644  llvm::errs() << "Error while converting the relative path specified by "
645  "--compile-commands-dir to an absolute path: "
646  << EC.message() << ". The argument will be ignored.\n";
647  } else {
648  CompileCommandsDirPath = std::string(Path.str());
649  }
650  } else {
651  llvm::errs()
652  << "Path specified by --compile-commands-dir does not exist. The "
653  "argument will be ignored.\n";
654  }
655  }
656 
658  switch (PCHStorage) {
659  case PCHStorageFlag::Memory:
660  Opts.StorePreamblesInMemory = true;
661  break;
662  case PCHStorageFlag::Disk:
663  Opts.StorePreamblesInMemory = false;
664  break;
665  }
666  if (!ResourceDir.empty())
667  Opts.ResourceDir = ResourceDir;
668  Opts.BuildDynamicSymbolIndex = EnableIndex;
669  Opts.BackgroundIndex = EnableBackgroundIndex;
670  std::unique_ptr<SymbolIndex> StaticIdx;
671  std::future<void> AsyncIndexLoad; // Block exit while loading the index.
672  if (EnableIndex && !IndexFile.empty()) {
673  // Load the index asynchronously. Meanwhile SwapIndex returns no results.
674  SwapIndex *Placeholder;
675  StaticIdx.reset(Placeholder = new SwapIndex(std::make_unique<MemIndex>()));
676  AsyncIndexLoad = runAsync<void>([Placeholder] {
677  if (auto Idx = loadIndex(IndexFile, /*UseDex=*/true))
678  Placeholder->reset(std::move(Idx));
679  });
680  if (Sync)
681  AsyncIndexLoad.wait();
682  }
683  Opts.StaticIndex = StaticIdx.get();
684  Opts.AsyncThreadsCount = WorkerThreadsCount;
685  Opts.BuildRecoveryAST = RecoveryAST;
686  Opts.PreserveRecoveryASTType = RecoveryASTType;
687  Opts.FoldingRanges = FoldingRanges;
688 
690  CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
691  CCOpts.Limit = LimitResults;
692  if (CompletionStyle.getNumOccurrences())
693  CCOpts.BundleOverloads = CompletionStyle != Detailed;
694  CCOpts.ShowOrigins = ShowOrigins;
695  CCOpts.InsertIncludes = HeaderInsertion;
696  if (!HeaderInsertionDecorators) {
699  }
700  CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
701  CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
702  CCOpts.AllScopes = AllScopesCompletion;
703  CCOpts.RunParser = CodeCompletionParse;
704 
705  RealThreadsafeFS TFS;
706  std::vector<std::unique_ptr<config::Provider>> ProviderStack;
707  std::unique_ptr<config::Provider> Config;
708  if (EnableConfig) {
709  ProviderStack.push_back(
711  llvm::SmallString<256> UserConfig;
712  if (llvm::sys::path::user_config_directory(UserConfig)) {
713  llvm::sys::path::append(UserConfig, "clangd", "config.yaml");
714  vlog("User config file is {0}", UserConfig);
715  ProviderStack.push_back(config::Provider::fromYAMLFile(UserConfig, TFS));
716  } else {
717  elog("Couldn't determine user config file, not loading");
718  }
719  std::vector<const config::Provider *> ProviderPointers;
720  for (const auto& P : ProviderStack)
721  ProviderPointers.push_back(P.get());
722  Config = config::Provider::combine(std::move(ProviderPointers));
723  Opts.ConfigProvider = Config.get();
724  }
725 
726  // Initialize and run ClangdLSPServer.
727  // Change stdin to binary to not lose \r\n on windows.
728  llvm::sys::ChangeStdinToBinary();
729 
730  std::unique_ptr<Transport> TransportLayer;
731  if (getenv("CLANGD_AS_XPC_SERVICE")) {
732 #if CLANGD_BUILD_XPC
733  log("Starting LSP over XPC service");
734  TransportLayer = newXPCTransport();
735 #else
736  llvm::errs() << "This clangd binary wasn't built with XPC support.\n";
738 #endif
739  } else {
740  log("Starting LSP over stdin/stdout");
741  TransportLayer = newJSONTransport(
742  stdin, llvm::outs(),
743  InputMirrorStream ? InputMirrorStream.getPointer() : nullptr,
744  PrettyPrint, InputStyle);
745  }
746  if (!PathMappingsArg.empty()) {
747  auto Mappings = parsePathMappings(PathMappingsArg);
748  if (!Mappings) {
749  elog("Invalid -path-mappings: {0}", Mappings.takeError());
750  return 1;
751  }
752  TransportLayer = createPathMappingTransport(std::move(TransportLayer),
753  std::move(*Mappings));
754  }
755  // Create an empty clang-tidy option.
756  std::mutex ClangTidyOptMu;
757  std::unique_ptr<tidy::ClangTidyOptionsProvider>
758  ClangTidyOptProvider; /*GUARDED_BY(ClangTidyOptMu)*/
759  if (EnableClangTidy) {
760  auto EmptyDefaults = tidy::ClangTidyOptions::getDefaults();
761  EmptyDefaults.Checks.reset(); // So we can tell if checks were ever set.
762  tidy::ClangTidyOptions OverrideClangTidyOptions;
763  if (!ClangTidyChecks.empty())
764  OverrideClangTidyOptions.Checks = ClangTidyChecks;
765  ClangTidyOptProvider = std::make_unique<tidy::FileOptionsProvider>(
767  /* Default */ EmptyDefaults,
768  /* Override */ OverrideClangTidyOptions, TFS.view(/*CWD=*/llvm::None));
769  Opts.GetClangTidyOptions = [&](llvm::vfs::FileSystem &,
770  llvm::StringRef File) {
771  // This function must be thread-safe and tidy option providers are not.
773  {
774  std::lock_guard<std::mutex> Lock(ClangTidyOptMu);
775  // FIXME: use the FS provided to the function.
776  Opts = ClangTidyOptProvider->getOptions(File);
777  }
778  if (!Opts.Checks) {
779  // If the user hasn't configured clang-tidy checks at all, including
780  // via .clang-tidy, give them a nice set of checks.
781  // (This should be what the "default" options does, but it isn't...)
782  //
783  // These default checks are chosen for:
784  // - low false-positive rate
785  // - providing a lot of value
786  // - being reasonably efficient
787  Opts.Checks = llvm::join_items(
788  ",", "readability-misleading-indentation",
789  "readability-deleted-default", "bugprone-integer-division",
790  "bugprone-sizeof-expression", "bugprone-suspicious-missing-comma",
791  "bugprone-unused-raii", "bugprone-unused-return-value",
792  "misc-unused-using-decls", "misc-unused-alias-decls",
793  "misc-definitions-in-headers");
794  }
795  return Opts;
796  };
797  }
798  Opts.SuggestMissingIncludes = SuggestMissingIncludes;
799  Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
800 
801  Opts.TweakFilter = [&](const Tweak &T) {
802  if (T.hidden() && !HiddenFeatures)
803  return false;
804  if (TweakList.getNumOccurrences())
805  return llvm::is_contained(TweakList, T.id());
806  return true;
807  };
808  llvm::Optional<OffsetEncoding> OffsetEncodingFromFlag;
809  if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
810  OffsetEncodingFromFlag = ForceOffsetEncoding;
811 
813  // Shall we allow to customize the file limit?
814  RenameOpts.AllowCrossFile = CrossFileRename;
815 
816  Opts.AsyncPreambleBuilds = AsyncPreamble;
817 
818  ClangdLSPServer LSPServer(
819  *TransportLayer, TFS, CCOpts, RenameOpts, CompileCommandsDirPath,
820  /*UseDirBasedCDB=*/CompileArgsFrom == FilesystemCompileArgs,
821  OffsetEncodingFromFlag, Opts);
822  llvm::set_thread_name("clangd.main");
823  int ExitCode = LSPServer.run()
824  ? 0
825  : static_cast<int>(ErrorResultCode::NoShutdownRequest);
826  log("LSP finished, exiting with status {0}", ExitCode);
827 
828  // There may still be lingering background threads (e.g. slow requests
829  // whose results will be dropped, background index shutting down).
830  //
831  // These should terminate quickly, and ~ClangdLSPServer blocks on them.
832  // However if a bug causes them to run forever, we want to ensure the process
833  // eventually exits. As clangd isn't directly user-facing, an editor can
834  // "leak" clangd processes. Crashing in this case contains the damage.
835  abortAfterTimeout(std::chrono::minutes(5));
836 
837  return ExitCode;
838 }
clang::clangd::@837::CompileArgsFrom
CompileArgsFrom
Definition: ClangdMain.cpp:70
clang::clangd::ClangdLSPServer::run
bool run()
Run LSP server loop, communicating with the Transport provided in the constructor.
Definition: ClangdLSPServer.cpp:1417
CCOpts
CodeCompleteOptions CCOpts
Definition: ClangdLSPServerTests.cpp:67
clang::clangd::CodeCompleteOptions::IncludeIndicator
struct clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator IncludeIndicator
Shutdown.h
Background.h
clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator::Insert
std::string Insert
Definition: CodeComplete.h:89
clang::clangd::@837::CompletionStyleFlag
CompletionStyleFlag
Definition: ClangdMain.cpp:170
clang::tidy::ClangTidyOptions::Checks
llvm::Optional< std::string > Checks
Checks filter.
Definition: ClangTidyOptions.h:66
clang::clangd::getDefaultAsyncThreadsCount
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
Definition: TUScheduler.cpp:1215
CodeComplete.h
clang::clangd::CodeCompleteOptions::ShowOrigins
bool ShowOrigins
Expose origins of completion items in the label (for debugging).
Definition: CodeComplete.h:94
clang::clangd::CodeCompleteOptions::RunParser
enum clang::clangd::CodeCompleteOptions::CodeCompletionParse RunParser
clang::clangd::Path
std::string Path
A typedef to represent a file path.
Definition: Path.h:20
clang::clangd::Logger::Verbose
Definition: Logger.h:27
Tracer
std::unique_ptr< trace::EventTracer > Tracer
Definition: TraceTests.cpp:163
clang::clangd::Logger::Debug
Definition: Logger.h:27
Path.h
clang::clangd::Logger
Interface to allow custom logging in clangd.
Definition: Logger.h:23
clang::clangd::SwapIndex::reset
void reset(std::unique_ptr< SymbolIndex >)
Definition: Index.cpp:20
clang::clangd::SwapIndex
Definition: Index.h:128
clang::clangd::StreamLogger
Definition: Logger.h:90
clang::clangd::OffsetEncoding::UTF32
clang::clangd::CodeCompleteOptions::ParseIfReady
Run the parser if inputs (preamble) are ready.
Definition: CodeComplete.h:136
clang::clangd::X
static URISchemeRegistry::Add< TestScheme > X(TestScheme::Scheme, "Test schema")
Trace.h
clang::clangd::Config
Settings that express user/project preferences and control clangd behavior.
Definition: Config.h:40
llvm::sys
Definition: BenchmarkHeader.h:10
clang::clangd::TestScheme::getAbsolutePath
llvm::Expected< std::string > getAbsolutePath(llvm::StringRef, llvm::StringRef Body, llvm::StringRef HintPath) const override
Returns the absolute path of the file corresponding to the URI authority+body in the file system.
Definition: TestFS.cpp:100
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
clang::clangd::CodeCompleteOptions::EnableFunctionArgSnippets
bool EnableFunctionArgSnippets
Whether to generate snippets for function arguments on code-completion.
Definition: CodeComplete.h:119
clang::clangd::abortAfterTimeout
void abortAfterTimeout(std::chrono::seconds Timeout)
Causes this process to crash if still running after Timeout.
Definition: Shutdown.cpp:18
clang::clangd::RealThreadsafeFS
Definition: ThreadsafeFS.h:49
clang::tidy::ClangTidyOptions
Contains options for clang-tidy.
Definition: ClangTidyOptions.h:50
clang::clangd::trace::createJSONTracer
std::unique_ptr< EventTracer > createJSONTracer(llvm::raw_ostream &OS, bool Pretty)
Create an instance of EventTracer that produces an output in the Trace Event format supported by Chro...
Definition: Trace.cpp:265
clang::clangd::CodeCompleteOptions::AllScopes
bool AllScopes
Whether to include index symbols that are not defined in the scopes visible from the code completion ...
Definition: CodeComplete.h:126
clang::clangd::requestShutdown
void requestShutdown()
Sets a flag to indicate that clangd was sent a shutdown signal, and the transport loop should exit at...
Definition: Shutdown.cpp:28
clang::clangd
Definition: AST.cpp:39
clang::clangd::OffsetEncoding::UTF8
run-clang-tidy.make_absolute
def make_absolute(f, directory)
Definition: run-clang-tidy.py:76
Protocol.h
ThreadsafeFS.h
clang::clangd::newXPCTransport
std::unique_ptr< Transport > newXPCTransport()
Definition: XPCTransport.cpp:212
clang::clangd::ClangdLSPServer
This class exposes ClangdServer's capabilities via Language Server Protocol.
Definition: ClangdLSPServer.h:37
clang::clangd::ClangdServer::Options
Definition: ClangdServer.h:90
Rename.h
clang::clangd::trace::createCSVMetricTracer
std::unique_ptr< EventTracer > createCSVMetricTracer(llvm::raw_ostream &OS)
Create an instance of EventTracer that outputs metric measurements as CSV.
Definition: Trace.cpp:270
ClangdLSPServer.h
clang::clangd::CodeCompleteOptions::SpeculativeIndexRequest
bool SpeculativeIndexRequest
If set to true, this will send an asynchronous speculative index request, based on the index request ...
Definition: CodeComplete.h:104
clang::clangd::CodeCompleteOptions::IncludeIneligibleResults
bool IncludeIneligibleResults
Include results that are not legal completions in the current context.
Definition: CodeComplete.h:66
clang::clangd::OffsetEncoding::UTF16
clang::clangd::BackgroundQueue::preventThreadStarvationInTests
static void preventThreadStarvationInTests()
Definition: BackgroundQueue.cpp:17
PathMapping.h
clang::clangd::loadIndex
std::unique_ptr< SymbolIndex > loadIndex(llvm::StringRef SymbolFilename, bool UseDex)
Definition: Serialization.cpp:668
ErrorResultCode
ErrorResultCode
Definition: ClangdMain.cpp:502
clang::clangd::config::Provider::fromAncestorRelativeYAMLFiles
static std::unique_ptr< Provider > fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &)
Definition: ConfigProvider.cpp:131
main
int main(int argc, char *argv[])
Definition: ClangdMain.cpp:507
clang::clangd::RenameOptions
Definition: Rename.h:29
clang::clangd::CodeCompleteOptions::NeverParse
Always use text-based completion.
Definition: CodeComplete.h:138
clang::clangd::LoggingSession
Only one LoggingSession can be active at a time.
Definition: Logger.h:77
Serialization.h
clang::clangd::vlog
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:67
clang::clangd::CodeCompleteOptions::BundleOverloads
llvm::Optional< bool > BundleOverloads
Combine overloads into a single completion item where possible.
Definition: CodeComplete.h:72
clang::clangd::Logger::Error
Definition: Logger.h:27
clang::clangd::Standard
Definition: Transport.h:67
ErrorResultCode::NoShutdownRequest
clang::clangd::CodeCompleteOptions
Definition: CodeComplete.h:44
clang::clangd::log
void log(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
Config
static cl::opt< std::string > Config("config", cl::desc(R"( Specifies a configuration in YAML/JSON format: -config="{Checks:' *', CheckOptions:[{key:x, value:y}]}" When the value is empty, clang-tidy will attempt to find a file named .clang-tidy for each source file in its parent directories. )"), cl::init(""), cl::cat(ClangTidyCategory))
clang::tidy::ClangTidyGlobalOptions
Global options.
Definition: ClangTidyOptions.h:42
clang::clangd::CodeCompleteOptions::NeverInsert
Definition: CodeComplete.h:83
Transport.h
clang::clangd::config::Provider::combine
static std::unique_ptr< Provider > combine(std::vector< const Provider * >)
A provider that includes fragments from all the supplied providers.
Definition: ConfigProvider.cpp:196
clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator::NoInsert
std::string NoInsert
Definition: CodeComplete.h:90
RenameOpts
RenameOptions RenameOpts
Definition: ClangdLSPServerTests.cpp:68
clang::clangd::ThreadsafeFS::view
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > view(llvm::NoneType CWD) const
Obtain a vfs::FileSystem with an arbitrary initial working directory.
Definition: ThreadsafeFS.h:34
clang::clangd::CodeCompleteOptions::InsertIncludes
enum clang::clangd::CodeCompleteOptions::IncludeInsertion InsertIncludes
clang::clangd::CodeCompleteOptions::AlwaysParse
Block until we can run the parser (e.g.
Definition: CodeComplete.h:133
clang::clangd::TestScheme::uriFromAbsolutePath
llvm::Expected< URI > uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override
Definition: TestFS.cpp:116
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:162
clang::clangd::CodeCompleteOptions::Limit
size_t Limit
Limit the number of results returned (0 means no limit).
Definition: CodeComplete.h:76
clang::clangd::Tweak
An interface base for small context-sensitive refactoring actions.
Definition: Tweak.h:46
clang::clangd::newJSONTransport
std::unique_ptr< Transport > newJSONTransport(std::FILE *In, llvm::raw_ostream &Out, llvm::raw_ostream *InMirror, bool Pretty, JSONStreamStyle Style)
Definition: JSONTransport.cpp:320
clang::clangd::CodeCompleteOptions::IWYU
Definition: CodeComplete.h:82
clang::clangd::OffsetEncoding::UnsupportedEncoding
clang::clangd::@837::PCHStorageFlag
PCHStorageFlag
Definition: ClangdMain.cpp:337
ErrorResultCode::CantRunAsXPCService
clang::clangd::parsePathMappings
llvm::Expected< PathMappings > parsePathMappings(llvm::StringRef RawPathMappings)
Parse the command line RawPathMappings (e.g.
Definition: PathMapping.cpp:170
clang::clangd::Delimited
Definition: Transport.h:69
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
clang::clangd::createPathMappingTransport
std::unique_ptr< Transport > createPathMappingTransport(std::unique_ptr< Transport > Transp, PathMappings Mappings)
Creates a wrapping transport over Transp that applies the Mappings to all inbound and outbound LSP me...
Definition: PathMapping.cpp:193
clang::clangd::RenameOptions::AllowCrossFile
bool AllowCrossFile
If true, enable cross-file rename; otherwise, only allows to rename a symbol that's only used in the ...
Definition: Rename.h:32
clang::clangd::Logger::Info
Definition: Logger.h:27
clang::tidy::ClangTidyOptions::getDefaults
static ClangTidyOptions getDefaults()
These options are used for all settings that haven't been overridden by the OptionsProvider.
Definition: ClangTidyOptions.cpp:109
clang::clangd::config::Provider::fromYAMLFile
static std::unique_ptr< Provider > fromYAMLFile(llvm::StringRef AbsPathPath, const ThreadsafeFS &)
Definition: ConfigProvider.cpp:107