//===-- TransformActions.cpp - Migration to ARC mode ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Internals.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseSet.h"
#include <map>
using namespace clang;
using namespace arcmt;

namespace {

/// Collects transformations and merges them before applying them with
/// with applyRewrites(). E.g. if the same source range
/// is requested to be removed twice, only one rewriter remove will be invoked.
/// Rewrites happen in "transactions"; if one rewrite in the transaction cannot
/// be done (e.g. it resides in a macro) all rewrites in the transaction are
/// aborted.
/// FIXME: "Transactional" rewrites support should be baked in the Rewriter.
class TransformActionsImpl {
  CapturedDiagList &CapturedDiags;
  ASTContext &Ctx;
  Preprocessor &PP;

  bool IsInTransaction;

  enum ActionKind {
    Act_Insert, Act_InsertAfterToken,
    Act_Remove, Act_RemoveStmt,
    Act_Replace, Act_ReplaceText,
    Act_IncreaseIndentation,
    Act_ClearDiagnostic
  };

  struct ActionData {
    ActionKind Kind;
    SourceLocation Loc;
    SourceRange R1, R2;
    StringRef Text1, Text2;
    Stmt *S;
    SmallVector<unsigned, 2> DiagIDs;
  };

  std::vector<ActionData> CachedActions;

  enum RangeComparison {
    Range_Before,
    Range_After,
    Range_Contains,
    Range_Contained,
    Range_ExtendsBegin,
    Range_ExtendsEnd
  };

  /// A range to remove. It is a character range.
  struct CharRange {
    FullSourceLoc Begin, End;

    CharRange(CharSourceRange range, SourceManager &srcMgr, Preprocessor &PP) {
      SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd();
      assert(beginLoc.isValid() && endLoc.isValid());
      if (range.isTokenRange()) {
        Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
        End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr);
      } else {
        Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
        End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
      }
      assert(Begin.isValid() && End.isValid());
    }

    RangeComparison compareWith(const CharRange &RHS) const {
      if (End.isBeforeInTranslationUnitThan(RHS.Begin))
        return Range_Before;
      if (RHS.End.isBeforeInTranslationUnitThan(Begin))
        return Range_After;
      if (!Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
          !RHS.End.isBeforeInTranslationUnitThan(End))
        return Range_Contained;
      if (Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
          RHS.End.isBeforeInTranslationUnitThan(End))
        return Range_Contains;
      if (Begin.isBeforeInTranslationUnitThan(RHS.Begin))
        return Range_ExtendsBegin;
      else
        return Range_ExtendsEnd;
    }

    static RangeComparison compare(SourceRange LHS, SourceRange RHS,
                                   SourceManager &SrcMgr, Preprocessor &PP) {
      return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP)
                  .compareWith(CharRange(CharSourceRange::getTokenRange(RHS),
                                            SrcMgr, PP));
    }
  };

  typedef SmallVector<StringRef, 2> TextsVec;
  typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
      InsertsMap;
  InsertsMap Inserts;
  /// A list of ranges to remove. They are always sorted and they never
  /// intersect with each other.
  std::list<CharRange> Removals;

  llvm::DenseSet<Stmt *> StmtRemovals;

  std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges;

  /// Keeps text passed to transformation methods.
  llvm::StringMap<bool> UniqueText;

public:
  TransformActionsImpl(CapturedDiagList &capturedDiags,
                       ASTContext &ctx, Preprocessor &PP)
    : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }

  ASTContext &getASTContext() { return Ctx; }

  void startTransaction();
  bool commitTransaction();
  void abortTransaction();

  bool isInTransaction() const { return IsInTransaction; }

  void insert(SourceLocation loc, StringRef text);
  void insertAfterToken(SourceLocation loc, StringRef text);
  void remove(SourceRange range);
  void removeStmt(Stmt *S);
  void replace(SourceRange range, StringRef text);
  void replace(SourceRange range, SourceRange replacementRange);
  void replaceStmt(Stmt *S, StringRef text);
  void replaceText(SourceLocation loc, StringRef text,
                   StringRef replacementText);
  void increaseIndentation(SourceRange range,
                           SourceLocation parentIndent);

  bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);

  void applyRewrites(TransformActions::RewriteReceiver &receiver);

