//===- IndexingContext.cpp - Indexing context data ------------------------===//
//
// 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 "IndexingContext.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Index/IndexDataConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"

using namespace clang;
using namespace index;

static bool isGeneratedDecl(const Decl *D) {
  if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
    return attr->getGeneratedDeclaration();
  }
  return false;
}

bool IndexingContext::shouldIndex(const Decl *D) {
  return !isGeneratedDecl(D);
}

const LangOptions &IndexingContext::getLangOpts() const {
  return Ctx->getLangOpts();
}

bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
  return IndexOpts.IndexFunctionLocals;
}

bool IndexingContext::shouldIndexImplicitInstantiation() const {
  return IndexOpts.IndexImplicitInstantiation;
}

bool IndexingContext::shouldIndexParametersInDeclarations() const {
  return IndexOpts.IndexParametersInDeclarations;
}

bool IndexingContext::shouldIndexTemplateParameters() const {
  return IndexOpts.IndexTemplateParameters;
}

bool IndexingContext::handleDecl(const Decl *D,
                                 SymbolRoleSet Roles,
                                 ArrayRef<SymbolRelation> Relations) {
  return handleDecl(D, D->getLocation(), Roles, Relations);
}

bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
                                 SymbolRoleSet Roles,
                                 ArrayRef<SymbolRelation> Relations,
                                 const DeclContext *DC) {
  if (!DC)
    DC = D->getDeclContext();

  const Decl *OrigD = D;
  if (isa<ObjCPropertyImplDecl>(D)) {
    D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
  }
  return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
                              Roles, Relations,
                              nullptr, OrigD, DC);
}

bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
                                      const NamedDecl *Parent,
                                      const DeclContext *DC,
                                      SymbolRoleSet Roles,
                                      ArrayRef<SymbolRelation> Relations,
                                      const Expr *RefE,
                                      const Decl *RefD) {
  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
    return true;

  if (!shouldIndexTemplateParameters() &&
      (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
       isa<TemplateTemplateParmDecl>(D))) {
    return true;
  }

  return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
                              RefE, RefD, DC);
}

static void reportModuleReferences(const Module *Mod,
                                   ArrayRef<SourceLocation> IdLocs,
                                   const ImportDecl *ImportD,
                                   IndexDataConsumer &DataConsumer) {
  if (!Mod)
    return;
  reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
                         DataConsumer);
  DataConsumer.handleModuleOccurence(ImportD, Mod,
                                     (SymbolRoleSet)SymbolRole::Reference,
                                     IdLocs.back());
}

bool IndexingContext::importedModule(const ImportDecl *ImportD) {
  if (ImportD->isInvalidDecl())
    return true;

  SourceLocation Loc;
  auto IdLocs = ImportD->getIdentifierLocs();
  if (!IdLocs.empty())
    Loc = IdLocs.back();
  else
    Loc = ImportD->getLocation();

  SourceManager &SM = Ctx->getSourceManager();
  FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  if (FID.isInvalid())
    return true;

  bool Invalid = false;
  const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  if (Invalid || !SEntry.isFile())
    return true;

  if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
    switch (IndexOpts.SystemSymbolFilter) {
    case IndexingOptions::SystemSymbolFilterKind::None:
      return true;
    case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
    case IndexingOptions::SystemSymbolFilterKind::All:
      break;
    }
  }

  const Module *Mod = ImportD->getImportedModule();
  if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
    reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
                           DataConsumer);
  }

  SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
  if (ImportD->isImplicit())
    Roles |= (unsigned)SymbolRole::Implicit;

  return DataConsumer.handleModuleOccurence(ImportD, Mod, Roles, Loc);
}

bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
  TemplateSpecializationKind TKind = TSK_Undeclared;
  if (const ClassTemplateSpecializationDecl *
      SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
    TKind = SD->getSpecializationKind();
  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    TKind = FD->getTemplateSpecializationKind();
  } else if (auto *VD = dyn_cast<VarDecl>(D)) {
    TKind = VD->getTemplateSpecializationKind();
  } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
    if (RD->getInstantiatedFromMemberClass())
      TKind = RD->getTemplateSpecializationKind();
  } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
    if (ED->getInstantiatedFromMemberEnum())
      TKind = ED->getTemplateSpecializationKind();
  } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
             isa<EnumConstantDecl>(D)) {
    if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
      return isTemplateImplicitInstantiation(Parent);
  }
  switch (TKind) {
    case TSK_Undeclared:
    case TSK_ExplicitSpecialization:
      return false;
    case TSK_ImplicitInstantiation:
    case TSK_ExplicitInstantiationDeclaration:
    case TSK_ExplicitInstantiationDefinition:
      return true;
  }
  llvm_unreachable("invalid TemplateSpecializationKind");
}

bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
  if (isa<ObjCInterfaceDecl>(D))
    return false;
  if (isa<ObjCCategoryDecl>(D))
    return false;
  if (isa<ObjCIvarDecl>(D))
    return false;
  if (isa<ObjCMethodDecl>(D))
    return false;
  if (isa<ImportDecl>(D))
    return false;
  return true;
}

static const CXXRecordDecl *
getDeclContextForTemplateInstationPattern(const Decl *D) {
  if (const auto *CTSD =
          dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
    return CTSD->getTemplateInstantiationPattern();
  else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
    return RD->getInstantiatedFromMemberClass();
  return nullptr;
}

static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
  if (const ClassTemplateSpecializationDecl *
      SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
    return SD->getTemplateInstantiationPattern();
  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    return FD->getTemplateInstantiationPattern();
  } else if (auto *VD = dyn_cast<VarDecl>(D)) {
    return VD->getTemplateInstantiationPattern();
  } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
    return RD->getInstantiatedFromMemberClass();
  } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
    return ED->getInstantiatedFromMemberEnum();
  } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
    const auto *ND = cast<NamedDecl>(D);
    if (const CXXRecordDecl *Pattern =
            getDeclContextForTemplateInstationPattern(ND)) {
      for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
        if (BaseND->isImplicit())
          continue;
        if (BaseND->getKind() == ND->getKind())
          return BaseND;
      }
    }
  } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
    if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
      if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
        for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
          return BaseECD;
      }
    }
  }
  return nullptr;
}

static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
  if (auto VD = dyn_cast<VarDecl>(D))
    return VD->isThisDeclarationADefinition(Ctx);

  if (auto FD = dyn_cast<FunctionDecl>(D))
    return FD->isThisDeclarationADefinition();

  if (auto TD = dyn_cast<TagDecl>(D))
    return TD->isThisDeclarationADefinition();

  if (auto MD = dyn_cast<ObjCMethodDecl>(D))
    return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);

  if (isa<TypedefNameDecl>(D) ||
      isa<EnumConstantDecl>(D) ||
      isa<FieldDecl>(D) ||
      isa<MSPropertyDecl>(D) ||
      isa<ObjCImplDecl>(D) ||
      isa<ObjCPropertyImplDecl>(D))
    return true;

  return false;
}

/// Whether the given NamedDecl should be skipped because it has no name.
static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
  return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
          !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
}

static const Decl *adjustParent(const Decl *Parent) {
  if (!Parent)
    return nullptr;
  for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
    if (isa<TranslationUnitDecl>(Parent))
      return nullptr;
    if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
      continue;
    if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
      if (NS->isAnonymousNamespace())
        continue;
    } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
      if (RD->isAnonymousStructOrUnion())
        continue;
    } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
      if (shouldSkipNamelessDecl(ND))
        continue;
    }
    return Parent;
  }
}

static const Decl *getCanonicalDecl(const Decl *D) {
  D = D->getCanonicalDecl();
  if (auto TD = dyn_cast<TemplateDecl>(D)) {
    if (auto TTD = TD->getTemplatedDecl()) {
      D = TTD;
      assert(D->isCanonicalDecl());
    }
  }

  return D;
}

