//===- InterpolatingCompilationDatabase.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
//
//===----------------------------------------------------------------------===//
//
// InterpolatingCompilationDatabase wraps another CompilationDatabase and
// attempts to heuristically determine appropriate compile commands for files
// that are not included, such as headers or newly created files.
//
// Motivating cases include:
//   Header files that live next to their implementation files. These typically
// share a base filename. (libclang/CXString.h, libclang/CXString.cpp).
//   Some projects separate headers from includes. Filenames still typically
// match, maybe other path segments too. (include/llvm/IR/Use.h, lib/IR/Use.cc).
//   Matches are sometimes only approximate (Sema.h, SemaDecl.cpp). This goes
// for directories too (Support/Unix/Process.inc, lib/Support/Process.cpp).
//   Even if we can't find a "right" compile command, even a random one from
// the project will tend to get important flags like -I and -x right.
//
// We "borrow" the compile command for the closest available file:
//   - points are awarded if the filename matches (ignoring extension)
//   - points are awarded if the directory structure matches
//   - ties are broken by length of path prefix match
//
// The compile command is adjusted, replacing the filename and removing output
// file arguments. The -x and -std flags may be affected too.
//
// Source language is a tricky issue: is it OK to use a .c file's command
// for building a .cc file? What language is a .h file in?
//   - We only consider compile commands for c-family languages as candidates.
//   - For files whose language is implied by the filename (e.g. .m, .hpp)
//     we prefer candidates from the same language.
//     If we must cross languages, we drop any -x and -std flags.
//   - For .h files, candidates from any c-family language are acceptable.
//     We use the candidate's language, inserting  e.g. -x c++-header.
//
// This class is only useful when wrapping databases that can enumerate all
// their compile commands. If getAllFilenames() is empty, no inference occurs.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Options.h"
#include "clang/Driver/Types.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>

namespace clang {
namespace tooling {
namespace {
using namespace llvm;
namespace types = clang::driver::types;
namespace path = llvm::sys::path;

// The length of the prefix these two strings have in common.
size_t matchingPrefix(StringRef L, StringRef R) {
  size_t Limit = std::min(L.size(), R.size());
  for (size_t I = 0; I < Limit; ++I)
    if (L[I] != R[I])
      return I;
  return Limit;
}

// A comparator for searching SubstringWithIndexes with std::equal_range etc.
// Optionaly prefix semantics: compares equal if the key is a prefix.
template <bool Prefix> struct Less {
  bool operator()(StringRef Key, std::pair<StringRef, size_t> Value) const {
    StringRef V = Prefix ? Value.first.substr(0, Key.size()) : Value.first;
    return Key < V;
  }
  bool operator()(std::pair<StringRef, size_t> Value, StringRef Key) const {
    StringRef V = Prefix ? Value.first.substr(0, Key.size()) : Value.first;
    return V < Key;
  }
};

// Infer type from filename. If we might have gotten it wrong, set *Certain.
// *.h will be inferred as a C header, but not certain.
types::ID guessType(StringRef Filename, bool *Certain = nullptr) {
  // path::extension is ".cpp", lookupTypeForExtension wants "cpp".
  auto Lang =
      types::lookupTypeForExtension(path::extension(Filename).substr(1));
  if (Certain)
    *Certain = Lang != types::TY_CHeader && Lang != types::TY_INVALID;
  return Lang;
}

// Return Lang as one of the canonical supported types.
// e.g. c-header --> c; fortran --> TY_INVALID
static types::ID foldType(types::ID Lang) {
  switch (Lang) {
  case types::TY_C:
  case types::TY_CHeader:
    return types::TY_C;
  case types::TY_ObjC:
  case types::TY_ObjCHeader:
    return types::TY_ObjC;
  case types::TY_CXX:
  case types::TY_CXXHeader:
    return types::TY_CXX;
  case types::TY_ObjCXX:
  case types::TY_ObjCXXHeader:
    return types::TY_ObjCXX;
  default:
    return types::TY_INVALID;
  }
}

// A CompileCommand that can be applied to another file.
struct TransferableCommand {
  // Flags that should not apply to all files are stripped from CommandLine.
  CompileCommand Cmd;
  // Language detected from -x or the filename. Never TY_INVALID.
  Optional<types::ID> Type;
  // Standard specified by -std.
  LangStandard::Kind Std = LangStandard::lang_unspecified;
  // Whether the command line is for the cl-compatible driver.
  bool ClangCLMode;

