1 //===--- RefactoringCallbacks.h - Structural query framework ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Provides callbacks to make common kinds of refactorings easy.
12 // The general idea is to construct a matcher expression that describes a
13 // subtree match on the AST and then replace the corresponding source code
14 // either by some specific text or some other AST node.
17 // int main(int argc, char **argv) {
18 // ClangTool Tool(argc, argv);
19 // MatchFinder Finder;
20 // ReplaceStmtWithText Callback("integer", "42");
21 // Finder.AddMatcher(id("integer", expression(integerLiteral())), Callback);
22 // return Tool.run(newFrontendActionFactory(&Finder));
25 // This will replace all integer literals with "42".
27 //===----------------------------------------------------------------------===//
29 #ifndef LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H
30 #define LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H
32 #include "clang/ASTMatchers/ASTMatchFinder.h"
33 #include "clang/Tooling/Refactoring.h"
38 /// \brief Base class for RefactoringCallbacks.
40 /// Collects \c tooling::Replacements while running.
41 class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback {
43 RefactoringCallback();
44 Replacements &getReplacements();
50 /// \brief Adaptor between \c ast_matchers::MatchFinder and \c
51 /// tooling::RefactoringTool.
53 /// Runs AST matchers and stores the \c tooling::Replacements in a map.
54 class ASTMatchRefactorer {
56 explicit ASTMatchRefactorer(
57 std::map<std::string, Replacements> &FileToReplaces);
60 void addMatcher(const T &Matcher, RefactoringCallback *Callback) {
61 MatchFinder.addMatcher(Matcher, Callback);
62 Callbacks.push_back(Callback);
65 void addDynamicMatcher(const ast_matchers::internal::DynTypedMatcher &Matcher,
66 RefactoringCallback *Callback);
68 std::unique_ptr<ASTConsumer> newASTConsumer();
71 friend class RefactoringASTConsumer;
72 std::vector<RefactoringCallback *> Callbacks;
73 ast_matchers::MatchFinder MatchFinder;
74 std::map<std::string, Replacements> &FileToReplaces;
77 /// \brief Replace the text of the statement bound to \c FromId with the text in
79 class ReplaceStmtWithText : public RefactoringCallback {
81 ReplaceStmtWithText(StringRef FromId, StringRef ToText);
82 void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
89 /// \brief Replace the text of an AST node bound to \c FromId with the result of
90 /// evaluating the template in \c ToTemplate.
92 /// Expressions of the form ${NodeName} in \c ToTemplate will be
93 /// replaced by the text of the node bound to ${NodeName}. The string
94 /// "$$" will be replaced by "$".
95 class ReplaceNodeWithTemplate : public RefactoringCallback {
97 static llvm::Expected<std::unique_ptr<ReplaceNodeWithTemplate>>
98 create(StringRef FromId, StringRef ToTemplate);
99 void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
102 struct TemplateElement {
103 enum { Literal, Identifier } Type;
106 ReplaceNodeWithTemplate(llvm::StringRef FromId,
107 std::vector<TemplateElement> Template);
109 std::vector<TemplateElement> Template;
112 /// \brief Replace the text of the statement bound to \c FromId with the text of
113 /// the statement bound to \c ToId.
114 class ReplaceStmtWithStmt : public RefactoringCallback {
116 ReplaceStmtWithStmt(StringRef FromId, StringRef ToId);
117 void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
124 /// \brief Replace an if-statement bound to \c Id with the outdented text of its
125 /// body, choosing the consequent or the alternative based on whether
126 /// \c PickTrueBranch is true.
127 class ReplaceIfStmtWithItsBody : public RefactoringCallback {
129 ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch);
130 void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
134 const bool PickTrueBranch;
137 } // end namespace tooling
138 } // end namespace clang