//===--- APINotesManager.cpp - Manage API Notes Files ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the APINotesManager class.
//
//===----------------------------------------------------------------------===//

#include "clang/APINotes/APINotesManager.h"
#include "clang/APINotes/APINotesOptions.h"
#include "clang/APINotes/APINotesReader.h"
#include "clang/APINotes/APINotesYAMLCompiler.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceMgrAdapter.h"
#include "clang/Basic/Version.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include <sys/stat.h>

using namespace clang;
using namespace api_notes;

#define DEBUG_TYPE "API Notes"
STATISTIC(NumHeaderAPINotes,
          "non-framework API notes files loaded");
STATISTIC(NumPublicFrameworkAPINotes,
          "framework public API notes loaded");
STATISTIC(NumPrivateFrameworkAPINotes,
          "framework private API notes loaded");
STATISTIC(NumFrameworksSearched,
          "frameworks searched");
STATISTIC(NumDirectoriesSearched,
          "header directories searched");
STATISTIC(NumDirectoryCacheHits,
          "directory cache hits");
STATISTIC(NumBinaryCacheHits,
          "binary form cache hits");
STATISTIC(NumBinaryCacheMisses,
          "binary form cache misses");
STATISTIC(NumBinaryCacheRebuilds,
          "binary form cache rebuilds");

namespace {
  /// Prints two successive strings, which much be kept alive as long as the
  /// PrettyStackTrace entry.
  class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
    StringRef First, Second;
  public:
    PrettyStackTraceDoubleString(StringRef first, StringRef second)
        : First(first), Second(second) {}
    void print(raw_ostream &OS) const override {
      OS << First << Second;
    }
  };
}

APINotesManager::APINotesManager(SourceManager &sourceMgr,
                                 const LangOptions &langOpts)
  : SourceMgr(sourceMgr), ImplicitAPINotes(langOpts.APINotes),
    PrunedCache(false) { }

APINotesManager::~APINotesManager() {
  // Free the API notes readers.
  for (const auto &entry : Readers) {
    if (auto reader = entry.second.dyn_cast<APINotesReader *>()) {
      delete reader;
    }
  }

  delete CurrentModuleReaders[0];
  delete CurrentModuleReaders[1];
}

/// \brief Write a new timestamp file with the given path.
static void writeTimestampFile(StringRef TimestampFile) {
  std::error_code EC;
  llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None);
}

/// \brief Prune the API notes cache of API notes that haven't been accessed in
/// a long time.
static void pruneAPINotesCache(StringRef APINotesCachePath) {
  struct stat StatBuf;
  llvm::SmallString<128> TimestampFile;
  TimestampFile = APINotesCachePath;
  llvm::sys::path::append(TimestampFile, "APINotes.timestamp");

  // Try to stat() the timestamp file.
  if (::stat(TimestampFile.c_str(), &StatBuf)) {
    // If the timestamp file wasn't there, create one now.
    if (errno == ENOENT) {
      llvm::sys::fs::create_directories(APINotesCachePath);
      writeTimestampFile(TimestampFile);
    }
    return;
  }

  const unsigned APINotesCachePruneInterval = 7 * 24 * 60 * 60;
  const unsigned APINotesCachePruneAfter = 31 * 24 * 60 * 60;

  // Check whether the time stamp is older than our pruning interval.
  // If not, do nothing.
  time_t TimeStampModTime = StatBuf.st_mtime;
  time_t CurrentTime = time(nullptr);
  if (CurrentTime - TimeStampModTime <= time_t(APINotesCachePruneInterval))
    return;

  // Write a new timestamp file so that nobody else attempts to prune.
  // There is a benign race condition here, if two Clang instances happen to
  // notice at the same time that the timestamp is out-of-date.
  writeTimestampFile(TimestampFile);

  // Walk the entire API notes cache, looking for unused compiled API notes.
  std::error_code EC;
  SmallString<128> APINotesCachePathNative;
  llvm::sys::path::native(APINotesCachePath, APINotesCachePathNative);
  for (llvm::sys::fs::directory_iterator
         File(APINotesCachePathNative.str(), EC), DirEnd;
       File != DirEnd && !EC; File.increment(EC)) {
    StringRef Extension = llvm::sys::path::extension(File->path());
    if (Extension.empty())
      continue;

    if (Extension.substr(1) != BINARY_APINOTES_EXTENSION)
      continue;

    // Look at this file. If we can't stat it, there's nothing interesting
    // there.
    if (::stat(File->path().c_str(), &StatBuf))
      continue;

    // If the file has been used recently enough, leave it there.
    time_t FileAccessTime = StatBuf.st_atime;
    if (CurrentTime - FileAccessTime <= time_t(APINotesCachePruneAfter)) {
      continue;
    }

    // Remove the file.
    llvm::sys::fs::remove(File->path());
  }
}

