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