//===----- Commit.cpp - A unit of edits -----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Edit/Commit.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"

using namespace clang;
using namespace edit;

SourceLocation Commit::Edit::getFileLocation(SourceManager &SM) const {
  SourceLocation Loc = SM.getLocForStartOfFile(Offset.getFID());
  Loc = Loc.getLocWithOffset(Offset.getOffset());
  assert(Loc.isFileID());
  return Loc;
}

CharSourceRange Commit::Edit::getFileRange(SourceManager &SM) const {
  SourceLocation Loc = getFileLocation(SM);
  return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
}

CharSourceRange Commit::Edit::getInsertFromRange(SourceManager &SM) const {
  SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID());
  Loc = Loc.getLocWithOffset(InsertFromRangeOffs.getOffset());
  assert(Loc.isFileID());
  return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
}

Commit::Commit(EditedSource &Editor)
  : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
    PPRec(Editor.getPreprocessingRecord()),
    Editor(&Editor), IsCommitable(true) { }

bool Commit::insert(SourceLocation loc, StringRef text,
                    bool afterToken, bool beforePreviousInsertions) {
  if (text.empty())
    return true;

  FileOffset Offs;
  if ((!afterToken && !canInsert(loc, Offs)) ||
      ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
    IsCommitable = false;
    return false;
  }

  addInsert(loc, Offs, text, beforePreviousInsertions);
  return true;
}

bool Commit::insertFromRange(SourceLocation loc,
                             CharSourceRange range,
                             bool afterToken, bool beforePreviousInsertions) {
  FileOffset RangeOffs;
  unsigned RangeLen;
  if (!canRemoveRange(range, RangeOffs, RangeLen)) {
    IsCommitable = false;
    return false;
  }

  FileOffset Offs;
  if ((!afterToken && !canInsert(loc, Offs)) ||
      ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
    IsCommitable = false;
    return false;
  }

  if (PPRec &&
      PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) {
    IsCommitable = false;
    return false;
  }

  addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions);
  return true;
}

bool Commit::remove(CharSourceRange range) {
  FileOffset Offs;
  unsigned Len;
  if (!canRemoveRange(range, Offs, Len)) {
    IsCommitable = false;
    return false;
  }

  addRemove(range.getBegin(), Offs, Len);
  return true;
}

bool Commit::insertWrap(StringRef before, CharSourceRange range,
                        StringRef after) {
  bool commitableBefore = insert(range.getBegin(), before, /*afterToken=*/false,
                                 /*beforePreviousInsertions=*/true);
  bool commitableAfter;
  if (range.isTokenRange())
    commitableAfter = insertAfterToken(range.getEnd(), after);
  else
    commitableAfter = insert(range.getEnd(), after);

  return commitableBefore && commitableAfter;
}

bool Commit::replace(CharSourceRange range, StringRef text) {
  if (text.empty())
    return remove(range);

  FileOffset Offs;
  unsigned Len;
  if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) {
    IsCommitable = false;
    return false;
  }

  addRemove(range.getBegin(), Offs, Len);
  addInsert(range.getBegin(), Offs, text, false);
  return true;
}

bool Commit::replaceWithInner(CharSourceRange range,
                              CharSourceRange replacementRange) {
  FileOffset OuterBegin;
  unsigned OuterLen;
  if (!canRemoveRange(range, OuterBegin, OuterLen)) {
    IsCommitable = false;
    return false;
  }

  FileOffset InnerBegin;
  unsigned InnerLen;
  if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) {
    IsCommitable = false;
    return false;
  }

  FileOffset OuterEnd = OuterBegin.getWithOffset(OuterLen);
  FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen); 
  if (OuterBegin.getFID() != InnerBegin.getFID() ||
      InnerBegin < OuterBegin ||
      InnerBegin > OuterEnd ||
      InnerEnd > OuterEnd) {
    IsCommitable = false;
    return false;
  }

  addRemove(range.getBegin(),
            OuterBegin, InnerBegin.getOffset() - OuterBegin.getOffset());
  addRemove(replacementRange.getEnd(),
            InnerEnd, OuterEnd.getOffset() - InnerEnd.getOffset());
  return true;
}

bool Commit::replaceText(SourceLocation loc, StringRef text,
                         StringRef replacementText) {
  if (text.empty() || replacementText.empty())
    return true;

  FileOffset Offs;
  unsigned Len;
  if (!canReplaceText(loc, replacementText, Offs, Len)) {
    IsCommitable = false;
    return false;
  }

  addRemove(loc, Offs, Len);
  addInsert(loc, Offs, text, false);
  return true;
}