  TransferableCommand(CompileCommand C)
      : Cmd(std::move(C)), Type(guessType(Cmd.Filename)),
        ClangCLMode(checkIsCLMode(Cmd.CommandLine)) {
    std::vector<std::string> OldArgs = std::move(Cmd.CommandLine);
    Cmd.CommandLine.clear();

    // Wrap the old arguments in an InputArgList.
    llvm::opt::InputArgList ArgList;
    {
      SmallVector<const char *, 16> TmpArgv;
      for (const std::string &S : OldArgs)
        TmpArgv.push_back(S.c_str());
      ArgList = {TmpArgv.begin(), TmpArgv.end()};
    }

    // Parse the old args in order to strip out and record unwanted flags.
    // We parse each argument individually so that we can retain the exact
    // spelling of each argument; re-rendering is lossy for aliased flags.
    // E.g. in CL mode, /W4 maps to -Wall.
    auto OptTable = clang::driver::createDriverOptTable();
    Cmd.CommandLine.emplace_back(OldArgs.front());
    for (unsigned Pos = 1; Pos < OldArgs.size();) {
      using namespace driver::options;

      const unsigned OldPos = Pos;
      std::unique_ptr<llvm::opt::Arg> Arg(OptTable->ParseOneArg(
          ArgList, Pos,
          /* Include */ClangCLMode ? CoreOption | CLOption : 0,
          /* Exclude */ClangCLMode ? 0 : CLOption));

      if (!Arg)
        continue;

      const llvm::opt::Option &Opt = Arg->getOption();

      // Strip input and output files.
      if (Opt.matches(OPT_INPUT) || Opt.matches(OPT_o) ||
          (ClangCLMode && (Opt.matches(OPT__SLASH_Fa) ||
                           Opt.matches(OPT__SLASH_Fe) ||
                           Opt.matches(OPT__SLASH_Fi) ||
                           Opt.matches(OPT__SLASH_Fo))))
        continue;

      // Strip -x, but record the overridden language.
      if (const auto GivenType = tryParseTypeArg(*Arg)) {
        Type = *GivenType;
        continue;
      }

      // Strip -std, but record the value.
      if (const auto GivenStd = tryParseStdArg(*Arg)) {
        if (*GivenStd != LangStandard::lang_unspecified)
          Std = *GivenStd;
        continue;
      }

      Cmd.CommandLine.insert(Cmd.CommandLine.end(),
                             OldArgs.data() + OldPos, OldArgs.data() + Pos);
    }

    if (Std != LangStandard::lang_unspecified) // -std take precedence over -x
      Type = toType(LangStandard::getLangStandardForKind(Std).getLanguage());
    Type = foldType(*Type);
    // The contract is to store None instead of TY_INVALID.
    if (Type == types::TY_INVALID)
      Type = llvm::None;
  }

  // Produce a CompileCommand for \p filename, based on this one.
  CompileCommand transferTo(StringRef Filename) const {
    CompileCommand Result = Cmd;
    Result.Filename = Filename;
    bool TypeCertain;
    auto TargetType = guessType(Filename, &TypeCertain);
    // If the filename doesn't determine the language (.h), transfer with -x.
    if (TargetType != types::TY_INVALID && !TypeCertain && Type) {
      TargetType = types::onlyPrecompileType(TargetType) // header?
                       ? types::lookupHeaderTypeForSourceType(*Type)
                       : *Type;
      if (ClangCLMode) {
        const StringRef Flag = toCLFlag(TargetType);
        if (!Flag.empty())
          Result.CommandLine.push_back(Flag);
      } else {
        Result.CommandLine.push_back("-x");
        Result.CommandLine.push_back(types::getTypeName(TargetType));
      }
    }
    // --std flag may only be transferred if the language is the same.
    // We may consider "translating" these, e.g. c++11 -> c11.
    if (Std != LangStandard::lang_unspecified && foldType(TargetType) == Type) {
      Result.CommandLine.emplace_back((
          llvm::Twine(ClangCLMode ? "/std:" : "-std=") +
          LangStandard::getLangStandardForKind(Std).getName()).str());
    }
    Result.CommandLine.push_back(Filename);
    Result.Heuristic = "inferred from " + Cmd.Filename;
    return Result;
  }

private:
  // Determine whether the given command line is intended for the CL driver.
  static bool checkIsCLMode(ArrayRef<std::string> CmdLine) {
    // First look for --driver-mode.
    for (StringRef S : llvm::reverse(CmdLine)) {
      if (S.consume_front("--driver-mode="))
        return S == "cl";
    }

    // Otherwise just check the clang executable file name.
    return llvm::sys::path::stem(CmdLine.front()).endswith_lower("cl");
  }

