ObjCMT.cpp revision 7556853c60f3e2a3f43864d8ebe74ba5ac11e68e
130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
230660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
330660a898545416f0fea2d717f16f75640001e38Ted Kremenek//                     The LLVM Compiler Infrastructure
430660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
530660a898545416f0fea2d717f16f75640001e38Ted Kremenek// This file is distributed under the University of Illinois Open Source
630660a898545416f0fea2d717f16f75640001e38Ted Kremenek// License. See LICENSE.TXT for details.
730660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
830660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
1030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/ARCMigrate/ARCMTActions.h"
1155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ASTConsumer.h"
12471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h"
1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/NSAPI.h"
14a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis#include "clang/AST/ParentMap.h"
1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/RecursiveASTVisitor.h"
1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h"
1730660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h"
1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/EditedSource.h"
1930660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/Rewriters.h"
2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/CompilerInstance.h"
2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/MultiplexConsumer.h"
2337ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis#include "clang/Lex/PPConditionalDirectiveRecord.h"
2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h"
2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Rewrite/Core/Rewriter.h"
2630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/SmallString.h"
2730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
2830660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang;
2930660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace arcmt;
3030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3130660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
3230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3330660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrateASTConsumer : public ASTConsumer {
3430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  void migrateDecl(Decl *D);
35baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian  void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D);
367556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  void migrateProtocolConformance(ASTContext &Ctx,
377556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian                                  const ObjCImplementationDecl *ImpDecl);
3830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3930660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic:
4030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  std::string MigrateDir;
4130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool MigrateLiterals;
4230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool MigrateSubscripting;
43d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian  bool MigrateProperty;
44cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  OwningPtr<NSAPI> NSAPIObj;
45cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  OwningPtr<edit::EditedSource> Editor;
4630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  FileRemapper &Remapper;
4730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  FileManager &FileMgr;
4837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis  const PPConditionalDirectiveRecord *PPRec;
49baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian  Preprocessor &PP;
5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool IsOutputFile;
517556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
527556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian
5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ObjCMigrateASTConsumer(StringRef migrateDir,
5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         bool migrateLiterals,
5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         bool migrateSubscripting,
56d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian                         bool migrateProperty,
5730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         FileRemapper &remapper,
5830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         FileManager &fileMgr,
5937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis                         const PPConditionalDirectiveRecord *PPRec,
60baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian                         Preprocessor &PP,
6130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         bool isOutputFile = false)
6230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  : MigrateDir(migrateDir),
6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateLiterals(migrateLiterals),
6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateSubscripting(migrateSubscripting),
65d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian    MigrateProperty(migrateProperty),
66baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian    Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    IsOutputFile(isOutputFile) { }
6830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
6930660a898545416f0fea2d717f16f75640001e38Ted Kremenekprotected:
7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void Initialize(ASTContext &Context) {
7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    NSAPIObj.reset(new NSAPI(Context));
7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Editor.reset(new edit::EditedSource(Context.getSourceManager(),
734e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie                                        Context.getLangOpts(),
7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                        PPRec));
7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek      migrateDecl(*I);
8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
8230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void HandleInterestingDecl(DeclGroupRef DG) {
8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // Ignore decls from the PCH.
8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &Ctx);
9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
9430660a898545416f0fea2d717f16f75640001e38Ted KremenekObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                             StringRef migrateDir,
9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                             bool migrateLiterals,
97d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian                             bool migrateSubscripting,
98d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian                             bool migrateProperty)
9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting),
101d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian    MigrateProperty(migrateProperty),
10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CompInst(0) {
10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (MigrateDir.empty())
10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateDir = "."; // user current directory if none is given.
10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
10730660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI,
10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                  StringRef InFile) {
10937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis  PPConditionalDirectiveRecord *
11037ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis    PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
11137ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis  CompInst->getPreprocessor().addPPCallbacks(PPRec);
11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTConsumer *
11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir,
11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       MigrateLiterals,
11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       MigrateSubscripting,
117d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian                                                       MigrateProperty,
11830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       Remapper,
11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                    CompInst->getFileManager(),
120baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian                                                       PPRec,
121baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian                                                       CompInst->getPreprocessor());
12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer };
12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return new MultiplexConsumer(Consumers);
12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
12630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
12730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                        /*ignoreIfFilesChanges=*/true);
12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CompInst = &CI;
13030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CI.getDiagnostics().setIgnoreAllWarnings(true);
13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
13430660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
13530660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ObjCMigrateASTConsumer &Consumer;
137a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  ParentMap &PMap;
13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
13930660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic:
140a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
141a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    : Consumer(consumer), PMap(PMap) { }
14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool shouldVisitTemplateInstantiations() const { return false; }
14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool shouldWalkTypesOfTypeLocs() const { return false; }
14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Consumer.MigrateLiterals) {
14830660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::Commit commit(*Consumer.Editor);
149a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      Consumer.Editor->commit(commit);
15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Consumer.MigrateSubscripting) {
15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::Commit commit(*Consumer.Editor);
15530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek      Consumer.Editor->commit(commit);
15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
15830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
16030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // Do depth first; we want to rewrite the subexpressions first so that if
16430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // we have to move expressions we will move them already rewritten.
16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    for (Stmt::child_range range = E->children(); range; ++range)
16630660a898545416f0fea2d717f16f75640001e38Ted Kremenek      if (!TraverseStmt(*range))
16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek        return false;
16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
16930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return WalkUpFromObjCMessageExpr(E);
17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
172a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
173a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisclass BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
174a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  ObjCMigrateASTConsumer &Consumer;
175a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  OwningPtr<ParentMap> PMap;
176a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
177a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidispublic:
178a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
179a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
180a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  bool shouldVisitTemplateInstantiations() const { return false; }
181a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
182a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
183a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  bool TraverseStmt(Stmt *S) {
184a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    PMap.reset(new ParentMap(S));
185a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
186a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return true;
187a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  }
188a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis};
18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
19130660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!D)
19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return;
19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (isa<ObjCMethodDecl>(D))
19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return; // Wait for the ObjC container declaration.
19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
197a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  BodyMigrator(*this).TraverseDecl(D);
19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
200baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
201baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian                                                      ObjCInterfaceDecl *D) {
202baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian  for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end();
203baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian       M != MEnd; ++M) {
204baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian    ObjCMethodDecl *Method = (*M);
205dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    if (Method->isPropertyAccessor() ||  Method->param_size() != 0)
206baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian      continue;
207baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian    // Is this method candidate to be a getter?
208dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    QualType GRT = Method->getResultType();
209dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    if (GRT->isVoidType())
210dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian      continue;
2112a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian    // FIXME. Don't know what todo with attributes, skip for now.
2122a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian    if (Method->hasAttrs())
2132a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian      continue;
2142a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian
215dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    Selector GetterSelector = Method->getSelector();
216dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
217dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    Selector SetterSelector =
218dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian      SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
219dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian                                             PP.getSelectorTable(),
220dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian                                             getterName);
221dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian    if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) {
222dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian      // Is this a valid setter, matching the target getter?
223dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian      QualType SRT = SetterMethod->getResultType();
224dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian      if (!SRT->isVoidType())
225dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian        continue;
226dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian      const ParmVarDecl *argDecl = *SetterMethod->param_begin();
22752477fb1b86f99a2a8c77e1523d4f186490c28e9Fariborz Jahanian      QualType ArgType = argDecl->getType();
2282a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian      if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) ||
2292a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian          SetterMethod->hasAttrs())
23052477fb1b86f99a2a8c77e1523d4f186490c28e9Fariborz Jahanian          continue;
231afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian        edit::Commit commit(*Editor);
232afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian        edit::rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit);
233afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian        Editor->commit(commit);
234baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian      }
235baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian  }
236baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian}
237baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian
2387556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
2397556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian                                            const ObjCImplementationDecl *ImpDecl) {
2407556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
2417556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  if (!IDecl || ObjCProtocolDecls.empty())
2427556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian    return;
2437556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  // Find all implicit conforming protocols for this class
2447556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  // and make them explicit.
2457556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
2467556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
2477556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  llvm::SmallPtrSet<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
2487556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian
2497556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  for (llvm::SmallPtrSet<ObjCProtocolDecl*,32>::iterator I =
2507556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian       ObjCProtocolDecls.begin(),
2517556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian       E = ObjCProtocolDecls.end(); I != E; ++I)
2527556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian    if (!ExplicitProtocols.count(*I))
2537556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian      PotentialImplicitProtocols.insert(*I);
2547556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian
2557556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian  if (PotentialImplicitProtocols.empty())
2567556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian    return;
2577556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian}
2587556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian
25930660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
26030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
26130660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass RewritesReceiver : public edit::EditsReceiver {
26230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Rewriter &Rewrite;
26330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
26430660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic:
26530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
26630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
26730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void insert(SourceLocation loc, StringRef text) {
26830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Rewrite.InsertText(loc, text);
26930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
27030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void replace(CharSourceRange range, StringRef text) {
27130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
27230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
27330660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
27430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
27530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
27630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
27730660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
278baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian
279baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian  TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
280d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian  if (MigrateProperty)
281d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian    for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
282d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian         D != DEnd; ++D) {
283d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian      if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
284d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian        migrateObjCInterfaceDecl(Ctx, CDecl);
2857556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian      else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
2867556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian        ObjCProtocolDecls.insert(PDecl);
2877556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian      else if (const ObjCImplementationDecl *ImpDecl =
2887556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian               dyn_cast<ObjCImplementationDecl>(*D))
2897556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian        migrateProtocolConformance(Ctx, ImpDecl);
290d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian    }
291baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian
2924e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
29330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  RewritesReceiver Rec(rewriter);
29430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Editor->applyRewrites(Rec);
29530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
29630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  for (Rewriter::buffer_iterator
29730660a898545416f0fea2d717f16f75640001e38Ted Kremenek        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
29830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    FileID FID = I->first;
29930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    RewriteBuffer &buf = I->second;
30030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
30130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    assert(file);
302cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<512> newText;
30330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    llvm::raw_svector_ostream vecOS(newText);
30430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    buf.write(vecOS);
30530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    vecOS.flush();
30630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
30730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                   StringRef(newText.data(), newText.size()), file->getName());
308cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<64> filePath(file->getName());
30930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    FileMgr.FixupRelativePath(filePath);
31030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper.remap(filePath.str(), memBuf);
31130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
31330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (IsOutputFile) {
31430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
31530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  } else {
31630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
31730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
31830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
31930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
32030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
321013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis  CI.getDiagnostics().setIgnoreAllWarnings(true);
32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
32530660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI,
32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                  StringRef InFile) {
32737ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis  PPConditionalDirectiveRecord *
32837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis    PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
32937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis  CI.getPreprocessor().addPPCallbacks(PPRec);
33030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile,
33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    /*MigrateLiterals=*/true,
33230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    /*MigrateSubscripting=*/true,
333d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian                                    /*MigrateProperty*/true,
33430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    Remapper,
33530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    CI.getFileManager(),
33637ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis                                    PPRec,
337baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian                                    CI.getPreprocessor(),
33830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    /*isOutputFile=*/true);
33930660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
340