//===--- Migrator.cpp -----------------------------------------------------===//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Basic/Diff.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Migrator/ASTMigratorPass.h"
#include "swift/Migrator/EditorAdapter.h"
#include "swift/Migrator/FixitApplyDiagnosticConsumer.h"
#include "swift/Migrator/Migrator.h"
#include "swift/Migrator/RewriteBufferEditsReceiver.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "llvm/Support/FileSystem.h"

using namespace swift;
using namespace swift::migrator;

bool migrator::updateCodeAndEmitRemapIfNeeded(
    CompilerInstance *Instance, const CompilerInvocation &Invocation) {
  if (!Invocation.getMigratorOptions().shouldRunMigrator())
    return false;

  // Delete the remap file, in case someone is re-running the Migrator. If the
  // file fails to compile and we don't get a chance to overwrite it, the old
  // changes may get picked up.
  llvm::sys::fs::remove(Invocation.getMigratorOptions().EmitRemapFilePath);

  Migrator M { Instance, Invocation }; // Provide inputs and configuration

  // Phase 1: Pre Fix-it passes
  // These uses the initial frontend invocation to apply any obvious fix-its
  // to see if we can get an error-free AST to get to Phase 2.
  std::unique_ptr<swift::CompilerInstance> PreFixItInstance;
  if (Instance->getASTContext().hadError()) {
    PreFixItInstance = M.repeatFixitMigrations(2,
      Invocation.getLangOptions().EffectiveLanguageVersion);

    // If we still couldn't fix all of the errors, give up.
    if (PreFixItInstance == nullptr ||
        !PreFixItInstance->hasASTContext() ||
        PreFixItInstance->getASTContext().hadError()) {
      return true;
    }
    M.StartInstance = PreFixItInstance.get();
  }

  // Phase 2: Syntactic Transformations
  // Don't run these passes if we're already in Swift 4.2
  auto Opts = Invocation.getLangOptions().EffectiveLanguageVersion;
  bool isFourTwo = Opts.size() == 2 && Opts[0] == 4 && Opts[1] == 2;
  if (!isFourTwo) {
    auto FailedSyntacticPasses = M.performSyntacticPasses();
    if (FailedSyntacticPasses) {
      return true;
    }
  }

  // Phase 3: Post Fix-it Passes
  // Perform fix-it based migrations on the compiler, some number of times in
  // order to give the compiler an opportunity to
  // take its time reaching a fixed point.
  // This is the end of the pipeline, so we throw away the compiler instance(s)
  // we used in these fix-it runs.

  if (M.getMigratorOptions().EnableMigratorFixits) {
    M.repeatFixitMigrations(Migrator::MaxCompilerFixitPassIterations,
                            {4, 0, 0});
  }

  // OK, we have a final resulting text. Now we compare against the input
  // to calculate a replacement map describing the changes to the input
  // necessary to get the output.
  // TODO: Document replacement map format.


  auto EmitRemapFailed = M.emitRemap();
  auto EmitMigratedFailed = M.emitMigratedFile();
  auto DumpMigrationStatesFailed = M.dumpStates();
  return EmitRemapFailed || EmitMigratedFailed || DumpMigrationStatesFailed;
}

Migrator::Migrator(CompilerInstance *StartInstance,
                   const CompilerInvocation &StartInvocation)
  : StartInstance(StartInstance), StartInvocation(StartInvocation) {

    auto ErrorOrStartBuffer = llvm::MemoryBuffer::getFile(getInputFilename());
    auto &StartBuffer = ErrorOrStartBuffer.get();
    auto StartBufferID = SrcMgr.addNewSourceBuffer(std::move(StartBuffer));
    States.push_back(MigrationState::start(SrcMgr, StartBufferID));
}