  // Map the language from the --std flag to that of the -x flag.
  static types::ID toType(InputKind::Language Lang) {
    switch (Lang) {
    case InputKind::C:
      return types::TY_C;
    case InputKind::CXX:
      return types::TY_CXX;
    case InputKind::ObjC:
      return types::TY_ObjC;
    case InputKind::ObjCXX:
      return types::TY_ObjCXX;
    default:
      return types::TY_INVALID;
    }
  }

  // Convert a file type to the matching CL-style type flag.
  static StringRef toCLFlag(types::ID Type) {
    switch (Type) {
    case types::TY_C:
    case types::TY_CHeader:
      return "/TC";
    case types::TY_CXX:
    case types::TY_CXXHeader:
      return "/TP";
    default:
      return StringRef();
    }
  }

  // Try to interpret the argument as a type specifier, e.g. '-x'.
  Optional<types::ID> tryParseTypeArg(const llvm::opt::Arg &Arg) {
    const llvm::opt::Option &Opt = Arg.getOption();
    using namespace driver::options;
    if (ClangCLMode) {
      if (Opt.matches(OPT__SLASH_TC) || Opt.matches(OPT__SLASH_Tc))
        return types::TY_C;
      if (Opt.matches(OPT__SLASH_TP) || Opt.matches(OPT__SLASH_Tp))
        return types::TY_CXX;
    } else {
      if (Opt.matches(driver::options::OPT_x))
        return types::lookupTypeForTypeSpecifier(Arg.getValue());
    }
    return None;
  }

  // Try to interpret the argument as '-std='.
  Optional<LangStandard::Kind> tryParseStdArg(const llvm::opt::Arg &Arg) {
    using namespace driver::options;
    if (Arg.getOption().matches(ClangCLMode ? OPT__SLASH_std : OPT_std_EQ)) {
      return llvm::StringSwitch<LangStandard::Kind>(Arg.getValue())
#define LANGSTANDARD(id, name, lang, ...) .Case(name, LangStandard::lang_##id)
#define LANGSTANDARD_ALIAS(id, alias) .Case(alias, LangStandard::lang_##id)
#include "clang/Frontend/LangStandards.def"
#undef LANGSTANDARD_ALIAS
#undef LANGSTANDARD
                 .Default(LangStandard::lang_unspecified);
    }
    return None;
  }
};

// Given a filename, FileIndex picks the best matching file from the underlying
// DB. This is the proxy file whose CompileCommand will be reused. The
// heuristics incorporate file name, extension, and directory structure.
// Strategy:
// - Build indexes of each of the substrings we want to look up by.
//   These indexes are just sorted lists of the substrings.
// - Each criterion corresponds to a range lookup into the index, so we only
//   need O(log N) string comparisons to determine scores.
//
// Apart from path proximity signals, also takes file extensions into account
// when scoring the candidates.
class FileIndex {
public:
  FileIndex(std::vector<std::string> Files)
      : OriginalPaths(std::move(Files)), Strings(Arena) {
    // Sort commands by filename for determinism (index is a tiebreaker later).
    llvm::sort(OriginalPaths);
    Paths.reserve(OriginalPaths.size());
    Types.reserve(OriginalPaths.size());
    Stems.reserve(OriginalPaths.size());
    for (size_t I = 0; I < OriginalPaths.size(); ++I) {
      StringRef Path = Strings.save(StringRef(OriginalPaths[I]).lower());

      Paths.emplace_back(Path, I);
      Types.push_back(foldType(guessType(Path)));
      Stems.emplace_back(sys::path::stem(Path), I);
      auto Dir = ++sys::path::rbegin(Path), DirEnd = sys::path::rend(Path);
      for (int J = 0; J < DirectorySegmentsIndexed && Dir != DirEnd; ++J, ++Dir)
        if (Dir->size() > ShortDirectorySegment) // not trivial ones
          Components.emplace_back(*Dir, I);
    }
    llvm::sort(Paths);
    llvm::sort(Stems);
    llvm::sort(Components);
  }

