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

Unified Diff: tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp

Issue 2592273002: Support rewriting |to##macroArg()| into |To##macroArg()|. (Closed)
Patch Set: Don't minimize the edit if not editing a macro. Created 4 years 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/macros-expected.cc » ('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 3374ea29ea6bd6ab8c3f0b796c90c6e5683384c2..b414f9e822c03308f2abfdde8cedacdd0debaf06 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -680,6 +680,60 @@ class RewriterBase : public MatchFinder::MatchCallback {
return *target_node;
}
+ bool GenerateReplacement(const MatchFinder::MatchResult& result,
+ clang::SourceLocation loc,
+ llvm::StringRef old_name,
+ std::string new_name,
+ Replacement* replacement) {
+ const clang::ASTContext& context = *result.Context;
+ const clang::SourceManager& source_manager = *result.SourceManager;
+
+ if (loc.isMacroID()) {
+ // Try to jump "above" the scratch buffer if |loc| is inside
+ // token##Concatenation.
+ const int kMaxJumps = 5;
+ bool verified_out_of_scratch_space = false;
+ for (int i = 0; i < kMaxJumps && !verified_out_of_scratch_space; i++) {
+ clang::SourceLocation spell = source_manager.getSpellingLoc(loc);
+ verified_out_of_scratch_space =
+ source_manager.getBufferName(spell) != "<scratch space>";
+ if (!verified_out_of_scratch_space)
+ loc = source_manager.getImmediateMacroCallerLoc(loc);
+ }
+ if (!verified_out_of_scratch_space)
+ return false;
+ }
+
+ // If the edit affects only the first character of the identifier, then
+ // narrow down the edit to only this single character. This is important
+ // for dealing with toFooBar -> ToFooBar method renaming when the method
+ // name is built using macro token concatenation like to##macroArgument - in
+ // this case we should only rewrite "t" -> "T" and leave "o##macroArgument"
+ // untouched.
+ llvm::StringRef expected_old_text = old_name;
+ llvm::StringRef new_text = new_name;
+ if (loc.isMacroID() && expected_old_text.substr(1) == new_text.substr(1)) {
+ expected_old_text = expected_old_text.substr(0, 1);
+ new_text = new_text.substr(0, 1);
+ }
+ clang::SourceLocation spell = source_manager.getSpellingLoc(loc);
+ clang::CharSourceRange range = clang::CharSourceRange::getCharRange(
+ spell, spell.getLocWithOffset(expected_old_text.size()));
+
+ // We need to ensure that |actual_old_text| is the same as
+ // |expected_old_text| - it can be different if |actual_old_text| contains
+ // a macro argument (see DEFINE_WITH_TOKEN_CONCATENATION2 in
+ // macros-original.cc testcase).
+ StringRef actual_old_text = clang::Lexer::getSourceText(
+ range, source_manager, context.getLangOpts());
+ if (actual_old_text != expected_old_text)
+ return false;
+
+ if (replacement)
+ *replacement = Replacement(source_manager, range, new_text);
+ return true;
+ }
+
void AddReplacement(const MatchFinder::MatchResult& result,
llvm::StringRef old_name,
std::string new_name) {
@@ -688,10 +742,13 @@ class RewriterBase : public MatchFinder::MatchCallback {
clang::SourceLocation loc =
TargetNodeTraits<TargetNode>::GetLoc(GetTargetNode(result));
- edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name);
- clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(loc);
- replacements_->emplace(*result.SourceManager, range, new_name);
+ Replacement replacement;
+ if (!GenerateReplacement(result, loc, old_name, new_name, &replacement))
+ return;
+
+ replacements_->insert(std::move(replacement));
+ edit_tracker_.Add(*result.SourceManager, loc, old_name, new_name);
}
const EditTracker& edit_tracker() const { return edit_tracker_; }
@@ -712,26 +769,25 @@ class DeclRewriterBase : public RewriterBase<TargetNode> {
void run(const MatchFinder::MatchResult& result) override {
const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
assert(decl);
- // If false, there's no name to be renamed.
+ llvm::StringRef old_name = decl->getName();
+
+ // Return early if there's no name to be renamed.
if (!decl->getIdentifier())
return;
- clang::SourceLocation decl_loc =
- TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
- if (decl_loc.isMacroID()) {
- // Get the location of the spelling of the declaration. If token pasting
- // was used this will be in "scratch space" and we don't know how to get
- // from there back to/ the actual macro with the foo##bar text. So just
- // don't replace in that case.
- clang::SourceLocation spell =
- result.SourceManager->getSpellingLoc(decl_loc);
- if (result.SourceManager->getBufferName(spell) == "<scratch space>")
- return;
- }
- clang::ASTContext* context = result.Context;
+
+ // Get the new name.
std::string new_name;
- if (!GetNameForDecl(*decl, *context, new_name))
+ if (!GetNameForDecl(*decl, *result.Context, new_name))
return; // If false, the name was not suitable for renaming.
- llvm::StringRef old_name = decl->getName();
+
+ // Check if we are able to rewrite the decl (to avoid rewriting if the
+ // decl's identifier is part of macro##Token##Concatenation).
+ clang::SourceLocation decl_loc =
+ TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
+ if (!Base::GenerateReplacement(result, decl_loc, old_name, new_name,
+ nullptr))
dcheng 2016/12/23 00:35:26 It seems a bit odd to call this twice; can we avoi
Łukasz Anforowicz 2016/12/27 19:17:23 First observation is that the call here is for |de
+ return;
+
Base::AddReplacement(result, old_name, std::move(new_name));
}
};
« no previous file with comments | « no previous file | tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698