[clang-tools-extra] 49268a6 - [clangd] Support dexp -c "some command"

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 8 05:02:57 PDT 2020


Author: Sam McCall
Date: 2020-04-08T14:02:49+02:00
New Revision: 49268a678c2f0233f71363b0988d4b159496b036

URL: https://github.com/llvm/llvm-project/commit/49268a678c2f0233f71363b0988d4b159496b036
DIFF: https://github.com/llvm/llvm-project/commit/49268a678c2f0233f71363b0988d4b159496b036.diff

LOG: [clangd] Support dexp -c "some command"

Summary:
It runs one command and exits.
See D77385 for motivation.

Reviewers: mnauw, kbobyrev

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D77645

Added: 
    

Modified: 
    clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
index 66477ad7d173..9bdc88d7d886 100644
--- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
+++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
@@ -14,6 +14,7 @@
 #include "SourceCode.h"
 #include "index/Serialization.h"
 #include "index/dex/Dex.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -29,6 +30,9 @@ llvm::cl::opt<std::string> IndexPath("index-path",
                                      llvm::cl::desc("Path to the index"),
                                      llvm::cl::Positional, llvm::cl::Required);
 
+llvm::cl::opt<std::string>
+    ExecCommand("c", llvm::cl::desc("Command to execute and then exit"));
+
 static const std::string Overview = R"(
 This is an **experimental** interactive tool to process user-provided search
 queries over given symbol collection obtained via clangd-indexer. The
@@ -78,6 +82,7 @@ class Command {
   llvm::cl::opt<bool, false, llvm::cl::parser<bool>> Help{
       "help", llvm::cl::desc("Display available options"),
       llvm::cl::ValueDisallowed, llvm::cl::cat(llvm::cl::GeneralCategory)};
+  // FIXME: Allow commands to signal failure.
   virtual void run() = 0;
 
 protected:
@@ -85,25 +90,27 @@ class Command {
 
 public:
   virtual ~Command() = default;
-  virtual void parseAndRun(llvm::ArrayRef<const char *> Argv,
-                           const char *Overview, const SymbolIndex &Index) {
+  bool parseAndRun(llvm::ArrayRef<const char *> Argv, const char *Overview,
+                   const SymbolIndex &Index) {
     std::string ParseErrs;
     llvm::raw_string_ostream OS(ParseErrs);
     bool Ok = llvm::cl::ParseCommandLineOptions(Argv.size(), Argv.data(),
                                                 Overview, &OS);
+    // must do this before opts are destroyed
+    auto Cleanup = llvm::make_scope_exit(llvm::cl::ResetCommandLineParser);
     if (Help.getNumOccurrences() > 0) {
       // Avoid printing parse errors in this case.
       // (Well, in theory. A bunch get printed to llvm::errs() regardless!)
       llvm::cl::PrintHelpMessage();
-    } else {
-      llvm::outs() << OS.str();
-      if (Ok) {
-        this->Index = &Index;
-        reportTime(Argv[0], [&] { run(); });
-      }
+      return true;
+    }
+
+    llvm::outs() << OS.str();
+    if (Ok) {
+      this->Index = &Index;
+      reportTime(Argv[0], [&] { run(); });
     }
-    llvm::cl::ResetCommandLineParser(); // must do this before opts are
-                                        // destroyed.
+    return Ok;
   }
 };
 
@@ -268,6 +275,34 @@ std::unique_ptr<SymbolIndex> openIndex(llvm::StringRef Index) {
   return loadIndex(Index, /*UseDex=*/true);
 }
 
+bool runCommand(std::string Request, const SymbolIndex &Index) {
+  // Split on spaces and add required null-termination.
+  std::replace(Request.begin(), Request.end(), ' ', '\0');
+  llvm::SmallVector<llvm::StringRef, 8> Args;
+  llvm::StringRef(Request).split(Args, '\0', /*MaxSplit=*/-1,
+                                 /*KeepEmpty=*/false);
+  if (Args.empty())
+    return false;
+  if (Args.front() == "help") {
+    llvm::outs() << "dexp - Index explorer\nCommands:\n";
+    for (const auto &C : CommandInfo)
+      llvm::outs() << llvm::formatv("{0,16} - {1}\n", C.Name, C.Description);
+    llvm::outs() << "Get detailed command help with e.g. `find -help`.\n";
+    return true;
+  }
+  llvm::SmallVector<const char *, 8> FakeArgv;
+  for (llvm::StringRef S : Args)
+    FakeArgv.push_back(S.data()); // Terminated by separator or end of string.
+
+  for (const auto &Cmd : CommandInfo) {
+    if (Cmd.Name == Args.front())
+      return Cmd.Implementation()->parseAndRun(FakeArgv, Cmd.Description,
+                                               Index);
+  }
+  llvm::outs() << "Unknown command. Try 'help'.\n";
+  return false;
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
@@ -289,38 +324,10 @@ int main(int argc, const char *argv[]) {
     return -1;
   }
 
-  llvm::LineEditor LE("dexp");
-
-  while (llvm::Optional<std::string> Request = LE.readLine()) {
-    // Split on spaces and add required null-termination.
-    std::replace(Request->begin(), Request->end(), ' ', '\0');
-    llvm::SmallVector<llvm::StringRef, 8> Args;
-    llvm::StringRef(*Request).split(Args, '\0', /*MaxSplit=*/-1,
-                                    /*KeepEmpty=*/false);
-    if (Args.empty())
-      continue;
-    if (Args.front() == "help") {
-      llvm::outs() << "dexp - Index explorer\nCommands:\n";
-      for (const auto &C : CommandInfo)
-        llvm::outs() << llvm::formatv("{0,16} - {1}\n", C.Name, C.Description);
-      llvm::outs() << "Get detailed command help with e.g. `find -help`.\n";
-      continue;
-    }
-    llvm::SmallVector<const char *, 8> FakeArgv;
-    for (llvm::StringRef S : Args)
-      FakeArgv.push_back(S.data()); // Terminated by separator or end of string.
-
-    bool Recognized = false;
-    for (const auto &Cmd : CommandInfo) {
-      if (Cmd.Name == Args.front()) {
-        Recognized = true;
-        Cmd.Implementation()->parseAndRun(FakeArgv, Cmd.Description, *Index);
-        break;
-      }
-    }
-    if (!Recognized)
-      llvm::outs() << "Unknown command. Try 'help'.\n";
-  }
+  if (!ExecCommand.empty())
+    return runCommand(ExecCommand, *Index) ? 0 : 1;
 
-  return 0;
+  llvm::LineEditor LE("dexp");
+  while (llvm::Optional<std::string> Request = LE.readLine())
+    runCommand(std::move(*Request), *Index);
 }


        


More information about the cfe-commits mailing list