  bool empty() const { return Paths.empty(); }

  // Returns the path for the file that best fits OriginalFilename.
  // Candidates with extensions matching PreferLanguage will be chosen over
  // others (unless it's TY_INVALID, or all candidates are bad).
  StringRef chooseProxy(StringRef OriginalFilename,
                        types::ID PreferLanguage) const {
    assert(!empty() && "need at least one candidate!");
    std::string Filename = OriginalFilename.lower();
    auto Candidates = scoreCandidates(Filename);
    std::pair<size_t, int> Best =
        pickWinner(Candidates, Filename, PreferLanguage);

    DEBUG_WITH_TYPE(
        "interpolate",
        llvm::dbgs() << "interpolate: chose " << OriginalPaths[Best.first]
                     << " as proxy for " << OriginalFilename << " preferring "
                     << (PreferLanguage == types::TY_INVALID
                             ? "none"
                             : types::getTypeName(PreferLanguage))
                     << " score=" << Best.second << "\n");
    return OriginalPaths[Best.first];
  }

private:
  using SubstringAndIndex = std::pair<StringRef, size_t>;
  // Directory matching parameters: we look at the last two segments of the
  // parent directory (usually the semantically significant ones in practice).
  // We search only the last four of each candidate (for efficiency).
  constexpr static int DirectorySegmentsIndexed = 4;
  constexpr static int DirectorySegmentsQueried = 2;
  constexpr static int ShortDirectorySegment = 1; // Only look at longer names.

  // Award points to candidate entries that should be considered for the file.
  // Returned keys are indexes into paths, and the values are (nonzero) scores.
  DenseMap<size_t, int> scoreCandidates(StringRef Filename) const {
    // Decompose Filename into the parts we care about.
    // /some/path/complicated/project/Interesting.h
    // [-prefix--][---dir---] [-dir-] [--stem---]
    StringRef Stem = sys::path::stem(Filename);
    llvm::SmallVector<StringRef, DirectorySegmentsQueried> Dirs;
    llvm::StringRef Prefix;
    auto Dir = ++sys::path::rbegin(Filename),
         DirEnd = sys::path::rend(Filename);
    for (int I = 0; I < DirectorySegmentsQueried && Dir != DirEnd; ++I, ++Dir) {
      if (Dir->size() > ShortDirectorySegment)
        Dirs.push_back(*Dir);
      Prefix = Filename.substr(0, Dir - DirEnd);
    }

    // Now award points based on lookups into our various indexes.
    DenseMap<size_t, int> Candidates; // Index -> score.
    auto Award = [&](int Points, ArrayRef<SubstringAndIndex> Range) {
      for (const auto &Entry : Range)
        Candidates[Entry.second] += Points;
    };
    // Award one point if the file's basename is a prefix of the candidate,
    // and another if it's an exact match (so exact matches get two points).
    Award(1, indexLookup</*Prefix=*/true>(Stem, Stems));
    Award(1, indexLookup</*Prefix=*/false>(Stem, Stems));
    // For each of the last few directories in the Filename, award a point
    // if it's present in the candidate.
    for (StringRef Dir : Dirs)
      Award(1, indexLookup</*Prefix=*/false>(Dir, Components));
    // Award one more point if the whole rest of the path matches.
    if (sys::path::root_directory(Prefix) != Prefix)
      Award(1, indexLookup</*Prefix=*/true>(Prefix, Paths));
    return Candidates;
  }

  // Pick a single winner from the set of scored candidates.
  // Returns (index, score).
  std::pair<size_t, int> pickWinner(const DenseMap<size_t, int> &Candidates,
                                    StringRef Filename,
                                    types::ID PreferredLanguage) const {
    struct ScoredCandidate {
      size_t Index;
      bool Preferred;
      int Points;
      size_t PrefixLength;
    };
    // Choose the best candidate by (preferred, points, prefix length, alpha).
    ScoredCandidate Best = {size_t(-1), false, 0, 0};
    for (const auto &Candidate : Candidates) {
      ScoredCandidate S;
      S.Index = Candidate.first;
      S.Preferred = PreferredLanguage == types::TY_INVALID ||
                    PreferredLanguage == Types[S.Index];
      S.Points = Candidate.second;
      if (!S.Preferred && Best.Preferred)
        continue;
      if (S.Preferred == Best.Preferred) {
        if (S.Points < Best.Points)
          continue;
        if (S.Points == Best.Points) {
          S.PrefixLength = matchingPrefix(Filename, Paths[S.Index].first);
          if (S.PrefixLength < Best.PrefixLength)
            continue;
          // hidden heuristics should at least be deterministic!
          if (S.PrefixLength == Best.PrefixLength)
            if (S.Index > Best.Index)
              continue;
        }
      }
      // PrefixLength was only set above if actually needed for a tiebreak.
      // But it definitely needs to be set to break ties in the future.
      S.PrefixLength = matchingPrefix(Filename, Paths[S.Index].first);
      Best = S;
    }
    // Edge case: no candidate got any points.
    // We ignore PreferredLanguage at this point (not ideal).
    if (Best.Index == size_t(-1))
      return {longestMatch(Filename, Paths).second, 0};
    return {Best.Index, Best.Points};
  }

