//===--- RewriteObjCFoundationAPI.cpp - Foundation API Rewriter -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Rewrites legacy method calls to modern syntax.
//
//===----------------------------------------------------------------------===//
#include "clang/Edit/Rewriters.h"
#include "clang/Edit/Commit.h"
#include "clang/Lex/Lexer.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NSAPI.h"
using namespace clang;
using namespace edit;
static bool checkForLiteralCreation(const ObjCMessageExpr *Msg,
IdentifierInfo *&ClassId) {
if (!Msg || Msg->isImplicit() || !Msg->getMethodDecl())
return false;
const ObjCInterfaceDecl *Receiver = Msg->getReceiverInterface();
if (!Receiver)
return false;
ClassId = Receiver->getIdentifier();
if (Msg->getReceiverKind() == ObjCMessageExpr::Class)
return true;
return false;
}
//===----------------------------------------------------------------------===//
// rewriteObjCRedundantCallWithLiteral.
//===----------------------------------------------------------------------===//
bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit) {
IdentifierInfo *II = 0;
if (!checkForLiteralCreation(Msg, II))
return false;
if (Msg->getNumArgs() != 1)
return false;
const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts();
Selector Sel = Msg->getSelector();
if ((isa<ObjCStringLiteral>(Arg) &&
NS.getNSClassId(NSAPI::ClassId_NSString) == II &&
NS.getNSStringSelector(NSAPI::NSStr_stringWithString) == Sel) ||
(isa<ObjCArrayLiteral>(Arg) &&
NS.getNSClassId(NSAPI::ClassId_NSArray) == II &&
NS.getNSArraySelector(NSAPI::NSArr_arrayWithArray) == Sel) ||
(isa<ObjCDictionaryLiteral>(Arg) &&
NS.getNSClassId(NSAPI::ClassId_NSDictionary) == II &&
NS.getNSDictionarySelector(
NSAPI::NSDict_dictionaryWithDictionary) == Sel)) {
commit.replaceWithInner(Msg->getSourceRange(),
Msg->getArg(0)->getSourceRange());
return true;
}
return false;
}
//===----------------------------------------------------------------------===//
// rewriteToObjCSubscriptSyntax.
//===----------------------------------------------------------------------===//
static bool subscriptOperatorNeedsParens(const Expr *FullExpr);
static void maybePutParensOnReceiver(const Expr *Receiver, Commit &commit) {
if (subscriptOperatorNeedsParens(Receiver)) {
SourceRange RecRange = Receiver->getSourceRange();
commit.insertWrap("(", RecRange, ")");
}
}
static bool rewriteToSubscriptGetCommon(const ObjCMessageExpr *Msg,
Commit &commit) {
if (Msg->getNumArgs() != 1)
return false;
const Expr *Rec = Msg->getInstanceReceiver();
if (!Rec)
return false;
SourceRange MsgRange = Msg->getSourceRange();
SourceRange RecRange = Rec->getSourceRange();
SourceRange ArgRange = Msg->getArg(0)->getSourceRange();
commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(),
ArgRange.getBegin()),
CharSourceRange::getTokenRange(RecRange));
commit.replaceWithInner(SourceRange(ArgRange.getBegin(), MsgRange.getEnd()),
ArgRange);
commit.insertWrap("[", ArgRange, "]");
maybePutParensOnReceiver(Rec, commit);
return true;
}
static bool rewriteToArraySubscriptGet(const ObjCInterfaceDecl *IFace,
const ObjCMessageExpr *Msg,
const NSAPI &NS,
Commit &commit) {
if (!IFace->getInstanceMethod(NS.getObjectAtIndexedSubscriptSelector()))
return false;
return rewriteToSubscriptGetCommon(Msg, commit);
}
static bool rewriteToDictionarySubscriptGet(const ObjCInterfaceDecl *IFace,
const ObjCMessageExpr *Msg,
const NSAPI &NS,
Commit &commit) {
if (!IFace->getInstanceMethod(NS.getObjectForKeyedSubscriptSelector()))
return false;
return rewriteToSubscriptGetCommon(Msg, commit);
}
static bool rewriteToArraySubscriptSet(const ObjCInterfaceDecl *IFace,
const ObjCMessageExpr *Msg,
const NSAPI &NS,
Commit &commit) {
if (Msg->getNumArgs() != 2)
return false;
const Expr *Rec = Msg->getInstanceReceiver();
if (!Rec)
return false;
if (!