void Commit::addInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text,
                       bool beforePreviousInsertions) {
  if (text.empty())
    return;

  Edit data;
  data.Kind = Act_Insert;
  data.OrigLoc = OrigLoc;
  data.Offset = Offs;
  data.Text = text;
  data.BeforePrev = beforePreviousInsertions;
  CachedEdits.push_back(data);
}

void Commit::addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
                                FileOffset RangeOffs, unsigned RangeLen,
                                bool beforePreviousInsertions) {
  if (RangeLen == 0)
    return;

  Edit data;
  data.Kind = Act_InsertFromRange;
  data.OrigLoc = OrigLoc;
  data.Offset = Offs;
  data.InsertFromRangeOffs = RangeOffs;
  data.Length = RangeLen;
  data.BeforePrev = beforePreviousInsertions;
  CachedEdits.push_back(data);
}

void Commit::addRemove(SourceLocation OrigLoc,
                       FileOffset Offs, unsigned Len) {
  if (Len == 0)
    return;

  Edit data;
  data.Kind = Act_Remove;
  data.OrigLoc = OrigLoc;
  data.Offset = Offs;
  data.Length = Len;
  CachedEdits.push_back(data);
}

bool Commit::canInsert(SourceLocation loc, FileOffset &offs) {
  if (loc.isInvalid())
    return false;

  if (loc.isMacroID())
    isAtStartOfMacroExpansion(loc, &loc);

  const SourceManager &SM = SourceMgr;
  while (SM.isMacroArgExpansion(loc))
    loc = SM.getImmediateSpellingLoc(loc);

  if (loc.isMacroID())
    if (!isAtStartOfMacroExpansion(loc, &loc))
      return false;

  if (SM.isInSystemHeader(loc))
    return false;

  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
  if (locInfo.first.isInvalid())
    return false;
  offs = FileOffset(locInfo.first, locInfo.second);
  return canInsertInOffset(loc, offs);
}

bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,
                                 SourceLocation &AfterLoc) {
  if (loc.isInvalid())

    return false;

  SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc);
  unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, SourceMgr, LangOpts);
  AfterLoc = loc.getLocWithOffset(tokLen);

  if (loc.isMacroID())
    isAtEndOfMacroExpansion(loc, &loc);

  const SourceManager &SM = SourceMgr;
  while (SM.isMacroArgExpansion(loc))
    loc = SM.getImmediateSpellingLoc(loc);

  if (loc.isMacroID())
    if (!isAtEndOfMacroExpansion(loc, &loc))
      return false;

  if (SM.isInSystemHeader(loc))
    return false;

  loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts);
  if (loc.isInvalid())
    return false;

  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
  if (locInfo.first.isInvalid())
    return false;
  offs = FileOffset(locInfo.first, locInfo.second);
  return canInsertInOffset(loc, offs);
}

bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
  for (unsigned i = 0, e = CachedEdits.size(); i != e; ++i) {
    Edit &act = CachedEdits[i];
    if (act.Kind == Act_Remove) {
      if (act.Offset.getFID() == Offs.getFID() &&
          Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))
        return false; // position has been removed.
    }
  }

  if (!Editor)
    return true;
  return Editor->canInsertInOffset(OrigLoc, Offs);
}

bool Commit::canRemoveRange(CharSourceRange range,
                            FileOffset &Offs, unsigned &Len) {
  const SourceManager &SM = SourceMgr;
  range = Lexer::makeFileCharRange(range, SM, LangOpts);
  if (range.isInvalid())
    return false;
  
  if (range.getBegin().isMacroID() || range.getEnd().isMacroID())
    return false;
  if (SM.isInSystemHeader(range.getBegin()) ||
      SM.isInSystemHeader(range.getEnd()))
    return false;

  if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange()))
    return false;

  std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin());
  std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd());
  if (beginInfo.first != endInfo.first ||
      beginInfo.second > endInfo.second)
    return false;

  Offs = FileOffset(beginInfo.first, beginInfo.second);
  Len = endInfo.second - beginInfo.second;
  return true;
}

bool Commit::canReplaceText(SourceLocation loc, StringRef text,
                            FileOffset &Offs, unsigned &Len) {
  assert(!text.empty());

  if (!canInsert(loc, Offs))
    return false;

  // Try to load the file buffer.
  bool invalidTemp = false;
  StringRef file = SourceMgr.getBufferData(Offs.getFID(), &invalidTemp);
  if (invalidTemp)
    return false;

  Len = text.size();
  return file.substr(Offs.getOffset()).startswith(text);
}

bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,
                                       SourceLocation *MacroBegin) const {
  return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin);
}
bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,
                                     SourceLocation *MacroEnd) const {
  return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
}