std::unique_ptr<APINotesReader>
APINotesManager::loadAPINotes(const FileEntry *apiNotesFile) {
  FileManager &fileMgr = SourceMgr.getFileManager();
  PrettyStackTraceDoubleString trace("Loading API notes from ",
                                     apiNotesFile->getName());

  // If the API notes file is already in the binary form, load it directly.
  StringRef apiNotesFileName = apiNotesFile->getName();
  StringRef apiNotesFileExt = llvm::sys::path::extension(apiNotesFileName);
  if (!apiNotesFileExt.empty() &&
      apiNotesFileExt.substr(1) == BINARY_APINOTES_EXTENSION) {
    auto compiledFileID = SourceMgr.createFileID(apiNotesFile, SourceLocation(), SrcMgr::C_User);

    // Load the file.
    auto buffer = SourceMgr.getBuffer(compiledFileID, SourceLocation());
    if (!buffer) return nullptr;

    // Load the binary form.
    return APINotesReader::getUnmanaged(buffer, SwiftVersion);
  }

  // If we haven't pruned the API notes cache yet during this execution, do
  // so now.
  if (!PrunedCache) {
    pruneAPINotesCache(fileMgr.getFileSystemOpts().APINotesCachePath);
    PrunedCache = true;
  }

  // Compute a hash of the API notes file's directory and the Clang version,
  // to be used as part of the filename for the cached binary copy.
  auto code = llvm::hash_value(StringRef(apiNotesFile->getDir()->getName()));
  code = hash_combine(code, getClangFullRepositoryVersion());

  // Determine the file name for the cached binary form.
  SmallString<128> compiledFileName;
  compiledFileName += fileMgr.getFileSystemOpts().APINotesCachePath;
  assert(!compiledFileName.empty() && "No API notes cache path provided?");
  llvm::sys::path::append(compiledFileName,
    (llvm::Twine(llvm::sys::path::stem(apiNotesFileName)) + "-"
     + llvm::APInt(64, code).toString(36, /*Signed=*/false) + "."
     + BINARY_APINOTES_EXTENSION));

  // Try to open the cached binary form.
  if (const FileEntry *compiledFile = fileMgr.getFile(compiledFileName,
                                                      /*openFile=*/true,
                                                      /*cacheFailure=*/false)) {
    // Load the file contents.
    if (auto buffer = fileMgr.getBufferForFile(compiledFile)) {
      // Load the file.
      if (auto reader = APINotesReader::get(std::move(buffer.get()),
                                            SwiftVersion)) {
        bool outOfDate = false;
        if (auto sizeAndModTime = reader->getSourceFileSizeAndModTime()) {
          if (sizeAndModTime->first != apiNotesFile->getSize() ||
              sizeAndModTime->second != apiNotesFile->getModificationTime())
            outOfDate = true;
        }

        if (!outOfDate) {
          // Success.
          ++NumBinaryCacheHits;
          return reader;
        }
      }
    }

    // The cache entry was somehow broken; delete this one so we can build a
    // new one below.
    llvm::sys::fs::remove(compiledFileName.str());
    ++NumBinaryCacheRebuilds;
  } else {
    ++NumBinaryCacheMisses;
  }

  // Open the source file.
  auto sourceFileID = SourceMgr.createFileID(apiNotesFile, SourceLocation(), SrcMgr::C_User);
  auto sourceBuffer = SourceMgr.getBuffer(sourceFileID, SourceLocation());
  if (!sourceBuffer) return nullptr;

  // Compile the API notes source into a buffer.
  // FIXME: Either propagate OSType through or, better yet, improve the binary
  // APINotes format to maintain complete availability information.
  llvm::SmallVector<char, 1024> apiNotesBuffer;
  std::unique_ptr<llvm::MemoryBuffer> compiledBuffer;
  {
    SourceMgrAdapter srcMgrAdapter(SourceMgr, SourceMgr.getDiagnostics(),
                                   diag::err_apinotes_message,
                                   diag::warn_apinotes_message,
                                   diag::note_apinotes_message,
                                   apiNotesFile);
    llvm::raw_svector_ostream OS(apiNotesBuffer);
    if (api_notes::compileAPINotes(sourceBuffer->getBuffer(),
                                   SourceMgr.getFileEntryForID(sourceFileID),
                                   OS,
                                   api_notes::OSType::Absent,
                                   srcMgrAdapter.getDiagHandler(),
                                   srcMgrAdapter.getDiagContext()))
      return nullptr;

    // Make a copy of the compiled form into the buffer.
    compiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
               StringRef(apiNotesBuffer.data(), apiNotesBuffer.size()));
  }

  // Save the binary form into the cache. Perform this operation
  // atomically.
  SmallString<64> temporaryBinaryFileName = compiledFileName.str();
  temporaryBinaryFileName.erase(
    temporaryBinaryFileName.end()
      - llvm::sys::path::extension(temporaryBinaryFileName).size(),
    temporaryBinaryFileName.end());
  temporaryBinaryFileName += "-%%%%%%.";
  temporaryBinaryFileName += BINARY_APINOTES_EXTENSION;

  int temporaryFD;
  llvm::sys::fs::create_directories(
    fileMgr.getFileSystemOpts().APINotesCachePath);
  if (!llvm::sys::fs::createUniqueFile(temporaryBinaryFileName.str(),
                                       temporaryFD, temporaryBinaryFileName)) {
    // Write the contents of the buffer.
    bool hadError;
    {
      llvm::raw_fd_ostream out(temporaryFD, /*shouldClose=*/true);
      out.write(compiledBuffer.get()->getBufferStart(),
                compiledBuffer.get()->getBufferSize());
      out.flush();

      hadError = out.has_error();
    }

    if (!hadError) {
      // Rename the temporary file to the actual compiled file.
      llvm::sys::fs::rename(temporaryBinaryFileName.str(),
                            compiledFileName.str());
    }
  }

  // Load the binary form we just compiled.
  auto reader = APINotesReader::get(std::move(compiledBuffer), SwiftVersion);
  assert(reader && "Could not load the API notes we just generated?");
  return reader;
}

