Index: tools/clang/rewrite_to_chrome_style/Renamer.cpp |
diff --git a/tools/clang/rewrite_to_chrome_style/Renamer.cpp b/tools/clang/rewrite_to_chrome_style/Renamer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b3fd8afdb2061e2e8bf45b7300207fb5eff3c107 |
--- /dev/null |
+++ b/tools/clang/rewrite_to_chrome_style/Renamer.cpp |
@@ -0,0 +1,147 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "Renamer.h" |
+ |
+#include <assert.h> |
+ |
+#include "clang/Basic/CharInfo.h" |
+#include "llvm/ADT/SmallVector.h" |
+ |
+namespace { |
+ |
+enum class Case { |
+ NEITHER, |
+ LOWER, |
+ UPPER, |
+}; |
+ |
+using WordList = llvm::SmallVector<llvm::StringRef, 6>; |
+ |
+Case DetermineCase(char c) { |
+ if (clang::isUppercase(c)) |
+ return Case::UPPER; |
+ if (clang::isLowercase(c)) |
+ return Case::LOWER; |
+ return Case::NEITHER; |
+} |
+ |
+// True if the input only contains letters of one case. |
+bool CanSplitWithUnderscores(llvm::StringRef input) { |
+ Case expected_case = Case::NEITHER; |
+ for (size_t i = 0; i < input.size(); ++i) { |
+ Case current_case = DetermineCase(input[i]); |
+ if (expected_case == Case::NEITHER) { |
+ expected_case = current_case; |
+ continue; |
+ } |
+ if (current_case == Case::NEITHER) |
+ continue; |
+ if (expected_case != current_case) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+WordList SplitWithUnderscores(llvm::StringRef input) { |
+ WordList output; |
+ input.split(output, "_", -1, false /*KeepEmpty*/); |
+ return output; |
+} |
+ |
+// Most identifiers in Blink use CamelCase, but some (incorrectly) mix in |
+// underscores. In that case, split into words, using uppercase letters and |
+// underscores signal the start of the next word, while trying to handle |
+// acronyms. |
+WordList SplitWithHeuristics(llvm::StringRef input) { |
+ WordList output; |
+ for (size_t i = 0; i < input.size();) { |
+ size_t start = i; |
+ size_t end = input.size(); |
+ Case previous_case = DetermineCase(input[start]); |
+ bool in_acronym = false; |
+ |
+ // Find the next "meaningful" uppercase letter or underscore. |
+ for (++i; i < input.size(); ++i) { |
+ // Underscore case: assume underscores always separate two words. |
+ if (input[i] == '_') { |
+ end = i; |
+ ++i; // Skip the underscore. |
+ break; |
+ } |
+ |
+ Case current_case = DetermineCase(input[i]); |
+ // Non-acronym case: the next uppercase letter is the beginning of the |
+ // next word. |
+ if (previous_case != Case::UPPER && current_case == Case::UPPER) { |
+ end = i; |
+ break; |
+ } |
+ // End of ACRONYM case: |
+ if (in_acronym && previous_case == Case::UPPER && |
+ current_case == Case::LOWER) { |
+ --i; // Already iterated into the next word, so backtrack. |
+ end = i; |
+ break; |
+ } |
+ // Seeing a non-uppercase letter after an uppercase letter means this is |
+ // probably part of an acronym. |
+ if (previous_case == Case::UPPER && current_case != Case::LOWER) { |
+ in_acronym = true; |
+ // Intentionally fallthrough, so casing state is updated. |
+ } |
+ |
+ previous_case = current_case; |
+ } |
+ // TODO(dcheng): Special acronym handling here. |
+ output.emplace_back(input.substr(start, end - start)); |
+ } |
+ return output; |
+} |
+ |
+WordList SplitIdentifier(llvm::StringRef input) { |
+ assert(input.size() > 0); |
+ |
+ if (CanSplitWithUnderscores(input)) |
+ return SplitWithUnderscores(input); |
+ |
+ return SplitWithHeuristics(input); |
+} |
+ |
+} // namespace |
+ |
+std::string IdentifierToCamelCase(llvm::StringRef input) { |
+ WordList words = SplitIdentifier(input); |
+ std::string output; |
+ for (const auto& word : words) { |
+ output += clang::toUppercase(word[0]); |
+ for (size_t i = 1; i < word.size(); ++i) |
+ output += clang::toLowercase(word[i]); |
+ } |
+ return output; |
+} |
+ |
+std::string IdentifierToUnderscoreCase(llvm::StringRef input) { |
+ WordList words = SplitIdentifier(input); |
+ std::string output; |
+ for (const auto& word : words) { |
+ if (!output.empty()) |
+ output += '_'; |
+ for (size_t i = 0; i < word.size(); ++i) |
+ output += clang::toLowercase(word[i]); |
+ } |
+ return output; |
+} |
+ |
+std::string identifierToShoutyCase(llvm::StringRef input) { |
+ WordList words = SplitIdentifier(input); |
+ std::string output; |
+ for (const auto& word : words) { |
+ if (!output.empty()) |
+ output += '_'; |
+ for (size_t i = 0; i < word.size(); ++i) |
+ output += clang::toUppercase(word[i]); |
+ } |
+ return output; |
+} |