[refactor] Use CommonOptionsParser in clang-refactor

This commit ensures that CommonOptionsParser works with subcommands. This allows
clang-refactor to use the CommonOptionsParser.

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

llvm-svn: 313260
This commit is contained in:
Alex Lorenz 2017-09-14 13:16:14 +00:00
parent 0b220c7524
commit 3d712c46e6
5 changed files with 27 additions and 60 deletions

View File

@ -84,24 +84,26 @@ std::vector<CompileCommand> ArgumentsAdjustingCompilations::adjustCommands(
CommonOptionsParser::CommonOptionsParser( CommonOptionsParser::CommonOptionsParser(
int &argc, const char **argv, cl::OptionCategory &Category, int &argc, const char **argv, cl::OptionCategory &Category,
llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) { llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden); static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden,
cl::sub(*cl::AllSubCommands));
static cl::opt<std::string> BuildPath("p", cl::desc("Build path"), static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
cl::Optional, cl::cat(Category)); cl::Optional, cl::cat(Category),
cl::sub(*cl::AllSubCommands));
static cl::list<std::string> SourcePaths( static cl::list<std::string> SourcePaths(
cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag, cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag,
cl::cat(Category)); cl::cat(Category), cl::sub(*cl::AllSubCommands));
static cl::list<std::string> ArgsAfter( static cl::list<std::string> ArgsAfter(
"extra-arg", "extra-arg",
cl::desc("Additional argument to append to the compiler command line"), cl::desc("Additional argument to append to the compiler command line"),
cl::cat(Category)); cl::cat(Category), cl::sub(*cl::AllSubCommands));
static cl::list<std::string> ArgsBefore( static cl::list<std::string> ArgsBefore(
"extra-arg-before", "extra-arg-before",
cl::desc("Additional argument to prepend to the compiler command line"), cl::desc("Additional argument to prepend to the compiler command line"),
cl::cat(Category)); cl::cat(Category), cl::sub(*cl::AllSubCommands));
cl::HideUnrelatedOptions(Category); cl::HideUnrelatedOptions(Category);

View File