bool APINotesManager::loadAPINotes(const DirectoryEntry *HeaderDir,
                                   const FileEntry *APINotesFile) {
  assert(Readers.find(HeaderDir) == Readers.end());
  if (auto reader = loadAPINotes(APINotesFile)) {
    Readers[HeaderDir] = reader.release();
    return false;
  }

  Readers[HeaderDir] = nullptr;
  return true;
}

const FileEntry *APINotesManager::findAPINotesFile(const DirectoryEntry *directory,
                                                   StringRef basename,
                                                   bool wantPublic) {
  FileManager &fileMgr = SourceMgr.getFileManager();

  llvm::SmallString<128> path;
  path += directory->getName();

  unsigned pathLen = path.size();

  StringRef basenameSuffix = "";
  if (!wantPublic) basenameSuffix = "_private";

  // Look for a binary API notes file.
  llvm::sys::path::append(path, 
    llvm::Twine(basename) + basenameSuffix + "." + BINARY_APINOTES_EXTENSION);
  if (const FileEntry *binaryFile = fileMgr.getFile(path))
    return binaryFile;

  // Go back to the original path.
  path.resize(pathLen);

  // Look for the source API notes file.
  llvm::sys::path::append(path, 
    llvm::Twine(basename) + basenameSuffix + "." + SOURCE_APINOTES_EXTENSION);
  return fileMgr.getFile(path);
}

