//===--- AtomicChange.cpp - AtomicChange implementation ---------*- C++ -*-===//
//
// 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 "clang/Tooling/Refactoring/AtomicChange.h"
#include "clang/Tooling/ReplacementsYaml.h"
#include "llvm/Support/YAMLTraits.h"
#include <string>

LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::AtomicChange)

namespace {
/// Helper to (de)serialize an AtomicChange since we don't have direct
/// access to its data members.
/// Data members of a normalized AtomicChange can be directly mapped from/to
/// YAML string.
struct NormalizedAtomicChange {
  NormalizedAtomicChange() = default;

  NormalizedAtomicChange(const llvm::yaml::IO &) {}

  // This converts AtomicChange's internal implementation of the replacements
  // set to a vector of replacements.
  NormalizedAtomicChange(const llvm::yaml::IO &,
                         const clang::tooling::AtomicChange &E)
      : Key(E.getKey()), FilePath(E.getFilePath()), Error(E.getError()),
        InsertedHeaders(E.getInsertedHeaders()),
        RemovedHeaders(E.getRemovedHeaders()),
        Replaces(E.getReplacements().begin(), E.getReplacements().end()) {}

  // This is not expected to be called but needed for template instantiation.
  clang::tooling::AtomicChange denormalize(const llvm::yaml::IO &) {
    llvm_unreachable("Do not convert YAML to AtomicChange directly with '>>'. "
                     "Use AtomicChange::convertFromYAML instead.");
  }
  std::string Key;
  std::string FilePath;
  std::string Error;
  std::vector<std::string> InsertedHeaders;
  std::vector<std::string> RemovedHeaders;
  std::vector<clang::tooling::Replacement> Replaces;
};
} // anonymous namespace

namespace llvm {
namespace yaml {

/// Specialized MappingTraits to describe how an AtomicChange is
/// (de)serialized.
template <> struct MappingTraits<NormalizedAtomicChange> {
  static void mapping(IO &Io, NormalizedAtomicChange &Doc) {
    Io.mapRequired("Key", Doc.Key);
    Io.mapRequired("FilePath", Doc.FilePath);
    Io.mapRequired("Error", Doc.Error);
    Io.mapRequired("InsertedHeaders", Doc.InsertedHeaders);
    Io.mapRequired("RemovedHeaders", Doc.RemovedHeaders);
    Io.mapRequired("Replacements", Doc.Replaces);
  }
};

/// Specialized MappingTraits to describe how an AtomicChange is
/// (de)serialized.
template <> struct MappingTraits<clang::tooling::AtomicChange> {
  static void mapping(IO &Io, clang::tooling::AtomicChange &Doc) {
    MappingNormalization<NormalizedAtomicChange, clang::tooling::AtomicChange>
        Keys(Io, Doc);
    Io.mapRequired("Key", Keys->Key);
    Io.mapRequired("FilePath", Keys->FilePath);
    Io.mapRequired("Error", Keys->Error);
    Io.mapRequired("InsertedHeaders", Keys->InsertedHeaders);
    Io.mapRequired("RemovedHeaders", Keys->RemovedHeaders);
    Io.mapRequired("Replacements", Keys->Replaces);
  }
};

} // end namespace yaml
} // end namespace llvm

