//===- InterfaceFile.cpp --------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Implements the Interface File.
//
//===----------------------------------------------------------------------===//

#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/RecordsSlice.h"
#include "llvm/TextAPI/TextAPIError.h"

using namespace llvm;
using namespace llvm::MachO;

void InterfaceFileRef::addTarget(const Target &Target) {
  addEntry(Targets, Target);
}

void InterfaceFile::addAllowableClient(StringRef InstallName,
                                       const Target &Target) {
  if (InstallName.empty())
    return;
  auto Client = addEntry(AllowableClients, InstallName);
  Client->addTarget(Target);
}

void InterfaceFile::addReexportedLibrary(StringRef InstallName,
                                         const Target &Target) {
  if (InstallName.empty())
    return;
  auto Lib = addEntry(ReexportedLibraries, InstallName);
  Lib->addTarget(Target);
}

void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
  if (Parent.empty())
    return;
  auto Iter = lower_bound(ParentUmbrellas, Target_,
                          [](const std::pair<Target, std::string> &LHS,
                             Target RHS) { return LHS.first < RHS; });

  if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
    Iter->second = std::string(Parent);
    return;
  }

  ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
}

void InterfaceFile::addRPath(StringRef RPath, const Target &InputTarget) {
  if (RPath.empty())
    return;
  using RPathEntryT = const std::pair<Target, std::string>;
  RPathEntryT Entry(InputTarget, RPath);

  if (is_contained(RPaths, Entry))
    return;

  RPaths.emplace_back(Entry);
}

void InterfaceFile::addTarget(const Target &Target) {
  addEntry(Targets, Target);
}

InterfaceFile::const_filtered_target_range
InterfaceFile::targets(ArchitectureSet Archs) const {
  std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
    return Archs.has(Target_.Arch);
  };
  return make_filter_range(Targets, fn);
}

void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
  auto Pos = llvm::lower_bound(Documents, Document,
                               [](const std::shared_ptr<InterfaceFile> &LHS,
                                  const std::shared_ptr<InterfaceFile> &RHS) {
                                 return LHS->InstallName < RHS->InstallName;
                               });
  assert((Pos == Documents.end() ||
          (*Pos)->InstallName != Document->InstallName) &&
         "Unexpected duplicate document added");
  Document->Parent = this;
  Documents.insert(Pos, Document);
}

void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
                                  bool Overwrite) {
  auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
    auto It = lower_bound(
        Documents, Reexport->getInstallName(),
        [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
          return Lhs->getInstallName() < Rhs;
        });

    if (Overwrite && It != Documents.end() &&
        Reexport->getInstallName() == (*It)->getInstallName()) {
      llvm::replace(Documents, *It, std::move(Reexport));
      return;
    }

    if ((It != Documents.end()) &&
        !(Reexport->getInstallName() < (*It)->getInstallName()))
      return;

    Documents.emplace(It, std::move(Reexport));
  };
  for (auto Doc : Library->documents())
    AddFwk(std::move(Doc));

  Library->Documents.clear();
  AddFwk(std::move(Library));
}