const DirectoryEntry *APINotesManager::loadFrameworkAPINotes(
                        llvm::StringRef FrameworkPath,
                        llvm::StringRef FrameworkName,
                        bool Public) {
  FileManager &FileMgr = SourceMgr.getFileManager();
  
  llvm::SmallString<128> Path;
  Path += FrameworkPath;
  unsigned FrameworkNameLength = Path.size();

  // Form the path to the APINotes file.
  llvm::sys::path::append(Path, "APINotes");
  if (Public)
    llvm::sys::path::append(Path,
                            (llvm::Twine(FrameworkName) + "."
                              + SOURCE_APINOTES_EXTENSION));
  else
    llvm::sys::path::append(Path,
                            (llvm::Twine(FrameworkName) + "_private."
                              + SOURCE_APINOTES_EXTENSION));

  // Try to open the APINotes file.
  const FileEntry *APINotesFile = FileMgr.getFile(Path);
  if (!APINotesFile)
    return nullptr;

  // Form the path to the corresponding header directory.
  Path.resize(FrameworkNameLength);
  if (Public)
    llvm::sys::path::append(Path, "Headers");
  else
    llvm::sys::path::append(Path, "PrivateHeaders");

  // Try to access the header directory.
  const DirectoryEntry *HeaderDir = FileMgr.getDirectory(Path);
  if (!HeaderDir)
    return nullptr;

  // Try to load the API notes.
  if (loadAPINotes(HeaderDir, APINotesFile))
    return nullptr;

  // Success: return the header directory.
  if (Public)
    ++NumPublicFrameworkAPINotes;
  else
    ++NumPrivateFrameworkAPINotes;
  return HeaderDir;
}

bool APINotesManager::loadCurrentModuleAPINotes(
                   const Module *module,
                   bool lookInModule,
                   ArrayRef<std::string> searchPaths) {
  assert(!CurrentModuleReaders[0] &&
         "Already loaded API notes for the current module?");

  FileManager &fileMgr = SourceMgr.getFileManager();
  auto moduleName = module->getTopLevelModuleName();

  // First, look relative to the module itself.
  if (lookInModule) {
    bool foundAny = false;
    unsigned numReaders = 0;

    // Local function to try loading an API notes file in the given directory.
    auto tryAPINotes = [&](const DirectoryEntry *dir, bool wantPublic) {
      if (auto file = findAPINotesFile(dir, moduleName, wantPublic)) {
        foundAny = true;

        // Try to load the API notes file.
        CurrentModuleReaders[numReaders] = loadAPINotes(file).release();
        if (CurrentModuleReaders[numReaders])
          ++numReaders;
      }
    };

    if (module->IsFramework) {
      // For frameworks, we search in the "Headers" or "PrivateHeaders"
      // subdirectory.
      llvm::SmallString<128> path;
      path += module->Directory->getName();
      unsigned pathLen = path.size();

      llvm::sys::path::append(path, "Headers");
      if (auto apinotesDir = fileMgr.getDirectory(path))
        tryAPINotes(apinotesDir, /*wantPublic=*/true);

      path.resize(pathLen);
      llvm::sys::path::append(path, "PrivateHeaders");
      if (auto privateAPINotesDir = fileMgr.getDirectory(path))
        tryAPINotes(privateAPINotesDir, /*wantPublic=*/false);
    } else {
      tryAPINotes(module->Directory, /*wantPublic=*/true);
      tryAPINotes(module->Directory, /*wantPublic=*/false);
    }

    if (foundAny)
      return numReaders > 0;
  }

  // Second, look for API notes for this module in the module API
  // notes search paths.
  for (const auto &searchPath : searchPaths) {
    if (auto searchDir = fileMgr.getDirectory(searchPath)) {
      if (auto file = findAPINotesFile(searchDir, moduleName)) {
        CurrentModuleReaders[0] = loadAPINotes(file).release();
        return !getCurrentModuleReaders().empty();
      }
    }
  }

  // Didn't find any API notes.
  return false;
}