private:
  bool canInsert(SourceLocation loc);
  bool canInsertAfterToken(SourceLocation loc);
  bool canRemoveRange(SourceRange range);
  bool canReplaceRange(SourceRange range, SourceRange replacementRange);
  bool canReplaceText(SourceLocation loc, StringRef text);

  void commitInsert(SourceLocation loc, StringRef text);
  void commitInsertAfterToken(SourceLocation loc, StringRef text);
  void commitRemove(SourceRange range);
  void commitRemoveStmt(Stmt *S);
  void commitReplace(SourceRange range, SourceRange replacementRange);
  void commitReplaceText(SourceLocation loc, StringRef text,
                         StringRef replacementText);
  void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent);
  void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);

  void addRemoval(CharSourceRange range);
  void addInsertion(SourceLocation loc, StringRef text);

  /// Stores text passed to the transformation methods to keep the string
  /// "alive". Since the vast majority of text will be the same, we also unique
  /// the strings using a StringMap.
  StringRef getUniqueText(StringRef text);

  /// Computes the source location just past the end of the token at
  /// the given source location. If the location points at a macro, the whole
  /// macro expansion is skipped.
  static SourceLocation getLocForEndOfToken(SourceLocation loc,
                                            SourceManager &SM,Preprocessor &PP);
};

} // anonymous namespace

void TransformActionsImpl::startTransaction() {
  assert(!IsInTransaction &&
         "Cannot start a transaction in the middle of another one");
  IsInTransaction = true;
}

bool TransformActionsImpl::commitTransaction() {
  assert(IsInTransaction && "No transaction started");

  if (CachedActions.empty()) {
    IsInTransaction = false;
    return false;
  }

  // Verify that all actions are possible otherwise abort the whole transaction.
  bool AllActionsPossible = true;
  for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
    ActionData &act = CachedActions[i];
    switch (act.Kind) {
    case Act_Insert:
      if (!canInsert(act.Loc))
        AllActionsPossible = false;
      break;
    case Act_InsertAfterToken:
      if (!canInsertAfterToken(act.Loc))
        AllActionsPossible = false;
      break;
    case Act_Remove:
      if (!canRemoveRange(act.R1))
        AllActionsPossible = false;
      break;
    case Act_RemoveStmt:
      assert(act.S);
      if (!canRemoveRange(act.S->getSourceRange()))
        AllActionsPossible = false;
      break;
    case Act_Replace:
      if (!canReplaceRange(act.R1, act.R2))
        AllActionsPossible = false;
      break;
    case Act_ReplaceText:
      if (!canReplaceText(act.Loc, act.Text1))
        AllActionsPossible = false;
      break;
    case Act_IncreaseIndentation:
      // This is not important, we don't care if it will fail.
      break;
    case Act_ClearDiagnostic:
      // We are just checking source rewrites.
      break;
    }
    if (!AllActionsPossible)
      break;
  }

  if (!AllActionsPossible) {
    abortTransaction();
    return true;
  }

  for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
    ActionData &act = CachedActions[i];
    switch (act.Kind) {
    case Act_Insert:
      commitInsert(act.Loc, act.Text1);
      break;
    case Act_InsertAfterToken:
      commitInsertAfterToken(act.Loc, act.Text1);
      break;
    case Act_Remove:
      commitRemove(act.R1);
      break;
    case Act_RemoveStmt:
      commitRemoveStmt(act.S);
      break;
    case Act_Replace:
      commitReplace(act.R1, act.R2);
      break;
    case Act_ReplaceText:
      commitReplaceText(act.Loc, act.Text1, act.Text2);
      break;
    case Act_IncreaseIndentation:
      commitIncreaseIndentation(act.R1, act.Loc);
      break;
    case Act_ClearDiagnostic:
      commitClearDiagnostic(act.DiagIDs, act.R1);
      break;
    }
  }

  CachedActions.clear();
  IsInTransaction = false;
  return false;
}

void TransformActionsImpl::abortTransaction() {
  assert(IsInTransaction && "No transaction started");
  CachedActions.clear();
  IsInTransaction = false;
}

void TransformActionsImpl::insert(SourceLocation loc, StringRef text) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  text = getUniqueText(text);
  ActionData data;
  data.Kind = Act_Insert;
  data.Loc = loc;
  data.Text1 = text;
  CachedActions.push_back(data);
}

