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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
index 5df98a529aea727ad79d3e991669a5db34c12b36..3a1465f587c8d352927d045dbd9b2021d045e2d2 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -34,6 +34,9 @@
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetSelect.h"
#include "EditTracker.h"
@@ -49,6 +52,7 @@ const char kBlinkFieldPrefix[] = "m_";
const char kBlinkStaticMemberPrefix[] = "s_";
const char kGeneratedFileRegex[] = "^gen/|/gen/";
const char kGMockMethodNamePrefix[] = "gmock_";
+const char kMethodBlocklistParamName[] = "method-blocklist";
template <typename MatcherType, typename NodeType>
bool IsMatching(const MatcherType& matcher,
@@ -119,6 +123,124 @@ AST_MATCHER_P(clang::CXXMethodDecl,
return false;
}
+class MethodBlocklist {
+ public:
+ explicit MethodBlocklist(const std::string& filepath) {
+ if (!filepath.empty())
+ ParseInputFile(filepath);
+ }
+
+ bool Contains(const clang::CXXMethodDecl& method) const {
+ auto it = method_to_class_to_args_.find(method.getName());
+ if (it == method_to_class_to_args_.end())
+ return false;
+
+ const clang::CXXRecordDecl* actual_class = method.getParent();
+ // Hopefully |getParent()| can find the class even for non-inlined method
+ // definitions (where CXXRecordDecl is not a parent AST node of
+ // CXXMethodDecl).
+ 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.
+
+ const llvm::StringMap<std::set<unsigned>>& class_to_args = it->second;
+ auto it2 = class_to_args.find(actual_class->getName());
+ if (it2 == class_to_args.end())
+ return false;
+
+ 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.
+ unsigned max_actual_number_of_args = method.param_size();
+ unsigned min_actual_number_of_args = max_actual_number_of_args;
+ for (const clang::ParmVarDecl* param : method.parameters()) {
+ if (param->hasInit())
+ min_actual_number_of_args--;
+ }
+ 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.
+ set_of_expected_number_of_args.begin(),
+ set_of_expected_number_of_args.end(),
+ [min_actual_number_of_args,
+ max_actual_number_of_args](unsigned expected_number_of_args) {
+ return (min_actual_number_of_args <= expected_number_of_args) &&
+ (expected_number_of_args <= max_actual_number_of_args);
+ });
+ if (!got_expected_number_of_args)
+ return false;
+
+ // No need to verify here that |actual_class| is in the |blink| namespace -
+ // this will be done by other matchers elsewhere.
+
+ // TODO(lukasza): Do we need to consider return type and/or param types?
+
+ 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.
+ }
+
+ private:
+ // Each line is expected to have the following format:
+ // <class name>:::<method name>:::<number of arguments>
+ void ParseInputFile(const std::string& filepath) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> file_or_err =
+ llvm::MemoryBuffer::getFile(filepath);
+ if (std::error_code err = file_or_err.getError()) {
+ llvm::errs() << "ERROR: Cannot open the file specified in --"
+ << kMethodBlocklistParamName << " argument: " << filepath
+ << ": " << err.message() << "\n";
+ assert(false);
+ return;
+ }
+
+ llvm::line_iterator it(**file_or_err, true /* SkipBlanks */, '#');
+ for (; !it.is_at_eof(); ++it) {
+ llvm::StringRef line = it->trim();
+ if (line.empty())
+ continue;
+
+ // Split the line into ':::'-delimited parts.
+ const size_t kExpectedNumberOfParts = 3;
+ llvm::SmallVector<llvm::StringRef, kExpectedNumberOfParts> parts;
+ line.split(parts, ":::");
+ if (parts.size() != kExpectedNumberOfParts) {
+ llvm::errs() << "ERROR: Parsing error - expected "
+ << kExpectedNumberOfParts
+ << " ':::'-delimited parts: " << filepath << ":"
+ << it.line_number() << ": " << line << "\n";
+ assert(false);
+ continue;
+ }
+
+ // Parse individual parts.
+ llvm::StringRef class_name = parts[0];
+ llvm::StringRef method_name = parts[1];
+ unsigned number_of_method_args;
+ if (parts[2].getAsInteger(0, number_of_method_args)) {
+ llvm::errs() << "ERROR: Parsing error - '" << parts[2] << "' "
+ << "is not an unsigned integer: " << filepath << ":"
+ << it.line_number() << ": " << line << "\n";
+ assert(false);
+ continue;
+ }
+
+ // Store the new entry.
+ method_to_class_to_args_[method_name][class_name].insert(
+ number_of_method_args);
+ }
+ }
+
+ // Stores methods to blacklist in a map:
+ // method name -> class name -> set of all allowed numbers of arguments.
+ llvm::StringMap<llvm::StringMap<std::set<unsigned>>> method_to_class_to_args_;
+};
+
+AST_MATCHER_P(clang::CXXMethodDecl,
+ internalIsBlocklistedMethod,
+ MethodBlocklist,
+ Blocklist) {
+ return Blocklist.Contains(Node);
+}
+
+clang::ast_matchers::internal::Matcher<clang::CXXMethodDecl>
+isBlocklistedMethod(const std::string& method_blocklist_filepath) {
+ return internalIsBlocklistedMethod(
+ 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'
+}
+
// If |InnerMatcher| matches |top|, then the returned matcher will match:
// - |top::function|
// - |top::Class::method|
@@ -1275,6 +1397,9 @@ int main(int argc, const char* argv[]) {
llvm::InitializeNativeTargetAsmParser();
llvm::cl::OptionCategory category(
"rewrite_to_chrome_style: convert Blink style to Chrome style.");
+ llvm::cl::opt<std::string> blocklisted_methods_file(
+ kMethodBlocklistParamName, llvm::cl::value_desc("filepath"),
+ llvm::cl::desc("file listing methods to be blocked (not renamed)"));
CommonOptionsParser options(argc, argv, category);
clang::tooling::ClangTool tool(options.getCompilations(),
options.getSourcePathList());
@@ -1426,7 +1551,8 @@ int main(int argc, const char* argv[]) {
// we use includeAllOverriddenMethods() to check these rules not just for the
// method being matched but for the methods it overrides also.
auto is_blink_method = includeAllOverriddenMethods(
- allOf(in_blink_namespace, unless(isBlacklistedMethod())));
+ allOf(in_blink_namespace, unless(isBlacklistedMethod()),
+ unless(isBlocklistedMethod(blocklisted_methods_file))));
auto method_decl_matcher = id(
"decl",
cxxMethodDecl(
« 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