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

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

Issue 2627003003: Add --idl-methods <filepath> parameter for skipping renaming of IDL methods. (Closed)
Patch Set: Being more whitespace-friendly. Created 3 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/blocked_methods.txt » ('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 (including parameters): 8 // variables (including parameters):
9 // int mySuperVariable => int my_super_variable 9 // int mySuperVariable => int my_super_variable
10 // constants: 10 // constants:
(...skipping 16 matching lines...) Expand all
27 #include "clang/Frontend/CompilerInstance.h" 27 #include "clang/Frontend/CompilerInstance.h"
28 #include "clang/Frontend/FrontendActions.h" 28 #include "clang/Frontend/FrontendActions.h"
29 #include "clang/Lex/MacroArgs.h" 29 #include "clang/Lex/MacroArgs.h"
30 #include "clang/Lex/Lexer.h" 30 #include "clang/Lex/Lexer.h"
31 #include "clang/Lex/PPCallbacks.h" 31 #include "clang/Lex/PPCallbacks.h"
32 #include "clang/Lex/Preprocessor.h" 32 #include "clang/Lex/Preprocessor.h"
33 #include "clang/Tooling/CommonOptionsParser.h" 33 #include "clang/Tooling/CommonOptionsParser.h"
34 #include "clang/Tooling/Refactoring.h" 34 #include "clang/Tooling/Refactoring.h"
35 #include "clang/Tooling/Tooling.h" 35 #include "clang/Tooling/Tooling.h"
36 #include "llvm/Support/CommandLine.h" 36 #include "llvm/Support/CommandLine.h"
37 #include "llvm/Support/ErrorOr.h"
38 #include "llvm/Support/LineIterator.h"
39 #include "llvm/Support/MemoryBuffer.h"
37 #include "llvm/Support/TargetSelect.h" 40 #include "llvm/Support/TargetSelect.h"
38 41
39 #include "EditTracker.h" 42 #include "EditTracker.h"
40 43
41 using namespace clang::ast_matchers; 44 using namespace clang::ast_matchers;
42 using clang::tooling::CommonOptionsParser; 45 using clang::tooling::CommonOptionsParser;
43 using clang::tooling::Replacement; 46 using clang::tooling::Replacement;
44 using llvm::StringRef; 47 using llvm::StringRef;
45 48
46 namespace { 49 namespace {
47 50
48 const char kBlinkFieldPrefix[] = "m_"; 51 const char kBlinkFieldPrefix[] = "m_";
49 const char kBlinkStaticMemberPrefix[] = "s_"; 52 const char kBlinkStaticMemberPrefix[] = "s_";
50 const char kGeneratedFileRegex[] = "^gen/|/gen/"; 53 const char kGeneratedFileRegex[] = "^gen/|/gen/";
51 const char kGMockMethodNamePrefix[] = "gmock_"; 54 const char kGMockMethodNamePrefix[] = "gmock_";
55 const char kMethodBlocklistParamName[] = "method-blocklist";
52 56
53 template <typename MatcherType, typename NodeType> 57 template <typename MatcherType, typename NodeType>
54 bool IsMatching(const MatcherType& matcher, 58 bool IsMatching(const MatcherType& matcher,
55 const NodeType& node, 59 const NodeType& node,
56 clang::ASTContext& context) { 60 clang::ASTContext& context) {
57 return !match(matcher, node, context).empty(); 61 return !match(matcher, node, context).empty();
58 } 62 }
59 63
60 const clang::ast_matchers::internal:: 64 const clang::ast_matchers::internal::
61 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> 65 VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr>
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 if (potentially_mocked_method->getNumParams() != Node.getNumParams()) 116 if (potentially_mocked_method->getNumParams() != Node.getNumParams())
113 continue; 117 continue;
114 118
115 if (InnerMatcher.matches(*potentially_mocked_method, Finder, Builder)) 119 if (InnerMatcher.matches(*potentially_mocked_method, Finder, Builder))
116 return true; 120 return true;
117 } 121 }
118 122
119 return false; 123 return false;
120 } 124 }
121 125
126 class MethodBlocklist {
127 public:
128 explicit MethodBlocklist(const std::string& filepath) {
129 if (!filepath.empty())
130 ParseInputFile(filepath);
131 }
132
133 bool Contains(const clang::CXXMethodDecl& method) const {
134 auto it = method_to_class_to_args_.find(method.getName());
135 if (it == method_to_class_to_args_.end())
136 return false;
137
138 const clang::CXXRecordDecl* actual_class = method.getParent();
139 // Hopefully |getParent()| can find the class even for non-inlined method
140 // definitions (where CXXRecordDecl is not a parent AST node of
141 // CXXMethodDecl).
142 assert(actual_class);
dcheng 2017/01/17 22:56:10 Nit: a lot of times, assert messages in LLVM look
Łukasz Anforowicz 2017/01/17 23:52:47 Done.
143
144 const llvm::StringMap<std::set<unsigned>>& class_to_args = it->second;
145 auto it2 = class_to_args.find(actual_class->getName());
146 if (it2 == class_to_args.end())
147 return false;
148
149 const std::set<unsigned>& set_of_expected_number_of_args = it2->second;
dcheng 2017/01/17 22:56:10 Nit: from the context, it's not clear if expected
Łukasz Anforowicz 2017/01/17 23:52:47 Done.
150 unsigned max_actual_number_of_args = method.param_size();
151 unsigned min_actual_number_of_args = max_actual_number_of_args;
152 for (const clang::ParmVarDecl* param : method.parameters()) {
153 if (param->hasInit())
154 min_actual_number_of_args--;
155 }
156 bool got_expected_number_of_args = std::any_of(
dcheng 2017/01/17 22:56:11 Nit: Rename got_expected_to_number_of_args => foun
Łukasz Anforowicz 2017/01/17 23:52:46 Done.
157 set_of_expected_number_of_args.begin(),
158 set_of_expected_number_of_args.end(),
159 [min_actual_number_of_args,
160 max_actual_number_of_args](unsigned expected_number_of_args) {
161 return (min_actual_number_of_args <= expected_number_of_args) &&
162 (expected_number_of_args <= max_actual_number_of_args);
163 });
164 if (!got_expected_number_of_args)
165 return false;
166
167 // No need to verify here that |actual_class| is in the |blink| namespace -
168 // this will be done by other matchers elsewhere.
169
170 // TODO(lukasza): Do we need to consider return type and/or param types?
171
172 return true;
dcheng 2017/01/17 22:56:10 Then just return found_matching_arg_count directly
Łukasz Anforowicz 2017/01/17 23:52:47 Done.
173 }
174
175 private:
176 // Each line is expected to have the following format:
177 // <class name>:::<method name>:::<number of arguments>
178 void ParseInputFile(const std::string& filepath) {
179 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> file_or_err =
180 llvm::MemoryBuffer::getFile(filepath);
181 if (std::error_code err = file_or_err.getError()) {
182 llvm::errs() << "ERROR: Cannot open the file specified in --"
183 << kMethodBlocklistParamName << " argument: " << filepath
184 << ": " << err.message() << "\n";
185 assert(false);
186 return;
187 }
188
189 llvm::line_iterator it(**file_or_err, true /* SkipBlanks */, '#');
190 for (; !it.is_at_eof(); ++it) {
191 llvm::StringRef line = it->trim();
192 if (line.empty())
193 continue;
194
195 // Split the line into ':::'-delimited parts.
196 const size_t kExpectedNumberOfParts = 3;
197 llvm::SmallVector<llvm::StringRef, kExpectedNumberOfParts> parts;
198 line.split(parts, ":::");
199 if (parts.size() != kExpectedNumberOfParts) {
200 llvm::errs() << "ERROR: Parsing error - expected "
201 << kExpectedNumberOfParts
202 << " ':::'-delimited parts: " << filepath << ":"
203 << it.line_number() << ": " << line << "\n";
204 assert(false);
205 continue;
206 }
207
208 // Parse individual parts.
209 llvm::StringRef class_name = parts[0];
210 llvm::StringRef method_name = parts[1];
211 unsigned number_of_method_args;
212 if (parts[2].getAsInteger(0, number_of_method_args)) {
213 llvm::errs() << "ERROR: Parsing error - '" << parts[2] << "' "
214 << "is not an unsigned integer: " << filepath << ":"
215 << it.line_number() << ": " << line << "\n";
216 assert(false);
217 continue;
218 }
219
220 // Store the new entry.
221 method_to_class_to_args_[method_name][class_name].insert(
222 number_of_method_args);
223 }
224 }
225
226 // Stores methods to blacklist in a map:
227 // method name -> class name -> set of all allowed numbers of arguments.
228 llvm::StringMap<llvm::StringMap<std::set<unsigned>>> method_to_class_to_args_;
229 };
230
231 AST_MATCHER_P(clang::CXXMethodDecl,
232 internalIsBlocklistedMethod,
233 MethodBlocklist,
234 Blocklist) {
235 return Blocklist.Contains(Node);
236 }
237
238 clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>
239 isBlocklistedMethod(const std::string& method_blocklist_filepath) {
240 return internalIsBlocklistedMethod(
241 MethodBlocklist(method_blocklist_filepath));
dcheng 2017/01/17 22:59:50 Oh, one other thing: do we need to split this betw
Łukasz Anforowicz 2017/01/17 23:52:47 Done. I did it this way thinking that one day we'
242 }
243
122 // If |InnerMatcher| matches |top|, then the returned matcher will match: 244 // If |InnerMatcher| matches |top|, then the returned matcher will match:
123 // - |top::function| 245 // - |top::function|
124 // - |top::Class::method| 246 // - |top::Class::method|
125 // - |top::internal::Class::method| 247 // - |top::internal::Class::method|
126 AST_MATCHER_P( 248 AST_MATCHER_P(
127 clang::NestedNameSpecifier, 249 clang::NestedNameSpecifier,
128 hasTopLevelPrefix, 250 hasTopLevelPrefix,
129 clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>, 251 clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>,
130 InnerMatcher) { 252 InnerMatcher) {
131 const clang::NestedNameSpecifier* NodeToMatch = &Node; 253 const clang::NestedNameSpecifier* NodeToMatch = &Node;
(...skipping 1136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 1390
1269 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); 1391 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
1270 1392
1271 int main(int argc, const char* argv[]) { 1393 int main(int argc, const char* argv[]) {
1272 // TODO(dcheng): Clang tooling should do this itself. 1394 // TODO(dcheng): Clang tooling should do this itself.
1273 // http://llvm.org/bugs/show_bug.cgi?id=21627 1395 // http://llvm.org/bugs/show_bug.cgi?id=21627
1274 llvm::InitializeNativeTarget(); 1396 llvm::InitializeNativeTarget();
1275 llvm::InitializeNativeTargetAsmParser(); 1397 llvm::InitializeNativeTargetAsmParser();
1276 llvm::cl::OptionCategory category( 1398 llvm::cl::OptionCategory category(
1277 "rewrite_to_chrome_style: convert Blink style to Chrome style."); 1399 "rewrite_to_chrome_style: convert Blink style to Chrome style.");
1400 llvm::cl::opt<std::string> blocklisted_methods_file(
1401 kMethodBlocklistParamName, llvm::cl::value_desc("filepath"),
1402 llvm::cl::desc("file listing methods to be blocked (not renamed)"));
1278 CommonOptionsParser options(argc, argv, category); 1403 CommonOptionsParser options(argc, argv, category);
1279 clang::tooling::ClangTool tool(options.getCompilations(), 1404 clang::tooling::ClangTool tool(options.getCompilations(),
1280 options.getSourcePathList()); 1405 options.getSourcePathList());
1281 1406
1282 MatchFinder match_finder; 1407 MatchFinder match_finder;
1283 std::set<Replacement> replacements; 1408 std::set<Replacement> replacements;
1284 1409
1285 // Blink namespace matchers ======== 1410 // Blink namespace matchers ========
1286 auto blink_namespace_decl = 1411 auto blink_namespace_decl =
1287 namespaceDecl(anyOf(hasName("blink"), hasName("WTF")), 1412 namespaceDecl(anyOf(hasName("blink"), hasName("WTF")),
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1419 // struct S { 1544 // struct S {
1420 // void g(); 1545 // void g();
1421 // }; 1546 // };
1422 // matches |g|. 1547 // matches |g|.
1423 // For a method to be considered for rewrite, it must not override something 1548 // For a method to be considered for rewrite, it must not override something
1424 // that we're not rewriting. Any methods that we would not normally consider 1549 // that we're not rewriting. Any methods that we would not normally consider
1425 // but that override something we are rewriting should also be rewritten. So 1550 // but that override something we are rewriting should also be rewritten. So
1426 // we use includeAllOverriddenMethods() to check these rules not just for the 1551 // we use includeAllOverriddenMethods() to check these rules not just for the
1427 // method being matched but for the methods it overrides also. 1552 // method being matched but for the methods it overrides also.
1428 auto is_blink_method = includeAllOverriddenMethods( 1553 auto is_blink_method = includeAllOverriddenMethods(
1429 allOf(in_blink_namespace, unless(isBlacklistedMethod()))); 1554 allOf(in_blink_namespace, unless(isBlacklistedMethod()),
1555 unless(isBlocklistedMethod(blocklisted_methods_file))));
1430 auto method_decl_matcher = id( 1556 auto method_decl_matcher = id(
1431 "decl", 1557 "decl",
1432 cxxMethodDecl( 1558 cxxMethodDecl(
1433 unless(anyOf( 1559 unless(anyOf(
1434 // Overloaded operators have special names and should never be 1560 // Overloaded operators have special names and should never be
1435 // renamed. 1561 // renamed.
1436 isOverloadedOperator(), 1562 isOverloadedOperator(),
1437 // Similarly, constructors, destructors, and conversion 1563 // Similarly, constructors, destructors, and conversion
1438 // functions should not be considered for renaming. 1564 // functions should not be considered for renaming.
1439 cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())), 1565 cxxConstructorDecl(), cxxDestructorDecl(), cxxConversionDecl())),
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 for (const auto& r : replacements) { 1793 for (const auto& r : replacements) {
1668 std::string replacement_text = r.getReplacementText().str(); 1794 std::string replacement_text = r.getReplacementText().str();
1669 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); 1795 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
1670 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() 1796 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
1671 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; 1797 << ":::" << r.getLength() << ":::" << replacement_text << "\n";
1672 } 1798 }
1673 llvm::outs() << "==== END EDITS ====\n"; 1799 llvm::outs() << "==== END EDITS ====\n";
1674 1800
1675 return 0; 1801 return 0;
1676 } 1802 }
OLDNEW
« no previous file with comments | « no previous file | tools/clang/rewrite_to_chrome_style/tests/blocked_methods.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698