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