Expected<std::unique_ptr<InterfaceFile>>
InterfaceFile::merge(const InterfaceFile *O) const {
  // Verify files can be merged.
  if (getInstallName() != O->getInstallName()) {
    return make_error<StringError>("install names do not match",
                                   inconvertibleErrorCode());
  }

  if (getCurrentVersion() != O->getCurrentVersion()) {
    return make_error<StringError>("current versions do not match",
                                   inconvertibleErrorCode());
  }

  if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
    return make_error<StringError>("compatibility versions do not match",
                                   inconvertibleErrorCode());
  }

  if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
      (getSwiftABIVersion() != O->getSwiftABIVersion())) {
    return make_error<StringError>("swift ABI versions do not match",
                                   inconvertibleErrorCode());
  }

  if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
    return make_error<StringError>("two level namespace flags do not match",
                                   inconvertibleErrorCode());
  }

  if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
    return make_error<StringError>(
        "application extension safe flags do not match",
        inconvertibleErrorCode());
  }

  std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
  IF->setFileType(std::max(getFileType(), O->getFileType()));
  IF->setPath(getPath());
  IF->setInstallName(getInstallName());
  IF->setCurrentVersion(getCurrentVersion());
  IF->setCompatibilityVersion(getCompatibilityVersion());

  if (getSwiftABIVersion() == 0)
    IF->setSwiftABIVersion(O->getSwiftABIVersion());
  else
    IF->setSwiftABIVersion(getSwiftABIVersion());

  IF->setTwoLevelNamespace(isTwoLevelNamespace());
  IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
  IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());

  for (const auto &It : umbrellas()) {
    if (!It.second.empty())
      IF->addParentUmbrella(It.first, It.second);
  }
  for (const auto &It : O->umbrellas()) {
    if (!It.second.empty())
      IF->addParentUmbrella(It.first, It.second);
  }
  IF->addTargets(targets());
  IF->addTargets(O->targets());

  for (const auto &Lib : allowableClients())
    for (const auto &Target : Lib.targets())
      IF->addAllowableClient(Lib.getInstallName(), Target);

  for (const auto &Lib : O->allowableClients())
    for (const auto &Target : Lib.targets())
      IF->addAllowableClient(Lib.getInstallName(), Target);

  for (const auto &Lib : reexportedLibraries())
    for (const auto &Target : Lib.targets())
      IF->addReexportedLibrary(Lib.getInstallName(), Target);

  for (const auto &Lib : O->reexportedLibraries())
    for (const auto &Target : Lib.targets())
      IF->addReexportedLibrary(Lib.getInstallName(), Target);

  for (const auto &[Target, Path] : rpaths())
    IF->addRPath(Path, Target);
  for (const auto &[Target, Path] : O->rpaths())
    IF->addRPath(Path, Target);

  for (const auto *Sym : symbols()) {
    IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
                  Sym->getFlags());
  }

  for (const auto *Sym : O->symbols()) {
    IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
                  Sym->getFlags());
  }

  return std::move(IF);
}

Expected<std::unique_ptr<InterfaceFile>>
InterfaceFile::remove(Architecture Arch) const {
  if (getArchitectures() == Arch)
    return make_error<StringError>("cannot remove last architecture slice '" +
                                       getArchitectureName(Arch) + "'",
                                   inconvertibleErrorCode());

  if (!getArchitectures().has(Arch)) {
    bool Found = false;
    for (auto &Doc : Documents) {
      if (Doc->getArchitectures().has(Arch)) {
        Found = true;
        break;
      }
    }

    if (!Found)
      return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
  }

  // FIXME: Figure out how to keep these attributes in sync when new ones are
  // added.
  std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
  IF->setFileType(getFileType());
  IF->setPath(getPath());
  IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
  IF->setInstallName(getInstallName());
  IF->setCurrentVersion(getCurrentVersion());
  IF->setCompatibilityVersion(getCompatibilityVersion());
  IF->setSwiftABIVersion(getSwiftABIVersion());
  IF->setTwoLevelNamespace(isTwoLevelNamespace());
  IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
  IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
  for (const auto &It : umbrellas())
    if (It.first.Arch != Arch)
      IF->addParentUmbrella(It.first, It.second);

  for (const auto &Lib : allowableClients()) {
    for (const auto &Target : Lib.targets())
      if (Target.Arch != Arch)
        IF->addAllowableClient(Lib.getInstallName(), Target);
  }

  for (const auto &Lib : reexportedLibraries()) {
    for (const auto &Target : Lib.targets())
      if (Target.Arch != Arch)
        IF->addReexportedLibrary(Lib.getInstallName(), Target);
  }

  for (const auto *Sym : symbols()) {
    auto Archs = Sym->getArchitectures();
    Archs.clear(Arch);
    if (Archs.empty())
      continue;

    IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
                  Sym->getFlags());
  }

  for (auto &Doc : Documents) {
    // Skip the inlined document if the to be removed architecture is the
    // only one left.
    if (Doc->getArchitectures() == Arch)
      continue;

    // If the document doesn't contain the arch, then no work is to be done
    // and it can be copied over.
    if (!Doc->getArchitectures().has(Arch)) {
      auto NewDoc = Doc;
      IF->addDocument(std::move(NewDoc));
      continue;
    }

    auto Result = Doc->remove(Arch);
    if (!Result)
      return Result;

    IF->addDocument(std::move(Result.get()));
  }

  return std::move(IF);
}

