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/PluginLoader.h"
42#include "llvm/Support/Process.h"
43#include "llvm/Support/Program.h"
44#include "llvm/Support/Signals.h"
45#include "llvm/Support/TargetSelect.h"
46#include "llvm/Support/raw_ostream.h"
75using llvm::cl::CommaSeparated;
77using llvm::cl::Hidden;
81using llvm::cl::OptionCategory;
82using llvm::cl::ValueOptional;
83using llvm::cl::values;
87OptionCategory CompileCommands(
"clangd compilation flags options");
88OptionCategory Features(
"clangd feature options");
89OptionCategory Misc(
"clangd miscellaneous options");
90OptionCategory Protocol(
"clangd protocol and logging options");
91OptionCategory Retired(
"clangd flags no longer in use");
92const OptionCategory *ClangdCategories[] = {&Features, &Protocol,
93 &CompileCommands, &Misc, &Retired};
95std::vector<const llvm::cl::Option *> RetiredOptions;
97template <
typename T>
class RetiredFlag {
101 RetiredFlag(llvm::StringRef Name)
102 : Option(Name, cat(Retired),
desc(
"Obsolete flag, ignored"), Hidden) {
103 RetiredOptions.push_back(&Option);
107enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs };
108opt<CompileArgsFrom> CompileArgsFrom{
110 cat(CompileCommands),
111 desc(
"The source of compile commands"),
112 values(clEnumValN(LSPCompileArgs,
"lsp",
113 "All compile commands come from LSP and "
114 "'compile_commands.json' files are ignored"),
115 clEnumValN(FilesystemCompileArgs,
"filesystem",
116 "All compile commands come from the "
117 "'compile_commands.json' files")),
118 init(FilesystemCompileArgs),
122opt<Path> CompileCommandsDir{
123 "compile-commands-dir",
124 cat(CompileCommands),
125 desc(
"Specify a path to look for compile_commands.json. If path "
126 "is invalid, clangd will look in the current directory and "
127 "parent paths of each source file"),
130opt<Path> ResourceDir{
132 cat(CompileCommands),
133 desc(
"Directory for system clang headers"),
138list<std::string> QueryDriverGlobs{
140 cat(CompileCommands),
142 "Comma separated list of globs for white-listing gcc-compatible "
143 "drivers that are safe to execute. Drivers matching any of these globs "
144 "will be used to extract system includes. e.g. "
145 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
151opt<bool> AllScopesCompletion{
152 "all-scopes-completion",
154 desc(
"If set to true, code completion will include index symbols that are "
155 "not defined in the scopes (e.g. "
156 "namespaces) visible from the code completion point. Such completions "
157 "can insert scope qualifiers"),
161opt<bool> ShowOrigins{
164 desc(
"Show origins of completion items"),
169opt<bool> EnableBackgroundIndex{
172 desc(
"Index project code in the background and persist index on disk."),
176opt<llvm::ThreadPriority> BackgroundIndexPriority{
177 "background-index-priority",
179 desc(
"Thread priority for building the background index. "
180 "The effect of this flag is OS-specific."),
181 values(clEnumValN(llvm::ThreadPriority::Background,
"background",
182 "Minimum priority, runs on idle CPUs. "
183 "May leave 'performance' cores unused."),
184 clEnumValN(llvm::ThreadPriority::Low,
"low",
185 "Reduced priority compared to interactive work."),
186 clEnumValN(llvm::ThreadPriority::Default,
"normal",
187 "Same priority as other clangd work.")),
188 init(llvm::ThreadPriority::Low),
191opt<bool> EnableClangTidy{
194 desc(
"Enable clang-tidy diagnostics"),
198opt<CodeCompleteOptions::CodeCompletionParse> CodeCompletionParse{
201 desc(
"Whether the clang-parser is used for code-completion"),
202 values(clEnumValN(CodeCompleteOptions::AlwaysParse,
"always",
203 "Block until the parser can be used"),
204 clEnumValN(CodeCompleteOptions::ParseIfReady,
"auto",
205 "Use text-based completion if the parser "
207 clEnumValN(CodeCompleteOptions::NeverParse,
"never",
208 "Always used text-based completion")),
213opt<CodeCompleteOptions::CodeCompletionRankingModel> RankingModel{
216 desc(
"Model to use to rank code-completion items"),
217 values(clEnumValN(CodeCompleteOptions::Heuristics,
"heuristics",
218 "Use heuristics to rank code completion items"),
219 clEnumValN(CodeCompleteOptions::DecisionForest,
"decision_forest",
220 "Use Decision Forest model to rank completion items")),
226enum CompletionStyleFlag { Detailed, Bundled };
227opt<CompletionStyleFlag> CompletionStyle{
230 desc(
"Granularity of code completion suggestions"),
231 values(clEnumValN(Detailed,
"detailed",
232 "One completion item for each semantically distinct "
233 "completion, with full type information"),
234 clEnumValN(Bundled,
"bundled",
235 "Similar completion items (e.g. function overloads) are "
236 "combined. Type information shown where possible")),
239opt<std::string> FallbackStyle{
242 desc(
"clang-format style to apply by default when "
243 "no .clang-format file is found"),
244 init(clang::format::DefaultFallbackStyle),
247opt<std::string> EnableFunctionArgSnippets{
248 "function-arg-placeholders",
250 desc(
"When disabled (0), completions contain only parentheses for "
251 "function calls. When enabled (1), completions also contain "
252 "placeholders for method parameters"),
256opt<Config::HeaderInsertionPolicy> HeaderInsertion{
259 desc(
"Add #include directives when accepting code completions"),
263 "Include what you use. "
264 "Insert the owning header for top-level symbols, unless the "
265 "header is already directly included or the symbol is "
269 "Never insert #include directives as part of code completion")),
272opt<bool> ImportInsertions{
275 desc(
"If header insertion is enabled, add #import directives when "
276 "accepting code completions or fixing includes in Objective-C code"),
280opt<bool> HeaderInsertionDecorators{
281 "header-insertion-decorators",
283 desc(
"Prepend a circular dot or space before the completion "
284 "label, depending on whether "
285 "an include line will be inserted or not"),
289opt<bool> HiddenFeatures{
292 desc(
"Enable hidden features mostly useful to clangd developers"),
297opt<bool> IncludeIneligibleResults{
298 "include-ineligible-results",
300 desc(
"Include ineligible completion results (e.g. private members)"),
305RetiredFlag<bool> EnableIndex(
"index");
306RetiredFlag<bool> SuggestMissingIncludes(
"suggest-missing-includes");
307RetiredFlag<bool> RecoveryAST(
"recovery-ast");
308RetiredFlag<bool> RecoveryASTType(
"recovery-ast-type");
309RetiredFlag<bool> AsyncPreamble(
"async-preamble");
310RetiredFlag<bool> CollectMainFileRefs(
"collect-main-file-refs");
311RetiredFlag<bool> CrossFileRename(
"cross-file-rename");
312RetiredFlag<std::string> ClangTidyChecks(
"clang-tidy-checks");
313RetiredFlag<bool> InlayHints(
"inlay-hints");
314RetiredFlag<bool> FoldingRanges(
"folding-ranges");
315RetiredFlag<bool> IncludeCleanerStdlib(
"include-cleaner-stdlib");
317opt<int> LimitResults{
320 desc(
"Limit the number of results returned by clangd. "
321 "0 means no limit (default=100)"),
325opt<int> ReferencesLimit{
328 desc(
"Limit the number of references returned by clangd. "
329 "0 means no limit (default=1000)"),
333opt<int> RenameFileLimit{
336 desc(
"Limit the number of files to be affected by symbol renaming. "
337 "0 means no limit (default=50)"),
341list<std::string> TweakList{
344 desc(
"Specify a list of Tweaks to enable (only for clangd developers)."),
349opt<unsigned> WorkerThreadsCount{
352 desc(
"Number of async workers used by clangd. Background index also "
353 "uses this many workers."),
361 "Index file to build the static index. The file must have been created "
362 "by a compatible clangd-indexer\n"
363 "WARNING: This option is experimental only, and will be removed "
364 "eventually. Don't rely on it"),
372 desc(
"Abbreviation for -input-style=delimited -pretty -sync "
373 "-enable-test-scheme -enable-config=0 -log=verbose -crash-pragmas. "
374 "Also sets config options: Index.StandardLibrary=false. "
375 "Intended to simplify lit tests"),
380opt<bool> CrashPragmas{
383 desc(
"Respect `#pragma clang __debug crash` and friends."),
391 desc(
"Parse one file in isolation instead of acting as a language server. "
392 "Useful to investigate/reproduce crashes or configuration problems. "
393 "With --check=<filename>, attempts to parse a particular file."),
398enum PCHStorageFlag { Disk, Memory };
399opt<PCHStorageFlag> PCHStorage{
402 desc(
"Storing PCHs in memory increases memory usages, but may "
403 "improve performance"),
405 clEnumValN(PCHStorageFlag::Disk,
"disk",
"store PCHs on disk"),
406 clEnumValN(PCHStorageFlag::Memory,
"memory",
"store PCHs in memory")),
407 init(PCHStorageFlag::Disk),
413 desc(
"Handle client requests on main thread. Background index still uses "
419opt<JSONStreamStyle> InputStyle{
422 desc(
"Input JSON stream encoding"),
426 "messages delimited by --- lines, with # comment support")),
431opt<bool> EnableTestScheme{
432 "enable-test-uri-scheme",
434 desc(
"Enable 'test:' URI scheme. Only use in lit tests"),
439opt<std::string> PathMappingsArg{
443 "Translates between client paths (as seen by a remote editor) and "
444 "server paths (where clangd sees files on disk). "
445 "Comma separated list of '<client_path>=<server_path>' pairs, the "
446 "first entry matching a given path is used. "
447 "e.g. /home/project/incl=/opt/include,/home/project=/workarea/project"),
451opt<Path> InputMirrorFile{
454 desc(
"Mirror all LSP input to the specified file. Useful for debugging"),
459opt<Logger::Level> LogLevel{
462 desc(
"Verbosity of log messages written to stderr"),
463 values(clEnumValN(
Logger::Error,
"error",
"Error messages only"),
464 clEnumValN(
Logger::Info,
"info",
"High level execution tracing"),
469opt<OffsetEncoding> ForceOffsetEncoding{
472 desc(
"Force the offsetEncoding used for character positions. "
473 "This bypasses negotiation via client capabilities"),
477 "Offsets are in UTF-16 code units"),
479 "Offsets are in unicode codepoints")),
483opt<bool> PrettyPrint{
486 desc(
"Pretty-print JSON output"),
490opt<bool> EnableConfig{
497opt<bool> StrongWorkspaceMode{
498 "strong-workspace-mode",
500 desc(
"An alternate mode of operation for clangd, where the clangd instance "
501 "is used to edit a single workspace.\n"
502 "When enabled, fallback commands use the workspace directory as their "
503 "working directory instead of the parent folder."),
508opt<bool> UseDirtyHeaders{
"use-dirty-headers", cat(Misc),
509 desc(
"Use files open in the editor when parsing "
510 "headers instead of reading from the disk"),
514opt<bool> PreambleParseForwardingFunctions{
515 "parse-forwarding-functions",
517 desc(
"Parse all emplace-like functions in included headers"),
522opt<bool> SkipPreambleBuild{
523 "skip-preamble-build",
525 desc(
"If ture, skip preamble build"),
530#if defined(__GLIBC__) && CLANGD_MALLOC_TRIM
531opt<bool> EnableMallocTrim{
534 desc(
"Release memory periodically via malloc_trim(3)."),
538std::function<void()> getMemoryCleanupFunction() {
539 if (!EnableMallocTrim)
543 constexpr size_t MallocTrimPad = 20'000'000;
545 if (malloc_trim(MallocTrimPad))
546 vlog(
"Released memory via malloc_trim");
550std::function<void()> getMemoryCleanupFunction() {
return nullptr; }
553#if CLANGD_ENABLE_REMOTE
554opt<std::string> RemoteIndexAddress{
555 "remote-index-address",
557 desc(
"Address of the remote index server"),
561opt<std::string> ProjectRoot{
564 desc(
"Path to the project root. Requires remote-index-address to be set."),
568opt<bool> ExperimentalModulesSupport{
569 "experimental-modules-support",
571 desc(
"Experimental support for standard c++ modules"),
581 llvm::Expected<std::string>
583 llvm::StringRef )
const override {
584 using namespace llvm::sys;
587 if (!Body.starts_with(
"/"))
589 "Expect URI body to be an absolute path starting with '/': {0}",
591 Body = Body.ltrim(
'/');
592 llvm::SmallString<16>
Path(Body);
594 path::make_absolute(testDir(),
Path);
595 return std::string(
Path);
600 llvm::StringRef Body = AbsolutePath;
601 if (!Body.consume_front(testDir()))
602 return error(
"Path {0} doesn't start with root {1}", AbsolutePath,
605 return URI(
"test",
"",
606 llvm::sys::path::convert_to_slash(Body));
610 static llvm::StringRef testDir() {
612 static const std::string TestDir = llvm::sys::path::native(
"C:/clangd-test");
615 return "/clangd-test";
620std::unique_ptr<SymbolIndex>
623 static const trace::Metric RemoteIndexUsed(
"used_remote_index",
625 switch (External.Kind) {
629 RemoteIndexUsed.record(1, External.Location);
630 log(
"Associating {0} with remote index at {1}.", External.MountPoint,
634 log(
"Associating {0} with monolithic index at {1}.", External.MountPoint,
636 auto NewIndex = std::make_unique<SwapIndex>(std::make_unique<MemIndex>());
637 auto IndexLoadTask = [
File = External.Location,
638 PlaceHolder = NewIndex.get(), SupportContainedRefs] {
640 SupportContainedRefs))
641 PlaceHolder->reset(std::move(Idx));
644 Tasks->runAsync(
"Load-index:" + External.Location,
645 std::move(IndexLoadTask));
649 return std::move(NewIndex);
651 llvm_unreachable(
"Invalid ExternalIndexKind.");
654std::optional<bool> shouldEnableFunctionArgSnippets() {
655 std::string Val = EnableFunctionArgSnippets;
659 if (Val ==
"1" || Val ==
"true" || Val ==
"True" || Val ==
"TRUE")
661 if (Val ==
"0" || Val ==
"false" || Val ==
"False" || Val ==
"FALSE")
664 elog(
"Value specified by --function-arg-placeholders is invalid. Provide a "
665 "boolean value or leave unspecified to use ArgumentListsPolicy from "
674 std::vector<config::CompiledFragment>
675 getFragments(
const config::Params &,
681 FlagsConfigProvider() {
682 std::optional<Config::CDBSearchSpec> CDBSearch;
683 std::optional<Config::ExternalIndexSpec> IndexSpec;
684 std::optional<Config::BackgroundPolicy> BGPolicy;
685 std::optional<Config::ArgumentListsPolicy> ArgumentLists;
689 if (!CompileCommandsDir.empty()) {
690 if (llvm::sys::fs::exists(CompileCommandsDir)) {
695 llvm::SmallString<128>
Path(CompileCommandsDir);
696 if (std::error_code EC = llvm::sys::fs::make_absolute(
Path)) {
697 elog(
"Error while converting the relative path specified by "
698 "--compile-commands-dir to an absolute path: {0}. The argument "
705 elog(
"Path specified by --compile-commands-dir does not exist. The "
706 "argument will be ignored.");
709 if (!IndexFile.empty()) {
710 Config::ExternalIndexSpec Spec;
711 Spec.Kind = Spec.File;
712 Spec.Location = IndexFile;
713 IndexSpec = std::move(Spec);
715#if CLANGD_ENABLE_REMOTE
716 if (!RemoteIndexAddress.empty()) {
717 assert(!ProjectRoot.empty() && IndexFile.empty());
718 Config::ExternalIndexSpec Spec;
719 Spec.Kind = Spec.Server;
720 Spec.Location = RemoteIndexAddress;
721 Spec.MountPoint = ProjectRoot;
722 IndexSpec = std::move(Spec);
726 if (!EnableBackgroundIndex) {
730 if (std::optional<bool> Enable = shouldEnableFunctionArgSnippets()) {
735 Frag = [=](
const config::Params &,
Config &
C) {
737 C.CompileFlags.CDBSearch = *CDBSearch;
739 C.Index.External = *IndexSpec;
741 C.Index.Background = *BGPolicy;
743 C.Completion.ArgumentLists = *ArgumentLists;
744 if (HeaderInsertion.getNumOccurrences())
745 C.Completion.HeaderInsertion = HeaderInsertion;
746 if (AllScopesCompletion.getNumOccurrences())
747 C.Completion.AllScopes = AllScopesCompletion;
750 C.Index.StandardLibrary =
false;
766 clang::noteBottomOfStack();
767 llvm::InitLLVM
X(argc, argv);
768 llvm::InitializeAllTargetInfos();
769 llvm::sys::AddSignalHandler(
773 llvm::errs().flush();
777 llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
782 const char *FlagsEnvVar =
"CLANGD_FLAGS";
783 const char *Overview =
784 R
"(clangd is a language server that provides IDE-like features to editors.
786It should be used via an editor plugin rather than invoked directly. For more information, see:
787 https://clangd.llvm.org/
788 https://microsoft.github.io/language-server-protocol/
790clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.
793 if (llvm::cl::Option *LoadOpt =
794 llvm::cl::getRegisteredOptions().
lookup(
"load"))
795 LoadOpt->addCategory(Features);
797 llvm::cl::HideUnrelatedOptions(ClangdCategories);
798 llvm::cl::ParseCommandLineOptions(argc, argv, Overview,
nullptr,
799 nullptr, FlagsEnvVar);
800 for (
const llvm::cl::Option *O : RetiredOptions)
801 if (O->getNumOccurrences())
802 llvm::errs() <<
"The flag `-" << O->ArgStr
803 <<
"` is obsolete and ignored.\n";
805 if (!Sync.getNumOccurrences())
807 if (!CrashPragmas.getNumOccurrences())
813 if (!EnableConfig.getNumOccurrences())
814 EnableConfig =
false;
816 if (!EnableBackgroundIndex.getNumOccurrences())
817 EnableBackgroundIndex =
false;
819 else if (EnableBackgroundIndex)
822 if (Test || EnableTestScheme) {
823 static URISchemeRegistry::Add<TestScheme>
X(
824 "test",
"Test scheme for clangd lit tests.");
829 if (!Sync && WorkerThreadsCount == 0) {
830 llvm::errs() <<
"A number of worker threads cannot be 0. Did you mean to "
836 if (WorkerThreadsCount.getNumOccurrences())
837 llvm::errs() <<
"Ignoring -j because -sync is set.\n";
838 WorkerThreadsCount = 0;
840 if (FallbackStyle.getNumOccurrences())
841 clang::format::DefaultFallbackStyle = FallbackStyle.c_str();
844 std::optional<llvm::raw_fd_ostream> InputMirrorStream;
845 if (!InputMirrorFile.empty()) {
847 InputMirrorStream.emplace(InputMirrorFile, EC,
848 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
850 InputMirrorStream.reset();
851 llvm::errs() <<
"Error while opening an input mirror file: "
854 InputMirrorStream->SetUnbuffered();
858#if !CLANGD_DECISION_FOREST
859 if (RankingModel == clangd::CodeCompleteOptions::DecisionForest) {
860 llvm::errs() <<
"Clangd was compiled without decision forest support.\n";
868 std::optional<llvm::raw_fd_ostream> TracerStream;
869 std::unique_ptr<trace::EventTracer> Tracer;
870 const char *JSONTraceFile = getenv(
"CLANGD_TRACE");
871 const char *MetricsCSVFile = getenv(
"CLANGD_METRICS");
872 const char *TracerFile = JSONTraceFile ? JSONTraceFile : MetricsCSVFile;
875 TracerStream.emplace(TracerFile, EC,
876 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
878 TracerStream.reset();
879 llvm::errs() <<
"Error while opening trace file " << TracerFile <<
": "
882 Tracer = (TracerFile == JSONTraceFile)
888 std::optional<trace::Session> TracingSession;
890 TracingSession.emplace(*Tracer);
895 if (llvm::outs().is_displayed() && llvm::errs().is_displayed() &&
896 !CheckFile.getNumOccurrences())
897 llvm::errs() << Overview <<
"\n";
900 llvm::errs().SetBuffered();
906 log(
"PID: {0}", llvm::sys::Process::getProcessId());
908 SmallString<128> CWD;
909 if (
auto Err = llvm::sys::fs::current_path(CWD))
910 log(
"Working directory unknown: {0}", Err.message());
912 log(
"Working directory: {0}", CWD);
914 for (
int I = 0; I < argc; ++I)
915 log(
"argv[{0}]: {1}", I, argv[I]);
916 for (
unsigned I = 0, E = llvm::PluginLoader::getNumPlugins(); I < E; ++I)
917 log(
"Loaded plugin: {0}", llvm::PluginLoader::getPlugin(I));
918 if (
auto EnvFlags = llvm::sys::Process::GetEnv(FlagsEnvVar))
919 log(
"{0}: {1}", FlagsEnvVar, *EnvFlags);
922 for (
const char *EnvVar : {
932 "CPLUS_INCLUDE_PATH",
937 if (
auto Val = llvm::sys::Process::GetEnv(EnvVar))
938 log(
"Env {0}: {1}", EnvVar, *Val);
946 switch (PCHStorage) {
947 case PCHStorageFlag::Memory:
950 case PCHStorageFlag::Disk:
954 if (!ResourceDir.empty())
958#if CLANGD_ENABLE_REMOTE
959 if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {
960 llvm::errs() <<
"remote-index-address and project-path have to be "
961 "specified at the same time.";
964 if (!RemoteIndexAddress.empty()) {
965 if (IndexFile.empty()) {
966 log(
"Connecting to remote index at {0}", RemoteIndexAddress);
968 elog(
"When enabling remote index, IndexFile should not be specified. "
969 "Only one can be used at time. Remote index will ignored.");
980 return loadExternalIndex(External, Tasks, SupportContainedRefs);
987 Opts.
CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
989 if (CompletionStyle.getNumOccurrences())
990 Opts.
CodeComplete.BundleOverloads = CompletionStyle != Detailed;
994 if (!HeaderInsertionDecorators) {
1002 Opts.
CodeComplete.ForceLoadPreamble = ExperimentalModulesSupport;
1004 std::vector<std::unique_ptr<config::Provider>> ProviderStack;
1007 ProviderStack.push_back(std::make_unique<FlagsConfigProvider>());
1012 if (EnableClangTidy) {
1013 std::vector<TidyProvider> Providers;
1014 Providers.reserve(4 + EnableConfig);
1021 ClangTidyOptProvider =
combine(std::move(Providers));
1030 if (T.hidden() && !HiddenFeatures)
1032 if (TweakList.getNumOccurrences())
1033 return llvm::is_contained(TweakList, T.id());
1037 Opts.
Encoding = ForceOffsetEncoding;
1040 if (ModuleSet.
begin() != ModuleSet.
end())
1043 if (CheckFile.getNumOccurrences()) {
1044 llvm::SmallString<256>
Path;
1046 llvm::sys::fs::real_path(CheckFile,
Path,
true)) {
1047 elog(
"Failed to resolve path {0}: {1}", CheckFile,
Error.message());
1050 log(
"Entering check mode (no LSP server)");
1051 return check(
Path, TFS, std::move(Opts))
1058 llvm::sys::ChangeStdinToBinary();
1059 std::unique_ptr<Transport> TransportLayer;
1060 if (getenv(
"CLANGD_AS_XPC_SERVICE")) {
1062 log(
"Starting LSP over XPC service");
1065 llvm::errs() <<
"This clangd binary wasn't built with XPC support.\n";
1069 log(
"Starting LSP over stdin/stdout");
1071 stdin, llvm::outs(), InputMirrorStream ? &*InputMirrorStream :
nullptr,
1072 PrettyPrint, InputStyle);
1074 if (!PathMappingsArg.empty()) {
1077 elog(
"Invalid -path-mappings: {0}", Mappings.takeError());
1081 std::move(*Mappings));
1085 llvm::set_thread_name(
"clangd.main");
1086 int ExitCode = LSPServer.
run()
1089 log(
"LSP finished, exiting with status {0}", ExitCode);
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.
static void preventThreadStarvationInTests()
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.
Only one LoggingSession can be active at a time.
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.
llvm::Expected< URI > uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override
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.
URIScheme is an extension point for teaching clangd to recognize a custom URI scheme.
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.
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...
std::unique_ptr< EventTracer > createCSVMetricTracer(llvm::raw_ostream &OS)
Create an instance of EventTracer that outputs metric measurements as CSV.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
llvm::unique_function< void(tidy::ClangTidyOptions &, llvm::StringRef) const > TidyProvider
A factory to modify a tidy::ClangTidyOptions.
TidyProvider combine(std::vector< TidyProvider > Providers)
bool check(llvm::StringRef File, const ThreadsafeFS &TFS, ClangdLSPServer::Options &&Opts)
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
void vlog(const char *Fmt, Ts &&... Vals)
std::string platformString()
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
llvm::Expected< PathMappings > parsePathMappings(llvm::StringRef RawPathMappings)
Parse the command line RawPathMappings (e.g.
std::string featureString()
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)
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.
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...
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.
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.
void elog(const char *Fmt, Ts &&... Vals)
std::string versionString()
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.
clangd::RenameOptions Rename
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.
TidyProviderRef ClangTidyProvider
The Options provider to use when running clang-tidy.
bool PreambleParseForwardingFunctions
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...
FeatureModuleSet * FeatureModules
bool EnableOutgoingCalls
Call hierarchy's outgoing calls feature requires additional index serving structures which increase m...
Describes an external index configuration.
@ Delimiters
empty pair of delimiters "()" or "<>".
@ FullPlaceholders
full name of both type and variable.
size_t LimitFiles
The maximum number of affected files (0 means no limit), only meaningful when AllowCrossFile = true.
Represents measurements of clangd events, e.g.
@ Value
A number whose value is meaningful, and may vary over time.