void TransformActionsImpl::insertAfterToken(SourceLocation loc, StringRef text) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  text = getUniqueText(text);
  ActionData data;
  data.Kind = Act_InsertAfterToken;
  data.Loc = loc;
  data.Text1 = text;
  CachedActions.push_back(data);
}

void TransformActionsImpl::remove(SourceRange range) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  ActionData data;
  data.Kind = Act_Remove;
  data.R1 = range;
  CachedActions.push_back(data);
}

void TransformActionsImpl::removeStmt(Stmt *S) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  ActionData data;
  data.Kind = Act_RemoveStmt;
  if (auto *E = dyn_cast<Expr>(S))
    S = E->IgnoreImplicit(); // important for uniquing
  data.S = S;
  CachedActions.push_back(data);
}

void TransformActionsImpl::replace(SourceRange range, StringRef text) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  text = getUniqueText(text);
  remove(range);
  insert(range.getBegin(), text);
}

void TransformActionsImpl::replace(SourceRange range,
                                   SourceRange replacementRange) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  ActionData data;
  data.Kind = Act_Replace;
  data.R1 = range;
  data.R2 = replacementRange;
  CachedActions.push_back(data);
}

void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text,
                                       StringRef replacementText) {
  text = getUniqueText(text);
  replacementText = getUniqueText(replacementText);
  ActionData data;
  data.Kind = Act_ReplaceText;
  data.Loc = loc;
  data.Text1 = text;
  data.Text2 = replacementText;
  CachedActions.push_back(data);
}

void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  text = getUniqueText(text);
  insert(S->getBeginLoc(), text);
  removeStmt(S);
}

void TransformActionsImpl::increaseIndentation(SourceRange range,
                                               SourceLocation parentIndent) {
  if (range.isInvalid()) return;
  assert(IsInTransaction && "Actions only allowed during a transaction");
  ActionData data;
  data.Kind = Act_IncreaseIndentation;
  data.R1 = range;
  data.Loc = parentIndent;
  CachedActions.push_back(data);
}

bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs,
                                           SourceRange range) {
  assert(IsInTransaction && "Actions only allowed during a transaction");
  if (!CapturedDiags.hasDiagnostic(IDs, range))
    return false;

  ActionData data;
  data.Kind = Act_ClearDiagnostic;
  data.R1 = range;
  data.DiagIDs.append(IDs.begin(), IDs.end());
  CachedActions.push_back(data);
  return true;
}

bool TransformActionsImpl::canInsert(SourceLocation loc) {
  if (loc.isInvalid())
    return false;

  SourceManager &SM = Ctx.getSourceManager();
  if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
    return false;

  if (loc.isFileID())
    return true;
  return PP.isAtStartOfMacroExpansion(loc);
}

bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) {
  if (loc.isInvalid())
    return false;

  SourceManager &SM = Ctx.getSourceManager();
  if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
    return false;

  if (loc.isFileID())
    return true;
  return PP.isAtEndOfMacroExpansion(loc);
}

bool TransformActionsImpl::canRemoveRange(SourceRange range) {
  return canInsert(range.getBegin()) && canInsertAfterToken(range.getEnd());
}

bool TransformActionsImpl::canReplaceRange(SourceRange range,
                                           SourceRange replacementRange) {
  return canRemoveRange(range) && canRemoveRange(replacementRange);
}

bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) {
  if (!canInsert(loc))
    return false;

  SourceManager &SM = Ctx.getSourceManager();
  loc = SM.getExpansionLoc(loc);

  // Break down the source location.
  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);

  // Try to load the file buffer.
  bool invalidTemp = false;
  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  if (invalidTemp)
    return false;

  return file.substr(locInfo.second).startswith(text);
}

void TransformActionsImpl::commitInsert(SourceLocation loc, StringRef text) {
  addInsertion(loc, text);
}

void TransformActionsImpl::commitInsertAfterToken(SourceLocation loc,
                                                  StringRef text) {
  addInsertion(getLocForEndOfToken(loc, Ctx.getSourceManager(), PP), text);
}

void TransformActionsImpl::commitRemove(SourceRange range) {
  addRemoval(CharSourceRange::getTokenRange(range));
}