Expected<std::unique_ptr<InterfaceFile>>
InterfaceFile::extract(Architecture Arch) const {
  if (!getArchitectures().has(Arch)) {
    return make_error<StringError>("file doesn't have architecture '" +
                                       getArchitectureName(Arch) + "'",
                                   inconvertibleErrorCode());
  }

  std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
  IF->setFileType(getFileType());
  IF->setPath(getPath());
  IF->addTargets(targets(Arch));
  IF->setInstallName(getInstallName());
  IF->setCurrentVersion(getCurrentVersion());
  IF->setCompatibilityVersion(getCompatibilityVersion());
  IF->setSwiftABIVersion(getSwiftABIVersion());
  IF->setTwoLevelNamespace(isTwoLevelNamespace());
  IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
  IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
  for (const auto &It : umbrellas())
    if (It.first.Arch == Arch)
      IF->addParentUmbrella(It.first, It.second);

  for (const auto &It : rpaths())
    if (It.first.Arch == Arch)
      IF->addRPath(It.second, It.first);

  for (const auto &Lib : allowableClients())
    for (const auto &Target : Lib.targets())
      if (Target.Arch == Arch)
        IF->addAllowableClient(Lib.getInstallName(), Target);

  for (const auto &Lib : reexportedLibraries())
    for (const auto &Target : Lib.targets())
      if (Target.Arch == Arch)
        IF->addReexportedLibrary(Lib.getInstallName(), Target);

  for (const auto *Sym : symbols()) {
    if (Sym->hasArchitecture(Arch))
      IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
                    Sym->getFlags());
  }

  for (auto &Doc : Documents) {
    // Skip documents that don't have the requested architecture.
    if (!Doc->getArchitectures().has(Arch))
      continue;

    auto Result = Doc->extract(Arch);
    if (!Result)
      return Result;

    IF->addDocument(std::move(Result.get()));
  }

  return std::move(IF);
}

void InterfaceFile::setFromBinaryAttrs(const RecordsSlice::BinaryAttrs &BA,
                                       const Target &Targ) {
  if (getFileType() != BA.File)
    setFileType(BA.File);
  if (getInstallName().empty())
    setInstallName(BA.InstallName);
  if (BA.AppExtensionSafe && !isApplicationExtensionSafe())
    setApplicationExtensionSafe();
  if (BA.TwoLevelNamespace && !isTwoLevelNamespace())
    setTwoLevelNamespace();
  if (BA.OSLibNotForSharedCache && !isOSLibNotForSharedCache())
    setOSLibNotForSharedCache();
  if (getCurrentVersion().empty())
    setCurrentVersion(BA.CurrentVersion);
  if (getCompatibilityVersion().empty())
    setCompatibilityVersion(BA.CompatVersion);
  if (getSwiftABIVersion() == 0)
    setSwiftABIVersion(BA.SwiftABI);
  if (getPath().empty())
    setPath(BA.Path);
  if (!BA.ParentUmbrella.empty())
    addParentUmbrella(Targ, BA.ParentUmbrella);
  for (const auto &Client : BA.AllowableClients)
    addAllowableClient(Client, Targ);
  for (const auto &Lib : BA.RexportedLibraries)
    addReexportedLibrary(Lib, Targ);
}

static bool isYAMLTextStub(const FileType &Kind) {
  return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
}

bool InterfaceFile::operator==(const InterfaceFile &O) const {
  if (Targets != O.Targets)
    return false;
  if (InstallName != O.InstallName)
    return false;
  if ((CurrentVersion != O.CurrentVersion) ||
      (CompatibilityVersion != O.CompatibilityVersion))
    return false;
  if (SwiftABIVersion != O.SwiftABIVersion)
    return false;
  if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
    return false;
  if (IsAppExtensionSafe != O.IsAppExtensionSafe)
    return false;
  if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
    return false;
  if (HasSimSupport != O.HasSimSupport)
    return false;
  if (ParentUmbrellas != O.ParentUmbrellas)
    return false;
  if (AllowableClients != O.AllowableClients)
    return false;
  if (ReexportedLibraries != O.ReexportedLibraries)
    return false;
  if (*SymbolsSet != *O.SymbolsSet)
    return false;
  // Don't compare run search paths for older filetypes that cannot express
  // them.
  if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
    if (RPaths != O.RPaths)
      return false;
    if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
      return false;
  }

  if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
                  O.Documents.end(),
                  [](const std::shared_ptr<InterfaceFile> LHS,
                     const std::shared_ptr<InterfaceFile> RHS) {
                    return *LHS == *RHS;
                  }))
    return false;
  return true;
}