std::unique_ptr<swift::CompilerInstance>
Migrator::repeatFixitMigrations(const unsigned Iterations,
                                version::Version SwiftLanguageVersion) {
  for (unsigned i = 0; i < Iterations; ++i) {
    auto ThisInstance = performAFixItMigration(SwiftLanguageVersion);
    if (ThisInstance == nullptr) {
      break;
    } else {
      if (States.back()->noChangesOccurred()) {
        return ThisInstance;
      }
    }
  }
  return nullptr;
}

std::unique_ptr<swift::CompilerInstance>
Migrator::performAFixItMigration(version::Version SwiftLanguageVersion) {
  auto InputState = States.back();
  auto InputText = InputState->getOutputText();
  auto InputBuffer =
    llvm::MemoryBuffer::getMemBufferCopy(InputText, getInputFilename());

  CompilerInvocation Invocation { StartInvocation };
  Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
  Invocation.getLangOptions().EffectiveLanguageVersion = SwiftLanguageVersion;
  auto &LLVMArgs = Invocation.getFrontendOptions().LLVMArgs;
  auto aarch64_use_tbi = std::find(LLVMArgs.begin(), LLVMArgs.end(),
                                   "-aarch64-use-tbi");
  if (aarch64_use_tbi != LLVMArgs.end()) {
    LLVMArgs.erase(aarch64_use_tbi);
  }

  // SE-0160: When migrating, always use the Swift 3 @objc inference rules,
  // which drives warnings with the "@objc" Fix-Its.
  Invocation.getLangOptions().EnableSwift3ObjCInference = true;

  // The default behavior of the migrator, referred to as "minimal" migration
  // in SE-0160, only adds @objc Fix-Its to those cases where the Objective-C
  // entry point is explicitly used somewhere in the source code. The user
  // may also select a workflow that adds @objc for every declaration that
  // would infer @objc under the Swift 3 rules but would no longer infer
  // @objc in Swift 4.
  Invocation.getLangOptions().WarnSwift3ObjCInference =
    getMigratorOptions().KeepObjcVisibility
      ? Swift3ObjCInferenceWarnings::Complete
      : Swift3ObjCInferenceWarnings::Minimal;

  const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();

  assert(OrigFrontendOpts.InputsAndOutputs.hasPrimaryInputs() &&
         "Migration must have a primary");
  for (const auto &input : OrigFrontendOpts.InputsAndOutputs.getAllInputs()) {
    Invocation.getFrontendOptions().InputsAndOutputs.addInput(
        InputFile(input.file(), input.isPrimary(),
                  input.isPrimary() ? InputBuffer.get() : input.buffer()));
  }

  auto Instance = llvm::make_unique<swift::CompilerInstance>();
  if (Instance->setup(Invocation)) {
    return nullptr;
  }

  FixitApplyDiagnosticConsumer FixitApplyConsumer {
    InputText,
    getInputFilename(),
  };
  Instance->addDiagnosticConsumer(&FixitApplyConsumer);

  Instance->performSema();

  StringRef ResultText = InputText;
  unsigned ResultBufferID = InputState->getOutputBufferID();

  if (FixitApplyConsumer.getNumFixitsApplied() > 0) {
    SmallString<4096> Scratch;
    llvm::raw_svector_ostream OS(Scratch);
    FixitApplyConsumer.printResult(OS);
    auto ResultBuffer = llvm::MemoryBuffer::getMemBufferCopy(OS.str());
    ResultText = ResultBuffer->getBuffer();
    ResultBufferID = SrcMgr.addNewSourceBuffer(std::move(ResultBuffer));
  }

  States.push_back(MigrationState::make(MigrationKind::CompilerFixits,
                                        SrcMgr, InputState->getOutputBufferID(),
                                        ResultBufferID));
  return Instance;
}

