//===--- ModuleAssistant.cpp - Module map generation manager -*- C++ -*---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
//
// This file defines the module generation entry point function,
// createModuleMap, a Module class for representing a module,
// and various implementation functions for doing the underlying
// work, described below.
//
// The "Module" class represents a module, with members for storing the module
// name, associated header file names, and sub-modules, and an "output"
// function that recursively writes the module definitions.
//
// The "createModuleMap" function implements the top-level logic of the
// assistant mode.  It calls a loadModuleDescriptions function to walk
// the header list passed to it and creates a tree of Module objects
// representing the module hierarchy, represented by a "Module" object,
// the "RootModule".  This root module may or may not represent an actual
// module in the module map, depending on the "--root-module" option passed
// to modularize.  It then calls a writeModuleMap function to set up the
// module map file output and walk the module tree, outputting the module
// map file using a stream obtained and managed by an
// llvm::tool_output_file object.
//
//===---------------------------------------------------------------------===//

#include "Modularize.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include <vector>

// Local definitions:

namespace {

// Internal class definitions:

// Represents a module.
class Module {
public:
  Module(llvm::StringRef Name, bool Problem);
  Module();
  ~Module();
  bool output(llvm::raw_fd_ostream &OS, int Indent);
  Module *findSubModule(llvm::StringRef SubName);

public:
  std::string Name;
  std::vector<std::string> HeaderFileNames;
  std::vector<Module *> SubModules;
  bool IsProblem;
};

} // end anonymous namespace.

// Module functions:

// Constructors.
Module::Module(llvm::StringRef Name, bool Problem)
  : Name(Name), IsProblem(Problem) {}
Module::Module() : IsProblem(false) {}

// Destructor.
Module::~Module() {
  // Free submodules.
  while (!SubModules.empty()) {
    Module *last = SubModules.back();
    SubModules.pop_back();
    delete last;
  }
}

// Write a module hierarchy to the given output stream.
bool Module::output(llvm::raw_fd_ostream &OS, int Indent) {
  // If this is not the nameless root module, start a module definition.
  if (Name.size() != 0) {
    OS.indent(Indent);
    OS << "module " << Name << " {\n";
    Indent += 2;
  }

  // Output submodules.
  for (std::vector<Module *>::iterator I = SubModules.begin(),
                                       E = SubModules.end();
       I != E; ++I) {
    if (!(*I)->output(OS, Indent))
      return false;
  }

  // Output header files.
  for (std::vector<std::string>::iterator I = HeaderFileNames.begin(),
                                          E = HeaderFileNames.end();
       I != E; ++I) {
    OS.indent(Indent);
    if (IsProblem || strstr((*I).c_str(), ".inl"))
      OS << "exclude header \"" << *I << "\"\n";
    else
      OS << "header \"" << *I << "\"\n";
  }

  // If this module has header files, output export directive.
  if (HeaderFileNames.size() != 0) {
    OS.indent(Indent);
    OS << "export *\n";
  }

  // If this is not the nameless root module, close the module definition.
  if (Name.size() != 0) {
    Indent -= 2;
    OS.indent(Indent);
    OS << "}\n";
  }

  return true;
}

// Lookup a sub-module.
Module *Module::findSubModule(llvm::StringRef SubName) {
  for (std::vector<Module *>::iterator I = SubModules.begin(),
                                       E = SubModules.end();
       I != E; ++I) {
    if ((*I)->Name == SubName)
      return *I;
  }
  return nullptr;
}

// Implementation functions:

// Reserved keywords in module.modulemap syntax.
// Keep in sync with keywords in module map parser in Lex/ModuleMap.cpp,
// such as in ModuleMapParser::consumeToken().
static const char *const ReservedNames[] = {
  "config_macros", "export",   "module", "conflict", "framework",
  "requires",      "exclude",  "header", "private",  "explicit",
  "link",          "umbrella", "extern", "use",      nullptr // Flag end.
};

// Convert module name to a non-keyword.
// Prepends a '_' to the name if and only if the name is a keyword.
static std::string
ensureNoCollisionWithReservedName(llvm::StringRef MightBeReservedName) {
  std::string SafeName = MightBeReservedName;
  for (int Index = 0; ReservedNames[Index] != nullptr; ++Index) {
    if (MightBeReservedName == ReservedNames[Index]) {
      SafeName.insert(0, "_");
      break;
    }
  }
  return SafeName;
}

// Convert module name to a non-keyword.
// Prepends a '_' to the name if and only if the name is a keyword.
static std::string
ensureVaidModuleName(llvm::StringRef MightBeInvalidName) {
  std::string SafeName = MightBeInvalidName;
  std::replace(SafeName.begin(), SafeName.end(), '-', '_');
  std::replace(SafeName.begin(), SafeName.end(), '.', '_');
  if (isdigit(SafeName[0]))
    SafeName = "_" + SafeName;
  return SafeName;
}

