[llvm-branch-commits] [clang-tools-extra] [clang] [llvm] [Clangd] Migrate command line options parsing to opttable. (PR #76767)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jan 2 16:04:17 PST 2024
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
More information about the llvm-branch-commits
mailing list