bool Migrator::performSyntacticPasses() {
  clang::FileSystemOptions ClangFileSystemOptions;
  clang::FileManager ClangFileManager { ClangFileSystemOptions };

  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DummyClangDiagIDs {
    new clang::DiagnosticIDs()
  };
  auto ClangDiags =
    llvm::make_unique<clang::DiagnosticsEngine>(DummyClangDiagIDs,
                                                new clang::DiagnosticOptions,
                                                new clang::DiagnosticConsumer(),
                                                /*ShouldOwnClient=*/true);

  clang::SourceManager ClangSourceManager { *ClangDiags, ClangFileManager };
  clang::LangOptions ClangLangOpts;
  clang::edit::EditedSource Edits { ClangSourceManager, ClangLangOpts };

  auto InputState = States.back();
  auto InputText = InputState->getOutputText();

  EditorAdapter Editor { StartInstance->getSourceMgr(), ClangSourceManager };

  runAPIDiffMigratorPass(Editor, StartInstance->getPrimarySourceFile(),
                         getMigratorOptions());
  runTupleSplatMigratorPass(Editor, StartInstance->getPrimarySourceFile(),
                            getMigratorOptions());
  runTypeOfMigratorPass(Editor, StartInstance->getPrimarySourceFile(),
                        getMigratorOptions());

  Edits.commit(Editor.getEdits());

  RewriteBufferEditsReceiver Rewriter {
    ClangSourceManager,
    Editor.getClangFileIDForSwiftBufferID(
      StartInstance->getPrimarySourceFile()->getBufferID().getValue()),
    InputState->getOutputText()
  };

  Edits.applyRewrites(Rewriter);

  SmallString<1024> Scratch;
  llvm::raw_svector_ostream OS(Scratch);
  Rewriter.printResult(OS);
  auto ResultBuffer = this->SrcMgr.addMemBufferCopy(OS.str());

  States.push_back(
    MigrationState::make(MigrationKind::Syntactic,
                         this->SrcMgr,
                         States.back()->getInputBufferID(),
                         ResultBuffer));
  return false;
}

namespace {
/// Print a replacement from a diff edit scriptto the given output stream.
///
/// \param Filename The filename of the original file
/// \param Rep The Replacement to print
/// \param OS The output stream
void printReplacement(const StringRef Filename,
                      const Replacement &Rep,
                      llvm::raw_ostream &OS) {
  assert(!Filename.empty());
  if (Rep.Remove == 0 && Rep.Text.empty()) {
    return;
  }
  OS << "  {\n";

  OS << "    \"file\": \"";
  OS.write_escaped(Filename);
  OS << "\",\n";

  OS << "    \"offset\": " << Rep.Offset;
  if (Rep.Remove > 0) {
    OS << ",\n";
    OS << "    \"remove\": " << Rep.Remove;
  }
  if (!Rep.Text.empty()) {
    OS << ",\n";
    OS << "    \"text\": \"";
    OS.write_escaped(Rep.Text);
    OS << "\"\n";
  } else {
    OS << "\n";
  }
  OS << "  }";
}

/// Print a remap file to the given output stream.
///
/// \param OriginalFilename The filename of the file that was edited
/// not the output file for printing here.
/// \param InputText The input text without any changes.
/// \param OutputText The result text after any changes.
/// \param OS The output stream.
void printRemap(const StringRef OriginalFilename,
                const StringRef InputText,
                const StringRef OutputText,
                llvm::raw_ostream &OS) {
  assert(!OriginalFilename.empty());

  diff_match_patch<std::string> DMP;
  const auto Diffs = DMP.diff_main(InputText, OutputText, /*checkLines=*/false);

  OS << "[";

  size_t Offset = 0;

  llvm::SmallVector<Replacement, 32> Replacements;

  for (const auto &Diff : Diffs) {
    size_t OffsetIncrement = 0;
    switch (Diff.operation) {
      case decltype(DMP)::EQUAL:
        OffsetIncrement += Diff.text.size();
        break;
      case decltype(DMP)::INSERT:
        Replacements.push_back({ Offset, 0, Diff.text });
        break;
      case decltype(DMP)::DELETE:
        Replacements.push_back({ Offset, Diff.text.size(), "" });
        OffsetIncrement = Diff.text.size();
        break;
    }
    Offset += OffsetIncrement;
  }

  assert(Offset == InputText.size());

  // Combine removal edits with previous edits that are consecutive.
  for (unsigned i = 1; i < Replacements.size();) {
    auto &Previous = Replacements[i-1];
    auto &Current = Replacements[i];
    assert(Current.Offset >= Previous.Offset + Previous.Remove);
    unsigned Distance = Current.Offset-(Previous.Offset + Previous.Remove);
    if (Distance > 0) {
      ++i;
      continue;
    }
    if (!Current.Text.empty()) {
      ++i;
      continue;
    }
    Previous.Remove += Current.Remove;
    Replacements.erase(Replacements.begin() + i);
  }

  // Combine removal edits with next edits that are consecutive.
  for (unsigned i = 0; i + 1 < Replacements.size();) {
    auto &Current = Replacements[i];
    auto &nextRep = Replacements[i + 1];
    assert(nextRep.Offset >= Current.Offset + Current.Remove);
    unsigned Distance = nextRep.Offset - (Current.Offset + Current.Remove);
    if (Distance > 0) {
      ++i;
      continue;
    }
    if (!Current.Text.empty()) {
      ++i;
      continue;
    }
    nextRep.Offset -= Current.Remove;
    nextRep.Remove += Current.Remove;
    Replacements.erase(Replacements.begin() + i);
  }

  // For remaining removal diffs, include the byte adjacent to the range on the
  // left. libclang applies the diffs as byte diffs, so it doesn't matter if the
  // byte is part of a multi-byte UTF8 character.
  for (unsigned i = 0; i < Replacements.size(); ++i) {
    auto &Current = Replacements[i];
    if (!Current.Text.empty())
      continue;
    if (Current.Offset == 0)
      continue;
    Current.Offset -= 1;
    Current.Remove += 1;
    Current.Text = InputText.substr(Current.Offset, 1);
  }

  for (auto Rep = Replacements.begin(); Rep != Replacements.end(); ++Rep) {
    if (Rep != Replacements.begin()) {
      OS << ",\n";
    } else {
      OS << "\n";
    }
    printReplacement(OriginalFilename, *Rep, OS);
  }

  OS << "\n]";
}

} // end anonymous namespace

