32#include "clang/Basic/Stack.h"
33#include "clang/Format/Format.h"
34#include "llvm/ADT/SmallString.h"
35#include "llvm/ADT/StringRef.h"
36#include "llvm/Support/CommandLine.h"
37#include "llvm/Support/FileSystem.h"
38#include "llvm/Support/InitLLVM.h"
39#include "llvm/Support/Path.h"
40#include "llvm/Support/Process.h"
41#include "llvm/Support/Program.h"
42#include "llvm/Support/Signals.h"
43#include "llvm/Support/TargetSelect.h"
44#include "llvm/Support/raw_ostream.h"
67bool check(
const llvm::StringRef
File,
const ThreadsafeFS &TFS,
68 const ClangdLSPServer::Options &Opts);
73using llvm::cl::CommaSeparated;
75using llvm::cl::Hidden;
79using llvm::cl::OptionCategory;
80using llvm::cl::ValueOptional;
81using llvm::cl::values;
85OptionCategory CompileCommands(
"clangd compilation flags options");
86OptionCategory Features(
"clangd feature options");
87OptionCategory Misc(
"clangd miscellaneous options");
88OptionCategory Protocol(
"clangd protocol and logging options");
89OptionCategory Retired(
"clangd flags no longer in use");
90const OptionCategory *ClangdCategories[] = {&Features, &Protocol,
91 &CompileCommands, &Misc, &Retired};
93template <
typename T>
class RetiredFlag {
97 RetiredFlag(llvm::StringRef
Name)
98 : Option(
Name, cat(Retired), desc(
"Obsolete flag, ignored"), Hidden,
101 <<
"The flag `-" <<
Name <<
"` is obsolete and ignored.\n";
105enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs };
106opt<CompileArgsFrom> CompileArgsFrom{
108 cat(CompileCommands),
109 desc(
"The source of compile commands"),
110 values(clEnumValN(LSPCompileArgs,
"lsp",
111 "All compile commands come from LSP and "
112 "'compile_commands.json' files are ignored"),
113 clEnumValN(FilesystemCompileArgs,
"filesystem",
114 "All compile commands come from the "
115 "'compile_commands.json' files")),
116 init(FilesystemCompileArgs),
120opt<Path> CompileCommandsDir{
121 "compile-commands-dir",
122 cat(CompileCommands),
123 desc(
"Specify a path to look for compile_commands.json. If path "
124 "is invalid, clangd will look in the current directory and "
125 "parent paths of each source file"),
128opt<Path> ResourceDir{
130 cat(CompileCommands),
131 desc(
"Directory for system clang headers"),
136list<std::string> QueryDriverGlobs{
138 cat(CompileCommands),
140 "Comma separated list of globs for white-listing gcc-compatible "
141 "drivers that are safe to execute. Drivers matching any of these globs "
142 "will be used to extract system includes. e.g. "
143 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
149opt<bool> AllScopesCompletion{
150 "all-scopes-completion",
152 desc(
"If set to true, code completion will include index symbols that are "
153 "not defined in the scopes (e.g. "
154 "namespaces) visible from the code completion point. Such completions "
155 "can insert scope qualifiers"),
159opt<bool> ShowOrigins{
162 desc(
"Show origins of completion items"),
163 init(CodeCompleteOptions().ShowOrigins),
167opt<bool> EnableBackgroundIndex{
170 desc(
"Index project code in the background and persist index on disk."),
174opt<llvm::ThreadPriority> BackgroundIndexPriority{
175 "background-index-priority",
177 desc(
"Thread priority for building the background index. "
178 "The effect of this flag is OS-specific."),
179 values(clEnumValN(llvm::ThreadPriority::Background,
"background",
180 "Minimum priority, runs on idle CPUs. "
181 "May leave 'performance' cores unused."),
182 clEnumValN(llvm::ThreadPriority::Low,
"low",
183 "Reduced priority compared to interactive work."),
184 clEnumValN(llvm::ThreadPriority::Default,
"normal",
185 "Same priority as other clangd work.")),
186 init(llvm::ThreadPriority::Low),
189opt<bool> EnableClangTidy{
192 desc(
"Enable clang-tidy diagnostics"),
196opt<CodeCompleteOptions::CodeCompletionParse> CodeCompletionParse{
199 desc(
"Whether the clang-parser is used for code-completion"),
201 "Block until the parser can be used"),
203 "Use text-based completion if the parser "
206 "Always used text-based completion")),
207 init(CodeCompleteOptions().RunParser),
211opt<CodeCompleteOptions::CodeCompletionRankingModel> RankingModel{
214 desc(
"Model to use to rank code-completion items"),
216 "Use heuristics to rank code completion items"),
218 "Use Decision Forest model to rank completion items")),
219 init(CodeCompleteOptions().RankingModel),
224enum CompletionStyleFlag { Detailed, Bundled };
225opt<CompletionStyleFlag> CompletionStyle{
228 desc(
"Granularity of code completion suggestions"),
229 values(clEnumValN(Detailed,
"detailed",
230 "One completion item for each semantically distinct "
231 "completion, with full type information"),
232 clEnumValN(Bundled,
"bundled",
233 "Similar completion items (e.g. function overloads) are "
234 "combined. Type information shown where possible")),
237opt<std::string> FallbackStyle{
240 desc(
"clang-format style to apply by default when "
241 "no .clang-format file is found"),
242 init(clang::format::DefaultFallbackStyle),
245opt<int> EnableFunctionArgSnippets{
246 "function-arg-placeholders",
248 desc(
"When disabled (0), completions contain only parentheses for "
249 "function calls. When enabled (1), completions also contain "
250 "placeholders for method parameters"),
254opt<CodeCompleteOptions::IncludeInsertion> HeaderInsertion{
257 desc(
"Add #include directives when accepting code completions"),
258 init(CodeCompleteOptions().InsertIncludes),
261 "Include what you use. "
262 "Insert the owning header for top-level symbols, unless the "
263 "header is already directly included or the symbol is "
267 "Never insert #include directives as part of code completion")),
270opt<bool> ImportInsertions{
273 desc(
"If header insertion is enabled, add #import directives when "
274 "accepting code completions or fixing includes in Objective-C code"),
275 init(CodeCompleteOptions().ImportInsertions),
278opt<bool> HeaderInsertionDecorators{
279 "header-insertion-decorators",
281 desc(
"Prepend a circular dot or space before the completion "
282 "label, depending on whether "
283 "an include line will be inserted or not"),
287opt<bool> HiddenFeatures{
290 desc(
"Enable hidden features mostly useful to clangd developers"),
295opt<bool> IncludeIneligibleResults{
296 "include-ineligible-results",
298 desc(
"Include ineligible completion results (e.g. private members)"),
299 init(CodeCompleteOptions().IncludeIneligibleResults),
303RetiredFlag<bool> EnableIndex(
"index");
304RetiredFlag<bool> SuggestMissingIncludes(
"suggest-missing-includes");
305RetiredFlag<bool> RecoveryAST(
"recovery-ast");
306RetiredFlag<bool> RecoveryASTType(
"recovery-ast-type");
307RetiredFlag<bool> AsyncPreamble(
"async-preamble");
308RetiredFlag<bool> CollectMainFileRefs(
"collect-main-file-refs");
309RetiredFlag<bool> CrossFileRename(
"cross-file-rename");
310RetiredFlag<std::string> ClangTidyChecks(
"clang-tidy-checks");
311RetiredFlag<bool> InlayHints(
"inlay-hints");
312RetiredFlag<bool> FoldingRanges(
"folding-ranges");
313RetiredFlag<bool> IncludeCleanerStdlib(
"include-cleaner-stdlib");
315opt<int> LimitResults{
318 desc(
"Limit the number of results returned by clangd. "
319 "0 means no limit (default=100)"),
323opt<int> ReferencesLimit{
326 desc(
"Limit the number of references returned by clangd. "
327 "0 means no limit (default=1000)"),
331opt<int> RenameFileLimit{
334 desc(
"Limit the number of files to be affected by symbol renaming. "
335 "0 means no limit (default=50)"),
339list<std::string> TweakList{
342 desc(
"Specify a list of Tweaks to enable (only for clangd developers)."),
347opt<unsigned> WorkerThreadsCount{
350 desc(
"Number of async workers used by clangd. Background index also "
351 "uses this many workers."),
359 "Index file to build the static index. The file must have been created "
360 "by a compatible clangd-indexer\n"
361 "WARNING: This option is experimental only, and will be removed "
362 "eventually. Don't rely on it"),
370 desc(
"Abbreviation for -input-style=delimited -pretty -sync "
371 "-enable-test-scheme -enable-config=0 -log=verbose -crash-pragmas. "
372 "Also sets config options: Index.StandardLibrary=false. "
373 "Intended to simplify lit tests"),
378opt<bool> CrashPragmas{
381 desc(
"Respect `#pragma clang __debug crash` and friends."),
389 desc(
"Parse one file in isolation instead of acting as a language server. "
390 "Useful to investigate/reproduce crashes or configuration problems. "
391 "With --check=<filename>, attempts to parse a particular file."),
396enum PCHStorageFlag { Disk, Memory };
397opt<PCHStorageFlag> PCHStorage{
400 desc(
"Storing PCHs in memory increases memory usages, but may "
401 "improve performance"),
403 clEnumValN(PCHStorageFlag::Disk,
"disk",
"store PCHs on disk"),
404 clEnumValN(PCHStorageFlag::Memory,
"memory",
"store PCHs in memory")),
405 init(PCHStorageFlag::Disk),
411 desc(
"Handle client requests on main thread. Background index still uses "
417opt<JSONStreamStyle> InputStyle{
420 desc(
"Input JSON stream encoding"),
424 "messages delimited by --- lines, with # comment support")),
429opt<bool> EnableTestScheme{
430 "enable-test-uri-scheme",
432 desc(
"Enable 'test:' URI scheme. Only use in lit tests"),
437opt<std::string> PathMappingsArg{
441 "Translates between client paths (as seen by a remote editor) and "
442 "server paths (where clangd sees files on disk). "
443 "Comma separated list of '<client_path>=<server_path>' pairs, the "
444 "first entry matching a given path is used. "
445 "e.g. /home/project/incl=/opt/include,/home/project=/workarea/project"),
449opt<Path> InputMirrorFile{
452 desc(
"Mirror all LSP input to the specified file. Useful for debugging"),
457opt<Logger::Level> LogLevel{
460 desc(
"Verbosity of log messages written to stderr"),
461 values(clEnumValN(
Logger::Error,
"error",
"Error messages only"),
462 clEnumValN(
Logger::Info,
"info",
"High level execution tracing"),
467opt<OffsetEncoding> ForceOffsetEncoding{
470 desc(
"Force the offsetEncoding used for character positions. "
471 "This bypasses negotiation via client capabilities"),
475 "Offsets are in UTF-16 code units"),
477 "Offsets are in unicode codepoints")),
481opt<bool> PrettyPrint{
484 desc(
"Pretty-print JSON output"),
488opt<bool> EnableConfig{
492 "Read user and project configuration from YAML files.\n"
493 "Project config is from a .clangd file in the project directory.\n"
494 "User config is from clangd/config.yaml in the following directories:\n"
495 "\tWindows: %USERPROFILE%\\AppData\\Local\n"
496 "\tMac OS: ~/Library/Preferences/\n"
497 "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n"
498 "Configuration is documented at https://clangd.llvm.org/config.html"),
502opt<bool> UseDirtyHeaders{
"use-dirty-headers", cat(Misc),
503 desc(
"Use files open in the editor when parsing "
504 "headers instead of reading from the disk"),
506 init(ClangdServer::Options().UseDirtyHeaders)};
508opt<bool> PreambleParseForwardingFunctions{
509 "parse-forwarding-functions",
511 desc(
"Parse all emplace-like functions in included headers"),
513 init(ParseOptions().PreambleParseForwardingFunctions),
516#if defined(__GLIBC__) && CLANGD_MALLOC_TRIM
517opt<bool> EnableMallocTrim{
520 desc(
"Release memory periodically via malloc_trim(3)."),
524std::function<void()> getMemoryCleanupFunction() {
525 if (!EnableMallocTrim)
529 constexpr size_t MallocTrimPad = 20'000'000;
531 if (malloc_trim(MallocTrimPad))
532 vlog(
"Released memory via malloc_trim");
536std::function<void()> getMemoryCleanupFunction() {
return nullptr; }
539#if CLANGD_ENABLE_REMOTE
540opt<std::string> RemoteIndexAddress{
541 "remote-index-address",
543 desc(
"Address of the remote index server"),
547opt<std::string> ProjectRoot{
550 desc(
"Path to the project root. Requires remote-index-address to be set."),
554opt<bool> ExperimentalModulesSupport{
555 "experimental-modules-support",
557 desc(
"Experimental support for standard c++ modules"),
565class TestScheme :
public URIScheme {
567 llvm::Expected<std::string>
569 llvm::StringRef )
const override {
570 using namespace llvm::sys;
573 if (!Body.starts_with(
"/"))
575 "Expect URI body to be an absolute path starting with '/': {0}",
577 Body = Body.ltrim(
'/');
578 llvm::SmallString<16>
Path(Body);
580 fs::make_absolute(TestScheme::TestDir,
Path);
581 return std::string(
Path);
586 llvm::StringRef Body = AbsolutePath;
587 if (!Body.consume_front(TestScheme::TestDir))
588 return error(
"Path {0} doesn't start with root {1}", AbsolutePath,
591 return URI(
"test",
"",
592 llvm::sys::path::convert_to_slash(Body));
596 const static char TestDir[];
600const char TestScheme::TestDir[] =
"C:\\clangd-test";
602const char TestScheme::TestDir[] =
"/clangd-test";
605std::unique_ptr<SymbolIndex>
606loadExternalIndex(
const Config::ExternalIndexSpec &External,
607 AsyncTaskRunner *Tasks,
bool SupportContainedRefs) {
608 static const trace::Metric RemoteIndexUsed(
"used_remote_index",
610 switch (External.Kind) {
614 RemoteIndexUsed.record(1, External.Location);
615 log(
"Associating {0} with remote index at {1}.", External.MountPoint,
619 log(
"Associating {0} with monolithic index at {1}.", External.MountPoint,
621 auto NewIndex = std::make_unique<SwapIndex>(std::make_unique<MemIndex>());
622 auto IndexLoadTask = [
File = External.Location,
623 PlaceHolder = NewIndex.get(), SupportContainedRefs] {
625 SupportContainedRefs))
626 PlaceHolder->reset(std::move(Idx));
629 Tasks->
runAsync(
"Load-index:" + External.Location,
630 std::move(IndexLoadTask));
634 return std::move(NewIndex);
636 llvm_unreachable(
"Invalid ExternalIndexKind.");
639class FlagsConfigProvider :
public config::Provider {
643 std::vector<config::CompiledFragment>
644 getFragments(
const config::Params &,
650 FlagsConfigProvider() {
651 std::optional<Config::CDBSearchSpec> CDBSearch;
652 std::optional<Config::ExternalIndexSpec> IndexSpec;
653 std::optional<Config::BackgroundPolicy> BGPolicy;
654 std::optional<Config::ArgumentListsPolicy> ArgumentLists;
658 if (!CompileCommandsDir.empty()) {
659 if (llvm::sys::fs::exists(CompileCommandsDir)) {
664 llvm::SmallString<128>
Path(CompileCommandsDir);
665 if (std::error_code EC = llvm::sys::fs::make_absolute(
Path)) {
666 elog(
"Error while converting the relative path specified by "
667 "--compile-commands-dir to an absolute path: {0}. The argument "
674 elog(
"Path specified by --compile-commands-dir does not exist. The "
675 "argument will be ignored.");
678 if (!IndexFile.empty()) {
679 Config::ExternalIndexSpec Spec;
680 Spec.Kind = Spec.File;
681 Spec.Location = IndexFile;
682 IndexSpec = std::move(Spec);
684#if CLANGD_ENABLE_REMOTE
685 if (!RemoteIndexAddress.empty()) {
686 assert(!ProjectRoot.empty() && IndexFile.empty());
687 Config::ExternalIndexSpec Spec;
688 Spec.Kind = Spec.Server;
689 Spec.Location = RemoteIndexAddress;
690 Spec.MountPoint = ProjectRoot;
691 IndexSpec = std::move(Spec);
695 if (!EnableBackgroundIndex) {
699 if (EnableFunctionArgSnippets >= 0) {
700 ArgumentLists = EnableFunctionArgSnippets
705 Frag = [=](
const config::Params &, Config &
C) {
707 C.CompileFlags.CDBSearch = *CDBSearch;
709 C.Index.External = *IndexSpec;
711 C.Index.Background = *BGPolicy;
713 C.Completion.ArgumentLists = *ArgumentLists;
714 if (AllScopesCompletion.getNumOccurrences())
715 C.Completion.AllScopes = AllScopesCompletion;
718 C.Index.StandardLibrary =
false;
734 clang::noteBottomOfStack();
735 llvm::InitLLVM
X(argc, argv);
736 llvm::InitializeAllTargetInfos();
737 llvm::sys::AddSignalHandler(
741 llvm::errs().flush();
745 llvm::cl::SetVersionPrinter([](llvm::raw_ostream &
OS) {
750 const char *FlagsEnvVar =
"CLANGD_FLAGS";
751 const char *Overview =
752 R
"(clangd is a language server that provides IDE-like features to editors.
754It should be used via an editor plugin rather than invoked directly. For more information, see:
755 https://clangd.llvm.org/
756 https://microsoft.github.io/language-server-protocol/
758clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.
760 llvm::cl::HideUnrelatedOptions(ClangdCategories);
761 llvm::cl::ParseCommandLineOptions(argc, argv, Overview,
762 nullptr, FlagsEnvVar);
764 if (!Sync.getNumOccurrences())
766 if (!CrashPragmas.getNumOccurrences())
772 if (!EnableConfig.getNumOccurrences())
773 EnableConfig =
false;
775 if (!EnableBackgroundIndex.getNumOccurrences())
776 EnableBackgroundIndex =
false;
778 else if (EnableBackgroundIndex)
781 if (Test || EnableTestScheme) {
782 static URISchemeRegistry::Add<TestScheme>
X(
783 "test",
"Test scheme for clangd lit tests.");
788 if (!Sync && WorkerThreadsCount == 0) {
789 llvm::errs() <<
"A number of worker threads cannot be 0. Did you mean to "
795 if (WorkerThreadsCount.getNumOccurrences())
796 llvm::errs() <<
"Ignoring -j because -sync is set.\n";
797 WorkerThreadsCount = 0;
799 if (FallbackStyle.getNumOccurrences())
800 clang::format::DefaultFallbackStyle = FallbackStyle.c_str();
803 std::optional<llvm::raw_fd_ostream> InputMirrorStream;
804 if (!InputMirrorFile.empty()) {
806 InputMirrorStream.emplace(InputMirrorFile, EC,
807 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
809 InputMirrorStream.reset();
810 llvm::errs() <<
"Error while opening an input mirror file: "
813 InputMirrorStream->SetUnbuffered();
817#if !CLANGD_DECISION_FOREST
819 llvm::errs() <<
"Clangd was compiled without decision forest support.\n";
827 std::optional<llvm::raw_fd_ostream> TracerStream;
828 std::unique_ptr<trace::EventTracer> Tracer;
829 const char *JSONTraceFile = getenv(
"CLANGD_TRACE");
830 const char *MetricsCSVFile = getenv(
"CLANGD_METRICS");
831 const char *TracerFile = JSONTraceFile ? JSONTraceFile : MetricsCSVFile;
834 TracerStream.emplace(TracerFile, EC,
835 llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
837 TracerStream.reset();
838 llvm::errs() <<
"Error while opening trace file " << TracerFile <<
": "
841 Tracer = (TracerFile == JSONTraceFile)
847 std::optional<trace::Session> TracingSession;
849 TracingSession.emplace(*Tracer);
854 if (llvm::outs().is_displayed() && llvm::errs().is_displayed() &&
855 !CheckFile.getNumOccurrences())
856 llvm::errs() << Overview <<
"\n";
859 llvm::errs().SetBuffered();
865 log(
"PID: {0}", llvm::sys::Process::getProcessId());
867 SmallString<128> CWD;
868 if (
auto Err = llvm::sys::fs::current_path(CWD))
869 log(
"Working directory unknown: {0}", Err.message());
871 log(
"Working directory: {0}", CWD);
873 for (
int I = 0; I < argc; ++I)
874 log(
"argv[{0}]: {1}", I, argv[I]);
875 if (
auto EnvFlags = llvm::sys::Process::GetEnv(FlagsEnvVar))
876 log(
"{0}: {1}", FlagsEnvVar, *EnvFlags);
879 Opts.UseDirBasedCDB = (CompileArgsFrom == FilesystemCompileArgs);
880 Opts.EnableExperimentalModulesSupport = ExperimentalModulesSupport;
882 switch (PCHStorage) {
883 case PCHStorageFlag::Memory:
884 Opts.StorePreamblesInMemory =
true;
886 case PCHStorageFlag::Disk:
887 Opts.StorePreamblesInMemory =
false;
890 if (!ResourceDir.empty())
891 Opts.ResourceDir = ResourceDir;
892 Opts.BuildDynamicSymbolIndex =
true;
893 std::vector<std::unique_ptr<SymbolIndex>> IdxStack;
894#
if CLANGD_ENABLE_REMOTE
895 if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {
896 llvm::errs() <<
"remote-index-address and project-path have to be "
897 "specified at the same time.";
900 if (!RemoteIndexAddress.empty()) {
901 if (IndexFile.empty()) {
902 log(
"Connecting to remote index at {0}", RemoteIndexAddress);
904 elog(
"When enabling remote index, IndexFile should not be specified. "
905 "Only one can be used at time. Remote index will ignored.");
909 Opts.BackgroundIndex = EnableBackgroundIndex;
910 Opts.BackgroundIndexPriority = BackgroundIndexPriority;
911 Opts.ReferencesLimit = ReferencesLimit;
912 Opts.Rename.LimitFiles = RenameFileLimit;
914 [SupportContainedRefs = Opts.EnableOutgoingCalls](
916 return loadExternalIndex(External, Tasks, SupportContainedRefs);
919 Opts.StaticIndex = PAI.get();
920 Opts.AsyncThreadsCount = WorkerThreadsCount;
921 Opts.MemoryCleanup = getMemoryCleanupFunction();
924 Opts.CodeComplete.
Limit = LimitResults;
925 if (CompletionStyle.getNumOccurrences())
930 if (!HeaderInsertionDecorators) {
934 Opts.CodeComplete.
RunParser = CodeCompletionParse;
941 std::vector<std::unique_ptr<config::Provider>> ProviderStack;
942 std::unique_ptr<config::Provider>
Config;
944 ProviderStack.push_back(
946 llvm::SmallString<256> UserConfig;
947 if (llvm::sys::path::user_config_directory(UserConfig)) {
948 llvm::sys::path::append(UserConfig,
"clangd",
"config.yaml");
949 vlog(
"User config file is {0}", UserConfig);
951 UserConfig,
"", TFS,
true));
953 elog(
"Couldn't determine user config file, not loading");
956 ProviderStack.push_back(std::make_unique<FlagsConfigProvider>());
957 std::vector<const config::Provider *> ProviderPointers;
958 for (
const auto &P : ProviderStack)
959 ProviderPointers.push_back(P.get());
961 Opts.ConfigProvider =
Config.get();
965 if (EnableClangTidy) {
966 std::vector<TidyProvider> Providers;
967 Providers.reserve(4 + EnableConfig);
974 ClangTidyOptProvider =
combine(std::move(Providers));
975 Opts.ClangTidyProvider = ClangTidyOptProvider;
977 Opts.UseDirtyHeaders = UseDirtyHeaders;
978 Opts.PreambleParseForwardingFunctions = PreambleParseForwardingFunctions;
980 Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
981 Opts.TweakFilter = [&](
const Tweak &T) {
982 if (T.hidden() && !HiddenFeatures)
984 if (TweakList.getNumOccurrences())
985 return llvm::is_contained(TweakList, T.id());
989 Opts.Encoding = ForceOffsetEncoding;
991 if (CheckFile.getNumOccurrences()) {
992 llvm::SmallString<256>
Path;
994 llvm::sys::fs::real_path(CheckFile,
Path,
true)) {
995 elog(
"Failed to resolve path {0}: {1}", CheckFile,
Error.message());
998 log(
"Entering check mode (no LSP server)");
1006 llvm::sys::ChangeStdinToBinary();
1007 std::unique_ptr<Transport> TransportLayer;
1008 if (getenv(
"CLANGD_AS_XPC_SERVICE")) {
1010 log(
"Starting LSP over XPC service");
1013 llvm::errs() <<
"This clangd binary wasn't built with XPC support.\n";
1017 log(
"Starting LSP over stdin/stdout");
1019 stdin, llvm::outs(), InputMirrorStream ? &*InputMirrorStream :
nullptr,
1020 PrettyPrint, InputStyle);
1022 if (!PathMappingsArg.empty()) {
1025 elog(
"Invalid -path-mappings: {0}", Mappings.takeError());
1029 std::move(*Mappings));
1033 llvm::set_thread_name(
"clangd.main");
1034 int ExitCode = LSPServer.
run()
1037 log(
"LSP finished, exiting with status {0}", ExitCode);
llvm::SmallString< 256U > Name
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.
void runAsync(const llvm::Twine &Name, llvm::unique_function< void()> Action)
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.
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.
An interface base for small context-sensitive refactoring actions.
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.
TidyProvider combine(std::vector< TidyProvider > Providers)
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
std::string Path
A typedef to represent a file path.
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()
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::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.
llvm::unique_function< void(tidy::ClangTidyOptions &, llvm::StringRef) const > TidyProvider
A factory to modify a tidy::ClangTidyOptions.
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++ -*-===//
Some operations such as code completion produce a set of candidates.
@ AlwaysParse
Block until we can run the parser (e.g.
@ ParseIfReady
Run the parser if inputs (preamble) are ready.
@ NeverParse
Always use text-based completion.
bool IncludeIneligibleResults
Include results that are not legal completions in the current context.
CodeCompletionRankingModel RankingModel
enum clang::clangd::CodeCompleteOptions::IncludeInsertion InsertIncludes
bool ImportInsertions
Whether include insertions for Objective-C code should use #import instead of #include.
size_t Limit
Limit the number of results returned (0 means no limit).
std::optional< bool > BundleOverloads
Combine overloads into a single completion item where possible.
struct clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator IncludeIndicator
enum clang::clangd::CodeCompleteOptions::CodeCompletionParse RunParser
bool ShowOrigins
Expose origins of completion items in the label (for debugging).
bool ForceLoadPreamble
Force sema to load decls from preamble even if an index is provided.
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.
@ Value
A number whose value is meaningful, and may vary over time.