OLD | NEW |
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 15 matching lines...) Expand all Loading... |
26 #include "clang/ASTMatchers/ASTMatchersMacros.h" | 26 #include "clang/ASTMatchers/ASTMatchersMacros.h" |
27 #include "clang/Basic/CharInfo.h" | 27 #include "clang/Basic/CharInfo.h" |
28 #include "clang/Basic/SourceManager.h" | 28 #include "clang/Basic/SourceManager.h" |
29 #include "clang/Frontend/FrontendActions.h" | 29 #include "clang/Frontend/FrontendActions.h" |
30 #include "clang/Lex/Lexer.h" | 30 #include "clang/Lex/Lexer.h" |
31 #include "clang/Tooling/CommonOptionsParser.h" | 31 #include "clang/Tooling/CommonOptionsParser.h" |
32 #include "clang/Tooling/Refactoring.h" | 32 #include "clang/Tooling/Refactoring.h" |
33 #include "clang/Tooling/Tooling.h" | 33 #include "clang/Tooling/Tooling.h" |
34 #include "llvm/Support/CommandLine.h" | 34 #include "llvm/Support/CommandLine.h" |
35 #include "llvm/Support/TargetSelect.h" | 35 #include "llvm/Support/TargetSelect.h" |
| 36 #include "tools/clang/rewrite_to_chrome_style/Renamer.h" |
36 | 37 |
37 using namespace clang::ast_matchers; | 38 using namespace clang::ast_matchers; |
38 using clang::tooling::CommonOptionsParser; | 39 using clang::tooling::CommonOptionsParser; |
39 using clang::tooling::Replacement; | 40 using clang::tooling::Replacement; |
40 using clang::tooling::Replacements; | 41 using clang::tooling::Replacements; |
41 using llvm::StringRef; | 42 using llvm::StringRef; |
42 | 43 |
43 namespace { | 44 namespace { |
44 | 45 |
45 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { | 46 AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { |
46 return Node.isOverloadedOperator(); | 47 return Node.isOverloadedOperator(); |
47 } | 48 } |
48 | 49 |
49 constexpr char kBlinkFieldPrefix[] = "m_"; | 50 constexpr char kBlinkFieldPrefix[] = "m_"; |
50 constexpr char kBlinkStaticMemberPrefix[] = "s_"; | 51 constexpr char kBlinkStaticMemberPrefix[] = "s_"; |
51 | 52 |
52 bool GetNameForDecl(const clang::FunctionDecl& decl, std::string& name) { | 53 bool GetNameForDecl(const clang::FunctionDecl& decl, std::string& name) { |
53 name = decl.getNameAsString(); | 54 name = IdentifierToCamelCase(decl.getName()); |
54 name[0] = clang::toUppercase(name[0]); | |
55 return true; | 55 return true; |
56 } | 56 } |
57 | 57 |
58 // Helper to convert from a camelCaseName to camel_case_name. It uses some | |
59 // heuristics to try to handle acronyms in camel case names correctly. | |
60 std::string CamelCaseToUnderscoreCase(StringRef input) { | |
61 std::string output; | |
62 bool needs_underscore = false; | |
63 bool was_lowercase = false; | |
64 bool was_uppercase = false; | |
65 // Iterate in reverse to minimize the amount of backtracking. | |
66 for (const unsigned char* i = input.bytes_end() - 1; i >= input.bytes_begin(); | |
67 --i) { | |
68 char c = *i; | |
69 bool is_lowercase = clang::isLowercase(c); | |
70 bool is_uppercase = clang::isUppercase(c); | |
71 c = clang::toLowercase(c); | |
72 // Transitioning from upper to lower case requires an underscore. This is | |
73 // needed to handle names with acronyms, e.g. handledHTTPRequest needs a '_' | |
74 // in 'dH'. This is a complement to the non-acronym case further down. | |
75 if (needs_underscore || (was_uppercase && is_lowercase)) { | |
76 output += '_'; | |
77 needs_underscore = false; | |
78 } | |
79 output += c; | |
80 // Handles the non-acronym case: transitioning from lower to upper case | |
81 // requires an underscore when emitting the next character, e.g. didLoad | |
82 // needs a '_' in 'dL'. | |
83 if (i != input.bytes_end() - 1 && was_lowercase && is_uppercase) | |
84 needs_underscore = true; | |
85 was_lowercase = is_lowercase; | |
86 was_uppercase = is_uppercase; | |
87 } | |
88 std::reverse(output.begin(), output.end()); | |
89 return output; | |
90 } | |
91 | |
92 bool GetNameForDecl(const clang::FieldDecl& decl, std::string& name) { | 58 bool GetNameForDecl(const clang::FieldDecl& decl, std::string& name) { |
93 StringRef original_name = decl.getName(); | 59 StringRef original_name = decl.getName(); |
94 // Blink style field names are prefixed with `m_`. If this prefix isn't | 60 // Blink style field names are prefixed with `m_`. If this prefix isn't |
95 // present, assume it's already been converted to Google style. | 61 // present, assume it's already been converted to Google style. |
96 if (original_name.size() < strlen(kBlinkFieldPrefix) || | 62 if (original_name.size() < strlen(kBlinkFieldPrefix) || |
97 !original_name.startswith(kBlinkFieldPrefix)) | 63 !original_name.startswith(kBlinkFieldPrefix)) |
98 return false; | 64 return false; |
99 name = CamelCaseToUnderscoreCase( | 65 name = IdentifierToUnderscoreCase( |
100 original_name.substr(strlen(kBlinkFieldPrefix))); | 66 original_name.substr(strlen(kBlinkFieldPrefix))); |
101 // The few examples I could find used struct-style naming with no `_` suffix | 67 // The few examples I could find used struct-style naming with no `_` suffix |
102 // for unions. | 68 // for unions. |
103 if (decl.getParent()->isClass()) | 69 if (decl.getParent()->isClass()) |
104 name += '_'; | 70 name += '_'; |
105 return true; | 71 return true; |
106 } | 72 } |
107 | 73 |
108 bool IsProbablyConst(const clang::VarDecl& decl) { | 74 bool IsProbablyConst(const clang::VarDecl& decl) { |
109 clang::QualType type = decl.getType(); | 75 clang::QualType type = decl.getType(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 original_name = original_name.substr(strlen(kBlinkStaticMemberPrefix)); | 121 original_name = original_name.substr(strlen(kBlinkStaticMemberPrefix)); |
156 else if (original_name.startswith(kBlinkFieldPrefix)) | 122 else if (original_name.startswith(kBlinkFieldPrefix)) |
157 original_name = original_name.substr(strlen(kBlinkFieldPrefix)); | 123 original_name = original_name.substr(strlen(kBlinkFieldPrefix)); |
158 | 124 |
159 if (IsProbablyConst(decl)) { | 125 if (IsProbablyConst(decl)) { |
160 // Don't try to rename constants that already conform to Chrome style. | 126 // Don't try to rename constants that already conform to Chrome style. |
161 if (original_name.size() >= 2 && original_name[0] == 'k' && | 127 if (original_name.size() >= 2 && original_name[0] == 'k' && |
162 clang::isUppercase(original_name[1])) | 128 clang::isUppercase(original_name[1])) |
163 return false; | 129 return false; |
164 name = 'k'; | 130 name = 'k'; |
165 name.append(original_name.data(), original_name.size()); | 131 name += IdentifierToCamelCase(original_name); |
166 name[1] = clang::toUppercase(name[1]); | |
167 } else { | 132 } else { |
168 name = CamelCaseToUnderscoreCase(original_name); | 133 name = IdentifierToUnderscoreCase(original_name); |
169 } | 134 } |
170 | 135 |
171 if (decl.isStaticDataMember()) { | 136 if (decl.isStaticDataMember()) { |
172 name += '_'; | 137 name += '_'; |
173 } | 138 } |
174 | 139 |
175 return true; | 140 return true; |
176 } | 141 } |
177 | 142 |
178 template <typename Type> | 143 template <typename Type> |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 for (const auto& r : replacements) { | 500 for (const auto& r : replacements) { |
536 std::string replacement_text = r.getReplacementText().str(); | 501 std::string replacement_text = r.getReplacementText().str(); |
537 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); | 502 std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0'); |
538 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() | 503 llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() |
539 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; | 504 << ":::" << r.getLength() << ":::" << replacement_text << "\n"; |
540 } | 505 } |
541 llvm::outs() << "==== END EDITS ====\n"; | 506 llvm::outs() << "==== END EDITS ====\n"; |
542 | 507 |
543 return 0; | 508 return 0; |
544 } | 509 } |
OLD | NEW |