//===-- FindAllSymbols.cpp - find all symbols--------------------*- 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 "FindAllSymbols.h"
#include "HeaderMapCollector.h"
#include "PathConfig.h"
#include "SymbolInfo.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/FileSystem.h"

using namespace clang::ast_matchers;

namespace clang {
namespace find_all_symbols {
namespace {

AST_MATCHER(EnumConstantDecl, isInScopedEnum) {
  if (const auto *ED = dyn_cast<EnumDecl>(Node.getDeclContext()))
    return ED->isScoped();
  return false;
}

AST_POLYMORPHIC_MATCHER(isFullySpecialized,
                        AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
                                                        CXXRecordDecl)) {
  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
    bool IsPartialSpecialization =
        llvm::isa<VarTemplatePartialSpecializationDecl>(Node) ||
        llvm::isa<ClassTemplatePartialSpecializationDecl>(Node);
    return !IsPartialSpecialization;
  }
  return false;
}

std::vector<SymbolInfo::Context> GetContexts(const NamedDecl *ND) {
  std::vector<SymbolInfo::Context> Contexts;
  for (const auto *Context = ND->getDeclContext(); Context;
       Context = Context->getParent()) {
    if (llvm::isa<TranslationUnitDecl>(Context) ||
        llvm::isa<LinkageSpecDecl>(Context))
      break;

    assert(llvm::isa<NamedDecl>(Context) &&
           "Expect Context to be a NamedDecl");
    if (const auto *NSD = dyn_cast<NamespaceDecl>(Context)) {
      if (!NSD->isInlineNamespace())
        Contexts.emplace_back(SymbolInfo::ContextType::Namespace,
                              NSD->getName().str());
    } else if (const auto *ED = dyn_cast<EnumDecl>(Context)) {
      Contexts.emplace_back(SymbolInfo::ContextType::EnumDecl,
                            ED->getName().str());
    } else {
      const auto *RD = cast<RecordDecl>(Context);
      Contexts.emplace_back(SymbolInfo::ContextType::Record,
                            RD->getName().str());
    }
  }
  return Contexts;
}

llvm::Optional<SymbolInfo>
CreateSymbolInfo(const NamedDecl *ND, const SourceManager &SM,
                 const HeaderMapCollector *Collector) {
  SymbolInfo::SymbolKind Type;
  if (llvm::isa<VarDecl>(ND)) {
    Type = SymbolInfo::SymbolKind::Variable;
  } else if (llvm::isa<FunctionDecl>(ND)) {
    Type = SymbolInfo::SymbolKind::Function;
  } else if (llvm::isa<TypedefNameDecl>(ND)) {
    Type = SymbolInfo::SymbolKind::TypedefName;
  } else if (llvm::isa<EnumConstantDecl>(ND)) {
    Type = SymbolInfo::SymbolKind::EnumConstantDecl;
  } else if (llvm::isa<EnumDecl>(ND)) {
    Type = SymbolInfo::SymbolKind::EnumDecl;
    // Ignore anonymous enum declarations.
    if (ND->getName().empty())
      return llvm::None;
  } else {
    assert(llvm::isa<RecordDecl>(ND) &&
           "Matched decl must be one of VarDecl, "
           "FunctionDecl, TypedefNameDecl, EnumConstantDecl, "
           "EnumDecl and RecordDecl!");
    // C-style record decl can have empty name, e.g "struct { ... } var;".
    if (ND->getName().empty())
      return llvm::None;
    Type = SymbolInfo::SymbolKind::Class;
  }

  SourceLocation Loc = SM.getExpansionLoc(ND->getLocation());
  if (!Loc.isValid()) {
    llvm::errs() << "Declaration " << ND->getNameAsString() << "("
                 << ND->getDeclKindName()
                 << ") has invalid declaration location.";
    return llvm::None;
  }

  std::string FilePath = getIncludePath(SM, Loc, Collector);
  if (FilePath.empty()) return llvm::None;

  return SymbolInfo(ND->getNameAsString(), Type, FilePath, GetContexts(ND));
}

} // namespace

