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"
74using llvm::cl::CommaSeparated;
76using llvm::cl::Hidden;
80using llvm::cl::OptionCategory;
81using llvm::cl::ValueOptional;
82using llvm::cl::values;
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};
94template <
typename T>
class RetiredFlag {
98 RetiredFlag(llvm::StringRef Name)
99 : Option(Name, cat(Retired),
desc(
"Obsolete flag, ignored"), Hidden,
100 llvm::cl::callback([Name](const
T &) {
102 <<
"The flag `-" << Name <<
"` is obsolete and ignored.\n";
106enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs };
107opt<CompileArgsFrom> CompileArgsFrom{
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),
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"),
129opt<Path> ResourceDir{
131 cat(CompileCommands),
132 desc(
"Directory for system clang headers"),
137list<std::string> QueryDriverGlobs{
139 cat(CompileCommands),
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++-*"),
150opt<bool> AllScopesCompletion{
151 "all-scopes-completion",
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"),
160opt<bool> ShowOrigins{
163 desc(
"Show origins of completion items"),
168opt<bool> EnableBackgroundIndex{
171 desc(
"Index project code in the background and persist index on disk."),
175opt<llvm::ThreadPriority> BackgroundIndexPriority{
176 "background-index-priority",
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),
190opt<bool> EnableClangTidy{
193 desc(
"Enable clang-tidy diagnostics"),
197opt<CodeCompleteOptions::CodeCompletionParse> CodeCompletionParse{
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 "
206 clEnumValN(CodeCompleteOptions::NeverParse,
"never",
207 "Always used text-based completion")),
212opt<CodeCompleteOptions::CodeCompletionRankingModel> RankingModel{
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")),
225enum CompletionStyleFlag { Detailed, Bundled };
226opt<CompletionStyleFlag> CompletionStyle{
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")),
238opt<std::string> FallbackStyle{
241 desc(
"clang-format style to apply by default when "
242 "no .clang-format file is found"),
243 init(clang::format::DefaultFallbackStyle),
246opt<std::string> EnableFunctionArgSnippets{
247 "function-arg-placeholders",
249 desc(
"When disabled (0), completions contain only parentheses for "
250 "function calls. When enabled (1), completions also contain "
251 "placeholders for method parameters"),
255opt<Config::HeaderInsertionPolicy> HeaderInsertion{
258 desc(
"Add #include directives when accepting code completions"),
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 "
268 "Never insert #include directives as part of code completion")),
271opt<bool> ImportInsertions{
274 desc(
"If header insertion is enabled, add #import directives when "
275 "accepting code completions or fixing includes in Objective-C code"),
279opt<bool> HeaderInsertionDecorators{
280 "header-insertion-decorators",
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"),
288opt<bool> HiddenFeatures{
291 desc(
"Enable hidden features mostly useful to clangd developers"),
296opt<bool> IncludeIneligibleResults{
297 "include-ineligible-results",
299 desc(
"Include ineligible completion results (e.g. private members)"),
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");
316opt<int> LimitResults{
319 desc(
"Limit the number of results returned by clangd. "
320 "0 means no limit (default=100)"),
324opt<int> ReferencesLimit{
327 desc(
"Limit the number of references returned by clangd. "
328 "0 means no limit (default=1000)"),
332opt<int> RenameFileLimit{
335 desc(
"Limit the number of files to be affected by symbol renaming. "
336 "0 means no limit (default=50)"),
340list<std::string> TweakList{
343 desc(
"Specify a list of Tweaks to enable (only for clangd developers)."),
348opt<unsigned> WorkerThreadsCount{
351 desc(
"Number of async workers used by clangd. Background index also "
352 "uses this many workers."),
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"),
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"),
379opt<bool> CrashPragmas{
382 desc(
"Respect `#pragma clang __debug crash` and friends."),
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."),
397enum PCHStorageFlag { Disk, Memory };
398opt<PCHStorageFlag> PCHStorage{
401 desc(
"Storing PCHs in memory increases memory usages, but may "
402 "improve performance"),
404 clEnumValN(PCHStorageFlag::Disk,
"disk",
"store PCHs on disk"),
405 clEnumValN(PCHStorageFlag::Memory,
"memory",
"store PCHs in memory")),
406 init(PCHStorageFlag::Disk),
412 desc(
"Handle client requests on main thread. Background index still uses "
418opt<JSONStreamStyle> InputStyle{
421 desc(
"Input JSON stream encoding"),
425 "messages delimited by --- lines, with # comment support")),
430opt<bool> EnableTestScheme{
431 "enable-test-uri-scheme",
433 desc(
"Enable 'test:' URI scheme. Only use in lit tests"),
438opt<std::string> PathMappingsArg{
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"),
450opt<Path> InputMirrorFile{
453 desc(
"Mirror all LSP input to the specified file. Useful for debugging"),
458opt<Logger::Level> LogLevel{
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"),
468opt<OffsetEncoding> ForceOffsetEncoding{
471 desc(
"Force the offsetEncoding used for character positions. "
472 "This bypasses negotiation via client capabilities"),
476 "Offsets are in UTF-16 code units"),
478 "Offsets are in unicode codepoints")),
482opt<bool> PrettyPrint{
485 desc(
"Pretty-print JSON output"),
489opt<bool> EnableConfig{
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"),
503opt<bool> StrongWorkspaceMode{
504 "strong-workspace-mode",
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."),
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"),
520opt<bool> PreambleParseForwardingFunctions{
521 "parse-forwarding-functions",
523 desc(
"Parse all emplace-like functions in included headers"),
528opt<bool> SkipPreambleBuild{
529 "skip-preamble-build",
531 desc(
"If ture, skip preamble build"),
536#if defined(__GLIBC__) && CLANGD_MALLOC_TRIM
537opt<bool> EnableMallocTrim{
540 desc(
"Release memory periodically via malloc_trim(3)."),
544std::function<void()> getMemoryCleanupFunction() {
545 if (!EnableMallocTrim)
549 constexpr size_t MallocTrimPad = 20'000'000;
551 if (malloc_trim(MallocTrimPad))
552 vlog(
"Released memory via malloc_trim");
556std::function<void()> getMemoryCleanupFunction() {
return nullptr; }
559#if CLANGD_ENABLE_REMOTE
560opt<std::string> RemoteIndexAddress{
561 "remote-index-address",
563 desc(
"Address of the remote index server"),
567opt<std::string> ProjectRoot{
570 desc(
"Path to the project root. Requires remote-index-address to be set."),
574opt<bool> ExperimentalModulesSupport{
575 "experimental-modules-support",
577 desc(
"Experimental support for standard c++ modules"),
587 llvm::Expected<std::string>
589 llvm::StringRef )
const override {
590 using namespace llvm::sys;
593 if (!Body.starts_with(
"/"))
595 "Expect URI body to be an absolute path starting with '/': {0}",
597 Body = Body.ltrim(
'/');
598 llvm::SmallString<16>
Path(Body);
600 path::make_absolute(testDir(),
Path);
601 return std::string(
Path);
606 llvm::StringRef Body = AbsolutePath;
607 if (!Body.consume_front(testDir()))
608 return error(
"Path {0} doesn't start with root {1}", AbsolutePath,
611 return URI(
"test",
"",
612 llvm::sys::path::convert_to_slash(Body));
616 static llvm::StringRef testDir() {
618 static const std::string TestDir = llvm::sys::path::native(
"C:/clangd-test");
621 return "/clangd-test";
626std::unique_ptr<SymbolIndex>
629 static const trace::Metric RemoteIndexUsed(
"used_remote_index",
631 switch (External.Kind) {
635 RemoteIndexUsed.record(1, External.Location);
636 log(
"Associating {0} with remote index at {1}.", External.MountPoint,
640 log(
"Associating {0} with monolithic index at {1}.", External.MountPoint,
642 auto NewIndex = std::make_unique<SwapIndex>(std::make_unique<MemIndex>());
643 auto IndexLoadTask = [
File = External.Location,
644 PlaceHolder = NewIndex.get(), SupportContainedRefs] {
646 SupportContainedRefs))
647 PlaceHolder->reset(std::move(Idx));
650 Tasks->runAsync(
"Load-index:" + External.Location,
651 std::move(IndexLoadTask));
655 return std::move(NewIndex);
657 llvm_unreachable(
"Invalid ExternalIndexKind.");
660std::optional<bool> shouldEnableFunctionArgSnippets() {
661 std::string Val = EnableFunctionArgSnippets;
665 if (Val ==
"1" || Val ==
"true" || Val ==
"True" || Val ==
"TRUE")
667 if (Val ==
"0" || Val ==
"false" || Val ==
"False" || Val ==
"FALSE")
670 elog(
"Value specified by --function-arg-placeholders is invalid. Provide a "
671 "boolean value or leave unspecified to use ArgumentListsPolicy from "
680 std::vector<config::CompiledFragment>
681 getFragments(
const config::Params &,
687 FlagsConfigProvider() {
688 std::optional<Config::CDBSearchSpec> CDBSearch;
689 std::optional<Config::ExternalIndexSpec> IndexSpec;
690 std::optional<Config::BackgroundPolicy> BGPolicy;
691 std::optional<Config::ArgumentListsPolicy> ArgumentLists;
695 if (!CompileCommandsDir.empty()) {
696 if (llvm::sys::fs::exists(CompileCommandsDir)) {
701 llvm::SmallString<128>
Path(CompileCommandsDir);
702 if (std::error_code EC = llvm::sys::fs::make_absolute(
Path)) {
703 elog(
"Error while converting the relative path specified by "
704 "--compile-commands-dir to an absolute path: {0}. The argument "
711 elog(
"Path specified by --compile-commands-dir does not exist. The "
712 "argument will be ignored.");
715 if (!IndexFile.empty()) {
716 Config::ExternalIndexSpec Spec;
717 Spec.Kind = Spec.File;
718 Spec.Location = IndexFile;
719 IndexSpec = std::move(Spec);
721#if CLANGD_ENABLE_REMOTE
722 if (!RemoteIndexAddress.empty()) {
723 assert(!ProjectRoot.empty() && IndexFile.empty());
724 Config::ExternalIndexSpec Spec;
725 Spec.Kind = Spec.Server;
726 Spec.Location = RemoteIndexAddress;
727 Spec.MountPoint = ProjectRoot;
728 IndexSpec = std::move(Spec);
732 if (!EnableBackgroundIndex) {
736 if (std::optional<bool> Enable = shouldEnableFunctionArgSnippets()) {
741 Frag = [=](
const config::Params &,
Config &
C) {
743 C.CompileFlags.CDBSearch = *CDBSearch;
745 C.Index.External = *IndexSpec;
747 C.Index.Background = *BGPolicy;
749 C.Completion.ArgumentLists = *ArgumentLists;
750 if (HeaderInsertion.getNumOccurrences())
751 C.Completion.HeaderInsertion = HeaderInsertion;
752 if (AllScopesCompletion.getNumOccurrences())
753 C.Completion.AllScopes = AllScopesCompletion;
756 C.Index.StandardLibrary =
false;
772 clang::noteBottomOfStack();
773 llvm::InitLLVM
X(argc, argv);
774 llvm::InitializeAllTargetInfos();
775 llvm::sys::AddSignalHandler(
779 llvm::errs().flush();
783 llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
788 const char *FlagsEnvVar =
"CLANGD_FLAGS";
789 const char *Overview =
790 R
"(clangd is a language server that provides IDE-like features to editors.
792It should be used via an editor plugin rather than invoked directly. For more information, see:
793 https://clangd.llvm.org/
794 https://microsoft.github.io/language-server-protocol/
796clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.
798 llvm::cl::HideUnrelatedOptions(ClangdCategories);
799 llvm::cl::ParseCommandLineOptions(argc, argv, Overview, nullptr,
800 nullptr, FlagsEnvVar);
802 if (!Sync.getNumOccurrences())
804 if (!CrashPragmas.getNumOccurrences())
810 if (!EnableConfig.getNumOccurrences())
811 EnableConfig =
false;
813 if (!EnableBackgroundIndex.getNumOccurrences())
814 EnableBackgroundIndex =
false;
816 else if (EnableBackgroundIndex)
819 if (Test || EnableTestScheme) {
820 static URISchemeRegistry::Add<TestScheme>
X(
821 "test",
"Test scheme for clangd lit tests.");
826 if (!Sync && WorkerThreadsCount == 0) {
827 llvm::errs() <<
"A number of worker threads cannot be 0. Did you mean to "
833 if (WorkerThreadsCount.getNumOccurrences())
834 llvm::errs() <<
"Ignoring -j because -sync is set.\n";
835 WorkerThreadsCount = 0;
837 if (FallbackStyle.getNumOccurrences())
838 clang::format::DefaultFallbackStyle = FallbackStyle.c_str();
841 std::optional<llvm::raw_fd_ostream> InputMirrorStream;
842 if (!InputMirrorFile.empty()) {
844 InputMirrorStream.emplace(InputMirrorFile, EC,
845 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
847 InputMirrorStream.reset();
848 llvm::errs() <<
"Error while opening an input mirror file: "
851 InputMirrorStream->SetUnbuffered();
855#if !CLANGD_DECISION_FOREST
856 if (RankingModel == clangd::CodeCompleteOptions::DecisionForest) {
857 llvm::errs() <<
"Clangd was compiled without decision forest support.\n";
865 std::optional<llvm::raw_fd_ostream> TracerStream;
866 std::unique_ptr<trace::EventTracer> Tracer;
867 const char *JSONTraceFile = getenv(
"CLANGD_TRACE");
868 const char *MetricsCSVFile = getenv(
"CLANGD_METRICS");
869 const char *TracerFile = JSONTraceFile ? JSONTraceFile : MetricsCSVFile;
872 TracerStream.emplace(TracerFile, EC,
873 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
875 TracerStream.reset();
876 llvm::errs() <<
"Error while opening trace file " << TracerFile <<
": "
879 Tracer = (TracerFile == JSONTraceFile)
885 std::optional<trace::Session> TracingSession;
887 TracingSession.emplace(*Tracer);
892 if (llvm::outs().is_displayed() && llvm::errs().is_displayed() &&
893 !CheckFile.getNumOccurrences())
894 llvm::errs() << Overview <<
"\n";
897 llvm::errs().SetBuffered();
903 log(
"PID: {0}", llvm::sys::Process::getProcessId());
905 SmallString<128> CWD;
906 if (
auto Err = llvm::sys::fs::current_path(CWD))
907 log(
"Working directory unknown: {0}", Err.message());
909 log(
"Working directory: {0}", CWD);
911 for (
int I = 0; I < argc; ++I)
912 log(
"argv[{0}]: {1}", I, argv[I]);
913 if (
auto EnvFlags = llvm::sys::Process::GetEnv(FlagsEnvVar))
914 log(
"{0}: {1}", FlagsEnvVar, *EnvFlags);
920 switch (PCHStorage) {
921 case PCHStorageFlag::Memory:
924 case PCHStorageFlag::Disk:
928 if (!ResourceDir.empty())
932#if CLANGD_ENABLE_REMOTE
933 if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {
934 llvm::errs() <<
"remote-index-address and project-path have to be "
935 "specified at the same time.";
938 if (!RemoteIndexAddress.empty()) {
939 if (IndexFile.empty()) {
940 log(
"Connecting to remote index at {0}", RemoteIndexAddress);
942 elog(
"When enabling remote index, IndexFile should not be specified. "
943 "Only one can be used at time. Remote index will ignored.");
954 return loadExternalIndex(External, Tasks, SupportContainedRefs);
961 Opts.
CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
963 if (CompletionStyle.getNumOccurrences())
964 Opts.
CodeComplete.BundleOverloads = CompletionStyle != Detailed;
968 if (!HeaderInsertionDecorators) {
976 Opts.
CodeComplete.ForceLoadPreamble = ExperimentalModulesSupport;
979 std::vector<std::unique_ptr<config::Provider>> ProviderStack;
980 std::unique_ptr<config::Provider>
Config;
982 ProviderStack.push_back(
984 llvm::SmallString<256> UserConfig;
985 if (llvm::sys::path::user_config_directory(UserConfig)) {
986 llvm::sys::path::append(UserConfig,
"clangd",
"config.yaml");
987 vlog(
"User config file is {0}", UserConfig);
989 UserConfig,
"", TFS,
true));
991 elog(
"Couldn't determine user config file, not loading");
994 ProviderStack.push_back(std::make_unique<FlagsConfigProvider>());
995 std::vector<const config::Provider *> ProviderPointers;
996 for (
const auto &P : ProviderStack)
997 ProviderPointers.push_back(P.get());
1003 if (EnableClangTidy) {
1004 std::vector<TidyProvider> Providers;
1005 Providers.reserve(4 + EnableConfig);
1012 ClangTidyOptProvider =
combine(std::move(Providers));
1021 if (T.hidden() && !HiddenFeatures)
1023 if (TweakList.getNumOccurrences())
1024 return llvm::is_contained(TweakList, T.id());
1028 Opts.
Encoding = ForceOffsetEncoding;
1030 if (CheckFile.getNumOccurrences()) {
1031 llvm::SmallString<256>
Path;
1033 llvm::sys::fs::real_path(CheckFile,
Path,
true)) {
1034 elog(
"Failed to resolve path {0}: {1}", CheckFile,
Error.message());
1037 log(
"Entering check mode (no LSP server)");
1044 if (ModuleSet.
begin() != ModuleSet.
end())
1049 llvm::sys::ChangeStdinToBinary();
1050 std::unique_ptr<Transport> TransportLayer;
1051 if (getenv(
"CLANGD_AS_XPC_SERVICE")) {
1053 log(
"Starting LSP over XPC service");
1056 llvm::errs() <<
"This clangd binary wasn't built with XPC support.\n";
1060 log(
"Starting LSP over stdin/stdout");
1062 stdin, llvm::outs(), InputMirrorStream ? &*InputMirrorStream :
nullptr,
1063 PrettyPrint, InputStyle);
1065 if (!PathMappingsArg.empty()) {
1068 elog(
"Invalid -path-mappings: {0}", Mappings.takeError());
1072 std::move(*Mappings));
1076 llvm::set_thread_name(
"clangd.main");
1077 int ExitCode = LSPServer.
run()
1080 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 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.
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)
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[])
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.
bool check(llvm::StringRef File, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts)
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.
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.
Settings that express user/project preferences and control clangd behavior.
@ 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.