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