static bool shouldReportOccurrenceForSystemDeclOnlyMode(
    bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
  if (!IsRef)
    return true;

  auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
    bool accept = false;
    applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
      switch (r) {
      case SymbolRole::RelationChildOf:
      case SymbolRole::RelationBaseOf:
      case SymbolRole::RelationOverrideOf:
      case SymbolRole::RelationExtendedBy:
      case SymbolRole::RelationAccessorOf:
      case SymbolRole::RelationIBTypeOf:
        accept = true;
        return false;
      case SymbolRole::Declaration:
      case SymbolRole::Definition:
      case SymbolRole::Reference:
      case SymbolRole::Read:
      case SymbolRole::Write:
      case SymbolRole::Call:
      case SymbolRole::Dynamic:
      case SymbolRole::AddressOf:
      case SymbolRole::Implicit:
      case SymbolRole::Undefinition:
      case SymbolRole::RelationReceivedBy:
      case SymbolRole::RelationCalledBy:
      case SymbolRole::RelationContainedBy:
      case SymbolRole::RelationSpecializationOf:
      case SymbolRole::NameReference:
        return true;
      }
      llvm_unreachable("Unsupported SymbolRole value!");
    });
    return accept;
  };

  for (auto &Rel : Relations) {
    if (acceptForRelation(Rel.Roles))
      return true;
  }

  return false;
}

bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
                                           bool IsRef, const Decl *Parent,
                                           SymbolRoleSet Roles,
                                           ArrayRef<SymbolRelation> Relations,
                                           const Expr *OrigE,
                                           const Decl *OrigD,
                                           const DeclContext *ContainerDC) {
  if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
    return true;
  if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
    return true;

  SourceManager &SM = Ctx->getSourceManager();
  FileID FID = SM.getFileID(SM.getFileLoc(Loc));
  if (FID.isInvalid())
    return true;

  bool Invalid = false;
  const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
  if (Invalid || !SEntry.isFile())
    return true;

  if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
    switch (IndexOpts.SystemSymbolFilter) {
    case IndexingOptions::SystemSymbolFilterKind::None:
      return true;
    case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
      if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
        return true;
      break;
    case IndexingOptions::SystemSymbolFilterKind::All:
      break;
    }
  }

  if (!OrigD)
    OrigD = D;

  if (isTemplateImplicitInstantiation(D)) {
    if (!IsRef)
      return true;
    D = adjustTemplateImplicitInstantiation(D);
    if (!D)
      return true;
    assert(!isTemplateImplicitInstantiation(D));
  }

  if (IsRef)
    Roles |= (unsigned)SymbolRole::Reference;
  else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
    Roles |= (unsigned)SymbolRole::Definition;
  else
    Roles |= (unsigned)SymbolRole::Declaration;

  D = getCanonicalDecl(D);
  Parent = adjustParent(Parent);
  if (Parent)
    Parent = getCanonicalDecl(Parent);

  SmallVector<SymbolRelation, 6> FinalRelations;
  FinalRelations.reserve(Relations.size()+1);

  auto addRelation = [&](SymbolRelation Rel) {
    auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
      return Elem.RelatedSymbol == Rel.RelatedSymbol;
    });
    if (It != FinalRelations.end()) {
      It->Roles |= Rel.Roles;
    } else {
      FinalRelations.push_back(Rel);
    }
    Roles |= Rel.Roles;
  };

  if (Parent) {
    if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
      addRelation(SymbolRelation{
        (unsigned)SymbolRole::RelationContainedBy,
        Parent
      });
    } else {
      addRelation(SymbolRelation{
        (unsigned)SymbolRole::RelationChildOf,
        Parent
      });
    }
  }

  for (auto &Rel : Relations) {
    addRelation(SymbolRelation(Rel.Roles,
                               Rel.RelatedSymbol->getCanonicalDecl()));
  }

  IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
  return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node);
}

void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
                                         SourceLocation Loc,
                                         const MacroInfo &MI) {
  SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
  DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
}

void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
                                           SourceLocation Loc,
                                           const MacroInfo &MI) {
  SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
  DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
}

void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
                                           SourceLocation Loc,
                                           const MacroInfo &MI) {
  SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
  DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
}
