//===--- HeaderSourceSwitch.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 "HeaderSourceSwitch.h"
#include "AST.h"
#include "SourceCode.h"
#include "index/SymbolCollector.h"
#include "support/Logger.h"
#include "support/Path.h"
#include "clang/AST/Decl.h"
#include <optional>

namespace clang {
namespace clangd {

std::optional<Path> getCorrespondingHeaderOrSource(
    PathRef OriginalFile, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
  llvm::StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
                                        ".c++", ".m", ".mm"};
  llvm::StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};

  llvm::StringRef PathExt = llvm::sys::path::extension(OriginalFile);

  // Lookup in a list of known extensions.
  bool IsSource = llvm::any_of(SourceExtensions, [&PathExt](PathRef SourceExt) {
    return SourceExt.equals_insensitive(PathExt);
  });

  bool IsHeader = llvm::any_of(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
    return HeaderExt.equals_insensitive(PathExt);
  });

  // We can only switch between the known extensions.
  if (!IsSource && !IsHeader)
    return std::nullopt;

  // Array to lookup extensions for the switch. An opposite of where original
  // extension was found.
  llvm::ArrayRef<llvm::StringRef> NewExts;
  if (IsSource)
    NewExts = HeaderExtensions;
  else
    NewExts = SourceExtensions;

  // Storage for the new path.
  llvm::SmallString<128> NewPath = OriginalFile;

  // Loop through switched extension candidates.
  for (llvm::StringRef NewExt : NewExts) {
    llvm::sys::path::replace_extension(NewPath, NewExt);
    if (VFS->exists(NewPath))
      return Path(NewPath);

    // Also check NewExt in upper-case, just in case.
    llvm::sys::path::replace_extension(NewPath, NewExt.upper());
    if (VFS->exists(NewPath))
      return Path(NewPath);
  }
  return std::nullopt;
}

std::optional<Path> getCorrespondingHeaderOrSource(PathRef OriginalFile,
                                                   ParsedAST &AST,
                                                   const SymbolIndex *Index) {
  if (!Index) {
    // FIXME: use the AST to do the inference.
    return std::nullopt;
  }
  LookupRequest Request;
  // Find all symbols present in the original file.
  for (const auto *D : getIndexableLocalDecls(AST)) {
    if (auto ID = getSymbolID(D))
      Request.IDs.insert(ID);
  }
  llvm::StringMap<int> Candidates; // Target path => score.
  auto AwardTarget = [&](const char *TargetURI) {
    if (auto TargetPath = URI::resolve(TargetURI, OriginalFile)) {
      if (!pathEqual(*TargetPath, OriginalFile)) // exclude the original file.
        ++Candidates[*TargetPath];
    } else {
      elog("Failed to resolve URI {0}: {1}", TargetURI, TargetPath.takeError());
    }
  };
  // If we switch from a header, we are looking for the implementation
  // file, so we use the definition loc; otherwise we look for the header file,
  // we use the decl loc;
  //
  // For each symbol in the original file, we get its target location (decl or
  // def) from the index, then award that target file.
  bool IsHeader = isHeaderFile(OriginalFile, AST.getLangOpts());
  Index->lookup(Request, [&](const Symbol &Sym) {
    if (IsHeader)
      AwardTarget(Sym.Definition.FileURI);
    else
      AwardTarget(Sym.CanonicalDeclaration.FileURI);
  });
  // FIXME: our index doesn't have any interesting information (this could be
  // that the background-index is not finished), we should use the decl/def
  // locations from the AST to do the inference (from .cc to .h).
  if (Candidates.empty())
    return std::nullopt;

  // Pickup the winner, who contains most of symbols.
  // FIXME: should we use other signals (file proximity) to help score?
  auto Best = Candidates.begin();
  for (auto It = Candidates.begin(); It != Candidates.end(); ++It) {
    if (It->second > Best->second)
      Best = It;
    else if (It->second == Best->second && It->first() < Best->first())
      // Select the first one in the lexical order if we have multiple
      // candidates.
      Best = It;
  }
  return Path(Best->first());
}

std::vector<const Decl *> getIndexableLocalDecls(ParsedAST &AST) {
  std::vector<const Decl *> Results;
  std::function<void(Decl *)> TraverseDecl = [&](Decl *D) {
    auto *ND = llvm::dyn_cast<NamedDecl>(D);
    if (!ND || ND->isImplicit())
      return;
    if (!SymbolCollector::shouldCollectSymbol(*ND, D->getASTContext(), {},
                                              /*IsMainFileSymbol=*/false))
      return;
    if (!llvm::isa<FunctionDecl>(ND)) {
      // Visit the children, but we skip function decls as we are not interested
      // in the function body.
      if (auto *Scope = llvm::dyn_cast<DeclContext>(ND)) {
        for (auto *D : Scope->decls())
          TraverseDecl(D);
      }
    }
    if (llvm::isa<NamespaceDecl>(D))
      return; // namespace is indexable, but we're not interested.
    Results.push_back(D);
  };
  // Traverses the ParsedAST directly to collect all decls present in the main
  // file.
  for (auto *TopLevel : AST.getLocalTopLevelDecls())
    TraverseDecl(TopLevel);
  return Results;
}

} // namespace clangd
} // namespace clang