void TransformActionsImpl::commitRemoveStmt(Stmt *S) {
  assert(S);
  if (StmtRemovals.count(S))
    return; // already removed.

  if (Expr *E = dyn_cast<Expr>(S)) {
    commitRemove(E->getSourceRange());
    commitInsert(E->getSourceRange().getBegin(), getARCMTMacroName());
  } else
    commitRemove(S->getSourceRange());

  StmtRemovals.insert(S);
}

void TransformActionsImpl::commitReplace(SourceRange range,
                                         SourceRange replacementRange) {
  RangeComparison comp = CharRange::compare(replacementRange, range,
                                               Ctx.getSourceManager(), PP);
  assert(comp == Range_Contained);
  if (comp != Range_Contained)
    return; // Although we asserted, be extra safe for release build.
  if (range.getBegin() != replacementRange.getBegin())
    addRemoval(CharSourceRange::getCharRange(range.getBegin(),
                                             replacementRange.getBegin()));
  if (replacementRange.getEnd() != range.getEnd())
    addRemoval(CharSourceRange::getTokenRange(
                                  getLocForEndOfToken(replacementRange.getEnd(),
                                                      Ctx.getSourceManager(), PP),
                                  range.getEnd()));
}
void TransformActionsImpl::commitReplaceText(SourceLocation loc,
                                             StringRef text,
                                             StringRef replacementText) {
  SourceManager &SM = Ctx.getSourceManager();
  loc = SM.getExpansionLoc(loc);
  // canReplaceText already checked if loc points at text.
  SourceLocation afterText = loc.getLocWithOffset(text.size());

  addRemoval(CharSourceRange::getCharRange(loc, afterText));
  commitInsert(loc, replacementText);
}

void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
                                                  SourceLocation parentIndent) {
  SourceManager &SM = Ctx.getSourceManager();
  IndentationRanges.push_back(
                 std::make_pair(CharRange(CharSourceRange::getTokenRange(range),
                                          SM, PP),
                                SM.getExpansionLoc(parentIndent)));
}

void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
                                                 SourceRange range) {
  CapturedDiags.clearDiagnostic(IDs, range);
}

void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
  SourceManager &SM = Ctx.getSourceManager();
  loc = SM.getExpansionLoc(loc);
  for (const CharRange &I : llvm::reverse(Removals)) {
    if (!SM.isBeforeInTranslationUnit(loc, I.End))
      break;
    if (I.Begin.isBeforeInTranslationUnitThan(loc))
      return;
  }

  Inserts[FullSourceLoc(loc, SM)].push_back(text);
}

void TransformActionsImpl::addRemoval(CharSourceRange range) {
  CharRange newRange(range, Ctx.getSourceManager(), PP);
  if (newRange.Begin == newRange.End)
    return;

  Inserts.erase(Inserts.upper_bound(newRange.Begin),
                Inserts.lower_bound(newRange.End));

  std::list<CharRange>::iterator I = Removals.end();
  while (I != Removals.begin()) {
    std::list<CharRange>::iterator RI = I;
    --RI;
    RangeComparison comp = newRange.compareWith(*RI);
    switch (comp) {
    case Range_Before:
      --I;
      break;
    case Range_After:
      Removals.insert(I, newRange);
      return;
    case Range_Contained:
      return;
    case Range_Contains:
      RI->End = newRange.End;
      LLVM_FALLTHROUGH;
    case Range_ExtendsBegin:
      newRange.End = RI->End;
      Removals.erase(RI);
      break;
    case Range_ExtendsEnd:
      RI->End = newRange.End;
      return;
    }
  }

  Removals.insert(Removals.begin(), newRange);
}

void TransformActionsImpl::applyRewrites(
                                  TransformActions::RewriteReceiver &receiver) {
  for (InsertsMap::iterator I = Inserts.begin(), E = Inserts.end(); I!=E; ++I) {
    SourceLocation loc = I->first;
    for (TextsVec::iterator
           TI = I->second.begin(), TE = I->second.end(); TI != TE; ++TI) {
      receiver.insert(loc, *TI);
    }
  }

  for (std::vector<std::pair<CharRange, SourceLocation> >::iterator
       I = IndentationRanges.begin(), E = IndentationRanges.end(); I!=E; ++I) {
    CharSourceRange range = CharSourceRange::getCharRange(I->first.Begin,
                                                          I->first.End);
    receiver.increaseIndentation(range, I->second);
  }

  for (std::list<CharRange>::iterator
         I = Removals.begin(), E = Removals.end(); I != E; ++I) {
    CharSourceRange range = CharSourceRange::getCharRange(I->Begin, I->End);
    receiver.remove(range);
  }
}

