llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangd Author: Andres Villegas (avillega) <details> <summary>Changes</summary> The motivation for this change is to include clangd as part of the multicall tool. Enable clangd in the multicall driver tool will be done a following change. --- Patch is 62.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76767.diff 3 Files Affected: - (modified) clang-tools-extra/clangd/tool/CMakeLists.txt (+7) - (modified) clang-tools-extra/clangd/tool/ClangdMain.cpp (+372-520) - (added) clang-tools-extra/clangd/tool/Opts.td (+426) ``````````diff diff --git a/clang-tools-extra/clangd/tool/CMakeLists.txt b/clang-tools-extra/clangd/tool/CMakeLists.txt index 6c21175d7687c3..54779463cce521 100644 --- a/clang-tools-extra/clangd/tool/CMakeLists.txt +++ b/clang-tools-extra/clangd/tool/CMakeLists.txt @@ -6,9 +6,16 @@ add_clang_library(clangdMain Check.cpp ) +set(LLVM_TARGET_DEFINITIONS Opts.td) +tablegen(LLVM Opts.inc -gen-opt-parser-defs) +add_public_tablegen_target(ClangdOptsTableGen) + add_clang_tool(clangd ClangdToolMain.cpp $<TARGET_OBJECTS:obj.clangDaemonTweaks> + + DEPENDS + ClangdOptsTableGen ) set(LLVM_LINK_COMPONENTS diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 3b08e023236dc1..ea122d1a585c84 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ClangdMain.h" + #include "Check.h" #include "ClangdLSPServer.h" #include "CodeComplete.h" @@ -14,7 +15,7 @@ #include "Config.h" #include "ConfigProvider.h" #include "Feature.h" -#include "IncludeCleaner.h" +#include "Opts.inc" #include "PathMapping.h" #include "Protocol.h" #include "TidyProvider.h" @@ -22,7 +23,6 @@ #include "index/Background.h" #include "index/Index.h" #include "index/MemIndex.h" -#include "index/Merge.h" #include "index/ProjectAware.h" #include "index/remote/Client.h" #include "support/Path.h" @@ -33,7 +33,13 @@ #include "clang/Basic/Stack.h" #include "clang/Format/Format.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/InitLLVM.h" @@ -42,14 +48,13 @@ #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #include <chrono> #include <cstdlib> #include <memory> -#include <mutex> #include <optional> #include <string> -#include <thread> #include <utility> #include <vector> @@ -61,464 +66,231 @@ #include <malloc.h> #endif -namespace clang { -namespace clangd { - namespace { -using llvm::cl::cat; -using llvm::cl::CommaSeparated; -using llvm::cl::desc; -using llvm::cl::Hidden; -using llvm::cl::init; -using llvm::cl::list; -using llvm::cl::opt; -using llvm::cl::OptionCategory; -using llvm::cl::ValueOptional; -using llvm::cl::values; - -// All flags must be placed in a category, or they will be shown neither in -// --help, nor --help-hidden! -OptionCategory CompileCommands("clangd compilation flags options"); -OptionCategory Features("clangd feature options"); -OptionCategory Misc("clangd miscellaneous options"); -OptionCategory Protocol("clangd protocol and logging options"); -OptionCategory Retired("clangd flags no longer in use"); -const OptionCategory *ClangdCategories[] = {&Features, &Protocol, - &CompileCommands, &Misc, &Retired}; - -template <typename T> class RetiredFlag { - opt<T> Option; - -public: - RetiredFlag(llvm::StringRef Name) - : Option(Name, cat(Retired), desc("Obsolete flag, ignored"), Hidden, - llvm::cl::callback([Name](const T &) { - llvm::errs() - << "The flag `-" << Name << "` is obsolete and ignored.\n"; - })) {} -}; - -enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs }; -opt<CompileArgsFrom> CompileArgsFrom{ - "compile_args_from", - cat(CompileCommands), - desc("The source of compile commands"), - values(clEnumValN(LSPCompileArgs, "lsp", - "All compile commands come from LSP and " - "'compile_commands.json' files are ignored"), - clEnumValN(FilesystemCompileArgs, "filesystem", - "All compile commands come from the " - "'compile_commands.json' files")), - init(FilesystemCompileArgs), - Hidden, -}; - -opt<Path> CompileCommandsDir{ - "compile-commands-dir", - cat(CompileCommands), - desc("Specify a path to look for compile_commands.json. If path " - "is invalid, clangd will look in the current directory and " - "parent paths of each source file"), -}; - -opt<Path> ResourceDir{ - "resource-dir", - cat(CompileCommands), - desc("Directory for system clang headers"), - init(""), - Hidden, -}; - -list<std::string> QueryDriverGlobs{ - "query-driver", - cat(CompileCommands), - desc( - "Comma separated list of globs for white-listing gcc-compatible " - "drivers that are safe to execute. Drivers matching any of these globs " - "will be used to extract system includes. e.g. " - "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"), - CommaSeparated, -}; - -// FIXME: Flags are the wrong mechanism for user preferences. -// We should probably read a dotfile or similar. -opt<bool> AllScopesCompletion{ - "all-scopes-completion", - cat(Features), - desc("If set to true, code completion will include index symbols that are " - "not defined in the scopes (e.g. " - "namespaces) visible from the code completion point. Such completions " - "can insert scope qualifiers"), - init(true), -}; +#if defined(__GLIBC__) && CLANGD_MALLOC_TRIM +static constexpr uint MallocTrimVis = (1 << 8); +#else +static constexpr uint MallocTrimVis = 0; +#endif -opt<bool> ShowOrigins{ - "debug-origin", - cat(Features), - desc("Show origins of completion items"), - init(CodeCompleteOptions().ShowOrigins), - Hidden, -}; +#if CLANGD_ENABLE_REMOTE +// FIXME(kirillbobyrev): Should this be the location of compile_commands.json? +static constexpr uint RemoteVis = (1 << 9); +#else +static constexpr uint RemoteVis = 0; +#endif -opt<bool> EnableBackgroundIndex{ - "background-index", - cat(Features), - desc("Index project code in the background and persist index on disk."), - init(true), +using namespace llvm; +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), +#include "Opts.inc" +#undef OPTION }; -opt<llvm::ThreadPriority> BackgroundIndexPriority{ - "background-index-priority", - cat(Features), - desc("Thread priority for building the background index. " - "The effect of this flag is OS-specific."), - values(clEnumValN(llvm::ThreadPriority::Background, "background", - "Minimum priority, runs on idle CPUs. " - "May leave 'performance' cores unused."), - clEnumValN(llvm::ThreadPriority::Low, "low", - "Reduced priority compared to interactive work."), - clEnumValN(llvm::ThreadPriority::Default, "normal", - "Same priority as other clangd work.")), - init(llvm::ThreadPriority::Low), -}; +#define PREFIX(NAME, VALUE) \ + static constexpr StringLiteral NAME##_init[] = VALUE; \ + static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ + std::size(NAME##_init) - 1); +#include "Opts.inc" +#undef PREFIX -opt<bool> EnableClangTidy{ - "clang-tidy", - cat(Features), - desc("Enable clang-tidy diagnostics"), - init(true), +using namespace llvm::opt; +static constexpr opt::OptTable::Info InfoTable[] = { +#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), +#include "Opts.inc" +#undef OPTION }; -opt<CodeCompleteOptions::CodeCompletionParse> CodeCompletionParse{ - "completion-parse", - cat(Features), - desc("Whether the clang-parser is used for code-completion"), - values(clEnumValN(CodeCompleteOptions::AlwaysParse, "always", - "Block until the parser can be used"), - clEnumValN(CodeCompleteOptions::ParseIfReady, "auto", - "Use text-based completion if the parser " - "is not ready"), - clEnumValN(CodeCompleteOptions::NeverParse, "never", - "Always used text-based completion")), - init(CodeCompleteOptions().RunParser), - Hidden, +class ClangdOptTable : public llvm::opt::GenericOptTable { +public: + ClangdOptTable() : GenericOptTable(InfoTable) { + setGroupedShortOptions(true); + } }; -opt<CodeCompleteOptions::CodeCompletionRankingModel> RankingModel{ - "ranking-model", - cat(Features), - desc("Model to use to rank code-completion items"), - values(clEnumValN(CodeCompleteOptions::Heuristics, "heuristics", - "Use heuristics to rank code completion items"), - clEnumValN(CodeCompleteOptions::DecisionForest, "decision_forest", - "Use Decision Forest model to rank completion items")), - init(CodeCompleteOptions().RankingModel), - Hidden, -}; +enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs }; // FIXME: also support "plain" style where signatures are always omitted. -enum CompletionStyleFlag { Detailed, Bundled }; -opt<CompletionStyleFlag> CompletionStyle{ - "completion-style", - cat(Features), - desc("Granularity of code completion suggestions"), - values(clEnumValN(Detailed, "detailed", - "One completion item for each semantically distinct " - "completion, with full type information"), - clEnumValN(Bundled, "bundled", - "Similar completion items (e.g. function overloads) are " - "combined. Type information shown where possible")), -}; - -opt<std::string> FallbackStyle{ - "fallback-style", - cat(Features), - desc("clang-format style to apply by default when " - "no .clang-format file is found"), - init(clang::format::DefaultFallbackStyle), -}; +enum CompletionStyleFlag { Detailed, Bundled, Invalid }; +enum PCHStorageFlag { Disk, Memory }; -opt<bool> EnableFunctionArgSnippets{ - "function-arg-placeholders", - cat(Features), - desc("When disabled, completions contain only parentheses for " - "function calls. When enabled, completions also contain " - "placeholders for method parameters"), - init(CodeCompleteOptions().EnableFunctionArgSnippets), -}; +} // namespace -opt<CodeCompleteOptions::IncludeInsertion> HeaderInsertion{ - "header-insertion", - cat(Features), - desc("Add #include directives when accepting code completions"), - init(CodeCompleteOptions().InsertIncludes), - values( - clEnumValN(CodeCompleteOptions::IWYU, "iwyu", - "Include what you use. " - "Insert the owning header for top-level symbols, unless the " - "header is already directly included or the symbol is " - "forward-declared"), - clEnumValN( - CodeCompleteOptions::NeverInsert, "never", - "Never insert #include directives as part of code completion")), -}; +namespace clang { +namespace clangd { -opt<bool> ImportInsertions{ - "import-insertions", - cat(Features), - desc("If header insertion is enabled, add #import directives when " - "accepting code completions or fixing includes in Objective-C code"), - init(CodeCompleteOptions().ImportInsertions), -}; +static void parseValueError(const StringRef ArgName, const StringRef Value) { + llvm::errs() << "for the " << ArgName << " option: Cannot find option named " + << Value; + exit(EXIT_FAILURE); +} -opt<bool> HeaderInsertionDecorators{ - "header-insertion-decorators", - cat(Features), - desc("Prepend a circular dot or space before the completion " - "label, depending on whether " - "an include line will be inserted or not"), - init(true), -}; +template <typename T> +static void parseIntArg(const opt::InputArgList &Args, int ID, T &Value, + T Default) { + if (const opt::Arg *A = Args.getLastArg(ID)) { + StringRef V(A->getValue()); + if (!llvm::to_integer(V, Value, 0)) { + errs() << A->getSpelling() + ": expected an integer, but got '" + V + "'"; + exit(1); + } + } else { + Value = Default; + } +} -opt<bool> HiddenFeatures{ - "hidden-features", - cat(Features), - desc("Enable hidden features mostly useful to clangd developers"), - init(false), - Hidden, -}; +static PCHStorageFlag parsePCHStorage(const opt::InputArgList &Args) { + if (Args.hasArg(OPT_pch_storage_EQ)) { + StringRef PCHStorageStr = Args.getLastArgValue(OPT_pch_storage_EQ); + if (PCHStorageStr.equals("disk")) + return PCHStorageFlag::Disk; + if (PCHStorageStr.equals("memory")) + return PCHStorageFlag::Memory; -opt<bool> IncludeIneligibleResults{ - "include-ineligible-results", - cat(Features), - desc("Include ineligible completion results (e.g. private members)"), - init(CodeCompleteOptions().IncludeIneligibleResults), - Hidden, -}; + parseValueError(Args.getArgString(OPT_pch_storage_EQ), PCHStorageStr); + } -RetiredFlag<bool> EnableIndex("index"); -RetiredFlag<bool> SuggestMissingIncludes("suggest-missing-includes"); -RetiredFlag<bool> RecoveryAST("recovery-ast"); -RetiredFlag<bool> RecoveryASTType("recovery-ast-type"); -RetiredFlag<bool> AsyncPreamble("async-preamble"); -RetiredFlag<bool> CollectMainFileRefs("collect-main-file-refs"); -RetiredFlag<bool> CrossFileRename("cross-file-rename"); -RetiredFlag<std::string> ClangTidyChecks("clang-tidy-checks"); -RetiredFlag<bool> InlayHints("inlay-hints"); -RetiredFlag<bool> FoldingRanges("folding-ranges"); -RetiredFlag<bool> IncludeCleanerStdlib("include-cleaner-stdlib"); - -opt<int> LimitResults{ - "limit-results", - cat(Features), - desc("Limit the number of results returned by clangd. " - "0 means no limit (default=100)"), - init(100), -}; + return PCHStorageFlag::Disk; +} -opt<int> ReferencesLimit{ - "limit-references", - cat(Features), - desc("Limit the number of references returned by clangd. " - "0 means no limit (default=1000)"), - init(1000), -}; +static JSONStreamStyle parseInputStyle(const opt::InputArgList &Args) { + if (Args.hasArg(OPT_input_style_EQ)) { + StringRef InputStyleStr = Args.getLastArgValue(OPT_input_style_EQ); + if (InputStyleStr.equals("standard")) + return JSONStreamStyle::Standard; + if (InputStyleStr.equals("delimited")) + return JSONStreamStyle::Delimited; -opt<int> RenameFileLimit{ - "rename-file-limit", - cat(Features), - desc("Limit the number of files to be affected by symbol renaming. " - "0 means no limit (default=50)"), - init(50), -}; + parseValueError(Args.getArgString(OPT_input_style_EQ), InputStyleStr); + } -list<std::string> TweakList{ - "tweaks", - cat(Features), - desc("Specify a list of Tweaks to enable (only for clangd developers)."), - Hidden, - CommaSeparated, -}; + return JSONStreamStyle::Standard; +} -opt<unsigned> WorkerThreadsCount{ - "j", - cat(Misc), - desc("Number of async workers used by clangd. Background index also " - "uses this many workers."), - init(getDefaultAsyncThreadsCount()), -}; +static Logger::Level parseLogLevel(const opt::InputArgList &Args) { + if (Args.hasArg(OPT_log_EQ)) { + StringRef LogLevelStr = Args.getLastArgValue(OPT_log_EQ); + if (LogLevelStr.equals("error")) + return Logger::Level::Error; + if (LogLevelStr.equals("info")) + return Logger::Level::Info; + if (LogLevelStr.equals("verbose")) + return Logger::Level::Verbose; + + parseValueError(Args.getArgString(OPT_log_EQ), LogLevelStr); + } -opt<Path> IndexFile{ - "index-file", - cat(Misc), - desc( - "Index file to build the static index. The file must have been created " - "by a compatible clangd-indexer\n" - "WARNING: This option is experimental only, and will be removed " - "eventually. Don't rely on it"), - init(""), - Hidden, -}; + return Logger::Level::Info; +} -opt<bool> Test{ - "lit-test", - cat(Misc), - desc("Abbreviation for -input-style=delimited -pretty -sync " - "-enable-test-scheme -enable-config=0 -log=verbose -crash-pragmas. " - "Also sets config options: Index.StandardLibrary=false. " - "Intended to simplify lit tests"), - init(false), - Hidden, -}; +static CodeCompleteOptions::CodeCompletionRankingModel +parseRankingModel(const opt::InputArgList &Args) { + if (Args.hasArg(OPT_ranking_model_EQ)) { + StringRef RankingModelStr = Args.getLastArgValue(OPT_ranking_model_EQ); + if (RankingModelStr.equals("heuristics")) + return CodeCompleteOptions::Heuristics; + if (RankingModelStr.equals("decision_forest")) + return CodeCompleteOptions::DecisionForest; -opt<bool> CrashPragmas{ - "crash-pragmas", - cat(Misc), - desc("Respect `#pragma clang __debug crash` and friends."), - init(false), - Hidden, -}; + parseValueError(Args.getArgString(OPT_ranking_model_EQ), RankingModelStr); + } -opt<Path> CheckFile{ - "check", - cat(Misc), - desc("Parse one file in isolation instead of acting as a language server. " - "Useful to investigate/reproduce crashes or configuration problems. " - "With --check=<filename>, attempts to parse a particular file."), - init(""), - ValueOptional, -}; + return CodeCompleteOptions().RankingModel; +} -enum PCHStorageFlag { Disk, Memory }; -opt<PCHStorageFlag> PCHStorage{ - "pch-storage", - cat(Misc), - desc("Storing PCHs in memory increases memory usages, but may " - "improve performance"), - values( - clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"), - clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")), - init(PCHStorageFlag::Disk), -}; +static CompileArgsFrom parseCompileArgsFrom(const opt::InputArgList &Args) { + if (Args.hasArg(OPT_compile_args_from_EQ)) { + StringRef CompileArgsFromStr = + Args.getLastArgValue(OPT_compile_args_from_EQ); + if (CompileArgsFromStr.equals("lsp")) + return CompileArgsFrom::LSPCompileArgs; + if (CompileArgsFromStr.equals("filesystem")) + return CompileArgsFrom::FilesystemCompileArgs; + + parseValueError(Args.getArgString(OPT_compile_args_from_EQ), + CompileArgsFromStr); + } -opt<bool> Sync{ - "sync", - cat(Misc), - desc("Handle client requests on main thread. Background index still uses " - "its own thread."), - init(false), - Hidden, -}; + return CompileArgsFrom::FilesystemCompileArgs; +} -opt<JSONStreamStyle> InputStyle{ - "input-style", - cat(Protocol), - desc("Input JSON stream encoding"), - values( - clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"), - clEnumValN(JSONStreamStyle::Delimited, "delimited", - "messages delimited by --- lines, with # comment support")), - init(JSONStreamStyle::Standard), - Hidden, -}; +static llvm::ThreadPriority +parseBackgroundIndexPriority(const opt::InputArgList &Args) { + if (Args.hasArg(OPT_background_index_priority_EQ)) { + StringRef BackgroundIndexPriorityStr = + Args.getLastArgValue(OPT_background_index_priority_EQ); + if (BackgroundIndexPriorityStr.equals("background")) + return llvm::ThreadPriority::Background; + if (BackgroundIndexPriorityStr.equals("normal")) + return llvm::ThreadPriority::Default; + if (BackgroundIndexPriorityStr.equals("low")) + return llvm::ThreadPriority::Low; + + parseValueError(Args.getArgString(OPT_background_index_priority_EQ), + BackgroundIndexPriorityStr); + } -opt<bool> EnableTestScheme{ - "enable-test-uri-scheme", - cat(Protocol), - desc("Enable 'test:' URI scheme. Only use in lit tests"), - init(false), - Hidden, -}; + return llvm::ThreadPriority::Low; +} -opt<std::string> PathMappingsArg{ - "path-mappings", - cat(Protocol), - desc( - "Translates between client paths (as seen by a remote editor) and " -... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/76767 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits