//===--- extra/modularize/ModularizeUtilities.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
//
//===----------------------------------------------------------------------===//
//
// This file implements a class for loading and validating a module map or
// header list by checking that all headers in the corresponding directories
// are accounted for.
//
//===----------------------------------------------------------------------===//

#include "ModularizeUtilities.h"
#include "CoverageChecker.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Options/Options.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace llvm;
using namespace Modularize;

namespace {
// Subclass TargetOptions so we can construct it inline with
// the minimal option, the triple.
class ModuleMapTargetOptions : public clang::TargetOptions {
public:
  ModuleMapTargetOptions() { Triple = llvm::sys::getDefaultTargetTriple(); }
};
} // namespace

// ModularizeUtilities class implementation.

// Constructor.
ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths,
                                         llvm::StringRef Prefix,
                                         llvm::StringRef ProblemFilesListPath)
    : InputFilePaths(InputPaths), HeaderPrefix(Prefix),
      ProblemFilesPath(ProblemFilesListPath), HasModuleMap(false),
      MissingHeaderCount(0),
      // Init clang stuff needed for loading the module map and preprocessing.
      LangOpts(new LangOptions()), DiagIDs(DiagnosticIDs::create()),
      DC(llvm::errs(), DiagnosticOpts),
      Diagnostics(new DiagnosticsEngine(DiagIDs, DiagnosticOpts, &DC, false)),
      TargetOpts(new ModuleMapTargetOptions()),
      Target(TargetInfo::CreateTargetInfo(*Diagnostics, *TargetOpts)),
      FileMgr(new FileManager(FileSystemOpts)),
      SourceMgr(new SourceManager(*Diagnostics, *FileMgr, false)), HSOpts(),
      HeaderInfo(new HeaderSearch(HSOpts, *SourceMgr, *Diagnostics, *LangOpts,
                                  Target.get())) {}

// Create instance of ModularizeUtilities, to simplify setting up
// subordinate objects.
ModularizeUtilities *ModularizeUtilities::createModularizeUtilities(
    std::vector<std::string> &InputPaths, llvm::StringRef Prefix,
    llvm::StringRef ProblemFilesListPath) {

  return new ModularizeUtilities(InputPaths, Prefix, ProblemFilesListPath);
}

// Load all header lists and dependencies.
std::error_code ModularizeUtilities::loadAllHeaderListsAndDependencies() {
  // For each input file.
  for (llvm::StringRef InputPath : InputFilePaths) {
    // If it's a module map.
    if (InputPath.ends_with(".modulemap")) {
      // Load the module map.
      if (std::error_code EC = loadModuleMap(InputPath))
        return EC;
    } else {
      // Else we assume it's a header list and load it.
      if (std::error_code EC = loadSingleHeaderListsAndDependencies(InputPath)) {
        errs() << "modularize: error: Unable to get header list '" << InputPath
          << "': " << EC.message() << '\n';
        return EC;
      }
    }
  }
  // If we have a problem files list.
  if (ProblemFilesPath.size() != 0) {
    // Load problem files list.
    if (std::error_code EC = loadProblemHeaderList(ProblemFilesPath)) {
      errs() << "modularize: error: Unable to get problem header list '" << ProblemFilesPath
        << "': " << EC.message() << '\n';
      return EC;
    }
  }
  return std::error_code();
}

// Do coverage checks.
// For each loaded module map, do header coverage check.
// Starting from the directory of the module.modulemap file,
// Find all header files, optionally looking only at files
// covered by the include path options, and compare against
// the headers referenced by the module.modulemap file.
// Display warnings for unaccounted-for header files.
// Returns 0 if there were no errors or warnings, 1 if there
// were warnings, 2 if any other problem, such as a bad
// module map path argument was specified.
std::error_code ModularizeUtilities::doCoverageCheck(
    std::vector<std::string> &IncludePaths,
    llvm::ArrayRef<std::string> CommandLine) {
  int ModuleMapCount = ModuleMaps.size();
  int ModuleMapIndex;
  std::error_code EC;
  for (ModuleMapIndex = 0; ModuleMapIndex < ModuleMapCount; ++ModuleMapIndex) {
    std::unique_ptr<clang::ModuleMap> &ModMap = ModuleMaps[ModuleMapIndex];
    auto Checker = CoverageChecker::createCoverageChecker(
        InputFilePaths[ModuleMapIndex], IncludePaths, CommandLine,
        ModMap.get());
    std::error_code LocalEC = Checker->doChecks();
    if (LocalEC.value() > 0)
      EC = LocalEC;
  }
  return EC;
}

// Load single header list and dependencies.
std::error_code ModularizeUtilities::loadSingleHeaderListsAndDependencies(
    llvm::StringRef InputPath) {

  // By default, use the path component of the list file name.
  SmallString<256> HeaderDirectory(InputPath);
  llvm::sys::path::remove_filename(HeaderDirectory);
  SmallString<256> CurrentDirectory;
  llvm::sys::fs::current_path(CurrentDirectory);

  // Get the prefix if we have one.
  if (HeaderPrefix.size() != 0)
    HeaderDirectory = HeaderPrefix;

  // Read the header list file into a buffer.
  ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
    MemoryBuffer::getFile(InputPath);
  if (std::error_code EC = listBuffer.getError())
    return EC;

  // Parse the header list into strings.
  SmallVector<StringRef, 32> Strings;
  listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);

  // Collect the header file names from the string list.
  for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
    E = Strings.end();
    I != E; ++I) {
    StringRef Line = I->trim();
    // Ignore comments and empty lines.
    if (Line.empty() || (Line[0] == '#'))
      continue;
    std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':');
    SmallString<256> HeaderFileName;
    // Prepend header file name prefix if it's not absolute.
    if (llvm::sys::path::is_absolute(TargetAndDependents.first))
      llvm::sys::path::native(TargetAndDependents.first, HeaderFileName);
    else {
      if (HeaderDirectory.size() != 0)
        HeaderFileName = HeaderDirectory;
      else
        HeaderFileName = CurrentDirectory;
      llvm::sys::path::append(HeaderFileName, TargetAndDependents.first);
      llvm::sys::path::native(HeaderFileName);
    }
    // Handle optional dependencies.
    DependentsVector Dependents;
    SmallVector<StringRef, 4> DependentsList;
    TargetAndDependents.second.split(DependentsList, " ", -1, false);
    int Count = DependentsList.size();
    for (int Index = 0; Index < Count; ++Index) {
      SmallString<256> Dependent;
      if (llvm::sys::path::is_absolute(DependentsList[Index]))
        Dependent = DependentsList[Index];
      else {
        if (HeaderDirectory.size() != 0)
          Dependent = HeaderDirectory;
        else
          Dependent = CurrentDirectory;
        llvm::sys::path::append(Dependent, DependentsList[Index]);
      }
      llvm::sys::path::native(Dependent);
      Dependents.push_back(getCanonicalPath(Dependent.str()));
    }
    // Get canonical form.
    HeaderFileName = getCanonicalPath(HeaderFileName);
    // Save the resulting header file path and dependencies.
    HeaderFileNames.push_back(std::string(HeaderFileName));
    Dependencies[HeaderFileName.str()] = Dependents;
  }
  return std::error_code();
}

// Load problem header list.
std::error_code ModularizeUtilities::loadProblemHeaderList(
  llvm::StringRef InputPath) {

  // By default, use the path component of the list file name.
  SmallString<256> HeaderDirectory(InputPath);
  llvm::sys::path::remove_filename(HeaderDirectory);
  SmallString<256> CurrentDirectory;
  llvm::sys::fs::current_path(CurrentDirectory);

  // Get the prefix if we have one.
  if (HeaderPrefix.size() != 0)
    HeaderDirectory = HeaderPrefix;

  // Read the header list file into a buffer.
  ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
    MemoryBuffer::getFile(InputPath);
  if (std::error_code EC = listBuffer.getError())
    return EC;

  // Parse the header list into strings.
  SmallVector<StringRef, 32> Strings;
  listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);

  // Collect the header file names from the string list.
  for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
    E = Strings.end();
    I != E; ++I) {
    StringRef Line = I->trim();
    // Ignore comments and empty lines.
    if (Line.empty() || (Line[0] == '#'))
      continue;
    SmallString<256> HeaderFileName;
    // Prepend header file name prefix if it's not absolute.
    if (llvm::sys::path::is_absolute(Line))
      llvm::sys::path::native(Line, HeaderFileName);
    else {
      if (HeaderDirectory.size() != 0)
        HeaderFileName = HeaderDirectory;
      else
        HeaderFileName = CurrentDirectory;
      llvm::sys::path::append(HeaderFileName, Line);
      llvm::sys::path::native(HeaderFileName);
    }
    // Get canonical form.
    HeaderFileName = getCanonicalPath(HeaderFileName);
    // Save the resulting header file path.
    ProblemFileNames.push_back(std::string(HeaderFileName));
  }
  return std::error_code();
}

// Load single module map and extract header file list.
std::error_code ModularizeUtilities::loadModuleMap(
    llvm::StringRef InputPath) {
  // Get file entry for module.modulemap file.
  auto ModuleMapEntryOrErr = SourceMgr->getFileManager().getFileRef(InputPath);

  // return error if not found.
  if (!ModuleMapEntryOrErr) {
    llvm::errs() << "error: File \"" << InputPath << "\" not found.\n";
    return errorToErrorCode(ModuleMapEntryOrErr.takeError());
  }
  FileEntryRef ModuleMapEntry = *ModuleMapEntryOrErr;

  // Because the module map parser uses a ForwardingDiagnosticConsumer,
  // which doesn't forward the BeginSourceFile call, we do it explicitly here.
  DC.BeginSourceFile(*LangOpts, nullptr);

  // Figure out the home directory for the module map file.
  DirectoryEntryRef Dir = ModuleMapEntry.getDir();
  StringRef DirName(Dir.getName());
  if (llvm::sys::path::filename(DirName) == "Modules") {
    DirName = llvm::sys::path::parent_path(DirName);
    if (DirName.ends_with(".framework")) {
      auto FrameworkDirOrErr = FileMgr->getDirectoryRef(DirName);
      if (!FrameworkDirOrErr) {
        // This can happen if there's a race between the above check and the
        // removal of the directory.
        return errorToErrorCode(FrameworkDirOrErr.takeError());
      }
      Dir = *FrameworkDirOrErr;
    }
  }

  std::unique_ptr<ModuleMap> ModMap;
  ModMap.reset(new ModuleMap(*SourceMgr, *Diagnostics, *LangOpts,
    Target.get(), *HeaderInfo));

  // Parse module.modulemap file into module map.
  if (ModMap->parseAndLoadModuleMapFile(ModuleMapEntry, /*IsSystem=*/false,
                                        /*ImplicitlyDiscovered=*/false, Dir)) {
    return std::error_code(1, std::generic_category());
  }

  // Do matching end call.
  DC.EndSourceFile();

  // Reset missing header count.
  MissingHeaderCount = 0;

  if (!collectModuleMapHeaders(ModMap.get()))
    return std::error_code(1, std::generic_category());

  // Save module map.
  ModuleMaps.push_back(std::move(ModMap));

  // Indicate we are using module maps.
  HasModuleMap = true;

  // Return code of 1 for missing headers.
  if (MissingHeaderCount)
    return std::error_code(1, std::generic_category());

  return std::error_code();
}

// Collect module map headers.
// Walks the modules and collects referenced headers into
// HeaderFileNames.
bool ModularizeUtilities::collectModuleMapHeaders(clang::ModuleMap *ModMap) {
  SmallVector<std::pair<StringRef, const clang::Module *>, 0> Vec;
  for (auto &M : ModMap->modules())
    Vec.emplace_back(M.first(), M.second);
  llvm::sort(Vec, llvm::less_first());
  for (auto &I : Vec)
    if (!collectModuleHeaders(*I.second))
      return false;
  return true;
}

// Collect referenced headers from one module.
// Collects the headers referenced in the given module into
// HeaderFileNames.
bool ModularizeUtilities::collectModuleHeaders(const clang::Module &Mod) {

  // Ignore explicit modules because they often have dependencies
  // we can't know.
  if (Mod.IsExplicit)
    return true;

  // Treat headers in umbrella directory as dependencies.
  DependentsVector UmbrellaDependents;

  // Recursively do submodules.
  for (auto *Submodule : Mod.submodules())
    collectModuleHeaders(*Submodule);

  if (std::optional<clang::Module::Header> UmbrellaHeader =
          Mod.getUmbrellaHeaderAsWritten()) {
    std::string HeaderPath = getCanonicalPath(UmbrellaHeader->Entry.getName());
    // Collect umbrella header.
    HeaderFileNames.push_back(HeaderPath);

    // FUTURE: When needed, umbrella header header collection goes here.
  } else if (std::optional<clang::Module::DirectoryName> UmbrellaDir =
                 Mod.getUmbrellaDirAsWritten()) {
    // If there normal headers, assume these are umbrellas and skip collection.
    if (Mod.getHeaders(Module::HK_Normal).empty()) {
      // Collect headers in umbrella directory.
      if (!collectUmbrellaHeaders(UmbrellaDir->Entry.getName(),
                                  UmbrellaDependents))
        return false;
    }
  }

  // We ignore HK_Private, HK_Textual, HK_PrivateTextual, and HK_Excluded,
  // assuming they are marked as such either because of unsuitability for
  // modules or because they are meant to be included by another header,
  // and thus should be ignored by modularize.

  for (const auto &Header : Mod.getHeaders(clang::Module::HK_Normal))
    HeaderFileNames.push_back(getCanonicalPath(Header.Entry.getName()));

  int MissingCountThisModule = Mod.MissingHeaders.size();

  for (int Index = 0; Index < MissingCountThisModule; ++Index) {
    std::string MissingFile = Mod.MissingHeaders[Index].FileName;
    SourceLocation Loc = Mod.MissingHeaders[Index].FileNameLoc;
    errs() << Loc.printToString(*SourceMgr)
      << ": error : Header not found: " << MissingFile << "\n";
  }

  MissingHeaderCount += MissingCountThisModule;

  return true;
}

// Collect headers from an umbrella directory.
bool ModularizeUtilities::collectUmbrellaHeaders(StringRef UmbrellaDirName,
  DependentsVector &Dependents) {
  // Initialize directory name.
  SmallString<256> Directory(UmbrellaDirName);
  // Walk the directory.
  std::error_code EC;
  for (llvm::sys::fs::directory_iterator I(Directory.str(), EC), E; I != E;
    I.increment(EC)) {
    if (EC)
      return false;
    std::string File(I->path());
    llvm::ErrorOr<llvm::sys::fs::basic_file_status> Status = I->status();
    if (!Status)
      return false;
    llvm::sys::fs::file_type Type = Status->type();
    // If the file is a directory, ignore the name and recurse.
    if (Type == llvm::sys::fs::file_type::directory_file) {
      if (!collectUmbrellaHeaders(File, Dependents))
        return false;
      continue;
    }
    // If the file does not have a common header extension, ignore it.
    if (!isHeader(File))
      continue;
    // Save header name.
    std::string HeaderPath = getCanonicalPath(File);
    Dependents.push_back(HeaderPath);
  }
  return true;
}

// Replace .. embedded in path for purposes of having
// a canonical path.
static std::string replaceDotDot(StringRef Path) {
  SmallString<128> Buffer;
  llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path),
    E = llvm::sys::path::end(Path);
  while (B != E) {
    if (*B == "..")
      llvm::sys::path::remove_filename(Buffer);
    else if (*B != ".")
      llvm::sys::path::append(Buffer, *B);
    ++B;
  }
  if (Path.ends_with("/") || Path.ends_with("\\"))
    Buffer.append(1, Path.back());
  return Buffer.c_str();
}

// Convert header path to canonical form.
// The canonical form is basically just use forward slashes, and remove "./".
// \param FilePath The file path, relative to the module map directory.
// \returns The file path in canonical form.
std::string ModularizeUtilities::getCanonicalPath(StringRef FilePath) {
  std::string Tmp(replaceDotDot(FilePath));
  llvm::replace(Tmp, '\\', '/');
  StringRef Tmp2(Tmp);
  if (Tmp2.starts_with("./"))
    Tmp = std::string(Tmp2.substr(2));
  return Tmp;
}

// Check for header file extension.
// If the file extension is .h, .inc, or missing, it's
// assumed to be a header.
// \param FileName The file name.  Must not be a directory.
// \returns true if it has a header extension or no extension.
bool ModularizeUtilities::isHeader(StringRef FileName) {
  StringRef Extension = llvm::sys::path::extension(FileName);
  if (Extension.size() == 0)
    return true;
  if (Extension.equals_insensitive(".h"))
    return true;
  if (Extension.equals_insensitive(".inc"))
    return true;
  return false;
}

// Get directory path component from file path.
// \returns the component of the given path, which will be
// relative if the given path is relative, absolute if the
// given path is absolute, or "." if the path has no leading
// path component.
std::string ModularizeUtilities::getDirectoryFromPath(StringRef Path) {
  SmallString<256> Directory(Path);
  sys::path::remove_filename(Directory);
  if (Directory.size() == 0)
    return ".";
  return std::string(Directory);
}

// Add unique problem file.
// Also standardizes the path.
void ModularizeUtilities::addUniqueProblemFile(std::string FilePath) {
  FilePath = getCanonicalPath(FilePath);
  // Don't add if already present.
  for(auto &TestFilePath : ProblemFileNames) {
    if (TestFilePath == FilePath)
      return;
  }
  ProblemFileNames.push_back(FilePath);
}

// Add file with no compile errors.
// Also standardizes the path.
void ModularizeUtilities::addNoCompileErrorsFile(std::string FilePath) {
  FilePath = getCanonicalPath(FilePath);
  GoodFileNames.push_back(FilePath);
}

// List problem files.
void ModularizeUtilities::displayProblemFiles() {
  errs() << "\nThese are the files with possible errors:\n\n";
  for (auto &ProblemFile : ProblemFileNames) {
    errs() << ProblemFile << "\n";
  }
}

// List files with no problems.
void ModularizeUtilities::displayGoodFiles() {
  errs() << "\nThese are the files with no detected errors:\n\n";
  for (auto &GoodFile : HeaderFileNames) {
    bool Good = true;
    for (auto &ProblemFile : ProblemFileNames) {
      if (ProblemFile == GoodFile) {
        Good = false;
        break;
      }
    }
    if (Good)
      errs() << GoodFile << "\n";
  }
}

// List files with problem files commented out.
void ModularizeUtilities::displayCombinedFiles() {
  errs() <<
    "\nThese are the combined files, with problem files preceded by #:\n\n";
  for (auto &File : HeaderFileNames) {
    bool Good = true;
    for (auto &ProblemFile : ProblemFileNames) {
      if (ProblemFile == File) {
        Good = false;
        break;
      }
    }
    errs() << (Good ? "" : "#") << File << "\n";
  }
}