/// Stores text passed to the transformation methods to keep the string
/// "alive". Since the vast majority of text will be the same, we also unique
/// the strings using a StringMap.
StringRef TransformActionsImpl::getUniqueText(StringRef text) {
  return UniqueText.insert(std::make_pair(text, false)).first->first();
}

/// Computes the source location just past the end of the token at
/// the given source location. If the location points at a macro, the whole
/// macro expansion is skipped.
SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
                                                         SourceManager &SM,
                                                         Preprocessor &PP) {
  if (loc.isMacroID()) {
    CharSourceRange Exp = SM.getExpansionRange(loc);
    if (Exp.isCharRange())
      return Exp.getEnd();
    loc = Exp.getEnd();
  }
  return PP.getLocForEndOfToken(loc);
}

TransformActions::RewriteReceiver::~RewriteReceiver() { }

TransformActions::TransformActions(DiagnosticsEngine &diag,
                                   CapturedDiagList &capturedDiags,
                                   ASTContext &ctx, Preprocessor &PP)
    : Diags(diag), CapturedDiags(capturedDiags) {
  Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
}

TransformActions::~TransformActions() {
  delete static_cast<TransformActionsImpl*>(Impl);
}

void TransformActions::startTransaction() {
  static_cast<TransformActionsImpl*>(Impl)->startTransaction();
}

bool TransformActions::commitTransaction() {
  return static_cast<TransformActionsImpl*>(Impl)->commitTransaction();
}

void TransformActions::abortTransaction() {
  static_cast<TransformActionsImpl*>(Impl)->abortTransaction();
}


void TransformActions::insert(SourceLocation loc, StringRef text) {
  static_cast<TransformActionsImpl*>(Impl)->insert(loc, text);
}

void TransformActions::insertAfterToken(SourceLocation loc,
                                        StringRef text) {
  static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text);
}

void TransformActions::remove(SourceRange range) {
  static_cast<TransformActionsImpl*>(Impl)->remove(range);
}

void TransformActions::removeStmt(Stmt *S) {
  static_cast<TransformActionsImpl*>(Impl)->removeStmt(S);
}

void TransformActions::replace(SourceRange range, StringRef text) {
  static_cast<TransformActionsImpl*>(Impl)->replace(range, text);
}

void TransformActions::replace(SourceRange range,
                               SourceRange replacementRange) {
  static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange);
}

void TransformActions::replaceStmt(Stmt *S, StringRef text) {
  static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text);
}

void TransformActions::replaceText(SourceLocation loc, StringRef text,
                                   StringRef replacementText) {
  static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text,
                                                        replacementText);
}

void TransformActions::increaseIndentation(SourceRange range,
                                           SourceLocation parentIndent) {
  static_cast<TransformActionsImpl*>(Impl)->increaseIndentation(range,
                                                                parentIndent);
}

bool TransformActions::clearDiagnostic(ArrayRef<unsigned> IDs,
                                       SourceRange range) {
  return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range);
}

void TransformActions::applyRewrites(RewriteReceiver &receiver) {
  static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver);
}

DiagnosticBuilder TransformActions::report(SourceLocation loc, unsigned diagId,
                                           SourceRange range) {
  assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() &&
         "Errors should be emitted out of a transaction");
  return Diags.Report(loc, diagId) << range;
}

void TransformActions::reportError(StringRef message, SourceLocation loc,
                                   SourceRange range) {
  report(loc, diag::err_mt_message, range) << message;
}

void TransformActions::reportWarning(StringRef message, SourceLocation loc,
                                     SourceRange range) {
  report(loc, diag::warn_mt_message, range) << message;
}

void TransformActions::reportNote(StringRef message, SourceLocation loc,
                                  SourceRange range) {
  report(loc, diag::note_mt_message, range) << message;
}