llvm::SmallVector<APINotesReader *, 2> APINotesManager::findAPINotes(SourceLocation Loc) {
  llvm::SmallVector<APINotesReader *, 2> Results;

  // If there are readers for the current module, return them.
  if (!getCurrentModuleReaders().empty()) {
    Results.append(getCurrentModuleReaders().begin(), getCurrentModuleReaders().end());
    return Results;
  }

  // If we're not allowed to implicitly load API notes files, we're done.
  if (!ImplicitAPINotes) return Results;

  // If we don't have source location information, we're done.
  if (Loc.isInvalid()) return Results;

  // API notes are associated with the expansion location. Retrieve the
  // file for this location.
  SourceLocation ExpansionLoc = SourceMgr.getExpansionLoc(Loc);
  FileID ID = SourceMgr.getFileID(ExpansionLoc);
  if (ID.isInvalid()) return Results;
  const FileEntry *File = SourceMgr.getFileEntryForID(ID);
  if (!File) return Results;

  // Look for API notes in the directory corresponding to this file, or one of
  // its its parent directories.
  const DirectoryEntry *Dir = File->getDir();
  FileManager &FileMgr = SourceMgr.getFileManager();
  llvm::SetVector<const DirectoryEntry *,
                  SmallVector<const DirectoryEntry *, 4>,
                  llvm::SmallPtrSet<const DirectoryEntry *, 4>> DirsVisited;
  do {
    // Look for an API notes reader for this header search directory.
    auto Known = Readers.find(Dir);

    // If we already know the answer, chase it.
    if (Known != Readers.end()) {
      ++NumDirectoryCacheHits;

      // We've been redirected to another directory for answers. Follow it.
      if (auto OtherDir = Known->second.dyn_cast<const DirectoryEntry *>()) {
        DirsVisited.insert(Dir);
        Dir = OtherDir;
        continue;
      }

      // We have the answer.
      if (auto Reader = Known->second.dyn_cast<APINotesReader *>())
        Results.push_back(Reader);
      break;
    }

    // Look for API notes corresponding to this directory.
    StringRef Path = Dir->getName();
    if (llvm::sys::path::extension(Path) == ".framework") {
      // If this is a framework directory, check whether there are API notes
      // in the APINotes subdirectory.
      auto FrameworkName = llvm::sys::path::stem(Path);
      ++NumFrameworksSearched;

      // Look for API notes for both the public and private headers.
      const DirectoryEntry *PublicDir
        = loadFrameworkAPINotes(Path, FrameworkName, /*Public=*/true);
      const DirectoryEntry *PrivateDir
        = loadFrameworkAPINotes(Path, FrameworkName, /*Public=*/false);

      if (PublicDir || PrivateDir) {
        // We found API notes: don't ever look past the framework directory.
        Readers[Dir] = nullptr;

        // Pretend we found the result in the public or private directory,
        // as appropriate. All headers should be in one of those two places,
        // but be defensive here.
        if (!DirsVisited.empty()) {
          if (DirsVisited.back() == PublicDir) {
            DirsVisited.pop_back();
            Dir = PublicDir;
          } else if (DirsVisited.back() == PrivateDir) {
            DirsVisited.pop_back();
            Dir = PrivateDir;
          }
        }

        // Grab the result.
        if (auto Reader = Readers[Dir].dyn_cast<APINotesReader *>())
          Results.push_back(Reader);
        break;
      }
    } else {
      // Look for an APINotes file in this directory.
      llvm::SmallString<128> APINotesPath;
      APINotesPath += Dir->getName();
      llvm::sys::path::append(APINotesPath,
                              (llvm::Twine("APINotes.")
                                 + SOURCE_APINOTES_EXTENSION));

      // If there is an API notes file here, try to load it.
      ++NumDirectoriesSearched;
      if (const FileEntry *APINotesFile = FileMgr.getFile(APINotesPath)) {
        if (!loadAPINotes(Dir, APINotesFile)) {
          ++NumHeaderAPINotes;
          if (auto Reader = Readers[Dir].dyn_cast<APINotesReader *>())
            Results.push_back(Reader);
          break;
        }
      }
    }

    // We didn't find anything. Look at the parent directory.
    if (!DirsVisited.insert(Dir)) {
      Dir = 0;
      break;
    }

    StringRef ParentPath = llvm::sys::path::parent_path(Path);
    while (llvm::sys::path::stem(ParentPath) == "..") {
      ParentPath = llvm::sys::path::parent_path(ParentPath);
    }
    if (ParentPath.empty()) {
      Dir = nullptr;
    } else {
      Dir = FileMgr.getDirectory(ParentPath);
    }
  } while (Dir);

  // Path compression for all of the directories we visited, redirecting
  // them to the directory we ended on. If no API notes were found, the
  // resulting directory will be NULL, indicating no API notes.
  for (const auto Visited : DirsVisited) {
    Readers[Visited] = Dir;
  }

  return Results;
}
