//===--- 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 "clang/AST/Decl.h"

namespace clang {
namespace clangd {

llvm::Optional<Path> getCorrespondingHeaderOrSource(
    const Path &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.
  auto SourceIter =
      llvm::find_if(SourceExtensions, [&PathExt](PathRef SourceExt) {
        return SourceExt.equals_lower(PathExt);
      });
  bool IsSource = SourceIter != std::end(SourceExtensions);

  auto HeaderIter =
      llvm::find_if(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
        return HeaderExt.equals_lower(PathExt);
      });
  bool IsHeader = HeaderIter != std::end(HeaderExtensions);

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

  // 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 = llvm::StringRef(OriginalFile);

  // Loop through switched extension candidates.
  for (llvm::StringRef NewExt : NewExts) {
    llvm::sys::path::replace_extension(NewPath, NewExt);
    if (VFS->exists(NewPath))
      return NewPath.str().str(); // First str() to convert from SmallString to
                                  // StringRef, second to convert from StringRef
                                  // to std::string

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

llvm::Optional<Path> getCorrespondingHeaderOrSource(const Path &OriginalFile,
                                                    ParsedAST &AST,
                                                    const SymbolIndex *Index) {
  if (!Index) {
    // FIXME: use the AST to do the inference.
    return None;
  }
  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 (*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 None;

  // 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(std::string(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
