Home | History | Annotate | Line # | Download | only in clang-refactor
      1 //===--- ClangRefactor.cpp - Clang-based refactoring tool -----------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 ///
      9 /// \file
     10 /// This file implements a clang-refactor tool that performs various
     11 /// source transformations.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "TestSupport.h"
     16 #include "clang/Frontend/CommandLineSourceLoc.h"
     17 #include "clang/Frontend/TextDiagnosticPrinter.h"
     18 #include "clang/Rewrite/Core/Rewriter.h"
     19 #include "clang/Tooling/CommonOptionsParser.h"
     20 #include "clang/Tooling/Refactoring.h"
     21 #include "clang/Tooling/Refactoring/RefactoringAction.h"
     22 #include "clang/Tooling/Refactoring/RefactoringOptions.h"
     23 #include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
     24 #include "clang/Tooling/Tooling.h"
     25 #include "llvm/Support/CommandLine.h"
     26 #include "llvm/Support/FileSystem.h"
     27 #include "llvm/Support/Signals.h"
     28 #include "llvm/Support/raw_ostream.h"
     29 #include <string>
     30 
     31 using namespace clang;
     32 using namespace tooling;
     33 using namespace refactor;
     34 namespace cl = llvm::cl;
     35 
     36 namespace opts {
     37 
     38 static cl::OptionCategory CommonRefactorOptions("Refactoring options");
     39 
     40 static cl::opt<bool> Verbose("v", cl::desc("Use verbose output"),
     41                              cl::cat(cl::GeneralCategory),
     42                              cl::sub(*cl::AllSubCommands));
     43 
     44 static cl::opt<bool> Inplace("i", cl::desc("Inplace edit <file>s"),
     45                              cl::cat(cl::GeneralCategory),
     46                              cl::sub(*cl::AllSubCommands));
     47 
     48 } // end namespace opts
     49 
     50 namespace {
     51 
     52 /// Stores the parsed `-selection` argument.
     53 class SourceSelectionArgument {
     54 public:
     55   virtual ~SourceSelectionArgument() {}
     56 
     57   /// Parse the `-selection` argument.
     58   ///
     59   /// \returns A valid argument when the parse succedeed, null otherwise.
     60   static std::unique_ptr<SourceSelectionArgument> fromString(StringRef Value);
     61 
     62   /// Prints any additional state associated with the selection argument to
     63   /// the given output stream.
     64   virtual void print(raw_ostream &OS) {}
     65 
     66   /// Returns a replacement refactoring result consumer (if any) that should
     67   /// consume the results of a refactoring operation.
     68   ///
     69   /// The replacement refactoring result consumer is used by \c
     70   /// TestSourceSelectionArgument to inject a test-specific result handling
     71   /// logic into the refactoring operation. The test-specific consumer
     72   /// ensures that the individual results in a particular test group are
     73   /// identical.
     74   virtual std::unique_ptr<ClangRefactorToolConsumerInterface>
     75   createCustomConsumer() {
     76     return nullptr;
     77   }
     78 
     79   /// Runs the give refactoring function for each specified selection.
     80   ///
     81   /// \returns true if an error occurred, false otherwise.
     82   virtual bool
     83   forAllRanges(const SourceManager &SM,
     84                llvm::function_ref<void(SourceRange R)> Callback) = 0;
     85 };
     86 
     87 /// Stores the parsed -selection=test:<filename> option.
     88 class TestSourceSelectionArgument final : public SourceSelectionArgument {
     89 public:
     90   TestSourceSelectionArgument(TestSelectionRangesInFile TestSelections)
     91       : TestSelections(std::move(TestSelections)) {}
     92 
     93   void print(raw_ostream &OS) override { TestSelections.dump(OS); }
     94 
     95   std::unique_ptr<ClangRefactorToolConsumerInterface>
     96   createCustomConsumer() override {
     97     return TestSelections.createConsumer();
     98   }
     99 
    100   /// Testing support: invokes the selection action for each selection range in
    101   /// the test file.
    102   bool forAllRanges(const SourceManager &SM,
    103                     llvm::function_ref<void(SourceRange R)> Callback) override {
    104     return TestSelections.foreachRange(SM, Callback);
    105   }
    106 
    107 private:
    108   TestSelectionRangesInFile TestSelections;
    109 };
    110 
    111 /// Stores the parsed -selection=filename:line:column[-line:column] option.
    112 class SourceRangeSelectionArgument final : public SourceSelectionArgument {
    113 public:
    114   SourceRangeSelectionArgument(ParsedSourceRange Range)
    115       : Range(std::move(Range)) {}
    116 
    117   bool forAllRanges(const SourceManager &SM,
    118                     llvm::function_ref<void(SourceRange R)> Callback) override {
    119     auto FE = SM.getFileManager().getFile(Range.FileName);
    120     FileID FID = FE ? SM.translateFile(*FE) : FileID();
    121     if (!FE || FID.isInvalid()) {
    122       llvm::errs() << "error: -selection=" << Range.FileName
    123                    << ":... : given file is not in the target TU\n";
    124       return true;
    125     }
    126 
    127     SourceLocation Start = SM.getMacroArgExpandedLocation(
    128         SM.translateLineCol(FID, Range.Begin.first, Range.Begin.second));
    129     SourceLocation End = SM.getMacroArgExpandedLocation(
    130         SM.translateLineCol(FID, Range.End.first, Range.End.second));
    131     if (Start.isInvalid() || End.isInvalid()) {
    132       llvm::errs() << "error: -selection=" << Range.FileName << ':'
    133                    << Range.Begin.first << ':' << Range.Begin.second << '-'
    134                    << Range.End.first << ':' << Range.End.second
    135                    << " : invalid source location\n";
    136       return true;
    137     }
    138     Callback(SourceRange(Start, End));
    139     return false;
    140   }
    141 
    142 private:
    143   ParsedSourceRange Range;
    144 };
    145 
    146 std::unique_ptr<SourceSelectionArgument>
    147 SourceSelectionArgument::fromString(StringRef Value) {
    148   if (Value.startswith("test:")) {
    149     StringRef Filename = Value.drop_front(strlen("test:"));
    150     Optional<TestSelectionRangesInFile> ParsedTestSelection =
    151         findTestSelectionRanges(Filename);
    152     if (!ParsedTestSelection)
    153       return nullptr; // A parsing error was already reported.
    154     return std::make_unique<TestSourceSelectionArgument>(
    155         std::move(*ParsedTestSelection));
    156   }
    157   Optional<ParsedSourceRange> Range = ParsedSourceRange::fromString(Value);
    158   if (Range)
    159     return std::make_unique<SourceRangeSelectionArgument>(std::move(*Range));
    160   llvm::errs() << "error: '-selection' option must be specified using "
    161                   "<file>:<line>:<column> or "
    162                   "<file>:<line>:<column>-<line>:<column> format\n";
    163   return nullptr;
    164 }
    165 
    166 /// A container that stores the command-line options used by a single
    167 /// refactoring option.
    168 class RefactoringActionCommandLineOptions {
    169 public:
    170   void addStringOption(const RefactoringOption &Option,
    171                        std::unique_ptr<cl::opt<std::string>> CLOption) {
    172     StringOptions[&Option] = std::move(CLOption);
    173   }
    174 
    175   const cl::opt<std::string> &
    176   getStringOption(const RefactoringOption &Opt) const {
    177     auto It = StringOptions.find(&Opt);
    178     return *It->second;
    179   }
    180 
    181 private:
    182   llvm::DenseMap<const RefactoringOption *,
    183                  std::unique_ptr<cl::opt<std::string>>>
    184       StringOptions;
    185 };
    186 
    187 /// Passes the command-line option values to the options used by a single
    188 /// refactoring action rule.
    189 class CommandLineRefactoringOptionVisitor final
    190     : public RefactoringOptionVisitor {
    191 public:
    192   CommandLineRefactoringOptionVisitor(
    193       const RefactoringActionCommandLineOptions &Options)
    194       : Options(Options) {}
    195 
    196   void visit(const RefactoringOption &Opt,
    197              Optional<std::string> &Value) override {
    198     const cl::opt<std::string> &CLOpt = Options.getStringOption(Opt);
    199     if (!CLOpt.getValue().empty()) {
    200       Value = CLOpt.getValue();
    201       return;
    202     }
    203     Value = None;
    204     if (Opt.isRequired())
    205       MissingRequiredOptions.push_back(&Opt);
    206   }
    207 
    208   ArrayRef<const RefactoringOption *> getMissingRequiredOptions() const {
    209     return MissingRequiredOptions;
    210   }
    211 
    212 private:
    213   llvm::SmallVector<const RefactoringOption *, 4> MissingRequiredOptions;
    214   const RefactoringActionCommandLineOptions &Options;
    215 };
    216 
    217 /// Creates the refactoring options used by all the rules in a single
    218 /// refactoring action.
    219 class CommandLineRefactoringOptionCreator final
    220     : public RefactoringOptionVisitor {
    221 public:
    222   CommandLineRefactoringOptionCreator(
    223       cl::OptionCategory &Category, cl::SubCommand &Subcommand,
    224       RefactoringActionCommandLineOptions &Options)
    225       : Category(Category), Subcommand(Subcommand), Options(Options) {}
    226 
    227   void visit(const RefactoringOption &Opt, Optional<std::string> &) override {
    228     if (Visited.insert(&Opt).second)
    229       Options.addStringOption(Opt, create<std::string>(Opt));
    230   }
    231 
    232 private:
    233   template <typename T>
    234   std::unique_ptr<cl::opt<T>> create(const RefactoringOption &Opt) {
    235     if (!OptionNames.insert(Opt.getName()).second)
    236       llvm::report_fatal_error("Multiple identical refactoring options "
    237                                "specified for one refactoring action");
    238     // FIXME: cl::Required can be specified when this option is present
    239     // in all rules in an action.
    240     return std::make_unique<cl::opt<T>>(
    241         Opt.getName(), cl::desc(Opt.getDescription()), cl::Optional,
    242         cl::cat(Category), cl::sub(Subcommand));
    243   }
    244 
    245   llvm::SmallPtrSet<const RefactoringOption *, 8> Visited;
    246   llvm::StringSet<> OptionNames;
    247   cl::OptionCategory &Category;
    248   cl::SubCommand &Subcommand;
    249   RefactoringActionCommandLineOptions &Options;
    250 };
    251 
    252 /// A subcommand that corresponds to individual refactoring action.
    253 class RefactoringActionSubcommand : public cl::SubCommand {
    254 public:
    255   RefactoringActionSubcommand(std::unique_ptr<RefactoringAction> Action,
    256                               RefactoringActionRules ActionRules,
    257                               cl::OptionCategory &Category)
    258       : SubCommand(Action->getCommand(), Action->getDescription()),
    259         Action(std::move(Action)), ActionRules(std::move(ActionRules)) {
    260     // Check if the selection option is supported.
    261     for (const auto &Rule : this->ActionRules) {
    262       if (Rule->hasSelectionRequirement()) {
    263         Selection = std::make_unique<cl::opt<std::string>>(
    264             "selection",
    265             cl::desc(
    266                 "The selected source range in which the refactoring should "
    267                 "be initiated (<file>:<line>:<column>-<line>:<column> or "
    268                 "<file>:<line>:<column>)"),
    269             cl::cat(Category), cl::sub(*this));
    270         break;
    271       }
    272     }
    273     // Create the refactoring options.
    274     for (const auto &Rule : this->ActionRules) {
    275       CommandLineRefactoringOptionCreator OptionCreator(Category, *this,
    276                                                         Options);
    277       Rule->visitRefactoringOptions(OptionCreator);
    278     }
    279   }
    280 
    281   ~RefactoringActionSubcommand() { unregisterSubCommand(); }
    282 
    283   const RefactoringActionRules &getActionRules() const { return ActionRules; }
    284 
    285   /// Parses the "-selection" command-line argument.
    286   ///
    287   /// \returns true on error, false otherwise.
    288   bool parseSelectionArgument() {
    289     if (Selection) {
    290       ParsedSelection = SourceSelectionArgument::fromString(*Selection);
    291       if (!ParsedSelection)
    292         return true;
    293     }
    294     return false;
    295   }
    296 
    297   SourceSelectionArgument *getSelection() const {
    298     assert(Selection && "selection not supported!");
    299     return ParsedSelection.get();
    300   }
    301 
    302   const RefactoringActionCommandLineOptions &getOptions() const {
    303     return Options;
    304   }
    305 
    306 private:
    307   std::unique_ptr<RefactoringAction> Action;
    308   RefactoringActionRules ActionRules;
    309   std::unique_ptr<cl::opt<std::string>> Selection;
    310   std::unique_ptr<SourceSelectionArgument> ParsedSelection;
    311   RefactoringActionCommandLineOptions Options;
    312 };
    313 
    314 class ClangRefactorConsumer final : public ClangRefactorToolConsumerInterface {
    315 public:
    316   ClangRefactorConsumer(AtomicChanges &Changes) : SourceChanges(&Changes) {}
    317 
    318   void handleError(llvm::Error Err) override {
    319     Optional<PartialDiagnosticAt> Diag = DiagnosticError::take(Err);
    320     if (!Diag) {
    321       llvm::errs() << llvm::toString(std::move(Err)) << "\n";
    322       return;
    323     }
    324     llvm::cantFail(std::move(Err)); // This is a success.
    325     DiagnosticBuilder DB(
    326         getDiags().Report(Diag->first, Diag->second.getDiagID()));
    327     Diag->second.Emit(DB);
    328   }
    329 
    330   void handle(AtomicChanges Changes) override {
    331     SourceChanges->insert(SourceChanges->begin(), Changes.begin(),
    332                           Changes.end());
    333   }
    334 
    335   void handle(SymbolOccurrences Occurrences) override {
    336     llvm_unreachable("symbol occurrence results are not handled yet");
    337   }
    338 
    339 private:
    340   AtomicChanges *SourceChanges;
    341 };
    342 
    343 class ClangRefactorTool {
    344 public:
    345   ClangRefactorTool()
    346       : SelectedSubcommand(nullptr), MatchingRule(nullptr),
    347         Consumer(new ClangRefactorConsumer(Changes)), HasFailed(false) {
    348     std::vector<std::unique_ptr<RefactoringAction>> Actions =
    349         createRefactoringActions();
    350 
    351     // Actions must have unique command names so that we can map them to one
    352     // subcommand.
    353     llvm::StringSet<> CommandNames;
    354     for (const auto &Action : Actions) {
    355       if (!CommandNames.insert(Action->getCommand()).second) {
    356         llvm::errs() << "duplicate refactoring action command '"
    357                      << Action->getCommand() << "'!";
    358         exit(1);
    359       }
    360     }
    361 
    362     // Create subcommands and command-line options.
    363     for (auto &Action : Actions) {
    364       SubCommands.push_back(std::make_unique<RefactoringActionSubcommand>(
    365           std::move(Action), Action->createActiveActionRules(),
    366           opts::CommonRefactorOptions));
    367     }
    368   }
    369 
    370   // Initializes the selected subcommand and refactoring rule based on the
    371   // command line options.
    372   llvm::Error Init() {
    373     auto Subcommand = getSelectedSubcommand();
    374     if (!Subcommand)
    375       return Subcommand.takeError();
    376     auto Rule = getMatchingRule(**Subcommand);
    377     if (!Rule)
    378       return Rule.takeError();
    379 
    380     SelectedSubcommand = *Subcommand;
    381     MatchingRule = *Rule;
    382 
    383     return llvm::Error::success();
    384   }
    385 
    386   bool hasFailed() const { return HasFailed; }
    387 
    388   using TUCallbackType = std::function<void(ASTContext &)>;
    389 
    390   // Callback of an AST action. This invokes the matching rule on the given AST.
    391   void callback(ASTContext &AST) {
    392     assert(SelectedSubcommand && MatchingRule && Consumer);
    393     RefactoringRuleContext Context(AST.getSourceManager());
    394     Context.setASTContext(AST);
    395 
    396     // If the selection option is test specific, we use a test-specific
    397     // consumer.
    398     std::unique_ptr<ClangRefactorToolConsumerInterface> TestConsumer;
    399     bool HasSelection = MatchingRule->hasSelectionRequirement();
    400     if (HasSelection)
    401       TestConsumer = SelectedSubcommand->getSelection()->createCustomConsumer();
    402     ClangRefactorToolConsumerInterface *ActiveConsumer =
    403         TestConsumer ? TestConsumer.get() : Consumer.get();
    404     ActiveConsumer->beginTU(AST);
    405 
    406     auto InvokeRule = [&](RefactoringResultConsumer &Consumer) {
    407       if (opts::Verbose)
    408         logInvocation(*SelectedSubcommand, Context);
    409       MatchingRule->invoke(*ActiveConsumer, Context);
    410     };
    411     if (HasSelection) {
    412       assert(SelectedSubcommand->getSelection() &&
    413              "Missing selection argument?");
    414       if (opts::Verbose)
    415         SelectedSubcommand->getSelection()->print(llvm::outs());
    416       if (SelectedSubcommand->getSelection()->forAllRanges(
    417               Context.getSources(), [&](SourceRange R) {
    418                 Context.setSelectionRange(R);
    419                 InvokeRule(*ActiveConsumer);
    420               }))
    421         HasFailed = true;
    422       ActiveConsumer->endTU();
    423       return;
    424     }
    425     InvokeRule(*ActiveConsumer);
    426     ActiveConsumer->endTU();
    427   }
    428 
    429   llvm::Expected<std::unique_ptr<FrontendActionFactory>>
    430   getFrontendActionFactory() {
    431     class ToolASTConsumer : public ASTConsumer {
    432     public:
    433       TUCallbackType Callback;
    434       ToolASTConsumer(TUCallbackType Callback)
    435           : Callback(std::move(Callback)) {}
    436 
    437       void HandleTranslationUnit(ASTContext &Context) override {
    438         Callback(Context);
    439       }
    440     };
    441     class ToolASTAction : public ASTFrontendAction {
    442     public:
    443       explicit ToolASTAction(TUCallbackType Callback)
    444           : Callback(std::move(Callback)) {}
    445 
    446     protected:
    447       std::unique_ptr<clang::ASTConsumer>
    448       CreateASTConsumer(clang::CompilerInstance &compiler,
    449                         StringRef /* dummy */) override {
    450         std::unique_ptr<clang::ASTConsumer> Consumer{
    451             new ToolASTConsumer(Callback)};
    452         return Consumer;
    453       }
    454 
    455     private:
    456       TUCallbackType Callback;
    457     };
    458 
    459     class ToolActionFactory : public FrontendActionFactory {
    460     public:
    461       ToolActionFactory(TUCallbackType Callback)
    462           : Callback(std::move(Callback)) {}
    463 
    464       std::unique_ptr<FrontendAction> create() override {
    465         return std::make_unique<ToolASTAction>(Callback);
    466       }
    467 
    468     private:
    469       TUCallbackType Callback;
    470     };
    471 
    472     return std::make_unique<ToolActionFactory>(
    473         [this](ASTContext &AST) { return callback(AST); });
    474   }
    475 
    476   // FIXME(ioeric): this seems to only works for changes in a single file at
    477   // this point.
    478   bool applySourceChanges() {
    479     std::set<std::string> Files;
    480     for (const auto &Change : Changes)
    481       Files.insert(Change.getFilePath());
    482     // FIXME: Add automatic formatting support as well.
    483     tooling::ApplyChangesSpec Spec;
    484     // FIXME: We should probably cleanup the result by default as well.
    485     Spec.Cleanup = false;
    486     for (const auto &File : Files) {
    487       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferErr =
    488           llvm::MemoryBuffer::getFile(File);
    489       if (!BufferErr) {
    490         llvm::errs() << "error: failed to open " << File << " for rewriting\n";
    491         return true;
    492       }
    493       auto Result = tooling::applyAtomicChanges(File, (*BufferErr)->getBuffer(),
    494                                                 Changes, Spec);
    495       if (!Result) {
    496         llvm::errs() << toString(Result.takeError());
    497         return true;
    498       }
    499 
    500       if (opts::Inplace) {
    501         std::error_code EC;
    502         llvm::raw_fd_ostream OS(File, EC, llvm::sys::fs::OF_TextWithCRLF);
    503         if (EC) {
    504           llvm::errs() << EC.message() << "\n";
    505           return true;
    506         }
    507         OS << *Result;
    508         continue;
    509       }
    510 
    511       llvm::outs() << *Result;
    512     }
    513     return false;
    514   }
    515 
    516 private:
    517   /// Logs an individual refactoring action invocation to STDOUT.
    518   void logInvocation(RefactoringActionSubcommand &Subcommand,
    519                      const RefactoringRuleContext &Context) {
    520     llvm::outs() << "invoking action '" << Subcommand.getName() << "':\n";
    521     if (Context.getSelectionRange().isValid()) {
    522       SourceRange R = Context.getSelectionRange();
    523       llvm::outs() << "  -selection=";
    524       R.getBegin().print(llvm::outs(), Context.getSources());
    525       llvm::outs() << " -> ";
    526       R.getEnd().print(llvm::outs(), Context.getSources());
    527       llvm::outs() << "\n";
    528     }
    529   }
    530 
    531   llvm::Expected<RefactoringActionRule *>
    532   getMatchingRule(RefactoringActionSubcommand &Subcommand) {
    533     SmallVector<RefactoringActionRule *, 4> MatchingRules;
    534     llvm::StringSet<> MissingOptions;
    535 
    536     for (const auto &Rule : Subcommand.getActionRules()) {
    537       CommandLineRefactoringOptionVisitor Visitor(Subcommand.getOptions());
    538       Rule->visitRefactoringOptions(Visitor);
    539       if (Visitor.getMissingRequiredOptions().empty()) {
    540         if (!Rule->hasSelectionRequirement()) {
    541           MatchingRules.push_back(Rule.get());
    542         } else {
    543           Subcommand.parseSelectionArgument();
    544           if (Subcommand.getSelection()) {
    545             MatchingRules.push_back(Rule.get());
    546           } else {
    547             MissingOptions.insert("selection");
    548           }
    549         }
    550       }
    551       for (const RefactoringOption *Opt : Visitor.getMissingRequiredOptions())
    552         MissingOptions.insert(Opt->getName());
    553     }
    554     if (MatchingRules.empty()) {
    555       std::string Error;
    556       llvm::raw_string_ostream OS(Error);
    557       OS << "ERROR: '" << Subcommand.getName()
    558          << "' can't be invoked with the given arguments:\n";
    559       for (const auto &Opt : MissingOptions)
    560         OS << "  missing '-" << Opt.getKey() << "' option\n";
    561       OS.flush();
    562       return llvm::make_error<llvm::StringError>(
    563           Error, llvm::inconvertibleErrorCode());
    564     }
    565     if (MatchingRules.size() != 1) {
    566       return llvm::make_error<llvm::StringError>(
    567           llvm::Twine("ERROR: more than one matching rule of action") +
    568               Subcommand.getName() + "was found with given options.",
    569           llvm::inconvertibleErrorCode());
    570     }
    571     return MatchingRules.front();
    572   }
    573   // Figure out which action is specified by the user. The user must specify the
    574   // action using a command-line subcommand, e.g. the invocation `clang-refactor
    575   // local-rename` corresponds to the `LocalRename` refactoring action. All
    576   // subcommands must have a unique names. This allows us to figure out which
    577   // refactoring action should be invoked by looking at the first subcommand
    578   // that's enabled by LLVM's command-line parser.
    579   llvm::Expected<RefactoringActionSubcommand *> getSelectedSubcommand() {
    580     auto It = llvm::find_if(
    581         SubCommands,
    582         [](const std::unique_ptr<RefactoringActionSubcommand> &SubCommand) {
    583           return !!(*SubCommand);
    584         });
    585     if (It == SubCommands.end()) {
    586       std::string Error;
    587       llvm::raw_string_ostream OS(Error);
    588       OS << "error: no refactoring action given\n";
    589       OS << "note: the following actions are supported:\n";
    590       for (const auto &Subcommand : SubCommands)
    591         OS.indent(2) << Subcommand->getName() << "\n";
    592       OS.flush();
    593       return llvm::make_error<llvm::StringError>(
    594           Error, llvm::inconvertibleErrorCode());
    595     }
    596     RefactoringActionSubcommand *Subcommand = &(**It);
    597     return Subcommand;
    598   }
    599 
    600   std::vector<std::unique_ptr<RefactoringActionSubcommand>> SubCommands;
    601   RefactoringActionSubcommand *SelectedSubcommand;
    602   RefactoringActionRule *MatchingRule;
    603   std::unique_ptr<ClangRefactorToolConsumerInterface> Consumer;
    604   AtomicChanges Changes;
    605   bool HasFailed;
    606 };
    607 
    608 } // end anonymous namespace
    609 
    610 int main(int argc, const char **argv) {
    611   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
    612 
    613   ClangRefactorTool RefactorTool;
    614 
    615   auto ExpectedParser = CommonOptionsParser::create(
    616       argc, argv, cl::GeneralCategory, cl::ZeroOrMore,
    617       "Clang-based refactoring tool for C, C++ and Objective-C");
    618   if (!ExpectedParser) {
    619     llvm::errs() << ExpectedParser.takeError();
    620     return 1;
    621   }
    622   CommonOptionsParser &Options = ExpectedParser.get();
    623 
    624   if (auto Err = RefactorTool.Init()) {
    625     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
    626     return 1;
    627   }
    628 
    629   auto ActionFactory = RefactorTool.getFrontendActionFactory();
    630   if (!ActionFactory) {
    631     llvm::errs() << llvm::toString(ActionFactory.takeError()) << "\n";
    632     return 1;
    633   }
    634   ClangTool Tool(Options.getCompilations(), Options.getSourcePathList());
    635   bool Failed = false;
    636   if (Tool.run(ActionFactory->get()) != 0) {
    637     llvm::errs() << "Failed to run refactoring action on files\n";
    638     // It is possible that TUs are broken while changes are generated correctly,
    639     // so we still try applying changes.
    640     Failed = true;
    641   }
    642   return RefactorTool.applySourceChanges() || Failed ||
    643          RefactorTool.hasFailed();
    644 }
    645