Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp

Issue 1557243002: Update rewrite_to_chrome_style tool to also rename methods. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix bad renaming Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Changes Blink-style names to Chrome-style names. Currently transforms: 5 // Changes Blink-style names to Chrome-style names. Currently transforms:
6 // fields: 6 // fields:
7 // int m_operationCount => int operation_count_ 7 // int m_operationCount => int operation_count_
8 // variables: 8 // variables (including parameters):
9 // int mySuperVariable => int my_super_variable 9 // int mySuperVariable => int my_super_variable
10 // constants: 10 // constants:
11 // const int maxThings => const int kMaxThings 11 // const int maxThings => const int kMaxThings
12 // free functions: 12 // free functions and methods:
13 // void doThisThenThat() => void DoThisAndThat() 13 // void doThisThenThat() => void DoThisAndThat()
14 14
15 #include <assert.h>
15 #include <algorithm> 16 #include <algorithm>
16 #include <memory> 17 #include <memory>
17 #include <string> 18 #include <string>
19 #include <unordered_set>
18 20
19 #include "clang/AST/ASTContext.h" 21 #include "clang/AST/ASTContext.h"
20 #include "clang/ASTMatchers/ASTMatchFinder.h" 22 #include "clang/ASTMatchers/ASTMatchFinder.h"
21 #include "clang/ASTMatchers/ASTMatchers.h" 23 #include "clang/ASTMatchers/ASTMatchers.h"
22 #include "clang/ASTMatchers/ASTMatchersMacros.h" 24 #include "clang/ASTMatchers/ASTMatchersMacros.h"
23 #include "clang/Basic/CharInfo.h" 25 #include "clang/Basic/CharInfo.h"
24 #include "clang/Basic/SourceManager.h" 26 #include "clang/Basic/SourceManager.h"
25 #include "clang/Frontend/FrontendActions.h" 27 #include "clang/Frontend/FrontendActions.h"
26 #include "clang/Lex/Lexer.h" 28 #include "clang/Lex/Lexer.h"
27 #include "clang/Tooling/CommonOptionsParser.h" 29 #include "clang/Tooling/CommonOptionsParser.h"
28 #include "clang/Tooling/Refactoring.h" 30 #include "clang/Tooling/Refactoring.h"
29 #include "clang/Tooling/Tooling.h" 31 #include "clang/Tooling/Tooling.h"
30 #include "llvm/Support/CommandLine.h" 32 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/TargetSelect.h" 33 #include "llvm/Support/TargetSelect.h"
32 34
33 using namespace clang::ast_matchers; 35 using namespace clang::ast_matchers;
34 using clang::tooling::CommonOptionsParser; 36 using clang::tooling::CommonOptionsParser;
35 using clang::tooling::Replacement; 37 using clang::tooling::Replacement;
36 using clang::tooling::Replacements; 38 using clang::tooling::Replacements;
37 using llvm::StringRef; 39 using llvm::StringRef;
38 40
39 namespace { 41 namespace {
40 42
43 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) {
44 return Node.isOverloadedOperator();
45 }
46
41 constexpr char kBlinkFieldPrefix[] = "m_"; 47 constexpr char kBlinkFieldPrefix[] = "m_";
42 constexpr char kBlinkStaticMemberPrefix[] = "s_"; 48 constexpr char kBlinkStaticMemberPrefix[] = "s_";
43 49
44 bool GetNameForDecl(const clang::FunctionDecl& decl, 50 bool GetNameForDecl(const clang::FunctionDecl& decl, std::string& name) {
45 clang::ASTContext* context,
46 std::string& name) {
47 name = decl.getNameAsString(); 51 name = decl.getNameAsString();
48 name[0] = clang::toUppercase(name[0]); 52 name[0] = clang::toUppercase(name[0]);
49 return true; 53 return true;
50 } 54 }
51 55
52 // Helper to convert from a camelCaseName to camel_case_name. It uses some 56 // Helper to convert from a camelCaseName to camel_case_name. It uses some
53 // heuristics to try to handle acronyms in camel case names correctly. 57 // heuristics to try to handle acronyms in camel case names correctly.
54 std::string CamelCaseToUnderscoreCase(StringRef input) { 58 std::string CamelCaseToUnderscoreCase(StringRef input) {
55 std::string output; 59 std::string output;
56 bool needs_underscore = false; 60 bool needs_underscore = false;
(...skipping 19 matching lines...) Expand all
76 // needs a '_' in 'dL'. 80 // needs a '_' in 'dL'.
77 if (i != input.bytes_end() - 1 && was_lowercase && is_uppercase) 81 if (i != input.bytes_end() - 1 && was_lowercase && is_uppercase)
78 needs_underscore = true; 82 needs_underscore = true;
79 was_lowercase = is_lowercase; 83 was_lowercase = is_lowercase;
80 was_uppercase = is_uppercase; 84 was_uppercase = is_uppercase;
81 } 85 }
82 std::reverse(output.begin(), output.end()); 86 std::reverse(output.begin(), output.end());
83 return output; 87 return output;
84 } 88 }
85 89
86 bool GetNameForDecl(const clang::FieldDecl& decl, 90 bool GetNameForDecl(const clang::FieldDecl& decl, std::string& name) {
87 clang::ASTContext* context,
88 std::string& name) {
89 StringRef original_name = decl.getName(); 91 StringRef original_name = decl.getName();
90 // Blink style field names are prefixed with `m_`. If this prefix isn't 92 // Blink style field names are prefixed with `m_`. If this prefix isn't
91 // present, assume it's already been converted to Google style. 93 // present, assume it's already been converted to Google style.
92 if (original_name.size() < strlen(kBlinkFieldPrefix) || 94 if (original_name.size() < strlen(kBlinkFieldPrefix) ||
93 !original_name.startswith(kBlinkFieldPrefix)) 95 !original_name.startswith(kBlinkFieldPrefix))
94 return false; 96 return false;
95 name = CamelCaseToUnderscoreCase( 97 name = CamelCaseToUnderscoreCase(
96 original_name.substr(strlen(kBlinkFieldPrefix))); 98 original_name.substr(strlen(kBlinkFieldPrefix)));
97 // The few examples I could find used struct-style naming with no `_` suffix 99 // The few examples I could find used struct-style naming with no `_` suffix
98 // for unions. 100 // for unions.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 return clang::isa<clang::CharacterLiteral>(initializer) || 132 return clang::isa<clang::CharacterLiteral>(initializer) ||
131 clang::isa<clang::CompoundLiteralExpr>(initializer) || 133 clang::isa<clang::CompoundLiteralExpr>(initializer) ||
132 clang::isa<clang::CXXBoolLiteralExpr>(initializer) || 134 clang::isa<clang::CXXBoolLiteralExpr>(initializer) ||
133 clang::isa<clang::CXXNullPtrLiteralExpr>(initializer) || 135 clang::isa<clang::CXXNullPtrLiteralExpr>(initializer) ||
134 clang::isa<clang::FloatingLiteral>(initializer) || 136 clang::isa<clang::FloatingLiteral>(initializer) ||
135 clang::isa<clang::IntegerLiteral>(initializer) || 137 clang::isa<clang::IntegerLiteral>(initializer) ||
136 clang::isa<clang::StringLiteral>(initializer) || 138 clang::isa<clang::StringLiteral>(initializer) ||
137 clang::isa<clang::UserDefinedLiteral>(initializer); 139 clang::isa<clang::UserDefinedLiteral>(initializer);
138 } 140 }
139 141
140 bool GetNameForDecl(const clang::VarDecl& decl, 142 bool GetNameForDecl(const clang::VarDecl& decl, std::string& name) {
141 clang::ASTContext* context,
142 std::string& name) {
143 StringRef original_name = decl.getName(); 143 StringRef original_name = decl.getName();
144 144
145 // Nothing to do for unnamed parameters. 145 // Nothing to do for unnamed parameters.
146 if (clang::isa<clang::ParmVarDecl>(decl) && original_name.empty()) 146 if (clang::isa<clang::ParmVarDecl>(decl) && original_name.empty())
147 return false; 147 return false;
148 148
149 // static class members match against VarDecls. Blink style dictates that 149 // static class members match against VarDecls. Blink style dictates that
150 // these should be prefixed with `s_`, so strip that off. Also check for `m_` 150 // these should be prefixed with `s_`, so strip that off. Also check for `m_`
151 // and strip that off too, for code that accidentally uses the wrong prefix. 151 // and strip that off too, for code that accidentally uses the wrong prefix.
152 if (original_name.startswith(kBlinkStaticMemberPrefix)) 152 if (original_name.startswith(kBlinkStaticMemberPrefix))
(...skipping 13 matching lines...) Expand all
166 name = CamelCaseToUnderscoreCase(original_name); 166 name = CamelCaseToUnderscoreCase(original_name);
167 } 167 }
168 168
169 if (decl.isStaticDataMember()) { 169 if (decl.isStaticDataMember()) {
170 name += '_'; 170 name += '_';
171 } 171 }
172 172
173 return true; 173 return true;
174 } 174 }
175 175
176 template <typename DeclNodeType, typename TargetTraits> 176 template <typename Type>
177 class RewriterCallbackBase : public MatchFinder::MatchCallback { 177 struct TargetNodeTraits;
178
179 template <>
180 struct TargetNodeTraits<clang::NamedDecl> {
181 static constexpr char kName[] = "decl";
182 static clang::CharSourceRange GetRange(const clang::NamedDecl& decl) {
183 return clang::CharSourceRange::getTokenRange(decl.getLocation());
184 }
185 };
186 constexpr char TargetNodeTraits<clang::NamedDecl>::kName[];
187
188 template <>
189 struct TargetNodeTraits<clang::MemberExpr> {
190 static constexpr char kName[] = "expr";
191 static clang::CharSourceRange GetRange(const clang::MemberExpr& expr) {
192 return clang::CharSourceRange::getTokenRange(expr.getMemberLoc());
193 }
194 };
195 constexpr char TargetNodeTraits<clang::MemberExpr>::kName[];
196
197 template <>
198 struct TargetNodeTraits<clang::DeclRefExpr> {
199 static constexpr char kName[] = "expr";
200 static clang::CharSourceRange GetRange(const clang::DeclRefExpr& expr) {
201 return clang::CharSourceRange::getTokenRange(expr.getLocation());
202 }
203 };
204 constexpr char TargetNodeTraits<clang::DeclRefExpr>::kName[];
205
206 template <>
207 struct TargetNodeTraits<clang::CXXCtorInitializer> {
208 static constexpr char kName[] = "initializer";
209 static clang::CharSourceRange GetRange(
210 const clang::CXXCtorInitializer& init) {
211 return clang::CharSourceRange::getTokenRange(init.getSourceLocation());
212 }
213 };
214 constexpr char TargetNodeTraits<clang::CXXCtorInitializer>::kName[];
215
216 template <typename DeclNode, typename TargetNode>
217 class RewriterBase : public MatchFinder::MatchCallback {
178 public: 218 public:
179 explicit RewriterCallbackBase(Replacements* replacements) 219 explicit RewriterBase(Replacements* replacements)
180 : replacements_(replacements) {} 220 : replacements_(replacements) {}
181 virtual void run(const MatchFinder::MatchResult& result) override { 221
222 void run(const MatchFinder::MatchResult& result) override {
182 std::string name; 223 std::string name;
183 if (!GetNameForDecl(*result.Nodes.getNodeAs<DeclNodeType>("decl"), 224 if (!GetNameForDecl(*result.Nodes.getNodeAs<DeclNode>("decl"), name))
184 result.Context, name))
185 return; 225 return;
186 replacements_->emplace( 226 replacements_->emplace(*result.SourceManager,
187 *result.SourceManager, 227 TargetNodeTraits<TargetNode>::GetRange(
188 TargetTraits::GetRange( 228 *result.Nodes.getNodeAs<TargetNode>(
189 *result.Nodes.getNodeAs<typename TargetTraits::NodeType>( 229 TargetNodeTraits<TargetNode>::kName)),
190 TargetTraits::kName)), 230 name);
191 name);
192 } 231 }
193 232
194 private: 233 private:
195 Replacements* const replacements_; 234 Replacements* const replacements_;
196 }; 235 };
197 236
198 struct DeclTargetTraits { 237 using FieldDeclRewriter = RewriterBase<clang::FieldDecl, clang::NamedDecl>;
199 using NodeType = clang::NamedDecl; 238 using VarDeclRewriter = RewriterBase<clang::VarDecl, clang::NamedDecl>;
200 static constexpr char kName[] = "decl"; 239 using MemberRewriter = RewriterBase<clang::FieldDecl, clang::MemberExpr>;
201 static clang::CharSourceRange GetRange(const NodeType& decl) { 240 using DeclRefRewriter = RewriterBase<clang::VarDecl, clang::DeclRefExpr>;
202 return clang::CharSourceRange::getTokenRange(decl.getLocation()); 241 using FunctionDeclRewriter =
242 RewriterBase<clang::FunctionDecl, clang::NamedDecl>;
243 using FunctionRefRewriter =
244 RewriterBase<clang::FunctionDecl, clang::DeclRefExpr>;
245 using ConstructorInitializerRewriter =
246 RewriterBase<clang::FieldDecl, clang::CXXCtorInitializer>;
247
248 // Helpers for rewriting methods. The tool needs to detect overrides of Blink
249 // methods, and uses two matchers to help accomplish this goal:
250 // - The first matcher matches all method declarations in Blink. When the
251 // callback rewrites the declaration, it also stores a pointer to the
252 // canonical declaration, to record it as a Blink method.
253 // - The second matcher matches all method declarations that are overrides. When
254 // the callback processes the match, it checks if its overriding a method that
255 // was marked as a Blink method. If so, it rewrites the declaration.
256 // - Because an override is determined based on inclusion in the set of Blink
257 // methods, the overridden methods matcher does not need to filter out special
258 // member functions: they get filtered out by virtue of the first matcher.
259 //
260 // This works because per the documentation on MatchFinder:
261 // The order of matches is guaranteed to be equivalent to doing a pre-order
262 // traversal on the AST, and applying the matchers in the order in which they
263 // were added to the MatchFinder.
264 //
265 // Since classes cannot forward declare their base classes, it is guaranteed
266 // that the base class methods will be seen before processing the overridden
267 // methods.
268 class MethodDeclRewriter
269 : public RewriterBase<clang::CXXMethodDecl, clang::NamedDecl> {
270 public:
271 explicit MethodDeclRewriter(Replacements* replacements)
272 : RewriterBase(replacements) {}
273
274 void run(const MatchFinder::MatchResult& result) override {
275 const clang::CXXMethodDecl* method_decl =
276 result.Nodes.getNodeAs<clang::CXXMethodDecl>("decl");
277 // TODO(dcheng): Does this need to check for the override attribute, or is
278 // this good enough?
279 if (method_decl->size_overridden_methods() > 0) {
280 if (!IsBlinkOverride(method_decl))
281 return;
282 } else {
283 blink_methods_.emplace(method_decl->getCanonicalDecl());
284 }
285
286 RewriterBase::run(result);
203 } 287 }
288
289 bool IsBlinkOverride(const clang::CXXMethodDecl* decl) const {
290 assert(decl->size_overridden_methods() > 0);
291 for (auto it = decl->begin_overridden_methods();
292 it != decl->end_overridden_methods(); ++it) {
293 if (blink_methods_.find((*it)->getCanonicalDecl()) !=
294 blink_methods_.end())
295 return true;
296 }
297 return false;
298 }
299
300 private:
301 std::unordered_set<const clang::CXXMethodDecl*> blink_methods_;
204 }; 302 };
205 constexpr char DeclTargetTraits::kName[];
206 303
207 struct ExprTargetTraits { 304 template <typename RewriterBase>
danakj 2016/01/08 02:02:52 This name is conflicty with a real type. The old n
dcheng 2016/01/08 02:14:01 I thought Base might be too vague, but I'll admit
208 using NodeType = clang::Expr; 305 class FilteringMethodRewriter : public RewriterBase {
209 static constexpr char kName[] = "expr"; 306 public:
210 static clang::CharSourceRange GetRange(const NodeType& expr) { 307 FilteringMethodRewriter(const MethodDeclRewriter& decl_rewriter,
211 return clang::CharSourceRange::getTokenRange(expr.getExprLoc()); 308 Replacements* replacements)
309 : RewriterBase(replacements), decl_rewriter_(decl_rewriter) {}
310
311 void run(const MatchFinder::MatchResult& result) override {
312 const clang::CXXMethodDecl* method_decl =
313 result.Nodes.getNodeAs<clang::CXXMethodDecl>("decl");
314 if (method_decl->size_overridden_methods() > 0 &&
315 !decl_rewriter_.IsBlinkOverride(method_decl))
316 return;
317 RewriterBase::run(result);
212 } 318 }
319
320 private:
321 const MethodDeclRewriter& decl_rewriter_;
213 }; 322 };
214 constexpr char ExprTargetTraits::kName[];
215 323
216 struct InitializerTargetTraits { 324 using MethodRefRewriter = FilteringMethodRewriter<
217 using NodeType = clang::CXXCtorInitializer; 325 RewriterBase<clang::CXXMethodDecl, clang::DeclRefExpr>>;
218 static constexpr char kName[] = "initializer"; 326 using MethodMemberRewriter = FilteringMethodRewriter<
219 static clang::CharSourceRange GetRange(const NodeType& init) { 327 RewriterBase<clang::CXXMethodDecl, clang::MemberExpr>>;
220 return clang::CharSourceRange::getTokenRange(init.getSourceLocation());
221 }
222 };
223 constexpr char InitializerTargetTraits::kName[];
224
225 using FunctionDeclRewriterCallback =
226 RewriterCallbackBase<clang::FunctionDecl, DeclTargetTraits>;
227 using FieldDeclRewriterCallback =
228 RewriterCallbackBase<clang::FieldDecl, DeclTargetTraits>;
229 using VarDeclRewriterCallback =
230 RewriterCallbackBase<clang::VarDecl, DeclTargetTraits>;
231
232 using CallRewriterCallback =
233 RewriterCallbackBase<clang::FunctionDecl, ExprTargetTraits>;
234 using MemberRewriterCallback =
235 RewriterCallbackBase<clang::FieldDecl, ExprTargetTraits>;
236 using DeclRefRewriterCallback =
237 RewriterCallbackBase<clang::VarDecl, ExprTargetTraits>;
238
239 using ConstructorInitializerRewriterCallback =
240 RewriterCallbackBase<clang::FieldDecl, InitializerTargetTraits>;
241 328
242 } // namespace 329 } // namespace
243 330
244 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); 331 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
245 332
246 int main(int argc, const char* argv[]) { 333 int main(int argc, const char* argv[]) {
247 // TODO(dcheng): Clang tooling should do this itself. 334 // TODO(dcheng): Clang tooling should do this itself.
248 // http://llvm.org/bugs/show_bug.cgi?id=21627 335 // http://llvm.org/bugs/show_bug.cgi?id=21627
249 llvm::InitializeNativeTarget(); 336 llvm::InitializeNativeTarget();
250 llvm::InitializeNativeTargetAsmParser(); 337 llvm::InitializeNativeTargetAsmParser();
251 llvm::cl::OptionCategory category( 338 llvm::cl::OptionCategory category(
252 "rewrite_to_chrome_style: convert Blink style to Chrome style."); 339 "rewrite_to_chrome_style: convert Blink style to Chrome style.");
253 CommonOptionsParser options(argc, argv, category); 340 CommonOptionsParser options(argc, argv, category);
254 clang::tooling::ClangTool tool(options.getCompilations(), 341 clang::tooling::ClangTool tool(options.getCompilations(),
255 options.getSourcePathList()); 342 options.getSourcePathList());
256 343
257 MatchFinder match_finder; 344 MatchFinder match_finder;
258 Replacements replacements; 345 Replacements replacements;
259 346
260 auto in_blink_namespace = 347 auto in_blink_namespace =
261 decl(hasAncestor(namespaceDecl(anyOf(hasName("blink"), hasName("WTF"))))); 348 decl(hasAncestor(namespaceDecl(anyOf(hasName("blink"), hasName("WTF")))));
262 349
263 // Declaration handling (e.g. function definitions and variable definitions): 350 // Field and variable declarations ========
264 351 // Given
265 // Note: for now, only rewrite standalone functions until the question of JS 352 // int x;
266 // binding integration for class methods is resolved. 353 // struct S {
267 // TODO(dcheng): Since classes in public/ aren't directly web-exposed, just go 354 // int y;
268 // ahead and rewrite those. 355 // };
269 auto function_decl_matcher = 356 // matches |x| and |y|.
270 id("decl", functionDecl(unless(cxxMethodDecl()), in_blink_namespace));
271
272 auto field_decl_matcher = id("decl", fieldDecl(in_blink_namespace)); 357 auto field_decl_matcher = id("decl", fieldDecl(in_blink_namespace));
273 auto var_decl_matcher = id("decl", varDecl(in_blink_namespace)); 358 auto var_decl_matcher = id("decl", varDecl(in_blink_namespace));
274 359
275 FunctionDeclRewriterCallback function_decl_rewriter(&replacements); 360 FieldDeclRewriter field_decl_rewriter(&replacements);
276 match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter);
277 FieldDeclRewriterCallback field_decl_rewriter(&replacements);
278 match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter); 361 match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter);
279 VarDeclRewriterCallback var_decl_rewriter(&replacements); 362
363 VarDeclRewriter var_decl_rewriter(&replacements);
280 match_finder.addMatcher(var_decl_matcher, &var_decl_rewriter); 364 match_finder.addMatcher(var_decl_matcher, &var_decl_rewriter);
281 365
282 // Expression handling (e.g. calling a Blink function or referencing a 366 // Field and variable references ========
283 // variable defined in Blink): 367 // Given
284 auto call_matcher = id("expr", callExpr(callee(function_decl_matcher))); 368 // bool x = true;
369 // if (x) {
370 // ...
371 // }
372 // matches |x| in if (x).
285 auto member_matcher = id("expr", memberExpr(member(field_decl_matcher))); 373 auto member_matcher = id("expr", memberExpr(member(field_decl_matcher)));
286 auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher))); 374 auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher)));
287 375
288 CallRewriterCallback call_rewriter(&replacements); 376 MemberRewriter member_rewriter(&replacements);
289 match_finder.addMatcher(call_matcher, &call_rewriter);
290 MemberRewriterCallback member_rewriter(&replacements);
291 match_finder.addMatcher(member_matcher, &member_rewriter); 377 match_finder.addMatcher(member_matcher, &member_rewriter);
292 DeclRefRewriterCallback decl_ref_rewriter(&replacements); 378
379 DeclRefRewriter decl_ref_rewriter(&replacements);
293 match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter); 380 match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter);
294 381
295 // Function reference handling (e.g. getting a pointer to a function without 382 // Non-method function declarations ========
296 // calling it): 383 // Given
384 // void f();
385 // struct S {
386 // void g();
387 // };
388 // matches |f| but not |g|.
389 auto function_decl_matcher =
390 id("decl", functionDecl(unless(cxxMethodDecl()), in_blink_namespace));
391 FunctionDeclRewriter function_decl_rewriter(&replacements);
392 match_finder.addMatcher(function_decl_matcher, &function_decl_rewriter);
393
394 // Non-method function references ========
395 // Given
396 // f();
397 // void (*p)() = &f;
398 // matches |f()| and |&f|.
297 auto function_ref_matcher = 399 auto function_ref_matcher =
298 id("expr", declRefExpr(to(function_decl_matcher))); 400 id("expr", declRefExpr(to(function_decl_matcher)));
299 match_finder.addMatcher(function_ref_matcher, &call_rewriter); 401 FunctionRefRewriter function_ref_rewriter(&replacements);
402 match_finder.addMatcher(function_ref_matcher, &function_ref_rewriter);
300 403
301 // Initializer handling: 404 // Method declarations ========
danakj 2016/01/08 02:02:52 I like these comments much
405 // Given
406 // struct S {
407 // void g();
408 // };
409 // matches |g|.
410 //
411 // Note: the AST matchers don't provide a good way to match against an
412 // override from a given base class. Instead, the rewriter uses two matchers:
413 // one that matches all method declarations in the Blink namespace, and
414 // another which matches all overridden methods not in the Blink namespace.
415 // The second list is filtered against the first list to determine which
416 // methods are inherited from Blink classes and need to be rewritten.
417 auto blink_method_decl_matcher =
418 id("decl", cxxMethodDecl(unless(anyOf(
419 // Overloaded operators have special names
420 // and should never be renamed.
421 isOverloadedOperator(),
422 // Similarly, constructors and destructors
423 // should not be considered for renaming.
424 cxxConstructorDecl(), cxxDestructorDecl())),
425 in_blink_namespace));
426 // Note that the matcher for overridden methods doesn't need to filter for
427 // special member functions: see implementation of FunctionDeclRewriter for
428 // the full explanation.
429 auto non_blink_overridden_method_decl_matcher =
430 id("decl", cxxMethodDecl(isOverride(), unless(in_blink_namespace)));
431 MethodDeclRewriter method_decl_rewriter(&replacements);
432 match_finder.addMatcher(blink_method_decl_matcher, &method_decl_rewriter);
433 match_finder.addMatcher(non_blink_overridden_method_decl_matcher,
434 &method_decl_rewriter);
435
436 // Method references in a non-member context ========
437 // Given
438 // S s;
439 // s.g();
440 // void (S::*p)() = &S::g;
441 // matches |&S::g| but not |s.g()|.
442 auto blink_method_ref_matcher =
443 id("expr", declRefExpr(to(blink_method_decl_matcher)));
444 auto non_blink_overridden_method_ref_matcher =
445 id("expr", declRefExpr(to(non_blink_overridden_method_decl_matcher)));
446
447 MethodRefRewriter method_ref_rewriter(method_decl_rewriter, &replacements);
448 match_finder.addMatcher(blink_method_ref_matcher, &method_ref_rewriter);
449 match_finder.addMatcher(non_blink_overridden_method_ref_matcher,
450 &method_ref_rewriter);
451
452 // Method references in a member context ========
453 // Given
454 // S s;
455 // s.g();
456 // void (S::*p)() = &S::g;
457 // matches |s.g()| but not |&S::g|.
458 auto blink_method_member_matcher =
459 id("expr", memberExpr(member(blink_method_decl_matcher)));
460 auto non_blink_overridden_method_member_matcher =
461 id("expr", memberExpr(member(non_blink_overridden_method_decl_matcher)));
462
463 MethodMemberRewriter method_member_rewriter(method_decl_rewriter,
464 &replacements);
465 match_finder.addMatcher(blink_method_member_matcher, &method_member_rewriter);
466 match_finder.addMatcher(non_blink_overridden_method_member_matcher,
467 &method_member_rewriter);
468
469 // Initializers ========
470 // Given
471 // struct S {
472 // int x;
473 // S() : x(2) {}
474 // };
475 // matches each initializer in the constructor for S.
302 auto constructor_initializer_matcher = 476 auto constructor_initializer_matcher =
303 cxxConstructorDecl(forEachConstructorInitializer( 477 cxxConstructorDecl(forEachConstructorInitializer(
304 id("initializer", cxxCtorInitializer(forField(field_decl_matcher))))); 478 id("initializer", cxxCtorInitializer(forField(field_decl_matcher)))));
305 479
306 ConstructorInitializerRewriterCallback constructor_initializer_rewriter( 480 ConstructorInitializerRewriter constructor_initializer_rewriter(
307 &replacements); 481 &replacements);
308 match_finder.addMatcher(constructor_initializer_matcher, 482 match_finder.addMatcher(constructor_initializer_matcher,
309 &constructor_initializer_rewriter); 483 &constructor_initializer_rewriter);
310 484
311 std::unique_ptr<clang::tooling::FrontendActionFactory> factory = 485 std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
312 clang::tooling::newFrontendActionFactory(&match_finder); 486 clang::tooling::newFrontendActionFactory(&match_finder);
313 int result = tool.run(factory.get()); 487 int result = tool.run(factory.get());
314 if (result != 0) 488 if (result != 0)
315 return result; 489 return result;
316 490
317 // Serialization format is documented in tools/clang/scripts/run_tool.py 491 // Serialization format is documented in tools/clang/scripts/run_tool.py
318 llvm::outs() << "==== BEGIN EDITS ====\n"; 492 llvm::outs() << "==== BEGIN EDITS ====\n";
319 for (const auto& r : replacements) { 493 for (const auto& r : replacements) {
320 std::string replacement_text = r.getReplacementText().str(); 494 std::string replacement_text = r.getReplacementText().str();
321 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); 495 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
322 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() 496 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
323 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; 497 << ":::" << r.getLength() << ":::" << replacement_text << "\n";
324 } 498 }
325 llvm::outs() << "==== END EDITS ====\n"; 499 llvm::outs() << "==== END EDITS ====\n";
326 500
327 return 0; 501 return 0;
328 } 502 }
OLDNEW
« no previous file with comments | « no previous file | tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698