namespace clang {
namespace tooling {
namespace {

// Returns true if there is any line that violates \p ColumnLimit in range
// [Start, End].
bool violatesColumnLimit(llvm::StringRef Code, unsigned ColumnLimit,
                         unsigned Start, unsigned End) {
  auto StartPos = Code.rfind('\n', Start);
  StartPos = (StartPos == llvm::StringRef::npos) ? 0 : StartPos + 1;

  auto EndPos = Code.find("\n", End);
  if (EndPos == llvm::StringRef::npos)
    EndPos = Code.size();

  llvm::SmallVector<llvm::StringRef, 8> Lines;
  Code.substr(StartPos, EndPos - StartPos).split(Lines, '\n');
  for (llvm::StringRef Line : Lines)
    if (Line.size() > ColumnLimit)
      return true;
  return false;
}

std::vector<Range>
getRangesForFormating(llvm::StringRef Code, unsigned ColumnLimit,
                      ApplyChangesSpec::FormatOption Format,
                      const clang::tooling::Replacements &Replaces) {
  // kNone suppresses formatting entirely.
  if (Format == ApplyChangesSpec::kNone)
    return {};
  std::vector<clang::tooling::Range> Ranges;
  // This works assuming that replacements are ordered by offset.
  // FIXME: use `getAffectedRanges()` to calculate when it does not include '\n'
  // at the end of an insertion in affected ranges.
  int Offset = 0;
  for (const clang::tooling::Replacement &R : Replaces) {
    int Start = R.getOffset() + Offset;
    int End = Start + R.getReplacementText().size();
    if (!R.getReplacementText().empty() &&
        R.getReplacementText().back() == '\n' && R.getLength() == 0 &&
        R.getOffset() > 0 && R.getOffset() <= Code.size() &&
        Code[R.getOffset() - 1] == '\n')
      // If we are inserting at the start of a line and the replacement ends in
      // a newline, we don't need to format the subsequent line.
      --End;
    Offset += R.getReplacementText().size() - R.getLength();

    if (Format == ApplyChangesSpec::kAll ||
        violatesColumnLimit(Code, ColumnLimit, Start, End))
      Ranges.emplace_back(Start, End - Start);
  }
  return Ranges;
}

inline llvm::Error make_string_error(const llvm::Twine &Message) {
  return llvm::make_error<llvm::StringError>(Message,
                                             llvm::inconvertibleErrorCode());
}

// Creates replacements for inserting/deleting #include headers.
llvm::Expected<Replacements>
createReplacementsForHeaders(llvm::StringRef FilePath, llvm::StringRef Code,
                             llvm::ArrayRef<AtomicChange> Changes,
                             const format::FormatStyle &Style) {
  // Create header insertion/deletion replacements to be cleaned up
  // (i.e. converted to real insertion/deletion replacements).
  Replacements HeaderReplacements;
  for (const auto &Change : Changes) {
    for (llvm::StringRef Header : Change.getInsertedHeaders()) {
      std::string EscapedHeader =
          Header.starts_with("<") || Header.starts_with("\"")
              ? Header.str()
              : ("\"" + Header + "\"").str();
      std::string ReplacementText = "#include " + EscapedHeader;
      // Offset UINT_MAX and length 0 indicate that the replacement is a header
      // insertion.
      llvm::Error Err = HeaderReplacements.add(
          tooling::Replacement(FilePath, UINT_MAX, 0, ReplacementText));
      if (Err)
        return std::move(Err);
    }
    for (const std::string &Header : Change.getRemovedHeaders()) {
      // Offset UINT_MAX and length 1 indicate that the replacement is a header
      // deletion.
      llvm::Error Err =
          HeaderReplacements.add(Replacement(FilePath, UINT_MAX, 1, Header));
      if (Err)
        return std::move(Err);
    }
  }

  // cleanupAroundReplacements() converts header insertions/deletions into
  // actual replacements that add/remove headers at the right location.
  return clang::format::cleanupAroundReplacements(Code, HeaderReplacements,
                                                  Style);
}

// Combine replacements in all Changes as a `Replacements`. This ignores the
// file path in all replacements and replaces them with \p FilePath.
llvm::Expected<Replacements>
combineReplacementsInChanges(llvm::StringRef FilePath,
                             llvm::ArrayRef<AtomicChange> Changes) {
  Replacements Replaces;
  for (const auto &Change : Changes)
    for (const auto &R : Change.getReplacements())
      if (auto Err = Replaces.add(Replacement(
              FilePath, R.getOffset(), R.getLength(), R.getReplacementText())))
        return std::move(Err);
  return Replaces;
}

} // end namespace

AtomicChange::AtomicChange(const SourceManager &SM,
                           SourceLocation KeyPosition) {
  const FullSourceLoc FullKeyPosition(KeyPosition, SM);
  std::pair<FileID, unsigned> FileIDAndOffset =
      FullKeyPosition.getSpellingLoc().getDecomposedLoc();
  OptionalFileEntryRef FE = SM.getFileEntryRefForID(FileIDAndOffset.first);
  assert(FE && "Cannot create AtomicChange with invalid location.");
  FilePath = std::string(FE->getName());
  Key = FilePath + ":" + std::to_string(FileIDAndOffset.second);
}

AtomicChange::AtomicChange(const SourceManager &SM, SourceLocation KeyPosition,
                           llvm::Any M)
    : AtomicChange(SM, KeyPosition) {
  Metadata = std::move(M);
}

AtomicChange::AtomicChange(std::string Key, std::string FilePath,
                           std::string Error,
                           std::vector<std::string> InsertedHeaders,
                           std::vector<std::string> RemovedHeaders,
                           clang::tooling::Replacements Replaces)
    : Key(std::move(Key)), FilePath(std::move(FilePath)),
      Error(std::move(Error)), InsertedHeaders(std::move(InsertedHeaders)),
      RemovedHeaders(std::move(RemovedHeaders)), Replaces(std::move(Replaces)) {
}

bool AtomicChange::operator==(const AtomicChange &Other) const {
  if (Key != Other.Key || FilePath != Other.FilePath || Error != Other.Error)
    return false;
  if (!(Replaces == Other.Replaces))
    return false;
  // FXIME: Compare header insertions/removals.
  return true;
}

std::string AtomicChange::toYAMLString() {
  std::string YamlContent;
  llvm::raw_string_ostream YamlContentStream(YamlContent);

  llvm::yaml::Output YAML(YamlContentStream);
  YAML << *this;
  YamlContentStream.flush();
  return YamlContent;
}

AtomicChange AtomicChange::convertFromYAML(llvm::StringRef YAMLContent) {
  NormalizedAtomicChange NE;
  llvm::yaml::Input YAML(YAMLContent);
  YAML >> NE;
  AtomicChange E(NE.Key, NE.FilePath, NE.Error, NE.InsertedHeaders,
                 NE.RemovedHeaders, tooling::Replacements());
  for (const auto &R : NE.Replaces) {
    llvm::Error Err = E.Replaces.add(R);
    if (Err)
      llvm_unreachable(
          "Failed to add replacement when Converting YAML to AtomicChange.");
    llvm::consumeError(std::move(Err));
  }
  return E;
}

llvm::Error AtomicChange::replace(const SourceManager &SM,
                                  const CharSourceRange &Range,
                                  llvm::StringRef ReplacementText) {
  return Replaces.add(Replacement(SM, Range, ReplacementText));
}

llvm::Error AtomicChange::replace(const SourceManager &SM, SourceLocation Loc,
                                  unsigned Length, llvm::StringRef Text) {
  return Replaces.add(Replacement(SM, Loc, Length, Text));
}

llvm::Error AtomicChange::insert(const SourceManager &SM, SourceLocation Loc,
                                 llvm::StringRef Text, bool InsertAfter) {
  if (Text.empty())
    return llvm::Error::success();
  Replacement R(SM, Loc, 0, Text);
  llvm::Error Err = Replaces.add(R);
  if (Err) {
    return llvm::handleErrors(
        std::move(Err), [&](const ReplacementError &RE) -> llvm::Error {
          if (RE.get() != replacement_error::insert_conflict)
            return llvm::make_error<ReplacementError>(RE);
          unsigned NewOffset = Replaces.getShiftedCodePosition(R.getOffset());
          if (!InsertAfter)
            NewOffset -=
                RE.getExistingReplacement()->getReplacementText().size();
          Replacement NewR(R.getFilePath(), NewOffset, 0, Text);
          Replaces = Replaces.merge(Replacements(NewR));
          return llvm::Error::success();
        });
  }
  return llvm::Error::success();
}

void AtomicChange::addHeader(llvm::StringRef Header) {
  InsertedHeaders.push_back(std::string(Header));
}

void AtomicChange::removeHeader(llvm::StringRef Header) {
  RemovedHeaders.push_back(std::string(Header));
}

llvm::Expected<std::string>
applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
                   llvm::ArrayRef<AtomicChange> Changes,
                   const ApplyChangesSpec &Spec) {
  llvm::Expected<Replacements> HeaderReplacements =
      createReplacementsForHeaders(FilePath, Code, Changes, Spec.Style);
  if (!HeaderReplacements)
    return make_string_error(
        "Failed to create replacements for header changes: " +
        llvm::toString(HeaderReplacements.takeError()));

  llvm::Expected<Replacements> Replaces =
      combineReplacementsInChanges(FilePath, Changes);
  if (!Replaces)
    return make_string_error("Failed to combine replacements in all changes: " +
                             llvm::toString(Replaces.takeError()));

  Replacements AllReplaces = std::move(*Replaces);
  for (const auto &R : *HeaderReplacements) {
    llvm::Error Err = AllReplaces.add(R);
    if (Err)
      return make_string_error(
          "Failed to combine existing replacements with header replacements: " +
          llvm::toString(std::move(Err)));
  }

  if (Spec.Cleanup) {
    llvm::Expected<Replacements> CleanReplaces =
        format::cleanupAroundReplacements(Code, AllReplaces, Spec.Style);
    if (!CleanReplaces)
      return make_string_error("Failed to cleanup around replacements: " +
                               llvm::toString(CleanReplaces.takeError()));
    AllReplaces = std::move(*CleanReplaces);
  }

  // Apply all replacements.
  llvm::Expected<std::string> ChangedCode =
      applyAllReplacements(Code, AllReplaces);
  if (!ChangedCode)
    return make_string_error("Failed to apply all replacements: " +
                             llvm::toString(ChangedCode.takeError()));

  // Sort inserted headers. This is done even if other formatting is turned off
  // as incorrectly sorted headers are always just wrong, it's not a matter of
  // taste.
  Replacements HeaderSortingReplacements = format::sortIncludes(
      Spec.Style, *ChangedCode, AllReplaces.getAffectedRanges(), FilePath);
  ChangedCode = applyAllReplacements(*ChangedCode, HeaderSortingReplacements);
  if (!ChangedCode)
    return make_string_error(
        "Failed to apply replacements for sorting includes: " +
        llvm::toString(ChangedCode.takeError()));

  AllReplaces = AllReplaces.merge(HeaderSortingReplacements);

  std::vector<Range> FormatRanges = getRangesForFormating(
      *ChangedCode, Spec.Style.ColumnLimit, Spec.Format, AllReplaces);
  if (!FormatRanges.empty()) {
    Replacements FormatReplacements =
        format::reformat(Spec.Style, *ChangedCode, FormatRanges, FilePath);
    ChangedCode = applyAllReplacements(*ChangedCode, FormatReplacements);
    if (!ChangedCode)
      return make_string_error(
          "Failed to apply replacements for formatting changed code: " +
          llvm::toString(ChangedCode.takeError()));
  }
  return ChangedCode;
}

} // end namespace tooling
} // end namespace clang
