//===- Frontend.cpp ---------------------------------------------*- 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/InstallAPI/Frontend.h"
#include "clang/AST/Availability.h"
#include "clang/InstallAPI/FrontendRecords.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"

using namespace llvm;
using namespace llvm::MachO;

namespace clang::installapi {
std::pair<GlobalRecord *, FrontendAttrs *> FrontendRecordsSlice::addGlobal(
    StringRef Name, RecordLinkage Linkage, GlobalRecord::Kind GV,
    const clang::AvailabilityInfo Avail, const Decl *D, const HeaderType Access,
    SymbolFlags Flags, bool Inlined) {

  GlobalRecord *GR =
      llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags, Inlined);
  auto Result = FrontendRecords.insert(
      {GR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
  return {GR, &(Result.first->second)};
}

std::pair<ObjCInterfaceRecord *, FrontendAttrs *>
FrontendRecordsSlice::addObjCInterface(StringRef Name, RecordLinkage Linkage,
                                       const clang::AvailabilityInfo Avail,
                                       const Decl *D, HeaderType Access,
                                       bool IsEHType) {
  ObjCIFSymbolKind SymType =
      ObjCIFSymbolKind::Class | ObjCIFSymbolKind::MetaClass;
  if (IsEHType)
    SymType |= ObjCIFSymbolKind::EHType;

  ObjCInterfaceRecord *ObjCR =
      llvm::MachO::RecordsSlice::addObjCInterface(Name, Linkage, SymType);
  auto Result = FrontendRecords.insert(
      {ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
  return {ObjCR, &(Result.first->second)};
}

std::pair<ObjCCategoryRecord *, FrontendAttrs *>
FrontendRecordsSlice::addObjCCategory(StringRef ClassToExtend,
                                      StringRef CategoryName,
                                      const clang::AvailabilityInfo Avail,
                                      const Decl *D, HeaderType Access) {
  ObjCCategoryRecord *ObjCR =
      llvm::MachO::RecordsSlice::addObjCCategory(ClassToExtend, CategoryName);
  auto Result = FrontendRecords.insert(
      {ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
  return {ObjCR, &(Result.first->second)};
}

std::pair<ObjCIVarRecord *, FrontendAttrs *> FrontendRecordsSlice::addObjCIVar(
    ObjCContainerRecord *Container, StringRef IvarName, RecordLinkage Linkage,
    const clang::AvailabilityInfo Avail, const Decl *D, HeaderType Access,
    const clang::ObjCIvarDecl::AccessControl AC) {
  // If the decl otherwise would have been exported, check their access control.
  // Ivar's linkage is also determined by this.
  if ((Linkage == RecordLinkage::Exported) &&
      ((AC == ObjCIvarDecl::Private) || (AC == ObjCIvarDecl::Package)))
    Linkage = RecordLinkage::Internal;
  ObjCIVarRecord *ObjCR =
      llvm::MachO::RecordsSlice::addObjCIVar(Container, IvarName, Linkage);
  auto Result = FrontendRecords.insert(
      {ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});

  return {ObjCR, &(Result.first->second)};
}

std::optional<HeaderType>
InstallAPIContext::findAndRecordFile(const FileEntry *FE,
                                     const Preprocessor &PP) {
  if (!FE)
    return std::nullopt;

  // Check if header has been looked up already and whether it is something
  // installapi should use.
  auto It = KnownFiles.find(FE);
  if (It != KnownFiles.end()) {
    if (It->second != HeaderType::Unknown)
      return It->second;
    else
      return std::nullopt;
  }

  // If file was not found, search by how the header was
  // included. This is primarily to resolve headers found
  // in a different location than what passed directly as input.
  StringRef IncludeName = PP.getHeaderSearchInfo().getIncludeNameForHeader(FE);
  auto BackupIt = KnownIncludes.find(IncludeName);
  if (BackupIt != KnownIncludes.end()) {
    KnownFiles[FE] = BackupIt->second;
    return BackupIt->second;
  }

  // Record that the file was found to avoid future string searches for the
  // same file.
  KnownFiles.insert({FE, HeaderType::Unknown});
  return std::nullopt;
}

void InstallAPIContext::addKnownHeader(const HeaderFile &H) {
  auto FE = FM->getOptionalFileRef(H.getPath());
  if (!FE)
    return; // File does not exist.
  KnownFiles[*FE] = H.getType();

  if (!H.useIncludeName())
    return;

  KnownIncludes[H.getIncludeName()] = H.getType();
}

static StringRef getFileExtension(clang::Language Lang) {
  switch (Lang) {
  default:
    llvm_unreachable("Unexpected language option.");
  case clang::Language::C:
    return ".c";
  case clang::Language::CXX:
    return ".cpp";
  case clang::Language::ObjC:
    return ".m";
  case clang::Language::ObjCXX:
    return ".mm";
  }
}

std::unique_ptr<MemoryBuffer> createInputBuffer(InstallAPIContext &Ctx) {
  assert(Ctx.Type != HeaderType::Unknown &&
         "unexpected access level for parsing");
  SmallString<4096> Contents;
  raw_svector_ostream OS(Contents);
  for (const HeaderFile &H : Ctx.InputHeaders) {
    if (H.isExcluded())
      continue;
    if (H.getType() != Ctx.Type)
      continue;
    if (Ctx.LangMode == Language::C || Ctx.LangMode == Language::CXX)
      OS << "#include ";
    else
      OS << "#import ";
    if (H.useIncludeName())
      OS << "<" << H.getIncludeName() << ">\n";
    else
      OS << "\"" << H.getPath() << "\"\n";

    Ctx.addKnownHeader(H);
  }
  if (Contents.empty())
    return nullptr;

  SmallString<64> BufferName(
      {"installapi-includes-", Ctx.Slice->getTriple().str(), "-",
       getName(Ctx.Type), getFileExtension(Ctx.LangMode)});
  return llvm::MemoryBuffer::getMemBufferCopy(Contents, BufferName);
}

std::string findLibrary(StringRef InstallName, FileManager &FM,
                        ArrayRef<std::string> FrameworkSearchPaths,
                        ArrayRef<std::string> LibrarySearchPaths,
                        ArrayRef<std::string> SearchPaths) {
  auto getLibrary =
      [&](const StringRef FullPath) -> std::optional<std::string> {
    // Prefer TextAPI files when possible.
    SmallString<PATH_MAX> TextAPIFilePath = FullPath;
    replace_extension(TextAPIFilePath, ".tbd");

    if (FM.getOptionalFileRef(TextAPIFilePath))
      return std::string(TextAPIFilePath);

    if (FM.getOptionalFileRef(FullPath))
      return std::string(FullPath);

    return std::nullopt;
  };

  const StringRef Filename = sys::path::filename(InstallName);
  const bool IsFramework = sys::path::parent_path(InstallName)
                               .ends_with((Filename + ".framework").str());
  if (IsFramework) {
    for (const StringRef Path : FrameworkSearchPaths) {
      SmallString<PATH_MAX> FullPath(Path);
      sys::path::append(FullPath, Filename + StringRef(".framework"), Filename);
      if (auto LibOrNull = getLibrary(FullPath))
        return *LibOrNull;
    }
  } else {
    // Copy Apple's linker behavior: If this is a .dylib inside a framework, do
    // not search -L paths.
    bool IsEmbeddedDylib = (sys::path::extension(InstallName) == ".dylib") &&
                           InstallName.contains(".framework/");
    if (!IsEmbeddedDylib) {
      for (const StringRef Path : LibrarySearchPaths) {
        SmallString<PATH_MAX> FullPath(Path);
        sys::path::append(FullPath, Filename);
        if (auto LibOrNull = getLibrary(FullPath))
          return *LibOrNull;
      }
    }
  }

  for (const StringRef Path : SearchPaths) {
    SmallString<PATH_MAX> FullPath(Path);
    sys::path::append(FullPath, InstallName);
    if (auto LibOrNull = getLibrary(FullPath))
      return *LibOrNull;
  }

  return {};
}

} // namespace clang::installapi