// Add one module, given a header file path.
static bool addModuleDescription(Module *RootModule,
                                 llvm::StringRef HeaderFilePath,
                                 llvm::StringRef HeaderPrefix,
                                 DependencyMap &Dependencies,
                                 bool IsProblemFile) {
  Module *CurrentModule = RootModule;
  DependentsVector &FileDependents = Dependencies[HeaderFilePath];
  std::string FilePath;
  // Strip prefix.
  // HeaderFilePath should be compared to natively-canonicalized Prefix.
  llvm::SmallString<256> NativePath, NativePrefix;
  llvm::sys::path::native(HeaderFilePath, NativePath);
  llvm::sys::path::native(HeaderPrefix, NativePrefix);
  if (NativePath.startswith(NativePrefix))
    FilePath = NativePath.substr(NativePrefix.size() + 1);
  else
    FilePath = HeaderFilePath;
  int Count = FileDependents.size();
  // Headers that go into modules must not depend on other files being
  // included first.  If there are any dependents, warn user and omit.
  if (Count != 0) {
    llvm::errs() << "warning: " << FilePath
                 << " depends on other headers being included first,"
                    " meaning the module.modulemap won't compile."
                    "  This header will be omitted from the module map.\n";
    return true;
  }
  // Make canonical.
  std::replace(FilePath.begin(), FilePath.end(), '\\', '/');
  // Insert module into tree, using subdirectories as submodules.
  for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(FilePath),
                                       E = llvm::sys::path::end(FilePath);
       I != E; ++I) {
    if ((*I)[0] == '.')
      continue;
    std::string Stem = llvm::sys::path::stem(*I);
    Stem = ensureNoCollisionWithReservedName(Stem);
    Stem = ensureVaidModuleName(Stem);
    Module *SubModule = CurrentModule->findSubModule(Stem);
    if (!SubModule) {
      SubModule = new Module(Stem, IsProblemFile);
      CurrentModule->SubModules.push_back(SubModule);
    }
    CurrentModule = SubModule;
  }
  // Add header file name to headers.
  CurrentModule->HeaderFileNames.push_back(FilePath);
  return true;
}

// Create the internal module tree representation.
static Module *loadModuleDescriptions(
    llvm::StringRef RootModuleName, llvm::ArrayRef<std::string> HeaderFileNames,
    llvm::ArrayRef<std::string> ProblemFileNames,
    DependencyMap &Dependencies, llvm::StringRef HeaderPrefix) {

  // Create root module.
  Module *RootModule = new Module(RootModuleName, false);

  llvm::SmallString<256> CurrentDirectory;
  llvm::sys::fs::current_path(CurrentDirectory);

  // If no header prefix, use current directory.
  if (HeaderPrefix.size() == 0)
    HeaderPrefix = CurrentDirectory;

  // Walk the header file names and output the module map.
  for (llvm::ArrayRef<std::string>::iterator I = HeaderFileNames.begin(),
                                             E = HeaderFileNames.end();
       I != E; ++I) {
    std::string Header(*I);
    bool IsProblemFile = false;
    for (auto &ProblemFile : ProblemFileNames) {
      if (ProblemFile == Header) {
        IsProblemFile = true;
        break;
      }
    }
    // Add as a module.
    if (!addModuleDescription(RootModule, Header, HeaderPrefix, Dependencies, IsProblemFile))
      return nullptr;
  }

  return RootModule;
}

// Kick off the writing of the module map.
static bool writeModuleMap(llvm::StringRef ModuleMapPath,
                           llvm::StringRef HeaderPrefix, Module *RootModule) {
  llvm::SmallString<256> HeaderDirectory(ModuleMapPath);
  llvm::sys::path::remove_filename(HeaderDirectory);
  llvm::SmallString<256> FilePath;

  // Get the module map file path to be used.
  if ((HeaderDirectory.size() == 0) && (HeaderPrefix.size() != 0)) {
    FilePath = HeaderPrefix;
    // Prepend header file name prefix if it's not absolute.
    llvm::sys::path::append(FilePath, ModuleMapPath);
    llvm::sys::path::native(FilePath);
  } else {
    FilePath = ModuleMapPath;
    llvm::sys::path::native(FilePath);
  }

  // Set up module map output file.
  std::error_code EC;
  llvm::tool_output_file Out(FilePath, EC, llvm::sys::fs::F_Text);
  if (EC) {
    llvm::errs() << Argv0 << ": error opening " << FilePath << ":"
                 << EC.message() << "\n";
    return false;
  }

  // Get output stream from tool output buffer/manager.
  llvm::raw_fd_ostream &OS = Out.os();

  // Output file comment.
  OS << "// " << ModuleMapPath << "\n";
  OS << "// Generated by: " << CommandLine << "\n\n";

  // Write module hierarchy from internal representation.
  if (!RootModule->output(OS, 0))
    return false;

  // Tell tool_output_file that we want to keep the file.
  Out.keep();

  return true;
}

// Global functions:

// Module map generation entry point.
bool createModuleMap(llvm::StringRef ModuleMapPath,
                     llvm::ArrayRef<std::string> HeaderFileNames,
                     llvm::ArrayRef<std::string> ProblemFileNames,
                     DependencyMap &Dependencies, llvm::StringRef HeaderPrefix,
                     llvm::StringRef RootModuleName) {
  // Load internal representation of modules.
  std::unique_ptr<Module> RootModule(
    loadModuleDescriptions(
      RootModuleName, HeaderFileNames, ProblemFileNames, Dependencies,
      HeaderPrefix));
  if (!RootModule.get())
    return false;

  // Write module map file.
  return writeModuleMap(ModuleMapPath, HeaderPrefix, RootModule.get());
}