  // Returns the range within a sorted index that compares equal to Key.
  // If Prefix is true, it's instead the range starting with Key.
  template <bool Prefix>
  ArrayRef<SubstringAndIndex>
  indexLookup(StringRef Key, ArrayRef<SubstringAndIndex> Idx) const {
    // Use pointers as iteratiors to ease conversion of result to ArrayRef.
    auto Range = std::equal_range(Idx.data(), Idx.data() + Idx.size(), Key,
                                  Less<Prefix>());
    return {Range.first, Range.second};
  }

  // Performs a point lookup into a nonempty index, returning a longest match.
  SubstringAndIndex longestMatch(StringRef Key,
                                 ArrayRef<SubstringAndIndex> Idx) const {
    assert(!Idx.empty());
    // Longest substring match will be adjacent to a direct lookup.
    auto It =
        std::lower_bound(Idx.begin(), Idx.end(), SubstringAndIndex{Key, 0});
    if (It == Idx.begin())
      return *It;
    if (It == Idx.end())
      return *--It;
    // Have to choose between It and It-1
    size_t Prefix = matchingPrefix(Key, It->first);
    size_t PrevPrefix = matchingPrefix(Key, (It - 1)->first);
    return Prefix > PrevPrefix ? *It : *--It;
  }

  // Original paths, everything else is in lowercase.
  std::vector<std::string> OriginalPaths;
  BumpPtrAllocator Arena;
  StringSaver Strings;
  // Indexes of candidates by certain substrings.
  // String is lowercase and sorted, index points into OriginalPaths.
  std::vector<SubstringAndIndex> Paths;      // Full path.
  // Lang types obtained by guessing on the corresponding path. I-th element is
  // a type for the I-th path.
  std::vector<types::ID> Types;
  std::vector<SubstringAndIndex> Stems;      // Basename, without extension.
  std::vector<SubstringAndIndex> Components; // Last path components.
};

// The actual CompilationDatabase wrapper delegates to its inner database.
// If no match, looks up a proxy file in FileIndex and transfers its
// command to the requested file.
class InterpolatingCompilationDatabase : public CompilationDatabase {
public:
  InterpolatingCompilationDatabase(std::unique_ptr<CompilationDatabase> Inner)
      : Inner(std::move(Inner)), Index(this->Inner->getAllFiles()) {}

  std::vector<CompileCommand>
  getCompileCommands(StringRef Filename) const override {
    auto Known = Inner->getCompileCommands(Filename);
    if (Index.empty() || !Known.empty())
      return Known;
    bool TypeCertain;
    auto Lang = guessType(Filename, &TypeCertain);
    if (!TypeCertain)
      Lang = types::TY_INVALID;
    auto ProxyCommands =
        Inner->getCompileCommands(Index.chooseProxy(Filename, foldType(Lang)));
    if (ProxyCommands.empty())
      return {};
    return {TransferableCommand(ProxyCommands[0]).transferTo(Filename)};
  }

  std::vector<std::string> getAllFiles() const override {
    return Inner->getAllFiles();
  }

  std::vector<CompileCommand> getAllCompileCommands() const override {
    return Inner->getAllCompileCommands();
  }

private:
  std::unique_ptr<CompilationDatabase> Inner;
  FileIndex Index;
};

} // namespace

std::unique_ptr<CompilationDatabase>
inferMissingCompileCommands(std::unique_ptr<CompilationDatabase> Inner) {
  return llvm::make_unique<InterpolatingCompilationDatabase>(std::move(Inner));
}

} // namespace tooling
} // namespace clang
