//===--- 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
