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..26e00147720eb500fed184f17e1704d2b8e37f34 |
--- /dev/null |
+++ b/tools/clang/rewrite_to_chrome_style/Renamer.cpp |
@@ -0,0 +1,103 @@ |
+// 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 { |
+ |
+using WordList = llvm::SmallVector<llvm::StringRef, 6>; |
+ |
+WordList SplitIdentifier(llvm::StringRef input) { |
+ assert(input.size() > 0); |
+ |
+ WordList output; |
+ for (size_t i = 0; i < input.size(); ) { |
+ size_t start = i; |
+ size_t end = input.size(); |
+ bool was_lowercase = clang::isLowercase(input[start]); |
+ bool was_uppercase = clang::isUppercase(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; |
+ } |
+ |
+ bool is_lowercase = clang::isLowercase(input[i]); |
+ bool is_uppercase = clang::isUppercase(input[i]); |
+ // Non-acronym case: the next uppercase letter is the beginning of the |
+ // next word. |
+ if (was_lowercase && is_uppercase) { |
danakj
2016/01/26 21:32:10
What about V8Stuff?
8 won't be uppercase or lower
dcheng
2016/01/27 00:09:28
I made a small tweak so this gets handled correctl
|
+ end = i; |
+ break; |
+ } |
+ // End of ACRONYM case: |
+ if (in_acronym && was_uppercase && is_lowercase) { |
+ --i; // Already iterated into the next word, so backtrack. |
danakj
2016/01/26 21:32:10
Should it in_acronym = false?
dcheng
2016/01/27 00:09:28
This is scoped to the body of the outermost for lo
|
+ end = i; |
+ break; |
+ } |
+ // Seeing two consecutive uppercase letters indicates that this is |
+ // probably part of an acronym. |
danakj
2016/01/26 21:32:10
Heh, except AThing. I wonder if that happens..
It
dcheng
2016/01/27 00:09:28
This is OK though: we'll mark this as being in an
|
+ if (was_uppercase && is_uppercase) { |
+ in_acronym = true; |
+ // Intentionally fallthrough, so casing state is updated. |
+ } |
+ |
+ was_lowercase = is_lowercase; |
+ was_uppercase = is_uppercase; |
+ } |
+ // TODO(dcheng): Special acronym handling here. |
+ output.emplace_back(input.substr(start, end - start)); |
+ } |
+ |
+ return output; |
+} |
+ |
+} // 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; |
+} |