clang-tools 24.0.0git
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 "ClangdMain.h"
11#include "ClangdLSPServer.h"
12#include "CodeComplete.h"
13#include "Compiler.h"
14#include "Config.h"
15#include "ConfigProvider.h"
16#include "Feature.h"
17#include "FeatureModule.h"
18#include "IncludeCleaner.h"
19#include "PathMapping.h"
20#include "Protocol.h"
21#include "TidyProvider.h"
22#include "Transport.h"
23#include "index/Background.h"
24#include "index/Index.h"
25#include "index/MemIndex.h"
26#include "index/Merge.h"
27#include "index/ProjectAware.h"
28#include "index/remote/Client.h"
29#include "support/Path.h"
30#include "support/Shutdown.h"
33#include "support/Trace.h"
34#include "clang/Basic/Stack.h"
35#include "clang/Format/Format.h"
36#include "llvm/ADT/SmallString.h"
37#include "llvm/ADT/StringRef.h"
38#include "llvm/Support/CommandLine.h"
39#include "llvm/Support/FileSystem.h"
40#include "llvm/Support/InitLLVM.h"
41#include "llvm/Support/Path.h"
42#include "llvm/Support/PluginLoader.h"
43#include "llvm/Support/Process.h"
44#include "llvm/Support/Program.h"
45#include "llvm/Support/Signals.h"
46#include "llvm/Support/TargetSelect.h"
47#include "llvm/Support/raw_ostream.h"
48#include <chrono>
49#include <cstdlib>
50#include <memory>
51#include <mutex>
52#include <optional>
53#include <string>
54#include <thread>
55#include <utility>
56#include <vector>
57
58#ifndef _WIN32
59#include <unistd.h>
60#endif
61
62#ifdef __GLIBC__
63#include <malloc.h>
64#endif
65
66namespace clang {
67namespace clangd {
68
69// Implemented in Check.cpp.
70bool check(const llvm::StringRef File, const ThreadsafeFS &TFS,
72
73namespace {
74
75using llvm::cl::cat;
76using llvm::cl::CommaSeparated;
77using llvm::cl::desc;
78using llvm::cl::Hidden;
79using llvm::cl::init;
80using llvm::cl::list;
81using llvm::cl::opt;
82using llvm::cl::OptionCategory;
83using llvm::cl::ValueOptional;
84using llvm::cl::values;
85
86// All flags must be placed in a category, or they will be shown neither in
87// --help, nor --help-hidden!
88OptionCategory CompileCommands("clangd compilation flags options");
89OptionCategory Features("clangd feature options");
90OptionCategory Misc("clangd miscellaneous options");
91OptionCategory Protocol("clangd protocol and logging options");
92OptionCategory Retired("clangd flags no longer in use");
93const OptionCategory *ClangdCategories[] = {&Features, &Protocol,
94 &CompileCommands, &Misc, &Retired};
95
96std::vector<const llvm::cl::Option *> RetiredOptions;
97
98template <typename T> class RetiredFlag {
99 opt<T> Option;
100
101public:
102 RetiredFlag(llvm::StringRef Name)
103 : Option(Name, cat(Retired), desc("Obsolete flag, ignored"), Hidden) {
104 RetiredOptions.push_back(&Option);
105 }
106};
107
108enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs };
109opt<CompileArgsFrom> CompileArgsFrom{
110 "compile_args_from",
111 cat(CompileCommands),
112 desc("The source of compile commands"),
113 values(clEnumValN(LSPCompileArgs, "lsp",
114 "All compile commands come from LSP and "
115 "'compile_commands.json' files are ignored"),
116 clEnumValN(FilesystemCompileArgs, "filesystem",
117 "All compile commands come from the "
118 "'compile_commands.json' files")),
119 init(FilesystemCompileArgs),
120 Hidden,
121};
122
123opt<Path> CompileCommandsDir{
124 "compile-commands-dir",
125 cat(CompileCommands),
126 desc("Specify a path to look for compile_commands.json. If path "
127 "is invalid, clangd will look in the current directory and "
128 "parent paths of each source file"),
129};
130
131opt<Path> ResourceDir{
132 "resource-dir",
133 cat(CompileCommands),
134 desc("Directory for system clang headers"),
135 init(""),
136 Hidden,
137};
138
139list<std::string> QueryDriverGlobs{
140 "query-driver",
141 cat(CompileCommands),
142 desc(
143 "Comma separated list of globs for white-listing gcc-compatible "
144 "drivers that are safe to execute. Drivers matching any of these globs "
145 "will be used to extract system includes. e.g. "
146 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
147 CommaSeparated,
148};
149
150// FIXME: Flags are the wrong mechanism for user preferences.
151// We should probably read a dotfile or similar.
152opt<bool> AllScopesCompletion{
153 "all-scopes-completion",
154 cat(Features),
155 desc("If set to true, code completion will include index symbols that are "
156 "not defined in the scopes (e.g. "
157 "namespaces) visible from the code completion point. Such completions "
158 "can insert scope qualifiers"),
159 init(true),
160};
161
162opt<bool> ShowOrigins{
163 "debug-origin",
164 cat(Features),
165 desc("Show origins of completion items"),
166 init(CodeCompleteOptions().ShowOrigins),
167 Hidden,
168};
169
170opt<bool> EnableBackgroundIndex{
171 "background-index",
172 cat(Features),
173 desc("Index project code in the background and persist index on disk."),
174 init(true),
175};
176
177opt<llvm::ThreadPriority> BackgroundIndexPriority{
178 "background-index-priority",
179 cat(Features),
180 desc("Thread priority for building the background index. "
181 "The effect of this flag is OS-specific."),
182 values(clEnumValN(llvm::ThreadPriority::Background, "background",
183 "Minimum priority, runs on idle CPUs. "
184 "May leave 'performance' cores unused."),
185 clEnumValN(llvm::ThreadPriority::Low, "low",
186 "Reduced priority compared to interactive work."),
187 clEnumValN(llvm::ThreadPriority::Default, "normal",
188 "Same priority as other clangd work.")),
189 init(llvm::ThreadPriority::Low),
190};
191
192opt<bool> EnableClangTidy{
193 "clang-tidy",
194 cat(Features),
195 desc("Enable clang-tidy diagnostics"),
196 init(true),
197};
198
199opt<CodeCompleteOptions::CodeCompletionParse> CodeCompletionParse{
200 "completion-parse",
201 cat(Features),
202 desc("Whether the clang-parser is used for code-completion"),
203 values(clEnumValN(CodeCompleteOptions::AlwaysParse, "always",
204 "Block until the parser can be used"),
205 clEnumValN(CodeCompleteOptions::ParseIfReady, "auto",
206 "Use text-based completion if the parser "
207 "is not ready"),
208 clEnumValN(CodeCompleteOptions::NeverParse, "never",
209 "Always used text-based completion")),
210 init(CodeCompleteOptions().RunParser),
211 Hidden,
212};
213
214opt<CodeCompleteOptions::CodeCompletionRankingModel> RankingModel{
215 "ranking-model",
216 cat(Features),
217 desc("Model to use to rank code-completion items"),
218 values(clEnumValN(CodeCompleteOptions::Heuristics, "heuristics",
219 "Use heuristics to rank code completion items"),
220 clEnumValN(CodeCompleteOptions::DecisionForest, "decision_forest",
221 "Use Decision Forest model to rank completion items")),
222 init(CodeCompleteOptions().RankingModel),
223 Hidden,
224};
225
226// FIXME: also support "plain" style where signatures are always omitted.
227enum CompletionStyleFlag { Detailed, Bundled };
228opt<CompletionStyleFlag> CompletionStyle{
229 "completion-style",
230 cat(Features),
231 desc("Granularity of code completion suggestions"),
232 values(clEnumValN(Detailed, "detailed",
233 "One completion item for each semantically distinct "
234 "completion, with full type information"),
235 clEnumValN(Bundled, "bundled",
236 "Similar completion items (e.g. function overloads) are "
237 "combined. Type information shown where possible")),
238};
239
240opt<std::string> FallbackStyle{
241 "fallback-style",
242 cat(Features),
243 desc("clang-format style to apply by default when "
244 "no .clang-format file is found"),
245 init(clang::format::DefaultFallbackStyle),
246};
247
248opt<std::string> EnableFunctionArgSnippets{
249 "function-arg-placeholders",
250 cat(Features),
251 desc("When disabled (0), completions contain only parentheses for "
252 "function calls. When enabled (1), completions also contain "
253 "placeholders for method parameters"),
254 init("-1"),
255};
256
257opt<Config::HeaderInsertionPolicy> HeaderInsertion{
258 "header-insertion",
259 cat(Features),
260 desc("Add #include directives when accepting code completions"),
261 init(CodeCompleteOptions().InsertIncludes),
262 values(
263 clEnumValN(Config::HeaderInsertionPolicy::IWYU, "iwyu",
264 "Include what you use. "
265 "Insert the owning header for top-level symbols, unless the "
266 "header is already directly included or the symbol is "
267 "forward-declared"),
268 clEnumValN(
270 "Never insert #include directives as part of code completion")),
271};
272
273opt<bool> ImportInsertions{
274 "import-insertions",
275 cat(Features),
276 desc("If header insertion is enabled, add #import directives when "
277 "accepting code completions or fixing includes in Objective-C code"),
278 init(CodeCompleteOptions().ImportInsertions),
279};
280
281opt<bool> HeaderInsertionDecorators{
282 "header-insertion-decorators",
283 cat(Features),
284 desc("Prepend a circular dot or space before the completion "
285 "label, depending on whether "
286 "an include line will be inserted or not"),
287 init(true),
288};
289
290opt<bool> HiddenFeatures{
291 "hidden-features",
292 cat(Features),
293 desc("Enable hidden features mostly useful to clangd developers"),
294 init(false),
295 Hidden,
296};
297
298opt<bool> IncludeIneligibleResults{
299 "include-ineligible-results",
300 cat(Features),
301 desc("Include ineligible completion results (e.g. private members)"),
302 init(CodeCompleteOptions().IncludeIneligibleResults),
303 Hidden,
304};
305
306RetiredFlag<bool> EnableIndex("index");
307RetiredFlag<bool> SuggestMissingIncludes("suggest-missing-includes");
308RetiredFlag<bool> RecoveryAST("recovery-ast");
309RetiredFlag<bool> RecoveryASTType("recovery-ast-type");
310RetiredFlag<bool> AsyncPreamble("async-preamble");
311RetiredFlag<bool> CollectMainFileRefs("collect-main-file-refs");
312RetiredFlag<bool> CrossFileRename("cross-file-rename");
313RetiredFlag<std::string> ClangTidyChecks("clang-tidy-checks");
314RetiredFlag<bool> InlayHints("inlay-hints");
315RetiredFlag<bool> FoldingRanges("folding-ranges");
316RetiredFlag<bool> IncludeCleanerStdlib("include-cleaner-stdlib");
317
318opt<int> LimitResults{
319 "limit-results",
320 cat(Features),
321 desc("Limit the number of results returned by clangd. "
322 "0 means no limit (default=100)"),
323 init(100),
324};
325
326opt<int> ReferencesLimit{
327 "limit-references",
328 cat(Features),
329 desc("Limit the number of references returned by clangd. "
330 "0 means no limit (default=1000)"),
331 init(1000),
332};
333
334opt<int> RenameFileLimit{
335 "rename-file-limit",
336 cat(Features),
337 desc("Limit the number of files to be affected by symbol renaming. "
338 "0 means no limit (default=50)"),
339 init(50),
340};
341
342list<std::string> TweakList{
343 "tweaks",
344 cat(Features),
345 desc("Specify a list of Tweaks to enable (only for clangd developers)."),
346 Hidden,
347 CommaSeparated,
348};
349
350opt<unsigned> WorkerThreadsCount{
351 "j",
352 cat(Misc),
353 desc("Number of async workers used by clangd. Background index also "
354 "uses this many workers."),
356};
357
358opt<Path> IndexFile{
359 "index-file",
360 cat(Misc),
361 desc(
362 "Index file to build the static index. The file must have been created "
363 "by a compatible clangd-indexer\n"
364 "WARNING: This option is experimental only, and will be removed "
365 "eventually. Don't rely on it"),
366 init(""),
367 Hidden,
368};
369
370opt<bool> Test{
371 "lit-test",
372 cat(Misc),
373 desc("Abbreviation for -input-style=delimited -pretty -sync "
374 "-enable-test-scheme -enable-config=0 -log=verbose -crash-pragmas. "
375 "Also sets config options: Index.StandardLibrary=false. "
376 "Intended to simplify lit tests"),
377 init(false),
378 Hidden,
379};
380
381opt<bool> CrashPragmas{
382 "crash-pragmas",
383 cat(Misc),
384 desc("Respect `#pragma clang __debug crash` and friends."),
385 init(false),
386 Hidden,
387};
388
389opt<Path> CheckFile{
390 "check",
391 cat(Misc),
392 desc("Parse one file in isolation instead of acting as a language server. "
393 "Useful to investigate/reproduce crashes or configuration problems. "
394 "With --check=<filename>, attempts to parse a particular file."),
395 init(""),
396 ValueOptional,
397};
398
399enum PCHStorageFlag { Disk, Memory };
400opt<PCHStorageFlag> PCHStorage{
401 "pch-storage",
402 cat(Misc),
403 desc("Storing PCHs in memory increases memory usages, but may "
404 "improve performance"),
405 values(
406 clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"),
407 clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")),
408 init(PCHStorageFlag::Disk),
409};
410
411opt<bool> Sync{
412 "sync",
413 cat(Misc),
414 desc("Handle client requests on main thread. Background index still uses "
415 "its own thread."),
416 init(false),
417 Hidden,
418};
419
420opt<JSONStreamStyle> InputStyle{
421 "input-style",
422 cat(Protocol),
423 desc("Input JSON stream encoding"),
424 values(
425 clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"),
426 clEnumValN(JSONStreamStyle::Delimited, "delimited",
427 "messages delimited by --- lines, with # comment support")),
429 Hidden,
430};
431
432opt<bool> EnableTestScheme{
433 "enable-test-uri-scheme",
434 cat(Protocol),
435 desc("Enable 'test:' URI scheme. Only use in lit tests"),
436 init(false),
437 Hidden,
438};
439
440opt<std::string> PathMappingsArg{
441 "path-mappings",
442 cat(Protocol),
443 desc(
444 "Translates between client paths (as seen by a remote editor) and "
445 "server paths (where clangd sees files on disk). "
446 "Comma separated list of '<client_path>=<server_path>' pairs, the "
447 "first entry matching a given path is used. "
448 "e.g. /home/project/incl=/opt/include,/home/project=/workarea/project"),
449 init(""),
450};
451
452opt<Path> InputMirrorFile{
453 "input-mirror-file",
454 cat(Protocol),
455 desc("Mirror all LSP input to the specified file. Useful for debugging"),
456 init(""),
457 Hidden,
458};
459
460opt<Logger::Level> LogLevel{
461 "log",
462 cat(Protocol),
463 desc("Verbosity of log messages written to stderr"),
464 values(clEnumValN(Logger::Error, "error", "Error messages only"),
465 clEnumValN(Logger::Info, "info", "High level execution tracing"),
466 clEnumValN(Logger::Debug, "verbose", "Low level details")),
467 init(Logger::Info),
468};
469
470opt<OffsetEncoding> ForceOffsetEncoding{
471 "offset-encoding",
472 cat(Protocol),
473 desc("Force the offsetEncoding used for character positions. "
474 "This bypasses negotiation via client capabilities"),
475 values(
476 clEnumValN(OffsetEncoding::UTF8, "utf-8", "Offsets are in UTF-8 bytes"),
477 clEnumValN(OffsetEncoding::UTF16, "utf-16",
478 "Offsets are in UTF-16 code units"),
479 clEnumValN(OffsetEncoding::UTF32, "utf-32",
480 "Offsets are in unicode codepoints")),
482};
483
484opt<bool> PrettyPrint{
485 "pretty",
486 cat(Protocol),
487 desc("Pretty-print JSON output"),
488 init(false),
489};
490
491opt<bool> EnableConfig{
492 "enable-config",
493 cat(Misc),
495 init(true),
496};
497
498opt<bool> StrongWorkspaceMode{
499 "strong-workspace-mode",
500 cat(Features),
501 desc("An alternate mode of operation for clangd, where the clangd instance "
502 "is used to edit a single workspace.\n"
503 "When enabled, fallback commands use the workspace directory as their "
504 "working directory instead of the parent folder."),
505 init(false),
506 Hidden,
507};
508
509opt<bool> UseDirtyHeaders{"use-dirty-headers", cat(Misc),
510 desc("Use files open in the editor when parsing "
511 "headers instead of reading from the disk"),
512 Hidden,
513 init(ClangdServer::Options().UseDirtyHeaders)};
514
515opt<bool> PreambleParseForwardingFunctions{
516 "parse-forwarding-functions",
517 cat(Misc),
518 desc("Parse all emplace-like functions in included headers"),
519 Hidden,
520 init(ParseOptions().PreambleParseForwardingFunctions),
521};
522
523opt<ClangdServer::SkipPreambleBuildPolicy> SkipPreambleBuild{
524 "skip-preamble-build",
525 cat(Misc),
526 desc("Skip building the preamble"),
527 Hidden,
528 values(clEnumValN(ClangdServer::SkipPreambleBuildPolicy::Never, "never",
529 "never skip"),
531 "only if module use is encountered (default)"),
533 "always skip")),
534 init(ClangdServer::Options().SkipPreambleBuild),
535};
536
537#if defined(__GLIBC__) && CLANGD_MALLOC_TRIM
538opt<bool> EnableMallocTrim{
539 "malloc-trim",
540 cat(Misc),
541 desc("Release memory periodically via malloc_trim(3)."),
542 init(true),
543};
544
545std::function<void()> getMemoryCleanupFunction() {
546 if (!EnableMallocTrim)
547 return nullptr;
548 // Leave a few MB at the top of the heap: it is insignificant
549 // and will most likely be needed by the main thread
550 constexpr size_t MallocTrimPad = 20'000'000;
551 return []() {
552 if (malloc_trim(MallocTrimPad))
553 vlog("Released memory via malloc_trim");
554 };
555}
556#else
557std::function<void()> getMemoryCleanupFunction() { return nullptr; }
558#endif
559
560#if CLANGD_ENABLE_REMOTE
561opt<std::string> RemoteIndexAddress{
562 "remote-index-address",
563 cat(Features),
564 desc("Address of the remote index server"),
565};
566
567// FIXME(kirillbobyrev): Should this be the location of compile_commands.json?
568opt<std::string> ProjectRoot{
569 "project-root",
570 cat(Features),
571 desc("Path to the project root. Requires remote-index-address to be set."),
572};
573#endif
574
575opt<bool> ExperimentalModulesSupport{
576 "experimental-modules-support",
577 cat(Features),
578 desc("Experimental support for standard c++ modules"),
579 init(false),
580};
581
582/// Supports a test URI scheme with relaxed constraints for lit tests.
583/// The path in a test URI will be combined with a platform-specific fake
584/// directory to form an absolute path. For example, test:///a.cpp is resolved
585/// C:\clangd-test\a.cpp on Windows and /clangd-test/a.cpp on Unix.
586class TestScheme : public URIScheme {
587public:
588 llvm::Expected<std::string>
589 getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
590 llvm::StringRef /*HintPath*/) const override {
591 using namespace llvm::sys;
592 // Still require "/" in body to mimic file scheme, as we want lengths of an
593 // equivalent URI in both schemes to be the same.
594 if (!Body.starts_with("/"))
595 return error(
596 "Expect URI body to be an absolute path starting with '/': {0}",
597 Body);
598 Body = Body.ltrim('/');
599 llvm::SmallString<16> Path(Body);
600 path::native(Path);
601 path::make_absolute(testDir(), Path);
602 return std::string(Path);
603 }
604
605 llvm::Expected<URI>
606 uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
607 llvm::StringRef Body = AbsolutePath;
608 if (!Body.consume_front(testDir()))
609 return error("Path {0} doesn't start with root {1}", AbsolutePath,
610 testDir());
611
612 return URI("test", /*Authority=*/"",
613 llvm::sys::path::convert_to_slash(Body));
614 }
615
616private:
617 static llvm::StringRef testDir() {
618#ifdef _WIN32
619 static const std::string TestDir = llvm::sys::path::native("C:/clangd-test");
620 return TestDir;
621#else
622 return "/clangd-test";
623#endif
624 }
625};
626
627std::unique_ptr<SymbolIndex>
628loadExternalIndex(const Config::ExternalIndexSpec &External,
629 AsyncTaskRunner *Tasks, bool SupportContainedRefs) {
630 static const trace::Metric RemoteIndexUsed("used_remote_index",
631 trace::Metric::Value, "address");
632 switch (External.Kind) {
634 break;
636 RemoteIndexUsed.record(1, External.Location);
637 log("Associating {0} with remote index at {1}.", External.MountPoint,
638 External.Location);
639 return remote::getClient(External.Location, External.MountPoint);
641 log("Associating {0} with monolithic index at {1}.", External.MountPoint,
642 External.Location);
643 auto NewIndex = std::make_unique<SwapIndex>(std::make_unique<MemIndex>());
644 auto IndexLoadTask = [File = External.Location,
645 PlaceHolder = NewIndex.get(), SupportContainedRefs] {
646 if (auto Idx = loadIndex(File, SymbolOrigin::Static, /*UseDex=*/true,
647 SupportContainedRefs))
648 PlaceHolder->reset(std::move(Idx));
649 };
650 if (Tasks) {
651 Tasks->runAsync("Load-index:" + External.Location,
652 std::move(IndexLoadTask));
653 } else {
654 IndexLoadTask();
655 }
656 return std::move(NewIndex);
657 }
658 llvm_unreachable("Invalid ExternalIndexKind.");
659}
660
661std::optional<bool> shouldEnableFunctionArgSnippets() {
662 std::string Val = EnableFunctionArgSnippets;
663 // Accept the same values that a bool option parser would, but also accept
664 // -1 to indicate "unspecified", in which case the ArgumentListsPolicy
665 // config option will be respected.
666 if (Val == "1" || Val == "true" || Val == "True" || Val == "TRUE")
667 return true;
668 if (Val == "0" || Val == "false" || Val == "False" || Val == "FALSE")
669 return false;
670 if (Val != "-1")
671 elog("Value specified by --function-arg-placeholders is invalid. Provide a "
672 "boolean value or leave unspecified to use ArgumentListsPolicy from "
673 "config instead.");
674 return std::nullopt;
675}
676
677class FlagsConfigProvider : public config::Provider {
678private:
680
681 std::vector<config::CompiledFragment>
682 getFragments(const config::Params &,
683 config::DiagnosticCallback) const override {
684 return {Frag};
685 }
686
687public:
688 FlagsConfigProvider() {
689 std::optional<Config::CDBSearchSpec> CDBSearch;
690 std::optional<Config::ExternalIndexSpec> IndexSpec;
691 std::optional<Config::BackgroundPolicy> BGPolicy;
692 std::optional<Config::ArgumentListsPolicy> ArgumentLists;
693
694 // If --compile-commands-dir arg was invoked, check value and override
695 // default path.
696 if (!CompileCommandsDir.empty()) {
697 if (llvm::sys::fs::exists(CompileCommandsDir)) {
698 // We support passing both relative and absolute paths to the
699 // --compile-commands-dir argument, but we assume the path is absolute
700 // in the rest of clangd so we make sure the path is absolute before
701 // continuing.
702 llvm::SmallString<128> Path(CompileCommandsDir);
703 if (std::error_code EC = llvm::sys::fs::make_absolute(Path)) {
704 elog("Error while converting the relative path specified by "
705 "--compile-commands-dir to an absolute path: {0}. The argument "
706 "will be ignored.",
707 EC.message());
708 } else {
709 CDBSearch = {Config::CDBSearchSpec::FixedDir, Path.str().str()};
710 }
711 } else {
712 elog("Path specified by --compile-commands-dir does not exist. The "
713 "argument will be ignored.");
714 }
715 }
716 if (!IndexFile.empty()) {
717 Config::ExternalIndexSpec Spec;
718 Spec.Kind = Spec.File;
719 Spec.Location = IndexFile;
720 IndexSpec = std::move(Spec);
721 }
722#if CLANGD_ENABLE_REMOTE
723 if (!RemoteIndexAddress.empty()) {
724 assert(!ProjectRoot.empty() && IndexFile.empty());
725 Config::ExternalIndexSpec Spec;
726 Spec.Kind = Spec.Server;
727 Spec.Location = RemoteIndexAddress;
728 Spec.MountPoint = ProjectRoot;
729 IndexSpec = std::move(Spec);
731 }
732#endif
733 if (!EnableBackgroundIndex) {
735 }
736
737 if (std::optional<bool> Enable = shouldEnableFunctionArgSnippets()) {
738 ArgumentLists = *Enable ? Config::ArgumentListsPolicy::FullPlaceholders
740 }
741
742 Frag = [=](const config::Params &, Config &C) {
743 if (CDBSearch)
744 C.CompileFlags.CDBSearch = *CDBSearch;
745 if (IndexSpec)
746 C.Index.External = *IndexSpec;
747 if (BGPolicy)
748 C.Index.Background = *BGPolicy;
749 if (ArgumentLists)
750 C.Completion.ArgumentLists = *ArgumentLists;
751 if (HeaderInsertion.getNumOccurrences())
752 C.Completion.HeaderInsertion = HeaderInsertion;
753 if (AllScopesCompletion.getNumOccurrences())
754 C.Completion.AllScopes = AllScopesCompletion;
755
756 if (Test)
757 C.Index.StandardLibrary = false;
758 return true;
759 };
760 }
761};
762} // namespace
763
769
770int clangdMain(int argc, char *argv[]) {
771 // Clang could run on the main thread. e.g., when the flag '-check' or '-sync'
772 // is enabled.
773 clang::noteBottomOfStack();
774 llvm::InitLLVM X(argc, argv);
775 llvm::InitializeAllTargetInfos();
776 llvm::sys::AddSignalHandler(
777 [](void *) {
779 // Ensure ThreadCrashReporter and PrintStackTrace output is visible.
780 llvm::errs().flush();
781 },
782 nullptr);
783 llvm::sys::SetInterruptFunction(&requestShutdown);
784 llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
785 OS << versionString() << "\n"
786 << "Features: " << featureString() << "\n"
787 << "Platform: " << platformString() << "\n";
788 });
789 const char *FlagsEnvVar = "CLANGD_FLAGS";
790 const char *Overview =
791 R"(clangd is a language server that provides IDE-like features to editors.
792
793It should be used via an editor plugin rather than invoked directly. For more information, see:
794 https://clangd.llvm.org/
795 https://microsoft.github.io/language-server-protocol/
796
797clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.
798)";
799 // Enable help for -load option, if plugins are enabled.
800 if (llvm::cl::Option *LoadOpt =
801 llvm::cl::getRegisteredOptions().lookup("load"))
802 LoadOpt->addCategory(Features);
803
804 llvm::cl::HideUnrelatedOptions(ClangdCategories);
805 llvm::cl::ParseCommandLineOptions(argc, argv, Overview, /*Errs=*/nullptr,
806 /*VFS=*/nullptr, FlagsEnvVar);
807 for (const llvm::cl::Option *O : RetiredOptions)
808 if (O->getNumOccurrences())
809 llvm::errs() << "The flag `-" << O->ArgStr
810 << "` is obsolete and ignored.\n";
811 if (Test) {
812 if (!Sync.getNumOccurrences())
813 Sync = true;
814 if (!CrashPragmas.getNumOccurrences())
815 CrashPragmas = true;
816 InputStyle = JSONStreamStyle::Delimited;
817 LogLevel = Logger::Verbose;
818 PrettyPrint = true;
819 // Disable config system by default to avoid external reads.
820 if (!EnableConfig.getNumOccurrences())
821 EnableConfig = false;
822 // Disable background index on lit tests by default to prevent disk writes.
823 if (!EnableBackgroundIndex.getNumOccurrences())
824 EnableBackgroundIndex = false;
825 // Ensure background index makes progress.
826 else if (EnableBackgroundIndex)
828 }
829 if (Test || EnableTestScheme) {
830 static URISchemeRegistry::Add<TestScheme> X(
831 "test", "Test scheme for clangd lit tests.");
832 }
833 if (CrashPragmas)
835
836 if (!Sync && WorkerThreadsCount == 0) {
837 llvm::errs() << "A number of worker threads cannot be 0. Did you mean to "
838 "specify -sync?";
839 return 1;
840 }
841
842 if (Sync) {
843 if (WorkerThreadsCount.getNumOccurrences())
844 llvm::errs() << "Ignoring -j because -sync is set.\n";
845 WorkerThreadsCount = 0;
846 }
847 if (FallbackStyle.getNumOccurrences())
848 clang::format::DefaultFallbackStyle = FallbackStyle.c_str();
849
850 // Validate command line arguments.
851 std::optional<llvm::raw_fd_ostream> InputMirrorStream;
852 if (!InputMirrorFile.empty()) {
853 std::error_code EC;
854 InputMirrorStream.emplace(InputMirrorFile, /*ref*/ EC,
855 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
856 if (EC) {
857 InputMirrorStream.reset();
858 llvm::errs() << "Error while opening an input mirror file: "
859 << EC.message();
860 } else {
861 InputMirrorStream->SetUnbuffered();
862 }
863 }
864
865#if !CLANGD_DECISION_FOREST
866 if (RankingModel == clangd::CodeCompleteOptions::DecisionForest) {
867 llvm::errs() << "Clangd was compiled without decision forest support.\n";
868 return 1;
869 }
870#endif
871
872 // Setup tracing facilities if CLANGD_TRACE is set. In practice enabling a
873 // trace flag in your editor's config is annoying, launching with
874 // `CLANGD_TRACE=trace.json vim` is easier.
875 std::optional<llvm::raw_fd_ostream> TracerStream;
876 std::unique_ptr<trace::EventTracer> Tracer;
877 const char *JSONTraceFile = getenv("CLANGD_TRACE");
878 const char *MetricsCSVFile = getenv("CLANGD_METRICS");
879 const char *TracerFile = JSONTraceFile ? JSONTraceFile : MetricsCSVFile;
880 if (TracerFile) {
881 std::error_code EC;
882 TracerStream.emplace(TracerFile, /*ref*/ EC,
883 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
884 if (EC) {
885 TracerStream.reset();
886 llvm::errs() << "Error while opening trace file " << TracerFile << ": "
887 << EC.message();
888 } else {
889 Tracer = (TracerFile == JSONTraceFile)
890 ? trace::createJSONTracer(*TracerStream, PrettyPrint)
891 : trace::createCSVMetricTracer(*TracerStream);
892 }
893 }
894
895 std::optional<trace::Session> TracingSession;
896 if (Tracer)
897 TracingSession.emplace(*Tracer);
898
899 // If a user ran `clangd` in a terminal without redirecting anything,
900 // it's somewhat likely they're confused about how to use clangd.
901 // Show them the help overview, which explains.
902 if (llvm::outs().is_displayed() && llvm::errs().is_displayed() &&
903 !CheckFile.getNumOccurrences())
904 llvm::errs() << Overview << "\n";
905 // Use buffered stream to stderr (we still flush each log message). Unbuffered
906 // stream can cause significant (non-deterministic) latency for the logger.
907 llvm::errs().SetBuffered();
908 StreamLogger Logger(llvm::errs(), LogLevel);
910 // Write some initial logs before we start doing any real work.
911 log("{0}", versionString());
912 log("Features: {0}", featureString());
913 log("PID: {0}", llvm::sys::Process::getProcessId());
914 {
915 SmallString<128> CWD;
916 if (auto Err = llvm::sys::fs::current_path(CWD))
917 log("Working directory unknown: {0}", Err.message());
918 else
919 log("Working directory: {0}", CWD);
920 }
921 for (int I = 0; I < argc; ++I)
922 log("argv[{0}]: {1}", I, argv[I]);
923 for (unsigned I = 0, E = llvm::PluginLoader::getNumPlugins(); I < E; ++I)
924 log("Loaded plugin: {0}", llvm::PluginLoader::getPlugin(I));
925 if (auto EnvFlags = llvm::sys::Process::GetEnv(FlagsEnvVar))
926 log("{0}: {1}", FlagsEnvVar, *EnvFlags);
927 // Log environment variables that influence how clangd finds system headers.
928 // This helps diagnose missing-include issues, especially on Windows.
929 for (const char *EnvVar : {
930 // MSVC environment variables (set by vcvarsall.bat)
931 "INCLUDE",
932 "LIB",
933 "LIBPATH",
934 "CL",
935 "_CL_",
936 // GCC/Clang environment variables
937 "CPATH",
938 "C_INCLUDE_PATH",
939 "CPLUS_INCLUDE_PATH",
940 "OBJC_INCLUDE_PATH",
941 "LIBRARY_PATH",
942 "GCC_EXEC_PREFIX",
943 }) {
944 if (auto Val = llvm::sys::Process::GetEnv(EnvVar))
945 log("Env {0}: {1}", EnvVar, *Val);
946 }
947
950 Opts.UseDirBasedCDB = (CompileArgsFrom == FilesystemCompileArgs);
951 Opts.EnableExperimentalModulesSupport = ExperimentalModulesSupport;
952
953 switch (PCHStorage) {
954 case PCHStorageFlag::Memory:
955 Opts.StorePreamblesInMemory = true;
956 break;
957 case PCHStorageFlag::Disk:
958 Opts.StorePreamblesInMemory = false;
959 break;
960 }
961 if (!ResourceDir.empty())
962 Opts.ResourceDir = ResourceDir;
963 Opts.StrongWorkspaceMode = StrongWorkspaceMode;
964 Opts.BuildDynamicSymbolIndex = true;
965#if CLANGD_ENABLE_REMOTE
966 if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {
967 llvm::errs() << "remote-index-address and project-path have to be "
968 "specified at the same time.";
969 return 1;
970 }
971 if (!RemoteIndexAddress.empty()) {
972 if (IndexFile.empty()) {
973 log("Connecting to remote index at {0}", RemoteIndexAddress);
974 } else {
975 elog("When enabling remote index, IndexFile should not be specified. "
976 "Only one can be used at time. Remote index will ignored.");
977 }
978 }
979#endif
980 Opts.BackgroundIndex = EnableBackgroundIndex;
981 Opts.BackgroundIndexPriority = BackgroundIndexPriority;
982 Opts.ReferencesLimit = ReferencesLimit;
983 Opts.Rename.LimitFiles = RenameFileLimit;
984 auto PAI = createProjectAwareIndex(
985 [SupportContainedRefs = Opts.EnableOutgoingCalls](
986 const Config::ExternalIndexSpec &External, AsyncTaskRunner *Tasks) {
987 return loadExternalIndex(External, Tasks, SupportContainedRefs);
988 },
989 Sync);
990 Opts.StaticIndex = PAI.get();
991 Opts.AsyncThreadsCount = WorkerThreadsCount;
992 Opts.MemoryCleanup = getMemoryCleanupFunction();
993
994 Opts.CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
995 Opts.CodeComplete.Limit = LimitResults;
996 if (CompletionStyle.getNumOccurrences())
997 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
998 Opts.CodeComplete.ShowOrigins = ShowOrigins;
999 Opts.CodeComplete.InsertIncludes = HeaderInsertion;
1000 Opts.CodeComplete.ImportInsertions = ImportInsertions;
1001 if (!HeaderInsertionDecorators) {
1002 Opts.CodeComplete.IncludeIndicator.Insert.clear();
1003 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
1004 }
1005 Opts.CodeComplete.RunParser = CodeCompletionParse;
1006 Opts.CodeComplete.RankingModel = RankingModel;
1007 // FIXME: If we're using C++20 modules, force the lookup process to load
1008 // external decls, since currently the index doesn't support C++20 modules.
1009 Opts.CodeComplete.ForceLoadPreamble = ExperimentalModulesSupport;
1010
1011 std::vector<std::unique_ptr<config::Provider>> ProviderStack;
1012 if (EnableConfig)
1013 ProviderStack = config::Provider::createDefaultProviders(TFS);
1014 ProviderStack.push_back(std::make_unique<FlagsConfigProvider>());
1015 Opts.ConfigProvider = config::Provider::combine(std::move(ProviderStack));
1016
1017 // Create an empty clang-tidy option.
1018 TidyProvider ClangTidyOptProvider;
1019 if (EnableClangTidy) {
1020 std::vector<TidyProvider> Providers;
1021 Providers.reserve(4 + EnableConfig);
1022 Providers.push_back(provideEnvironment());
1023 Providers.push_back(provideClangTidyFiles(TFS));
1024 if (EnableConfig)
1025 Providers.push_back(provideClangdConfig());
1026 Providers.push_back(provideDefaultChecks());
1027 Providers.push_back(disableUnusableChecks());
1028 ClangTidyOptProvider = combine(std::move(Providers));
1029 }
1030 Opts.UseDirtyHeaders = UseDirtyHeaders;
1031 Opts.PreambleParseForwardingFunctions = PreambleParseForwardingFunctions;
1032 Opts.SkipPreambleBuild = SkipPreambleBuild;
1033 Opts.ImportInsertions = ImportInsertions;
1034 Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
1035 Opts.TweakFilter = [&](const Tweak &T) {
1036 if (T.hidden() && !HiddenFeatures)
1037 return false;
1038 if (TweakList.getNumOccurrences())
1039 return llvm::is_contained(TweakList, T.id());
1040 return true;
1041 };
1042 if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
1043 Opts.Encoding = ForceOffsetEncoding;
1044
1046 if (EnableClangTidy)
1047 ModuleSet.add(std::make_unique<ClangTidyFeatureModule>(
1048 std::move(ClangTidyOptProvider)));
1049 if (ModuleSet.begin() != ModuleSet.end())
1050 Opts.FeatureModules = &ModuleSet;
1051
1052 if (CheckFile.getNumOccurrences()) {
1053 llvm::SmallString<256> Path;
1054 if (auto Error =
1055 llvm::sys::fs::real_path(CheckFile, Path, /*expand_tilde=*/true)) {
1056 elog("Failed to resolve path {0}: {1}", CheckFile, Error.message());
1057 return 1;
1058 }
1059 log("Entering check mode (no LSP server)");
1060 return check(Path, TFS, std::move(Opts))
1061 ? 0
1062 : static_cast<int>(ErrorResultCode::CheckFailed);
1063 }
1064
1065 // Initialize and run ClangdLSPServer.
1066 // Change stdin to binary to not lose \r\n on windows.
1067 llvm::sys::ChangeStdinToBinary();
1068 std::unique_ptr<Transport> TransportLayer;
1069 if (getenv("CLANGD_AS_XPC_SERVICE")) {
1070#if CLANGD_BUILD_XPC
1071 log("Starting LSP over XPC service");
1072 TransportLayer = newXPCTransport();
1073#else
1074 llvm::errs() << "This clangd binary wasn't built with XPC support.\n";
1075 return static_cast<int>(ErrorResultCode::CantRunAsXPCService);
1076#endif
1077 } else {
1078 log("Starting LSP over stdin/stdout");
1079 TransportLayer = newJSONTransport(
1080 stdin, llvm::outs(), InputMirrorStream ? &*InputMirrorStream : nullptr,
1081 PrettyPrint, InputStyle);
1082 }
1083 if (!PathMappingsArg.empty()) {
1084 auto Mappings = parsePathMappings(PathMappingsArg);
1085 if (!Mappings) {
1086 elog("Invalid -path-mappings: {0}", Mappings.takeError());
1087 return 1;
1088 }
1089 TransportLayer = createPathMappingTransport(std::move(TransportLayer),
1090 std::move(*Mappings));
1091 }
1092
1093 ClangdLSPServer LSPServer(*TransportLayer, TFS, std::move(Opts));
1094 llvm::set_thread_name("clangd.main");
1095 int ExitCode = LSPServer.run()
1096 ? 0
1097 : static_cast<int>(ErrorResultCode::NoShutdownRequest);
1098 log("LSP finished, exiting with status {0}", ExitCode);
1099
1100 // There may still be lingering background threads (e.g. slow requests
1101 // whose results will be dropped, background index shutting down).
1102 //
1103 // These should terminate quickly, and ~ClangdLSPServer blocks on them.
1104 // However if a bug causes them to run forever, we want to ensure the process
1105 // eventually exits. As clangd isn't directly user-facing, an editor can
1106 // "leak" clangd processes. Crashing in this case contains the damage.
1107 abortAfterTimeout(std::chrono::minutes(5));
1108
1109 return ExitCode;
1110}
1111
1112} // namespace clangd
1113} // namespace clang
static cl::opt< std::string > Config("config", desc(R"( Specifies a configuration in YAML/JSON format: -config="{Checks:' *', CheckOptions:{x: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))
static cl::desc desc(StringRef Description)
Include Cleaner is clangd functionality for providing diagnostics for misuse of transitive headers an...
Runs tasks on separate (detached) threads and wait for all tasks to finish.
Definition Threading.h:108
This class exposes ClangdServer's capabilities via Language Server Protocol.
bool run()
Run LSP server loop, communicating with the Transport provided in the constructor.
A FeatureModuleSet is a collection of feature modules installed in clangd.
static FeatureModuleSet fromRegistry()
void add(std::unique_ptr< FeatureModule > M)
Interface to allow custom logging in clangd.
Definition Logger.h:22
Only one LoggingSession can be active at a time.
Definition Logger.h:106
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:112
llvm::Expected< URI > uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override
Definition TestFS.cpp:125
static void runCrashHandlers()
Calls all currently-active ThreadCrashReporters for the current thread.
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
An interface base for small context-sensitive refactoring actions.
Definition Tweak.h:46
URIScheme is an extension point for teaching clangd to recognize a custom URI scheme.
Definition URI.h:108
A source of configuration fragments.
static const char *const EnableConfigFlagDesc
Help text for the –enable-config flag, shared by clangd tools that expose createDefaultProviders() on...
static std::vector< std::unique_ptr< Provider > > createDefaultProviders(const ThreadsafeFS &)
Returns providers for the configuration files that clangd tools read by default: project config (ance...
static std::unique_ptr< Provider > combine(std::vector< std::unique_ptr< Provider > >)
A provider that includes fragments from all the supplied providers.
std::function< bool(const Params &, Config &)> CompiledFragment
A chunk of configuration that has been fully analyzed and is ready to apply.
llvm::function_ref< void(const llvm::SMDiagnostic &)> DiagnosticCallback
Used to report problems in parsing or interpreting a config.
std::unique_ptr< clangd::SymbolIndex > getClient(llvm::StringRef Address, llvm::StringRef ProjectRoot)
Returns an SymbolIndex client that passes requests to remote index located at Address.
Definition Client.cpp:203
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:268
std::unique_ptr< EventTracer > createCSVMetricTracer(llvm::raw_ostream &OS)
Create an instance of EventTracer that outputs metric measurements as CSV.
Definition Trace.cpp:273
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
llvm::unique_function< void(tidy::ClangTidyOptions &, llvm::StringRef) const > TidyProvider
A factory to modify a tidy::ClangTidyOptions.
@ Error
An error message.
Definition Protocol.h:751
TidyProvider combine(std::vector< TidyProvider > Providers)
bool check(llvm::StringRef File, const ThreadsafeFS &TFS, ClangdLSPServer::Options &&Opts)
Definition Check.cpp:480
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
void vlog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:72
std::string platformString()
Definition Feature.cpp:20
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
Definition Logger.h:79
llvm::Expected< PathMappings > parsePathMappings(llvm::StringRef RawPathMappings)
Parse the command line RawPathMappings (e.g.
std::string featureString()
Definition Feature.cpp:33
static URISchemeRegistry::Add< TestScheme > X(TestScheme::Scheme, "Test schema")
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...
std::unique_ptr< Transport > newXPCTransport()
void log(const char *Fmt, Ts &&... Vals)
Definition Logger.h:67
TidyProvider provideClangTidyFiles(ThreadsafeFS &TFS)
Provider that searches for .clang-tidy configuration files in the directory tree.
void allowCrashPragmasForTest()
Respect #pragma clang __debug crash etc, which are usually disabled.
Definition Compiler.cpp:45
std::unique_ptr< SymbolIndex > createProjectAwareIndex(IndexFactory Gen, bool Sync)
Returns an index that answers queries using external indices.
int clangdMain(int argc, char *argv[])
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
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
TidyProvider disableUnusableChecks(llvm::ArrayRef< std::string > ExtraBadChecks)
Provider that will disable checks known to not work with clangd.
std::string Path
A typedef to represent a file path.
Definition Path.h:26
std::unique_ptr< Transport > newJSONTransport(std::FILE *In, llvm::raw_ostream &Out, llvm::raw_ostream *InMirror, bool Pretty, JSONStreamStyle Style)
TidyProvider provideDefaultChecks()
Provider that will enable a nice set of default checks if none are specified.
TidyProvider provideClangdConfig()
void abortAfterTimeout(std::chrono::seconds Timeout)
Causes this process to crash if still running after Timeout.
Definition Shutdown.cpp:18
void elog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:61
std::string versionString()
Definition Feature.cpp:18
std::unique_ptr< SymbolIndex > loadIndex(llvm::StringRef SymbolFilename, SymbolOrigin Origin, bool UseDex, bool SupportContainedRefs)
TidyProvider provideEnvironment()
Provider that just sets the defaults.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
bool EnableExperimentalModulesSupport
Flag to hint the experimental modules support is enabled.
size_t ReferencesLimit
Limit the number of references returned (0 means no limit).
bool UseDirBasedCDB
Look for compilation databases, rather than using compile commands set via LSP (extensions) only.
std::function< void()> MemoryCleanup
If set, periodically called to release memory.
std::unique_ptr< config::Provider > ConfigProvider
Supplies configuration (overrides ClangdServer::ContextProvider).
clangd::CodeCompleteOptions CodeComplete
Per-feature options.
std::function< bool(const Tweak &)> TweakFilter
Returns true if the tweak should be enabled.
std::optional< OffsetEncoding > Encoding
The offset-encoding to use, or std::nullopt to negotiate it over LSP.
bool BuildDynamicSymbolIndex
If true, ClangdServer builds a dynamic in-memory index for symbols in opened files and uses the index...
std::vector< std::string > QueryDriverGlobs
Clangd will execute compiler drivers matching one of these globs to fetch system include path.
bool UseDirtyHeaders
If true, use the dirty buffer contents when building Preambles.
bool StorePreamblesInMemory
Cached preambles are potentially large. If false, store them on disk.
SymbolIndex * StaticIndex
If set, use this index to augment code completion results.
llvm::ThreadPriority BackgroundIndexPriority
bool BackgroundIndex
If true, ClangdServer automatically indexes files in the current project on background threads.
unsigned AsyncThreadsCount
To process requests asynchronously, ClangdServer spawns worker threads.
SkipPreambleBuildPolicy SkipPreambleBuild
bool ImportInsertions
Whether include fixer insertions for Objective-C code should use import instead of include.
bool StrongWorkspaceMode
Sets an alternate mode of operation.
std::optional< std::string > ResourceDir
The resource directory is used to find internal headers, overriding defaults and -resource-dir compil...
bool EnableOutgoingCalls
Call hierarchy's outgoing calls feature requires additional index serving structures which increase m...
Describes an external index configuration.
Definition Config.h:79
@ Delimiters
empty pair of delimiters "()" or "<>".
Definition Config.h:147
@ FullPlaceholders
full name of both type and variable.
Definition Config.h:149
size_t LimitFiles
The maximum number of affected files (0 means no limit), only meaningful when AllowCrossFile = true.
Definition Rename.h:29
Represents measurements of clangd events, e.g.
Definition Trace.h:38
@ Value
A number whose value is meaningful, and may vary over time.
Definition Trace.h:42