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

Side by Side Diff: tools/clang/BindMigrate/TransformPostTask.cpp

Issue 7886056: Clang plugin that rewrites PostTask(_, NewRunnableMethod(...)) to PostTask(_, base::Bind(...)); (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: break into files and make saner Created 9 years, 3 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #include "TransformPostTask.h"
2
3 #include "clang/AST/ASTContext.h"
4 #include "clang/AST/Expr.h"
5 #include "clang/AST/ExprCXX.h"
6 #include "clang/Rewrite/Rewriter.h"
7
8 #include "DiagnosticEmitter.h"
9
10 using namespace std;
11
12 namespace clang {
13
14 const char TransformPostTask::kPostTaskName[] = "PostTask";
15 const char TransformPostTask::kNewRunnableMethodName[] = "NewRunnableMethod";
16
17 TransformPostTask::TransformPostTask(ASTContext* context, Rewriter* rewriter,
18 DiagnosticEmitter* emitter)
19 : context_(context), rewriter_(rewriter), error_emitter_(emitter) {
20 interesting_classes_.insert("MessageLoop");
21 interesting_classes_.insert("MessageLoopProxy");
22 }
23
24 bool TransformPostTask::TraverseStmt(Stmt *statement) {
25 // Catch the MessageLoop and MessageLoopProxy calls.
26 if (CXXMemberCallExpr* mce = dyn_cast_or_null<CXXMemberCallExpr>(statement)) {
27 if (IsPostTaskExpr(mce)) {
28 if (mce->getNumArgs() < 2) {
29 error_emitter_->EmitError(
30 statement->getLocStart(),
31 "PostTask with less than 2 args?! Inconceivable!");
32 return false;
33 }
34 MaybeRewriteNewRunnableMethod(mce->getArgs()[1]);
35 }
36 }
37 return RecursiveASTVisitor<TransformPostTask>::TraverseStmt(statement);
38 }
39
40 bool TransformPostTask::IsPostTaskExpr(CXXMemberCallExpr* call) {
41 CXXMethodDecl* method_decl = call->getMethodDecl()->getCanonicalDecl();
42 // TODO(ajwong): Maybe just look up all the target Decls and compare those
43 // directly. Look at src/v8/tools/gcmole.cc for how to find the Decl.
44 if (kPostTaskName == method_decl->getNameAsString()) {
Nico 2011/09/16 03:00:54 Nit: with early returns, this gets less nested. It
awong 2011/09/16 10:24:32 Done.
45 string classname = method_decl->getThisType(*context_)
46 .getBaseTypeIdentifier()->getName();
47
48 if (!interesting_classes_.empty()) {
49 return true;
50 }
51 }
52 return false;
53 }
54
55 bool TransformPostTask::MaybeRewriteNewRunnableMethod(Expr* post_task_arg) {
56 // Skip any implicit conversions and any casts. We wantz the function!!
57 post_task_arg = post_task_arg->IgnoreImplicit()->IgnoreParenCasts();
58
59 // Strip implicit casts.
60 if (ImplicitCastExpr* ice = dyn_cast<ImplicitCastExpr>(post_task_arg)) {
61 return MaybeRewriteNewRunnableMethod(ice->getSubExpr());
62 }
63
64 CallExpr* ce = dyn_cast<CallExpr>(post_task_arg);
65 if (!ce) return false;
66 FunctionDecl *fd = ce->getDirectCallee();
67 if (!fd) return false;
68 if (kNewRunnableMethodName !=
69 fd->getNameInfo().getName().getAsIdentifierInfo()->getName())
70 return false;
71
72 if (ce->getNumArgs() < 2) {
73 error_emitter_->EmitWarning(
74 post_task_arg->getLocStart(),
75 "NewRunnableMethod with less than 2 args?! Inconceivable!");
76 return false;
77 }
78
79 // Okay, here's where it gets fun. We need to
80 // (1) replace the NRM identifier text with base::Bind.
81 // (2) Swap positions of the first two arguments.
82
83 // NewRunnableMethod -> base::Bind
84 rewriter_->ReplaceText(ce->getCallee()->getSourceRange(), "base::Bind");
85
86 // Swap the argument order.
87 Expr* arg1 = ce->getArgs()[0];
88 Expr* arg2 = ce->getArgs()[1];
89 bool failure = rewriter_->ReplaceStmt(arg1, arg2);
90 failure |= rewriter_->ReplaceStmt(arg2, arg1);
91
92 // TODO(ajwong):
93 // (3) Check the RunnableMethodTraits for the second argument, and
94 // wrap base::Unretained() if it is declared with
95 // DISABLE_RUNNABLE_METHOD_REFCOUNT.
96 return failure;
97 }
98
99 } // namespace clang
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698