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