bool Migrator::emitRemap() const {
  const auto &RemapPath = getMigratorOptions().EmitRemapFilePath;
  if (RemapPath.empty()) {
    return false;
  }

  std::error_code Error;
  llvm::raw_fd_ostream FileOS(RemapPath,
                              Error, llvm::sys::fs::F_Text);
  if (FileOS.has_error()) {
    return true;
  }

  auto InputText = States.front()->getOutputText();
  auto OutputText = States.back()->getOutputText();
  printRemap(getInputFilename(), InputText, OutputText, FileOS);

  FileOS.flush();
  return FileOS.has_error();
}

bool Migrator::emitMigratedFile() const {
  const auto &OutFilename = getMigratorOptions().EmitMigratedFilePath;
  if (OutFilename.empty()) {
    return false;
  }

  std::error_code Error;
  llvm::raw_fd_ostream FileOS(OutFilename,
                              Error, llvm::sys::fs::F_Text);
  if (FileOS.has_error()) {
    return true;
  }

  FileOS << States.back()->getOutputText();

  FileOS.flush();

  return FileOS.has_error();
}

bool Migrator::dumpStates() const {
  const auto &OutDir = getMigratorOptions().DumpMigrationStatesDir;
  if (OutDir.empty()) {
    return false;
  }

  auto Failed = false;
  for (size_t i = 0; i < States.size(); ++i) {
    Failed |= States[i]->print(i, OutDir);
  }

  return Failed;
}

const MigratorOptions &Migrator::getMigratorOptions() const {
  return StartInvocation.getMigratorOptions();
}

const StringRef Migrator::getInputFilename() const {
  auto &PrimaryInput = StartInvocation.getFrontendOptions()
                           .InputsAndOutputs.getRequiredUniquePrimaryInput();
  return PrimaryInput.file();
}