@ -1,4 +1,4 @@
// RUN: clang-refactor local-rename -selection=test:%s -no-dbs %s | FileCheck %s // RUN: clang-refactor local-rename -selection=test:%s %s -- | FileCheck %s
class Baz { class Baz {
int /*range=*/Foo; // CHECK: int /*range=*/Bar; int /*range=*/Foo; // CHECK: int /*range=*/Bar;

View File

@ -1,6 +1,3 @@
// RUN: not clang-refactor 2>&1 | FileCheck --check-prefix=MISSING_ACTION %s // RUN: not clang-refactor 2>&1 | FileCheck --check-prefix=MISSING_ACTION %s
// MISSING_ACTION: error: no refactoring action given // MISSING_ACTION: error: no refactoring action given
// MISSING_ACTION-NEXT: note: the following actions are supported: // MISSING_ACTION-NEXT: note: the following actions are supported:
// RUN: not clang-refactor local-rename -no-dbs 2>&1 | FileCheck --check-prefix=MISSING_SOURCES %s
// MISSING_SOURCES: error: must provide paths to the source files when '-no-dbs' is used

View File

@ -1,4 +1,4 @@
// RUN: clang-refactor local-rename -selection=test:%s -no-dbs -v %s 2>&1 | FileCheck %s // RUN: clang-refactor local-rename -selection=test:%s -v %s -- 2>&1 | FileCheck %s
/*range=*/int test; /*range=*/int test;
@ -11,12 +11,12 @@
/*range named =+0*/int test5; /*range named =+0*/int test5;
// CHECK: Test selection group '': // CHECK: Test selection group '':
// CHECK-NEXT: 100-100 // CHECK-NEXT: 95-95
// CHECK-NEXT: 153-153 // CHECK-NEXT: 148-148
// CHECK-NEXT: 192-192 // CHECK-NEXT: 187-187
// CHECK-NEXT: Test selection group 'named': // CHECK-NEXT: Test selection group 'named':
// CHECK-NEXT: 127-127 // CHECK-NEXT: 122-122
// CHECK-NEXT: 213-213 // CHECK-NEXT: 208-208
// The following invocations are in the default group: // The following invocations are in the default group:

View File

@ -15,6 +15,7 @@
#include "TestSupport.h" #include "TestSupport.h"
#include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/RefactoringAction.h" #include "clang/Tooling/Refactoring/RefactoringAction.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h" #include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
@ -33,12 +34,6 @@ namespace opts {
static cl::OptionCategory CommonRefactorOptions("Common refactoring options"); static cl::OptionCategory CommonRefactorOptions("Common refactoring options");
static cl::opt<bool>
NoDatabases("no-dbs",
cl::desc("Ignore external databases including Clang's "
"compilation database and indexer stores"),
cl::cat(CommonRefactorOptions), cl::sub(*cl::AllSubCommands));
static cl::opt<bool> Verbose("v", cl::desc("Use verbose output"), static cl::opt<bool> Verbose("v", cl::desc("Use verbose output"),
cl::cat(CommonRefactorOptions), cl::cat(CommonRefactorOptions),
cl::sub(*cl::AllSubCommands)); cl::sub(*cl::AllSubCommands));
@ -129,10 +124,6 @@ public:
cl::OptionCategory &Category) cl::OptionCategory &Category)
: SubCommand(Action->getCommand(), Action->getDescription()), : SubCommand(Action->getCommand(), Action->getDescription()),
Action(std::move(Action)), ActionRules(std::move(ActionRules)) { Action(std::move(Action)), ActionRules(std::move(ActionRules)) {
Sources = llvm::make_unique<cl::list<std::string>>(
cl::Positional, cl::ZeroOrMore, cl::desc("<source0> [... <sourceN>]"),
cl::cat(Category), cl::sub(*this));
// Check if the selection option is supported. // Check if the selection option is supported.
bool HasSelection = false; bool HasSelection = false;
for (const auto &Rule : this->ActionRules) { for (const auto &Rule : this->ActionRules) {
@ -169,13 +160,9 @@ public:
assert(Selection && "selection not supported!"); assert(Selection && "selection not supported!");
return ParsedSelection.get(); return ParsedSelection.get();
} }
ArrayRef<std::string> getSources() const { return *Sources; }
private: private:
std::unique_ptr<RefactoringAction> Action; std::unique_ptr<RefactoringAction> Action;
RefactoringActionRules ActionRules; RefactoringActionRules ActionRules;
std::unique_ptr<cl::list<std::string>> Sources;
std::unique_ptr<cl::opt<std::string>> Selection; std::unique_ptr<cl::opt<std::string>> Selection;
std::unique_ptr<SourceSelectionArgument> ParsedSelection; std::unique_ptr<SourceSelectionArgument> ParsedSelection;
}; };
@ -221,20 +208,9 @@ public:
/// Parses the translation units that were given to the subcommand using /// Parses the translation units that were given to the subcommand using
/// the 'sources' option and invokes the callback for each parsed /// the 'sources' option and invokes the callback for each parsed
/// translation unit. /// translation unit.
bool foreachTranslationUnit(RefactoringActionSubcommand &Subcommand, bool foreachTranslationUnit(const CompilationDatabase &DB,
ArrayRef<std::string> Sources,
TUCallbackType Callback) { TUCallbackType Callback) {
std::unique_ptr<CompilationDatabase> Compilations;
if (opts::NoDatabases) {
// FIXME (Alex L): Support compilation options.
Compilations =
llvm::make_unique<clang::tooling::FixedCompilationDatabase>(
".", std::vector<std::string>());
} else {
// FIXME (Alex L): Support compilation database.
llvm::errs() << "compilation databases are not supported yet!\n";
return true;
}
class ToolASTConsumer : public ASTConsumer { class ToolASTConsumer : public ASTConsumer {
public: public:
TUCallbackType Callback; TUCallbackType Callback;
@ -254,7 +230,7 @@ public:
} }
}; };
ClangTool Tool(*Compilations, Subcommand.getSources()); ClangTool Tool(DB, Sources);
ActionWrapper ToolAction(std::move(Callback)); ActionWrapper ToolAction(std::move(Callback));
std::unique_ptr<tooling::FrontendActionFactory> Factory = std::unique_ptr<tooling::FrontendActionFactory> Factory =
tooling::newFrontendActionFactory(&ToolAction); tooling::newFrontendActionFactory(&ToolAction);
@ -277,7 +253,9 @@ public:
} }
} }
bool invokeAction(RefactoringActionSubcommand &Subcommand) { bool invokeAction(RefactoringActionSubcommand &Subcommand,
const CompilationDatabase &DB,
ArrayRef<std::string> Sources) {
// Find a set of matching rules. // Find a set of matching rules.
SmallVector<RefactoringActionRule *, 4> MatchingRules; SmallVector<RefactoringActionRule *, 4> MatchingRules;
llvm::StringSet<> MissingOptions; llvm::StringSet<> MissingOptions;
@ -303,7 +281,7 @@ public:
bool HasFailed = false; bool HasFailed = false;
ClangRefactorConsumer Consumer; ClangRefactorConsumer Consumer;
if (foreachTranslationUnit(Subcommand, [&](ASTContext &AST) { if (foreachTranslationUnit(DB, Sources, [&](ASTContext &AST) {
RefactoringRuleContext Context(AST.getSourceManager()); RefactoringRuleContext Context(AST.getSourceManager());
Context.setASTContext(AST); Context.setASTContext(AST);
@ -347,12 +325,9 @@ public:
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
ClangRefactorTool Tool; ClangRefactorTool Tool;
// FIXME: Use LibTooling's CommonOptions parser when subcommands are supported CommonOptionsParser Options(
// by it. argc, argv, opts::CommonRefactorOptions, cl::ZeroOrMore,
cl::HideUnrelatedOptions(opts::CommonRefactorOptions); "Clang-based refactoring tool for C, C++ and Objective-C");
cl::ParseCommandLineOptions(
argc, argv, "Clang-based refactoring tool for C, C++ and Objective-C");
cl::PrintOptionValues();
// Figure out which action is specified by the user. The user must specify // Figure out which action is specified by the user. The user must specify
// the action using a command-line subcommand, e.g. the invocation // the action using a command-line subcommand, e.g. the invocation
@ -374,17 +349,10 @@ int main(int argc, const char **argv) {
} }
RefactoringActionSubcommand &ActionCommand = **It; RefactoringActionSubcommand &ActionCommand = **It;
ArrayRef<std::string> Sources = ActionCommand.getSources();
// When -no-dbs is used, at least one file (TU) must be given to any
// subcommand.
if (opts::NoDatabases && Sources.empty()) {
llvm::errs() << "error: must provide paths to the source files when "
"'-no-dbs' is used\n";
return 1;
}
if (ActionCommand.parseArguments()) if (ActionCommand.parseArguments())
return 1; return 1;
if (Tool.invokeAction(ActionCommand)) if (Tool.invokeAction(ActionCommand, Options.getCompilations(),
Options.getSourcePathList()))
return 1; return 1;
return 0; return 0;