TransformActions.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. //===--- ARCMT.cpp - Migration to ARC mode --------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "Internals.h"
  10. #include "clang/AST/ASTContext.h"
  11. #include "clang/AST/Expr.h"
  12. #include "clang/Basic/SourceManager.h"
  13. #include "clang/Lex/Preprocessor.h"
  14. #include "llvm/ADT/DenseSet.h"
  15. #include <map>
  16. using namespace clang;
  17. using namespace arcmt;
  18. namespace {
  19. /// \brief Collects transformations and merges them before applying them with
  20. /// with applyRewrites(). E.g. if the same source range
  21. /// is requested to be removed twice, only one rewriter remove will be invoked.
  22. /// Rewrites happen in "transactions"; if one rewrite in the transaction cannot
  23. /// be done (e.g. it resides in a macro) all rewrites in the transaction are
  24. /// aborted.
  25. /// FIXME: "Transactional" rewrites support should be baked in the Rewriter.
  26. class TransformActionsImpl {
  27. CapturedDiagList &CapturedDiags;
  28. ASTContext &Ctx;
  29. Preprocessor &PP;
  30. bool IsInTransaction;
  31. enum ActionKind {
  32. Act_Insert, Act_InsertAfterToken,
  33. Act_Remove, Act_RemoveStmt,
  34. Act_Replace, Act_ReplaceText,
  35. Act_IncreaseIndentation,
  36. Act_ClearDiagnostic
  37. };
  38. struct ActionData {
  39. ActionKind Kind;
  40. SourceLocation Loc;
  41. SourceRange R1, R2;
  42. StringRef Text1, Text2;
  43. Stmt *S;
  44. SmallVector<unsigned, 2> DiagIDs;
  45. };
  46. std::vector<ActionData> CachedActions;
  47. enum RangeComparison {
  48. Range_Before,
  49. Range_After,
  50. Range_Contains,
  51. Range_Contained,
  52. Range_ExtendsBegin,
  53. Range_ExtendsEnd
  54. };
  55. /// \brief A range to remove. It is a character range.
  56. struct CharRange {
  57. FullSourceLoc Begin, End;
  58. CharRange(CharSourceRange range, SourceManager &srcMgr, Preprocessor &PP) {
  59. SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd();
  60. assert(beginLoc.isValid() && endLoc.isValid());
  61. if (range.isTokenRange()) {
  62. Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
  63. End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr);
  64. } else {
  65. Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
  66. End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
  67. }
  68. assert(Begin.isValid() && End.isValid());
  69. }
  70. RangeComparison compareWith(const CharRange &RHS) const {
  71. if (End.isBeforeInTranslationUnitThan(RHS.Begin))
  72. return Range_Before;
  73. if (RHS.End.isBeforeInTranslationUnitThan(Begin))
  74. return Range_After;
  75. if (!Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
  76. !RHS.End.isBeforeInTranslationUnitThan(End))
  77. return Range_Contained;
  78. if (Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
  79. RHS.End.isBeforeInTranslationUnitThan(End))
  80. return Range_Contains;
  81. if (Begin.isBeforeInTranslationUnitThan(RHS.Begin))
  82. return Range_ExtendsBegin;
  83. else
  84. return Range_ExtendsEnd;
  85. }
  86. static RangeComparison compare(SourceRange LHS, SourceRange RHS,
  87. SourceManager &SrcMgr, Preprocessor &PP) {
  88. return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP)
  89. .compareWith(CharRange(CharSourceRange::getTokenRange(RHS),
  90. SrcMgr, PP));
  91. }
  92. };
  93. typedef SmallVector<StringRef, 2> TextsVec;
  94. typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
  95. InsertsMap;
  96. InsertsMap Inserts;
  97. /// \brief A list of ranges to remove. They are always sorted and they never
  98. /// intersect with each other.
  99. std::list<CharRange> Removals;
  100. llvm::DenseSet<Stmt *> StmtRemovals;
  101. std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges;
  102. /// \brief Keeps text passed to transformation methods.
  103. llvm::StringMap<bool> UniqueText;
  104. public:
  105. TransformActionsImpl(CapturedDiagList &capturedDiags,
  106. ASTContext &ctx, Preprocessor &PP)
  107. : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }
  108. ASTContext &getASTContext() { return Ctx; }
  109. void startTransaction();
  110. bool commitTransaction();
  111. void abortTransaction();
  112. bool isInTransaction() const { return IsInTransaction; }
  113. void insert(SourceLocation loc, StringRef text);
  114. void insertAfterToken(SourceLocation loc, StringRef text);
  115. void remove(SourceRange range);
  116. void removeStmt(Stmt *S);
  117. void replace(SourceRange range, StringRef text);
  118. void replace(SourceRange range, SourceRange replacementRange);
  119. void replaceStmt(Stmt *S, StringRef text);
  120. void replaceText(SourceLocation loc, StringRef text,
  121. StringRef replacementText);
  122. void increaseIndentation(SourceRange range,
  123. SourceLocation parentIndent);
  124. bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
  125. void applyRewrites(TransformActions::RewriteReceiver &receiver);
  126. private:
  127. bool canInsert(SourceLocation loc);
  128. bool canInsertAfterToken(SourceLocation loc);
  129. bool canRemoveRange(SourceRange range);
  130. bool canReplaceRange(SourceRange range, SourceRange replacementRange);
  131. bool canReplaceText(SourceLocation loc, StringRef text);
  132. void commitInsert(SourceLocation loc, StringRef text);
  133. void commitInsertAfterToken(SourceLocation loc, StringRef text);
  134. void commitRemove(SourceRange range);
  135. void commitRemoveStmt(Stmt *S);
  136. void commitReplace(SourceRange range, SourceRange replacementRange);
  137. void commitReplaceText(SourceLocation loc, StringRef text,
  138. StringRef replacementText);
  139. void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent);
  140. void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
  141. void addRemoval(CharSourceRange range);
  142. void addInsertion(SourceLocation loc, StringRef text);
  143. /// \brief Stores text passed to the transformation methods to keep the string
  144. /// "alive". Since the vast majority of text will be the same, we also unique
  145. /// the strings using a StringMap.
  146. StringRef getUniqueText(StringRef text);
  147. /// \brief Computes the source location just past the end of the token at
  148. /// the given source location. If the location points at a macro, the whole
  149. /// macro expansion is skipped.
  150. static SourceLocation getLocForEndOfToken(SourceLocation loc,
  151. SourceManager &SM,Preprocessor &PP);
  152. };
  153. } // anonymous namespace
  154. void TransformActionsImpl::startTransaction() {
  155. assert(!IsInTransaction &&
  156. "Cannot start a transaction in the middle of another one");
  157. IsInTransaction = true;
  158. }
  159. bool TransformActionsImpl::commitTransaction() {
  160. assert(IsInTransaction && "No transaction started");
  161. if (CachedActions.empty()) {
  162. IsInTransaction = false;
  163. return false;
  164. }
  165. // Verify that all actions are possible otherwise abort the whole transaction.
  166. bool AllActionsPossible = true;
  167. for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
  168. ActionData &act = CachedActions[i];
  169. switch (act.Kind) {
  170. case Act_Insert:
  171. if (!canInsert(act.Loc))
  172. AllActionsPossible = false;
  173. break;
  174. case Act_InsertAfterToken:
  175. if (!canInsertAfterToken(act.Loc))
  176. AllActionsPossible = false;
  177. break;
  178. case Act_Remove:
  179. if (!canRemoveRange(act.R1))
  180. AllActionsPossible = false;
  181. break;
  182. case Act_RemoveStmt:
  183. assert(act.S);
  184. if (!canRemoveRange(act.S->getSourceRange()))
  185. AllActionsPossible = false;
  186. break;
  187. case Act_Replace:
  188. if (!canReplaceRange(act.R1, act.R2))
  189. AllActionsPossible = false;
  190. break;
  191. case Act_ReplaceText:
  192. if (!canReplaceText(act.Loc, act.Text1))
  193. AllActionsPossible = false;
  194. break;
  195. case Act_IncreaseIndentation:
  196. // This is not important, we don't care if it will fail.
  197. break;
  198. case Act_ClearDiagnostic:
  199. // We are just checking source rewrites.
  200. break;
  201. }
  202. if (!AllActionsPossible)
  203. break;
  204. }
  205. if (!AllActionsPossible) {
  206. abortTransaction();
  207. return true;
  208. }
  209. for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
  210. ActionData &act = CachedActions[i];
  211. switch (act.Kind) {
  212. case Act_Insert:
  213. commitInsert(act.Loc, act.Text1);
  214. break;
  215. case Act_InsertAfterToken:
  216. commitInsertAfterToken(act.Loc, act.Text1);
  217. break;
  218. case Act_Remove:
  219. commitRemove(act.R1);
  220. break;
  221. case Act_RemoveStmt:
  222. commitRemoveStmt(act.S);
  223. break;
  224. case Act_Replace:
  225. commitReplace(act.R1, act.R2);
  226. break;
  227. case Act_ReplaceText:
  228. commitReplaceText(act.Loc, act.Text1, act.Text2);
  229. break;
  230. case Act_IncreaseIndentation:
  231. commitIncreaseIndentation(act.R1, act.Loc);
  232. break;
  233. case Act_ClearDiagnostic:
  234. commitClearDiagnostic(act.DiagIDs, act.R1);
  235. break;
  236. }
  237. }
  238. CachedActions.clear();
  239. IsInTransaction = false;
  240. return false;
  241. }
  242. void TransformActionsImpl::abortTransaction() {
  243. assert(IsInTransaction && "No transaction started");
  244. CachedActions.clear();
  245. IsInTransaction = false;
  246. }
  247. void TransformActionsImpl::insert(SourceLocation loc, StringRef text) {
  248. assert(IsInTransaction && "Actions only allowed during a transaction");
  249. text = getUniqueText(text);
  250. ActionData data;
  251. data.Kind = Act_Insert;
  252. data.Loc = loc;
  253. data.Text1 = text;
  254. CachedActions.push_back(data);
  255. }
  256. void TransformActionsImpl::insertAfterToken(SourceLocation loc, StringRef text) {
  257. assert(IsInTransaction && "Actions only allowed during a transaction");
  258. text = getUniqueText(text);
  259. ActionData data;
  260. data.Kind = Act_InsertAfterToken;
  261. data.Loc = loc;
  262. data.Text1 = text;
  263. CachedActions.push_back(data);
  264. }
  265. void TransformActionsImpl::remove(SourceRange range) {
  266. assert(IsInTransaction && "Actions only allowed during a transaction");
  267. ActionData data;
  268. data.Kind = Act_Remove;
  269. data.R1 = range;
  270. CachedActions.push_back(data);
  271. }
  272. void TransformActionsImpl::removeStmt(Stmt *S) {
  273. assert(IsInTransaction && "Actions only allowed during a transaction");
  274. ActionData data;
  275. data.Kind = Act_RemoveStmt;
  276. data.S = S->IgnoreImplicit(); // important for uniquing
  277. CachedActions.push_back(data);
  278. }
  279. void TransformActionsImpl::replace(SourceRange range, StringRef text) {
  280. assert(IsInTransaction && "Actions only allowed during a transaction");
  281. text = getUniqueText(text);
  282. remove(range);
  283. insert(range.getBegin(), text);
  284. }
  285. void TransformActionsImpl::replace(SourceRange range,
  286. SourceRange replacementRange) {
  287. assert(IsInTransaction && "Actions only allowed during a transaction");
  288. ActionData data;
  289. data.Kind = Act_Replace;
  290. data.R1 = range;
  291. data.R2 = replacementRange;
  292. CachedActions.push_back(data);
  293. }
  294. void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text,
  295. StringRef replacementText) {
  296. text = getUniqueText(text);
  297. replacementText = getUniqueText(replacementText);
  298. ActionData data;
  299. data.Kind = Act_ReplaceText;
  300. data.Loc = loc;
  301. data.Text1 = text;
  302. data.Text2 = replacementText;
  303. CachedActions.push_back(data);
  304. }
  305. void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) {
  306. assert(IsInTransaction && "Actions only allowed during a transaction");
  307. text = getUniqueText(text);
  308. insert(S->getLocStart(), text);
  309. removeStmt(S);
  310. }
  311. void TransformActionsImpl::increaseIndentation(SourceRange range,
  312. SourceLocation parentIndent) {
  313. if (range.isInvalid()) return;
  314. assert(IsInTransaction && "Actions only allowed during a transaction");
  315. ActionData data;
  316. data.Kind = Act_IncreaseIndentation;
  317. data.R1 = range;
  318. data.Loc = parentIndent;
  319. CachedActions.push_back(data);
  320. }
  321. bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs,
  322. SourceRange range) {
  323. assert(IsInTransaction && "Actions only allowed during a transaction");
  324. if (!CapturedDiags.hasDiagnostic(IDs, range))
  325. return false;
  326. ActionData data;
  327. data.Kind = Act_ClearDiagnostic;
  328. data.R1 = range;
  329. data.DiagIDs.append(IDs.begin(), IDs.end());
  330. CachedActions.push_back(data);
  331. return true;
  332. }
  333. bool TransformActionsImpl::canInsert(SourceLocation loc) {
  334. if (loc.isInvalid())
  335. return false;
  336. SourceManager &SM = Ctx.getSourceManager();
  337. if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
  338. return false;
  339. if (loc.isFileID())
  340. return true;
  341. return PP.isAtStartOfMacroExpansion(loc);
  342. }
  343. bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) {
  344. if (loc.isInvalid())
  345. return false;
  346. SourceManager &SM = Ctx.getSourceManager();
  347. if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
  348. return false;
  349. if (loc.isFileID())
  350. return true;
  351. return PP.isAtEndOfMacroExpansion(loc);
  352. }
  353. bool TransformActionsImpl::canRemoveRange(SourceRange range) {
  354. return canInsert(range.getBegin()) && canInsertAfterToken(range.getEnd());
  355. }
  356. bool TransformActionsImpl::canReplaceRange(SourceRange range,
  357. SourceRange replacementRange) {
  358. return canRemoveRange(range) && canRemoveRange(replacementRange);
  359. }
  360. bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) {
  361. if (!canInsert(loc))
  362. return false;
  363. SourceManager &SM = Ctx.getSourceManager();
  364. loc = SM.getExpansionLoc(loc);
  365. // Break down the source location.
  366. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
  367. // Try to load the file buffer.
  368. bool invalidTemp = false;
  369. StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  370. if (invalidTemp)
  371. return false;
  372. return file.substr(locInfo.second).startswith(text);
  373. }
  374. void TransformActionsImpl::commitInsert(SourceLocation loc, StringRef text) {
  375. addInsertion(loc, text);
  376. }
  377. void TransformActionsImpl::commitInsertAfterToken(SourceLocation loc,
  378. StringRef text) {
  379. addInsertion(getLocForEndOfToken(loc, Ctx.getSourceManager(), PP), text);
  380. }
  381. void TransformActionsImpl::commitRemove(SourceRange range) {
  382. addRemoval(CharSourceRange::getTokenRange(range));
  383. }
  384. void TransformActionsImpl::commitRemoveStmt(Stmt *S) {
  385. assert(S);
  386. if (StmtRemovals.count(S))
  387. return; // already removed.
  388. if (Expr *E = dyn_cast<Expr>(S)) {
  389. commitRemove(E->getSourceRange());
  390. commitInsert(E->getSourceRange().getBegin(), getARCMTMacroName());
  391. } else
  392. commitRemove(S->getSourceRange());
  393. StmtRemovals.insert(S);
  394. }
  395. void TransformActionsImpl::commitReplace(SourceRange range,
  396. SourceRange replacementRange) {
  397. RangeComparison comp = CharRange::compare(replacementRange, range,
  398. Ctx.getSourceManager(), PP);
  399. assert(comp == Range_Contained);
  400. if (comp != Range_Contained)
  401. return; // Although we asserted, be extra safe for release build.
  402. if (range.getBegin() != replacementRange.getBegin())
  403. addRemoval(CharSourceRange::getCharRange(range.getBegin(),
  404. replacementRange.getBegin()));
  405. if (replacementRange.getEnd() != range.getEnd())
  406. addRemoval(CharSourceRange::getTokenRange(
  407. getLocForEndOfToken(replacementRange.getEnd(),
  408. Ctx.getSourceManager(), PP),
  409. range.getEnd()));
  410. }
  411. void TransformActionsImpl::commitReplaceText(SourceLocation loc,
  412. StringRef text,
  413. StringRef replacementText) {
  414. SourceManager &SM = Ctx.getSourceManager();
  415. loc = SM.getExpansionLoc(loc);
  416. // canReplaceText already checked if loc points at text.
  417. SourceLocation afterText = loc.getLocWithOffset(text.size());
  418. addRemoval(CharSourceRange::getCharRange(loc, afterText));
  419. commitInsert(loc, replacementText);
  420. }
  421. void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
  422. SourceLocation parentIndent) {
  423. SourceManager &SM = Ctx.getSourceManager();
  424. IndentationRanges.push_back(
  425. std::make_pair(CharRange(CharSourceRange::getTokenRange(range),
  426. SM, PP),
  427. SM.getExpansionLoc(parentIndent)));
  428. }
  429. void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
  430. SourceRange range) {
  431. CapturedDiags.clearDiagnostic(IDs, range);
  432. }
  433. void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
  434. SourceManager &SM = Ctx.getSourceManager();
  435. loc = SM.getExpansionLoc(loc);
  436. for (std::list<CharRange>::reverse_iterator
  437. I = Removals.rbegin(), E = Removals.rend(); I != E; ++I) {
  438. if (!SM.isBeforeInTranslationUnit(loc, I->End))
  439. break;
  440. if (I->Begin.isBeforeInTranslationUnitThan(loc))
  441. return;
  442. }
  443. Inserts[FullSourceLoc(loc, SM)].push_back(text);
  444. }
  445. void TransformActionsImpl::addRemoval(CharSourceRange range) {
  446. CharRange newRange(range, Ctx.getSourceManager(), PP);
  447. if (newRange.Begin == newRange.End)
  448. return;
  449. Inserts.erase(Inserts.upper_bound(newRange.Begin),
  450. Inserts.lower_bound(newRange.End));
  451. std::list<CharRange>::iterator I = Removals.end();
  452. while (I != Removals.begin()) {
  453. std::list<CharRange>::iterator RI = I;
  454. --RI;
  455. RangeComparison comp = newRange.compareWith(*RI);
  456. switch (comp) {
  457. case Range_Before:
  458. --I;
  459. break;
  460. case Range_After:
  461. Removals.insert(I, newRange);
  462. return;
  463. case Range_Contained:
  464. return;
  465. case Range_Contains:
  466. RI->End = newRange.End;
  467. case Range_ExtendsBegin:
  468. newRange.End = RI->End;
  469. Removals.erase(RI);
  470. break;
  471. case Range_ExtendsEnd:
  472. RI->End = newRange.End;
  473. return;
  474. }
  475. }
  476. Removals.insert(Removals.begin(), newRange);
  477. }
  478. void TransformActionsImpl::applyRewrites(
  479. TransformActions::RewriteReceiver &receiver) {
  480. for (InsertsMap::iterator I = Inserts.begin(), E = Inserts.end(); I!=E; ++I) {
  481. SourceLocation loc = I->first;
  482. for (TextsVec::iterator
  483. TI = I->second.begin(), TE = I->second.end(); TI != TE; ++TI) {
  484. receiver.insert(loc, *TI);
  485. }
  486. }
  487. for (std::vector<std::pair<CharRange, SourceLocation> >::iterator
  488. I = IndentationRanges.begin(), E = IndentationRanges.end(); I!=E; ++I) {
  489. CharSourceRange range = CharSourceRange::getCharRange(I->first.Begin,
  490. I->first.End);
  491. receiver.increaseIndentation(range, I->second);
  492. }
  493. for (std::list<CharRange>::iterator
  494. I = Removals.begin(), E = Removals.end(); I != E; ++I) {
  495. CharSourceRange range = CharSourceRange::getCharRange(I->Begin, I->End);
  496. receiver.remove(range);
  497. }
  498. }
  499. /// \brief Stores text passed to the transformation methods to keep the string
  500. /// "alive". Since the vast majority of text will be the same, we also unique
  501. /// the strings using a StringMap.
  502. StringRef TransformActionsImpl::getUniqueText(StringRef text) {
  503. return UniqueText.insert(std::make_pair(text, false)).first->first();
  504. }
  505. /// \brief Computes the source location just past the end of the token at
  506. /// the given source location. If the location points at a macro, the whole
  507. /// macro expansion is skipped.
  508. SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
  509. SourceManager &SM,
  510. Preprocessor &PP) {
  511. if (loc.isMacroID())
  512. loc = SM.getExpansionRange(loc).second;
  513. return PP.getLocForEndOfToken(loc);
  514. }
  515. TransformActions::RewriteReceiver::~RewriteReceiver() { }
  516. TransformActions::TransformActions(DiagnosticsEngine &diag,
  517. CapturedDiagList &capturedDiags,
  518. ASTContext &ctx, Preprocessor &PP)
  519. : Diags(diag), CapturedDiags(capturedDiags) {
  520. Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
  521. }
  522. TransformActions::~TransformActions() {
  523. delete static_cast<TransformActionsImpl*>(Impl);
  524. }
  525. void TransformActions::startTransaction() {
  526. static_cast<TransformActionsImpl*>(Impl)->startTransaction();
  527. }
  528. bool TransformActions::commitTransaction() {
  529. return static_cast<TransformActionsImpl*>(Impl)->commitTransaction();
  530. }
  531. void TransformActions::abortTransaction() {
  532. static_cast<TransformActionsImpl*>(Impl)->abortTransaction();
  533. }
  534. void TransformActions::insert(SourceLocation loc, StringRef text) {
  535. static_cast<TransformActionsImpl*>(Impl)->insert(loc, text);
  536. }
  537. void TransformActions::insertAfterToken(SourceLocation loc,
  538. StringRef text) {
  539. static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text);
  540. }
  541. void TransformActions::remove(SourceRange range) {
  542. static_cast<TransformActionsImpl*>(Impl)->remove(range);
  543. }
  544. void TransformActions::removeStmt(Stmt *S) {
  545. static_cast<TransformActionsImpl*>(Impl)->removeStmt(S);
  546. }
  547. void TransformActions::replace(SourceRange range, StringRef text) {
  548. static_cast<TransformActionsImpl*>(Impl)->replace(range, text);
  549. }
  550. void TransformActions::replace(SourceRange range,
  551. SourceRange replacementRange) {
  552. static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange);
  553. }
  554. void TransformActions::replaceStmt(Stmt *S, StringRef text) {
  555. static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text);
  556. }
  557. void TransformActions::replaceText(SourceLocation loc, StringRef text,
  558. StringRef replacementText) {
  559. static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text,
  560. replacementText);
  561. }
  562. void TransformActions::increaseIndentation(SourceRange range,
  563. SourceLocation parentIndent) {
  564. static_cast<TransformActionsImpl*>(Impl)->increaseIndentation(range,
  565. parentIndent);
  566. }
  567. bool TransformActions::clearDiagnostic(ArrayRef<unsigned> IDs,
  568. SourceRange range) {
  569. return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range);
  570. }
  571. void TransformActions::applyRewrites(RewriteReceiver &receiver) {
  572. static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver);
  573. }
  574. DiagnosticBuilder TransformActions::report(SourceLocation loc, unsigned diagId,
  575. SourceRange range) {
  576. assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() &&
  577. "Errors should be emitted out of a transaction");
  578. return Diags.Report(loc, diagId) << range;
  579. }
  580. void TransformActions::reportError(StringRef message, SourceLocation loc,
  581. SourceRange range) {
  582. report(loc, diag::err_mt_message, range) << message;
  583. }
  584. void TransformActions::reportWarning(StringRef message, SourceLocation loc,
  585. SourceRange range) {
  586. report(loc, diag::warn_mt_message, range) << message;
  587. }
  588. void TransformActions::reportNote(StringRef message, SourceLocation loc,
  589. SourceRange range) {
  590. report(loc, diag::note_mt_message, range) << message;
  591. }