void FindAllSymbols::registerMatchers(MatchFinder *MatchFinder) {
  // FIXME: Handle specialization.
  auto IsInSpecialization = hasAncestor(
      decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
                 functionDecl(isExplicitTemplateSpecialization()))));

  // Matchers for both C and C++.
  // We only match symbols from header files, i.e. not from main files (see
  // function's comment for detailed explanation).
  auto CommonFilter =
      allOf(unless(isImplicit()), unless(isExpansionInMainFile()));

  auto HasNSOrTUCtxMatcher =
      hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));

  // We need seperate rules for C record types and C++ record types since some
  // template related matchers are inapplicable on C record declarations.
  //
  // Matchers specific to C++ code.
  // All declarations should be in namespace or translation unit.
  auto CCMatcher =
      allOf(HasNSOrTUCtxMatcher, unless(IsInSpecialization),
            unless(ast_matchers::isTemplateInstantiation()),
            unless(isInstantiated()), unless(isFullySpecialized()));

  // Matchers specific to code in extern "C" {...}.
  auto ExternCMatcher = hasDeclContext(linkageSpecDecl());

  // Matchers for variable declarations.
  //
  // In most cases, `ParmVarDecl` is filtered out by hasDeclContext(...)
  // matcher since the declaration context is usually `MethodDecl`. However,
  // this assumption does not hold for parameters of a function pointer
  // parameter.
  // For example, consider a function declaration:
  //        void Func(void (*)(float), int);
  // The float parameter of the function pointer has an empty name, and its
  // declaration context is an anonymous namespace; therefore, it won't be
  // filtered out by our matchers above.
  auto Vars = varDecl(CommonFilter, anyOf(ExternCMatcher, CCMatcher),
                      unless(parmVarDecl()));

  // Matchers for C-style record declarations in extern "C" {...}.
  auto CRecords = recordDecl(CommonFilter, ExternCMatcher, isDefinition());
  // Matchers for C++ record declarations.
  auto CXXRecords = cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());

  // Matchers for function declarations.
  // We want to exclude friend declaration, but the `DeclContext` of a friend
  // function declaration is not the class in which it is declared, so we need
  // to explicitly check if the parent is a `friendDecl`.
  auto Functions = functionDecl(CommonFilter, unless(hasParent(friendDecl())),
                                anyOf(ExternCMatcher, CCMatcher));

  // Matcher for typedef and type alias declarations.
  //
  // typedef and type alias can come from C-style headers and C++ headers.
  // For C-style headers, `DeclContxet` can be either `TranslationUnitDecl`
  // or `LinkageSpecDecl`.
  // For C++ headers, `DeclContext ` can be either `TranslationUnitDecl`
  // or `NamespaceDecl`.
  // With the following context matcher, we can match `typedefNameDecl` from
  // both C-style headers and C++ headers (except for those in classes).
  // "cc_matchers" are not included since template-related matchers are not
  // applicable on `TypedefNameDecl`.
  auto Typedefs =
      typedefNameDecl(CommonFilter, anyOf(HasNSOrTUCtxMatcher,
                                          hasDeclContext(linkageSpecDecl())));

  // Matchers for enum declarations.
  auto Enums = enumDecl(CommonFilter, isDefinition(),
                        anyOf(HasNSOrTUCtxMatcher, ExternCMatcher));

  // Matchers for enum constant declarations.
  // We only match the enum constants in non-scoped enum declarations which are
  // inside toplevel translation unit or a namespace.
  auto EnumConstants = enumConstantDecl(
      CommonFilter, unless(isInScopedEnum()),
      anyOf(hasDeclContext(enumDecl(HasNSOrTUCtxMatcher)), ExternCMatcher));

  // Most of the time we care about all matchable decls, or all types.
  auto Types = namedDecl(anyOf(CRecords, CXXRecords, Enums));
  auto Decls = namedDecl(anyOf(CRecords, CXXRecords, Enums, Typedefs, Vars,
                               EnumConstants, Functions));

  // We want eligible decls bound to "decl"...
  MatchFinder->addMatcher(Decls.bind("decl"), this);

  // ... and all uses of them bound to "use". These have many cases:
  // Uses of values/functions: these generate a declRefExpr.
  MatchFinder->addMatcher(
      declRefExpr(isExpansionInMainFile(), to(Decls.bind("use"))), this);
  // Uses of function templates:
  MatchFinder->addMatcher(
      declRefExpr(isExpansionInMainFile(),
                  to(functionDecl(hasParent(
                      functionTemplateDecl(has(Functions.bind("use"))))))),
      this);

  // Uses of most types: just look at what the typeLoc refers to.
  MatchFinder->addMatcher(
      typeLoc(isExpansionInMainFile(),
              loc(qualType(hasDeclaration(Types.bind("use"))))),
      this);
  // Uses of typedefs: these are often transparent to hasDeclaration, so we need
  // to handle them explicitly.
  MatchFinder->addMatcher(
      typeLoc(isExpansionInMainFile(),
              loc(typedefType(hasDeclaration(Typedefs.bind("use"))))),
      this);
  // Uses of class templates:
  // The typeLoc names the templateSpecializationType. Its declaration is the
  // ClassTemplateDecl, which contains the CXXRecordDecl we want.
  MatchFinder->addMatcher(
      typeLoc(isExpansionInMainFile(),
              loc(templateSpecializationType(hasDeclaration(
                  classTemplateSpecializationDecl(hasSpecializedTemplate(
                      classTemplateDecl(has(CXXRecords.bind("use"))))))))),
      this);
}

void FindAllSymbols::run(const MatchFinder::MatchResult &Result) {
  // Ignore Results in failing TUs.
  if (Result.Context->getDiagnostics().hasErrorOccurred()) {
    return;
  }

  SymbolInfo::Signals Signals;
  const NamedDecl *ND;
  if ((ND = Result.Nodes.getNodeAs<NamedDecl>("use")))
    Signals.Used = 1;
  else if ((ND = Result.Nodes.getNodeAs<NamedDecl>("decl")))
    Signals.Seen = 1;
  else
    assert(false && "Must match a NamedDecl!");

  const SourceManager *SM = Result.SourceManager;
  if (auto Symbol = CreateSymbolInfo(ND, *SM, Collector)) {
    Filename = SM->getFileEntryForID(SM->getMainFileID())->getName();
    FileSymbols[*Symbol] += Signals;
  }
}

void FindAllSymbols::onEndOfTranslationUnit() {
  if (Filename != "") {
    Reporter->reportSymbols(Filename, FileSymbols);
    FileSymbols.clear();
    Filename = "";
  }
}

} // namespace find_all_symbols
} // namespace clang
