Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 // | |
| 5 // This implements a Clang tool to rewrite all instances of scoped_array<T> to | |
| 6 // scoped_ptr<T[]>. The former is being deprecated in favor of the latter, to | |
| 7 // allow for an eventual transition from scoped_ptr to unique_ptr. | |
| 8 | |
| 9 #include "clang/AST/ASTContext.h" | |
| 10 #include "clang/ASTMatchers/ASTMatchers.h" | |
| 11 #include "clang/ASTMatchers/ASTMatchFinder.h" | |
| 12 #include "clang/Basic/SourceManager.h" | |
| 13 #include "clang/Frontend/FrontendActions.h" | |
| 14 #include "clang/Lex/Lexer.h" | |
| 15 #include "clang/Tooling/CommonOptionsParser.h" | |
| 16 #include "clang/Tooling/Refactoring.h" | |
| 17 #include "clang/Tooling/Tooling.h" | |
| 18 #include "llvm/Support/CommandLine.h" | |
| 19 | |
| 20 using clang::ast_matchers::MatchFinder; | |
| 21 using clang::ast_matchers::hasDeclaration; | |
| 22 using clang::ast_matchers::hasName; | |
| 23 using clang::ast_matchers::id; | |
| 24 using clang::ast_matchers::loc; | |
| 25 using clang::ast_matchers::qualType; | |
| 26 using clang::ast_matchers::recordDecl; | |
| 27 using clang::tooling::CommonOptionsParser; | |
| 28 using clang::tooling::Replacement; | |
| 29 using clang::tooling::Replacements; | |
| 30 using llvm::StringRef; | |
| 31 | |
| 32 namespace { | |
| 33 | |
| 34 class RewriterCallback : public MatchFinder::MatchCallback { | |
| 35 public: | |
| 36 RewriterCallback(Replacements* replacements) : replacements_(replacements) {} | |
| 37 virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE; | |
| 38 | |
| 39 private: | |
| 40 Replacements* const replacements_; | |
| 41 }; | |
| 42 | |
| 43 class ScopedArrayRewriter { | |
| 44 public: | |
| 45 explicit ScopedArrayRewriter(Replacements* replacements) | |
| 46 : callback_(replacements) {} | |
| 47 | |
| 48 void SetupMatchers(MatchFinder* match_finder); | |
| 49 | |
| 50 private: | |
| 51 RewriterCallback callback_; | |
| 52 }; | |
|
Nico
2013/04/06 04:24:26
Does this class add anything? Can't you dod the on
dcheng
2013/04/06 04:33:37
In theory, it makes this more testable in case I u
| |
| 53 | |
| 54 void ScopedArrayRewriter::SetupMatchers(MatchFinder* match_finder) { | |
| 55 match_finder->addMatcher( | |
| 56 id("loc", | |
| 57 loc(qualType(hasDeclaration(recordDecl(hasName("::scoped_array")))))), | |
| 58 &callback_); | |
| 59 } | |
| 60 | |
| 61 void RewriterCallback::run(const MatchFinder::MatchResult& result) { | |
| 62 const clang::TypeLoc type_location = | |
| 63 *result.Nodes.getNodeAs<clang::TypeLoc>("loc"); | |
| 64 clang::CharSourceRange range = clang::CharSourceRange::getTokenRange( | |
| 65 result.SourceManager->getSpellingLoc(type_location.getLocStart()), | |
| 66 result.SourceManager->getSpellingLoc(type_location.getLocEnd())); | |
| 67 // TODO(dcheng): Log an error? | |
| 68 if (!range.isValid()) | |
| 69 return; | |
| 70 std::string replacement_text = clang::Lexer::getSourceText( | |
| 71 range, *result.SourceManager, result.Context->getLangOpts()); | |
| 72 // TODO(dcheng): Log errors? | |
| 73 if (!StringRef(replacement_text).startswith("scoped_array<") || | |
|
Nico
2013/04/06 04:24:26
This will ignore code with spaces or newlines betw
dcheng
2013/04/06 04:33:37
Yeah. I'm assuming that's not going to a very comm
| |
| 74 !StringRef(replacement_text).endswith(">")) | |
| 75 return; | |
| 76 replacement_text.replace(strlen("scoped_"), strlen("array"), "ptr"); | |
| 77 replacement_text.insert(replacement_text.size() - 1, "[]"); | |
|
Nico
2013/04/06 04:24:26
This might not work if the type comes from a typeo
dcheng
2013/04/06 04:33:37
What typically happens is it emits multiple replac
| |
| 78 replacements_->insert( | |
| 79 Replacement(*result.SourceManager, range, replacement_text)); | |
| 80 } | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); | |
| 85 | |
| 86 int main(int argc, const char* argv[]) { | |
| 87 CommonOptionsParser options(argc, argv); | |
| 88 clang::tooling::ClangTool tool(options.getCompilations(), | |
| 89 options.getSourcePathList()); | |
| 90 | |
| 91 Replacements replacements; | |
| 92 ScopedArrayRewriter rewriter(&replacements); | |
| 93 MatchFinder match_finder; | |
| 94 rewriter.SetupMatchers(&match_finder); | |
| 95 | |
| 96 int result = | |
| 97 tool.run(clang::tooling::newFrontendActionFactory(&match_finder)); | |
| 98 if (result != 0) | |
| 99 return result; | |
| 100 | |
| 101 // Serialization format is documented in tools/clang/scripts/run_tool.py | |
| 102 llvm::outs() << "==== BEGIN EDITS ====\n"; | |
| 103 for (const Replacement& r : replacements) { | |
| 104 llvm::outs() << "r:" << r.getFilePath() << ":" << r.getOffset() << ":" | |
| 105 << r.getLength() << ":" << r.getReplacementText() << "\n"; | |
| 106 } | |
| 107 llvm::outs() << "==== END EDITS ====\n"; | |
| 108 | |
| 109 return 0; | |
| 110 } | |
| OLD | NEW |