//===--- Index.cpp --------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Index/Index.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/Comment.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeRepr.h"
#include "swift/AST/Types.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/StringExtras.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Markup/Markup.h"
#include "swift/Sema/IDETypeChecking.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include <tuple>

using namespace swift;
using namespace swift::index;

static bool
printArtificialName(const swift::AbstractStorageDecl *ASD, AccessorKind AK, llvm::raw_ostream &OS) {
  switch (AK) {
  case AccessorKind::Get:
    OS << "getter:" << ASD->getFullName();
    return false;
  case AccessorKind::Set:
    OS << "setter:" << ASD->getFullName();
    return false;
  case AccessorKind::DidSet:
    OS << "didSet:" << ASD->getFullName();
    return false;
  case AccessorKind::WillSet:
    OS << "willSet:" << ASD->getFullName() ;
    return false;

  case AccessorKind::Address:
  case AccessorKind::MutableAddress:
  case AccessorKind::Read:
  case AccessorKind::Modify:
    return true;
  }

  llvm_unreachable("Unhandled AccessorKind in switch.");
}

static bool printDisplayName(const swift::ValueDecl *D, llvm::raw_ostream &OS) {
  if (!D->hasName() && !isa<ParamDecl>(D)) {
    auto *FD = dyn_cast<AccessorDecl>(D);
    if (!FD)
      return true;
    return printArtificialName(FD->getStorage(), FD->getAccessorKind(), OS);
  }

  OS << D->getFullName();
  return false;
}

static bool isMemberwiseInit(swift::ValueDecl *D) {
  if (auto AFD = dyn_cast<AbstractFunctionDecl>(D))
    return AFD->getBodyKind() == AbstractFunctionDecl::BodyKind::MemberwiseInitializer;
  return false;
}

static SourceLoc getLocForExtension(ExtensionDecl *D) {
  // Use the 'End' token of the range, in case it is a compound name, e.g.
  //   extension A.B {}
  // we want the location of 'B' token.
  if (auto *repr = D->getExtendedTypeRepr()) {
    return repr->getSourceRange().End;
  }
  return SourceLoc();
}

namespace {
// Adapter providing a common interface for a SourceFile/Module.
class SourceFileOrModule {
  llvm::PointerUnion<SourceFile *, ModuleDecl *> SFOrMod;

public:
  SourceFileOrModule(SourceFile &SF) : SFOrMod(&SF) {}
  SourceFileOrModule(ModuleDecl &Mod) : SFOrMod(&Mod) {}

  SourceFile *getAsSourceFile() const {
    return SFOrMod.dyn_cast<SourceFile *>();
  }

  ModuleDecl *getAsModule() const { return SFOrMod.dyn_cast<ModuleDecl *>(); }

  ModuleDecl &getModule() const {
    if (auto SF = SFOrMod.dyn_cast<SourceFile *>())
      return *SF->getParentModule();
    return *SFOrMod.get<ModuleDecl *>();
  }

  ArrayRef<FileUnit *> getFiles() const {
    return SFOrMod.is<SourceFile *>() ? *SFOrMod.getAddrOfPtr1()
                                      : SFOrMod.get<ModuleDecl *>()->getFiles();
  }

  StringRef getFilename() const {
    if (auto *SF = SFOrMod.dyn_cast<SourceFile *>())
      return SF->getFilename();
    return SFOrMod.get<ModuleDecl *>()->getModuleFilename();
  }

  void
  getImportedModules(SmallVectorImpl<ModuleDecl::ImportedModule> &Modules) const {
    ModuleDecl::ImportFilter ImportFilter;
    ImportFilter |= ModuleDecl::ImportFilterKind::Public;
    ImportFilter |= ModuleDecl::ImportFilterKind::Private;
    ImportFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;

    if (auto *SF = SFOrMod.dyn_cast<SourceFile *>()) {
      SF->getImportedModules(Modules, ImportFilter);
    } else {
      SFOrMod.get<ModuleDecl *>()->getImportedModules(Modules, ImportFilter);
    }
  }
};

struct IndexedWitness {
  ValueDecl *Member;
  ValueDecl *Requirement;
};

class IndexSwiftASTWalker : public SourceEntityWalker {
  IndexDataConsumer &IdxConsumer;
  SourceManager &SrcMgr;
  unsigned BufferID;
  bool enableWarnings;

  bool IsModuleFile = false;
  bool isSystemModule = false;
  struct Entity {
    Decl *D;
    SymbolInfo SymInfo;
    SymbolRoleSet Roles;
    SmallVector<IndexedWitness, 6> ExplicitWitnesses;
    SmallVector<SourceLoc, 6> RefsToSuppress;
  };
  SmallVector<Entity, 6> EntitiesStack;
  SmallVector<Expr *, 8> ExprStack;
  SmallVector<const AccessorDecl *, 4> ManuallyVisitedAccessorStack;
  bool Cancelled = false;

  struct NameAndUSR {
    StringRef USR;
    StringRef name;
  };
  typedef llvm::PointerIntPair<Decl *, 3> DeclAccessorPair;
  llvm::DenseMap<void *, NameAndUSR> nameAndUSRCache;
  llvm::DenseMap<DeclAccessorPair, NameAndUSR> accessorNameAndUSRCache;
  StringScratchSpace stringStorage;

  bool getNameAndUSR(ValueDecl *D, ExtensionDecl *ExtD,
                     StringRef &name, StringRef &USR) {
    auto &result = nameAndUSRCache[ExtD ? (Decl*)ExtD : D];
    if (result.USR.empty()) {
      SmallString<128> storage;
      {
        llvm::raw_svector_ostream OS(storage);
        if (ExtD) {
          if (ide::printExtensionUSR(ExtD, OS))
            return true;
        } else {
          if (ide::printValueDeclUSR(D, OS))
            return true;
        }
        result.USR = stringStorage.copyString(OS.str());
      }

      storage.clear();
      {
        llvm::raw_svector_ostream OS(storage);
        printDisplayName(D, OS);
        result.name = stringStorage.copyString(OS.str());
      }
    }

    name = result.name;
    USR = result.USR;
    return false;
  }

  bool getModuleNameAndUSR(ModuleEntity Mod, StringRef &name, StringRef &USR) {
    auto &result = nameAndUSRCache[Mod.getOpaqueValue()];
    if (result.USR.empty()) {
      SmallString<128> storage;
      {
        llvm::raw_svector_ostream OS(storage);
        if (ide::printModuleUSR(Mod, OS))
          return true;
        result.USR = stringStorage.copyString(OS.str());
      }
      storage.clear();
      {
        llvm::raw_svector_ostream OS(storage);
        OS << Mod.getFullName();
        result.name = stringStorage.copyString(OS.str());
      }
    }
    name = result.name;
    USR = result.USR;
    return false;
  }

  bool getPseudoAccessorNameAndUSR(AbstractStorageDecl *D, AccessorKind AK, StringRef &Name, StringRef &USR) {
    assert(static_cast<int>(AK) < 0x111 && "AccessorKind too big for pair");
    DeclAccessorPair key(D, static_cast<int>(AK));
    auto &result = accessorNameAndUSRCache[key];
    if (result.USR.empty()) {
      SmallString<128> storage;
      {
        llvm::raw_svector_ostream OS(storage);
        if (ide::printAccessorUSR(D, AK, OS))
          return true;
        result.USR = stringStorage.copyString(OS.str());
      }

      storage.clear();
      {
        llvm::raw_svector_ostream OS(storage);
        printArtificialName(D, AK, OS);
        result.name = stringStorage.copyString(OS.str());
      }
    }

    Name = result.name;
    USR = result.USR;
    return false;
  }

  bool addRelation(IndexSymbol &Info, SymbolRoleSet RelationRoles, Decl *D) {
    assert(D);
    auto Match = std::find_if(Info.Relations.begin(), Info.Relations.end(),
                              [D](IndexRelation R) { return R.decl == D; });
    if (Match != Info.Relations.end()) {
      Match->roles |= RelationRoles;
      Info.roles |= RelationRoles;
      return false;
    }

    StringRef Name, USR;
    SymbolInfo SymInfo = getSymbolInfoForDecl(D);

    if (SymInfo.Kind == SymbolKind::Unknown)
      return true;
    if (auto *ExtD = dyn_cast<ExtensionDecl>(D)) {
      NominalTypeDecl *NTD = ExtD->getExtendedNominal();
      if (getNameAndUSR(NTD, ExtD, Name, USR))
        return true;
    } else {
      if (getNameAndUSR(cast<ValueDecl>(D), /*ExtD=*/nullptr, Name, USR))
        return true;
    }

    Info.Relations.push_back(IndexRelation(RelationRoles, D, SymInfo, Name, USR));
    Info.roles |= RelationRoles;
    return false;
  }

public:
  IndexSwiftASTWalker(IndexDataConsumer &IdxConsumer, ASTContext &Ctx,
                      unsigned BufferID = -1)
      : IdxConsumer(IdxConsumer), SrcMgr(Ctx.SourceMgr), BufferID(BufferID),
        enableWarnings(IdxConsumer.enableWarnings()) {}

  ~IndexSwiftASTWalker() override {
    assert(Cancelled || EntitiesStack.empty());
    assert(Cancelled || ManuallyVisitedAccessorStack.empty());
  }

  void visitModule(ModuleDecl &Mod);
  void visitDeclContext(DeclContext *DC);

private:
  bool visitImports(SourceFileOrModule Mod,
                    llvm::SmallPtrSetImpl<ModuleDecl *> &Visited);

  bool handleSourceOrModuleFile(SourceFileOrModule SFOrMod);

  bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
    // Do not handle unavailable decls.
    if (AvailableAttr::isUnavailable(D))
      return false;

    if (!handleCustomAttrInitRefs(D))
      return false;

    if (auto *AD = dyn_cast<AccessorDecl>(D)) {
      if (ManuallyVisitedAccessorStack.empty() ||
          ManuallyVisitedAccessorStack.back() != AD)
        return false; // already handled as part of the var decl.
    }
    if (auto *VD = dyn_cast<ValueDecl>(D)) {
      if (!report(VD))
        return false;
    }
    if (auto *ED = dyn_cast<ExtensionDecl>(D))
      return reportExtension(ED);
    return true;
  }

  bool walkToDeclPost(Decl *D) override {
    if (Cancelled)
      return false;

    if (getParentDecl() == D)
      return finishCurrentEntity();

    return true;
  }

  /// Report calls to the initializers of property wrapper types on wrapped properties.
  ///
  /// These may be either explicit:
  ///     `\@Wrapper(initialialValue: 42) var x: Int`
  /// or implicit:
  ///     `\@Wrapper var x = 10`
  bool handleCustomAttrInitRefs(Decl * D) {
    for (auto *customAttr : D->getAttrs().getAttributes<CustomAttr, true>()) {
      if (customAttr->isImplicit())
        continue;

      auto &Loc = customAttr->getTypeLoc();
      if (auto *semanticInit = dyn_cast_or_null<CallExpr>(customAttr->getSemanticInit())) {
        if (auto *CD = semanticInit->getCalledValue()) {
          if (!shouldIndex(CD, /*IsRef*/true))
            continue;
          IndexSymbol Info;
          if (initIndexSymbol(CD, Loc.getLoc(), /*IsRef=*/true, Info))
            continue;
          Info.roles |= (unsigned)SymbolRole::Call;
          if (semanticInit->isImplicit())
            Info.roles |= (unsigned)SymbolRole::Implicit;
          if (!startEntity(CD, Info, /*IsRef=*/true) || !finishCurrentEntity())
            return false;
        }
      }
    }
    return true;
  }

  void handleMemberwiseInitRefs(Expr *E) {
    if (!isa<ConstructorRefCallExpr>(E))
      return;

    auto *DeclRef = dyn_cast<DeclRefExpr>(cast<ConstructorRefCallExpr>(E)->getFn());
    if (!DeclRef || !isMemberwiseInit(DeclRef->getDecl()))
      return;

    // get label locations
    auto *MemberwiseInit = DeclRef->getDecl();
    std::vector<SourceLoc> LabelLocs;
    ArrayRef<Identifier> Labels;
    auto NameLoc = DeclRef->getNameLoc();
    if (NameLoc.isCompound()) {
      size_t LabelIndex = 0;
      SourceLoc ArgLoc;
      while ((ArgLoc = NameLoc.getArgumentLabelLoc(LabelIndex++)).isValid()) {
        LabelLocs.push_back(ArgLoc);
      }
      Labels = MemberwiseInit->getFullName().getArgumentNames();
    } else if (auto *CallParent = dyn_cast_or_null<CallExpr>(getParentExpr())) {
      LabelLocs = CallParent->getArgumentLabelLocs();
      Labels = CallParent->getArgumentLabels();
    }

    if (LabelLocs.empty())
      return;

    assert(Labels.size() == LabelLocs.size());

    // match labels to properties
    auto *TypeContext =
        MemberwiseInit->getDeclContext()->getSelfNominalTypeDecl();
    if (!TypeContext || !shouldIndex(TypeContext, false))
      return;

    unsigned CurLabel = 0;
    for (auto Member : TypeContext->getMembers()) {
      auto Prop = dyn_cast<VarDecl>(Member);
      if (!Prop)
        continue;

      if (!Prop->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
        continue;

      if (CurLabel == LabelLocs.size())
        break;

      if (Labels[CurLabel] != Prop->getName())
        continue;

      IndexSymbol Info;
      if (initIndexSymbol(Prop, LabelLocs[CurLabel++], /*IsRef=*/true, Info))
        continue;
      if (startEntity(Prop, Info, /*IsRef=*/true))
        finishCurrentEntity();
    }
  }

  bool walkToExprPre(Expr *E) override {
    if (Cancelled)
      return false;
    ExprStack.push_back(E);

    handleMemberwiseInitRefs(E);
    return true;
  }

  bool walkToExprPost(Expr *E) override {
    if (Cancelled)
      return false;
    assert(ExprStack.back() == E);
    ExprStack.pop_back();
    return true;
  }

  bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
                          TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T,
                          ReferenceMetaData Data) override {
    SourceLoc Loc = Range.getStart();

    if (isRepressed(Loc) || Loc.isInvalid())
      return true;

    IndexSymbol Info;

    if (Data.isImplicit)
      Info.roles |= (unsigned)SymbolRole::Implicit;

    if (CtorTyRef)
      if (!reportRef(CtorTyRef, Loc, Info, Data.AccKind))
        return false;
    if (!reportRef(D, Loc, Info, Data.AccKind))
      return false;

    // If this is a reference to a property wrapper backing property or
    // projected value, report a reference to the wrapped property too (i.e.
    // report an occurrence of `foo` in `_foo` and '$foo').
    if (auto *VD = dyn_cast<VarDecl>(D)) {
      if (auto *Wrapped = VD->getOriginalWrappedProperty()) {
        assert(Range.getByteLength() > 1 &&
               (Range.str().front() == '_' || Range.str().front() == '$'));
        auto AfterDollar = Loc.getAdvancedLoc(1);
        reportRef(Wrapped, AfterDollar, Info, None);
      }
    }

    return true;
  }

  bool visitModuleReference(ModuleEntity Mod, CharSourceRange Range) override {
    SourceLoc Loc = Range.getStart();

    if (Loc.isInvalid())
      return true;

    IndexSymbol Info;
    std::tie(Info.line, Info.column, Info.offset) = getLineColAndOffset(Loc);
    Info.roles |= (unsigned)SymbolRole::Reference;
    Info.symInfo = getSymbolInfoForModule(Mod);
    getModuleNameAndUSR(Mod, Info.name, Info.USR);

    if (auto Container = getContainingDecl())
      addRelation(Info, (unsigned)SymbolRole::RelationContainedBy, Container);

    if (!IdxConsumer.startSourceEntity(Info)) {
      Cancelled = true;
      return true;
    }

    return finishSourceEntity(Info.symInfo, Info.roles);
  }

  Decl *getParentDecl() const {
    if (!EntitiesStack.empty())
      return EntitiesStack.back().D;
    return nullptr;
  }

  Decl *getContainingDecl() const {
    for (const auto &Entity: EntitiesStack) {
      if (isa<AbstractFunctionDecl>(Entity.D) &&
          (Entity.Roles & (SymbolRoleSet)SymbolRole::Definition)) {
        return Entity.D;
      }
    }
    return nullptr;
  }

  void repressRefAtLoc(SourceLoc Loc) {
    if (Loc.isInvalid()) return;
    assert(!EntitiesStack.empty());
    EntitiesStack.back().RefsToSuppress.push_back(Loc);
  }

  bool isRepressed(SourceLoc Loc) const {
    if (EntitiesStack.empty() || Loc.isInvalid())
      return false;
    auto &Suppressed = EntitiesStack.back().RefsToSuppress;
    return std::find(Suppressed.begin(), Suppressed.end(), Loc) != Suppressed.end();

  }

  Expr *getContainingExpr(size_t index) const {
    if (ExprStack.size() > index)
      return ExprStack.end()[-std::ptrdiff_t(index + 1)];
    return nullptr;
  }

  Expr *getCurrentExpr() const {
    return ExprStack.empty() ? nullptr : ExprStack.back();
  }

  Expr *getParentExpr() const {
    return getContainingExpr(1);
  }


  bool report(ValueDecl *D);
  bool reportExtension(ExtensionDecl *D);
  bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
                 Optional<AccessKind> AccKind);
  bool reportImplicitConformance(ValueDecl *witness, ValueDecl *requirement,
                                 Decl *container);

  bool startEntity(Decl *D, IndexSymbol &Info, bool IsRef);
  bool startEntityDecl(ValueDecl *D);

  bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
  bool reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related);
  bool reportInheritedTypeRefs(ArrayRef<TypeLoc> Inherited, Decl *Inheritee);
  NominalTypeDecl *getTypeLocAsNominalTypeDecl(const TypeLoc &Ty);

  bool reportPseudoGetterDecl(VarDecl *D) {
    return reportPseudoAccessor(D, AccessorKind::Get, /*IsRef=*/false,
                                D->getLoc());
  }
  bool reportPseudoSetterDecl(VarDecl *D) {
    return reportPseudoAccessor(D, AccessorKind::Set, /*IsRef=*/false,
                                D->getLoc());
  }
  bool reportPseudoAccessor(AbstractStorageDecl *D, AccessorKind AccKind,
                            bool IsRef, SourceLoc Loc);

  bool finishCurrentEntity() {
    Entity CurrEnt = EntitiesStack.pop_back_val();
    assert(CurrEnt.SymInfo.Kind != SymbolKind::Unknown);
    return finishSourceEntity(CurrEnt.SymInfo, CurrEnt.Roles);
  }

  bool finishSourceEntity(SymbolInfo symInfo, SymbolRoleSet roles) {
    if (!IdxConsumer.finishSourceEntity(symInfo, roles)) {
      Cancelled = true;
      return false;
    }
    return true;
  }

  bool initIndexSymbol(ValueDecl *D, SourceLoc Loc, bool IsRef,
                       IndexSymbol &Info);
  bool initIndexSymbol(ExtensionDecl *D, ValueDecl *ExtendedD, SourceLoc Loc,
                       IndexSymbol &Info);
  bool initFuncDeclIndexSymbol(FuncDecl *D, IndexSymbol &Info);
  bool initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
  bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
                              IndexSymbol &Info, Optional<AccessKind> AccKind);

  bool indexComment(const Decl *D);

  std::tuple<unsigned, unsigned, Optional<unsigned>>
  getLineColAndOffset(SourceLoc Loc) {
    if (Loc.isInvalid())
      return std::make_tuple(0, 0, None);
    auto lineAndColumn = SrcMgr.getLineAndColumn(Loc, BufferID);
    unsigned offset = SrcMgr.getLocOffsetInBuffer(Loc, BufferID);
    return std::make_tuple(lineAndColumn.first, lineAndColumn.second, offset);
  }

  bool shouldIndex(ValueDecl *D, bool IsRef) const {
    if (D->isImplicit() && isa<VarDecl>(D) && IsRef) {
      // Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
      // canonical VarDecl for these checks instead.
      D = cast<VarDecl>(D)->getCanonicalVarDecl();
    }

    if (D->isImplicit() && !isa<ConstructorDecl>(D))
      return false;

    // Do not handle non-public imported decls.
    if (IsModuleFile && !D->isAccessibleFrom(nullptr))
      return false;

    if (!IdxConsumer.indexLocals() && isLocalSymbol(D))
      return isa<ParamDecl>(D) && !IsRef &&
        D->getDeclContext()->getContextKind() != DeclContextKind::AbstractClosureExpr;

    if (D->isPrivateStdlibDecl())
      return false;

    return true;
  }

  /// Reports all implicit member value decl conformances that \p D introduces
  /// as implicit overrides at the source location of \p D, and returns the
  /// explicit ones so we can check against them later on when visiting them as
  /// members.
  ///
  /// \returns false if AST visitation should stop.
  bool handleWitnesses(Decl *D, SmallVectorImpl<IndexedWitness> &explicitWitnesses);

  void getRecursiveModuleImports(ModuleDecl &Mod,
                                 SmallVectorImpl<ModuleDecl *> &Imports);
  void
  collectRecursiveModuleImports(ModuleDecl &Mod,
                                llvm::SmallPtrSetImpl<ModuleDecl *> &Visited);

  template <typename F>
  void warn(F log) {
    if (!enableWarnings)
      return;

    SmallString<128> warning;
    llvm::raw_svector_ostream OS(warning);
    log(OS);
  }

  // This maps a module to all its imports, recursively.
  llvm::DenseMap<ModuleDecl *, llvm::SmallVector<ModuleDecl *, 4>> ImportsMap;
};
} // anonymous namespace

void IndexSwiftASTWalker::visitDeclContext(DeclContext *Context) {
  IsModuleFile = false;
  isSystemModule = Context->getParentModule()->isSystemModule();
  auto accessor = dyn_cast<AccessorDecl>(Context);
  if (accessor)
    ManuallyVisitedAccessorStack.push_back(accessor);
  walk(Context);
  if (accessor)
    ManuallyVisitedAccessorStack.pop_back();
}

void IndexSwiftASTWalker::visitModule(ModuleDecl &Mod) {
  SourceFile *SrcFile = nullptr;
  for (auto File : Mod.getFiles()) {
    if (auto SF = dyn_cast<SourceFile>(File)) {
      auto BufID = SF->getBufferID();
      if (BufID.hasValue() && *BufID == BufferID) {
        SrcFile = SF;
        break;
      }
    }
  }

  if (SrcFile != nullptr) {
    IsModuleFile = false;
    if (!handleSourceOrModuleFile(*SrcFile))
      return;
    walk(*SrcFile);
  } else {
    IsModuleFile = true;
    isSystemModule = Mod.isSystemModule();
    if (!handleSourceOrModuleFile(Mod))
      return;
    walk(Mod);
  }
}

bool IndexSwiftASTWalker::handleSourceOrModuleFile(SourceFileOrModule SFOrMod) {
  // Common reporting for TU/module file.

  llvm::SmallPtrSet<ModuleDecl *, 16> Visited;
  return visitImports(SFOrMod, Visited);
}

bool IndexSwiftASTWalker::visitImports(
    SourceFileOrModule TopMod, llvm::SmallPtrSetImpl<ModuleDecl *> &Visited) {
  // Dependencies of the stdlib module (like SwiftShims module) are
  // implementation details.
  if (TopMod.getModule().isStdlibModule())
    return true;

  bool IsNew = Visited.insert(&TopMod.getModule()).second;
  if (!IsNew)
    return true;

  SmallVector<ModuleDecl::ImportedModule, 8> Imports;
  TopMod.getImportedModules(Imports);

  llvm::SmallPtrSet<ModuleDecl *, 8> Reported;
  for (auto Import : Imports) {
    ModuleDecl *Mod = Import.second;
    bool NewReport = Reported.insert(Mod).second;
    if (!NewReport)
      continue;

    // FIXME: Handle modules with multiple source files; these will fail on
    // getModuleFilename() (by returning an empty path). Note that such modules
    // may be heterogeneous.
    StringRef Path = Mod->getModuleFilename();
    if (Path.empty() || Path == TopMod.getFilename())
      continue; // this is a submodule.

    Optional<bool> IsClangModuleOpt;
    for (auto File : Mod->getFiles()) {
      switch (File->getKind()) {
      case FileUnitKind::Source:
      case FileUnitKind::Builtin:
        break;
      case FileUnitKind::SerializedAST:
        assert(!IsClangModuleOpt.hasValue() &&
               "cannot handle multi-file modules");
        IsClangModuleOpt = false;
        break;
      case FileUnitKind::ClangModule:
      case FileUnitKind::DWARFModule:
        assert(!IsClangModuleOpt.hasValue() &&
               "cannot handle multi-file modules");
        IsClangModuleOpt = true;
        break;
      }
    }
    if (!IsClangModuleOpt.hasValue())
      continue;
    bool IsClangModule = *IsClangModuleOpt;

    if (!IdxConsumer.startDependency(Mod->getName().str(), Path, IsClangModule,
                                     Mod->isSystemModule()))
      return false;
    if (!IsClangModule)
      if (!visitImports(*Mod, Visited))
        return false;
    if (!IdxConsumer.finishDependency(IsClangModule))
      return false;
  }

  return true;
}

bool IndexSwiftASTWalker::handleWitnesses(Decl *D, SmallVectorImpl<IndexedWitness> &explicitWitnesses) {
  auto DC = dyn_cast<DeclContext>(D);
  if (!DC)
    return true;

  for (auto *conf : DC->getLocalConformances()) {
    if (conf->isInvalid())
      continue;

    // Ignore self-conformances; they're not interesting to show to users.
    auto normal = dyn_cast<NormalProtocolConformance>(conf->getRootConformance());
    if (!normal)
      continue;

    normal->forEachValueWitness([&](ValueDecl *req, Witness witness) {
      if (Cancelled)
        return;

      auto *decl = witness.getDecl();
      if (decl == nullptr)
        return;

      if (decl->getDeclContext() == DC) {
        explicitWitnesses.push_back({decl, req});
      } else {
        reportImplicitConformance(decl, req, D);
      }
    });

    normal->forEachTypeWitness(
                [&](AssociatedTypeDecl *assoc, Type type, TypeDecl *typeDecl) {
      if (Cancelled)
        return true;
      if (typeDecl == nullptr)
        return false;

      if (typeDecl->getDeclContext() == DC) {
        explicitWitnesses.push_back({typeDecl, assoc});
      } else {
        // Report the implicit conformance.
        reportImplicitConformance(typeDecl, assoc, D);
      }
      return false;
    });
  }

  if (Cancelled)
    return false;

  return true;
}

bool IndexSwiftASTWalker::startEntity(Decl *D, IndexSymbol &Info, bool IsRef) {
  switch (IdxConsumer.startSourceEntity(Info)) {
    case swift::index::IndexDataConsumer::Abort:
      Cancelled = true;
      LLVM_FALLTHROUGH;
    case swift::index::IndexDataConsumer::Skip:
      return false;
    case swift::index::IndexDataConsumer::Continue: {
      SmallVector<IndexedWitness, 6> explicitWitnesses;
      if (!IsRef) {
        if (!handleWitnesses(D, explicitWitnesses))
          return false;
      }
      EntitiesStack.push_back({D, Info.symInfo, Info.roles, std::move(explicitWitnesses), {}});
      return true;
    }
  }

  llvm_unreachable("Unhandled IndexDataConsumer in switch.");
}

bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
  if (!shouldIndex(D, /*IsRef=*/false))
    return false;

  SourceLoc Loc = D->getLoc();
  if (Loc.isInvalid() && !IsModuleFile)
    return false;

  if (!IsModuleFile) {
    if (!indexComment(D))
      return false;
  }

  IndexSymbol Info;
  if (auto FD = dyn_cast<FuncDecl>(D)) {
    if (initFuncDeclIndexSymbol(FD, Info))
      return false;
  } else {
    if (initIndexSymbol(D, Loc, /*IsRef=*/false, Info))
      return false;
  }

  for (auto Overriden: collectAllOverriddenDecls(D, /*IncludeProtocolReqs=*/false)) {
    addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overriden);
  }

  if (auto Parent = getParentDecl()) {
    for (const IndexedWitness &witness : EntitiesStack.back().ExplicitWitnesses) {
      if (witness.Member == D)
        addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, witness.Requirement);
    }
    if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
      SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
      if (Info.symInfo.SubKind == SymbolSubKind::AccessorGetter ||
          Info.symInfo.SubKind == SymbolSubKind::AccessorSetter ||
          (Info.symInfo.SubKind >= SymbolSubKind::SwiftAccessorWillSet &&
           Info.symInfo.SubKind <= SymbolSubKind::SwiftAccessorMutableAddressor))
        RelationsToParent |= (SymbolRoleSet)SymbolRole::RelationAccessorOf;
      if (addRelation(Info, RelationsToParent, ParentVD))
        return false;

    } else if (auto ParentED = dyn_cast<ExtensionDecl>(Parent)) {
      if (ParentED->getExtendedNominal()) {
        if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationChildOf, ParentED))
          return false;
      }
    }
  }

  return startEntity(D, Info, /*IsRef=*/false);
}

bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit,
                                           SymbolRoleSet Relations, Decl *Related) {
  if (!shouldIndex(D, /*IsRef=*/true))
    return true;

  IndexSymbol Info;
  if (addRelation(Info, Relations, Related))
    return true;
  if (isImplicit)
    Info.roles |= (unsigned)SymbolRole::Implicit;

  // don't report this ref again when visitDeclReference reports it
  repressRefAtLoc(Loc);

  if (!reportRef(D, Loc, Info, None)) {
    Cancelled = true;
    return false;
  }

  return !Cancelled;
}

bool IndexSwiftASTWalker::reportInheritedTypeRefs(ArrayRef<TypeLoc> Inherited, Decl *Inheritee) {
  for (auto Base : Inherited) {
    if (!reportRelatedTypeRef(Base, (SymbolRoleSet) SymbolRole::RelationBaseOf, Inheritee))
      return false;
  }
  return true;
}

bool IndexSwiftASTWalker::reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related) {

  if (auto *T = dyn_cast_or_null<IdentTypeRepr>(Ty.getTypeRepr())) {
    auto Comps = T->getComponentRange();
    SourceLoc IdLoc = Comps.back()->getIdLoc();
    NominalTypeDecl *NTD = nullptr;
    bool isImplicit = false;
    if (auto *VD = Comps.back()->getBoundDecl()) {
      if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
        IndexSymbol Info;
        if (!reportRef(TAD, IdLoc, Info, None))
          return false;
        if (auto Ty = TAD->getUnderlyingType()) {
          NTD = Ty->getAnyNominal();
          isImplicit = true;
        }
      } else {
        NTD = dyn_cast<NominalTypeDecl>(VD);
      }
    }
    if (NTD) {
      if (!reportRelatedRef(NTD, IdLoc, isImplicit, Relations, Related))
        return false;
    }
    return true;
  }

  if (Ty.getType()) {
    if (auto nominal = Ty.getType()->getAnyNominal())
      if (!reportRelatedRef(nominal, Ty.getLoc(), /*isImplicit=*/false, Relations, Related))
        return false;
  }
  return true;
}

static bool isDynamicVarAccessorOrFunc(ValueDecl *D, SymbolInfo symInfo) {
  if (auto NTD = D->getDeclContext()->getSelfNominalTypeDecl()) {
    bool isClassOrProtocol = isa<ClassDecl>(NTD) || isa<ProtocolDecl>(NTD);
    bool isInternalAccessor =
      symInfo.SubKind == SymbolSubKind::SwiftAccessorWillSet ||
      symInfo.SubKind == SymbolSubKind::SwiftAccessorDidSet ||
      symInfo.SubKind == SymbolSubKind::SwiftAccessorAddressor ||
      symInfo.SubKind == SymbolSubKind::SwiftAccessorMutableAddressor;
    if (isClassOrProtocol &&
        symInfo.Kind != SymbolKind::StaticMethod &&
        !isInternalAccessor &&
        !D->isFinal()) {
      return true;
    }
  }
  return false;
}

bool IndexSwiftASTWalker::reportPseudoAccessor(AbstractStorageDecl *D,
                                               AccessorKind AccKind, bool IsRef,
                                               SourceLoc Loc) {
  if (!shouldIndex(D, IsRef))
    return true; // continue walking.

  auto updateInfo = [this, D, AccKind](IndexSymbol &Info) {
    if (getPseudoAccessorNameAndUSR(D, AccKind, Info.name, Info.USR))
      return true;
    Info.symInfo.Kind = SymbolKind::Function;
    if (D->getDeclContext()->isTypeContext()) {
      if (D->isStatic()) {
        if (D->getCorrectStaticSpelling() == StaticSpellingKind::KeywordClass)
          Info.symInfo.Kind = SymbolKind::ClassMethod;
        else
          Info.symInfo.Kind = SymbolKind::StaticMethod;
      } else {
        Info.symInfo.Kind = SymbolKind::InstanceMethod;
      }
    }
    Info.symInfo.SubKind = getSubKindForAccessor(AccKind);
    Info.roles |= (SymbolRoleSet)SymbolRole::Implicit;
    Info.group = "";
    if (isDynamicVarAccessorOrFunc(D, Info.symInfo)) {
      Info.roles |= (SymbolRoleSet)SymbolRole::Dynamic;
    }
    return false;
  };

  if (IsRef) {
    IndexSymbol Info;

    // initFuncRefIndexSymbol uses the top of the entities stack as the caller,
    // but in this case the top of the stack is the referenced
    // AbstractStorageDecl.
    assert(getParentDecl() == D);
    auto PreviousTop = EntitiesStack.pop_back_val();
    bool initFailed = initFuncRefIndexSymbol(D, Loc, Info);
    EntitiesStack.push_back(PreviousTop);

    if (initFailed)
      return true; // continue walking.
    if (updateInfo(Info))
      return true;

    if (!IdxConsumer.startSourceEntity(Info) || !IdxConsumer.finishSourceEntity(Info.symInfo, Info.roles))
      Cancelled = true;
  } else {
    IndexSymbol Info;
    if (initIndexSymbol(D, Loc, IsRef, Info))
      return true; // continue walking.
    if (updateInfo(Info))
      return true;
    if (addRelation(Info, (SymbolRoleSet)SymbolRole::RelationAccessorOf |
                    (SymbolRoleSet)SymbolRole::RelationChildOf , D))
      return true;

    if (!IdxConsumer.startSourceEntity(Info) || !IdxConsumer.finishSourceEntity(Info.symInfo, Info.roles))
      Cancelled = true;
  }
  return !Cancelled;
}

NominalTypeDecl *
IndexSwiftASTWalker::getTypeLocAsNominalTypeDecl(const TypeLoc &Ty) {
  if (Type T = Ty.getType())
    return T->getAnyNominal();
  if (auto *T = dyn_cast_or_null<IdentTypeRepr>(Ty.getTypeRepr())) {
    auto Comp = T->getComponentRange().back();
    if (auto NTD = dyn_cast_or_null<NominalTypeDecl>(Comp->getBoundDecl()))
      return NTD;
  }
  return nullptr;
}

bool IndexSwiftASTWalker::reportExtension(ExtensionDecl *D) {
  SourceLoc Loc = getLocForExtension(D);
  NominalTypeDecl *NTD = D->getExtendedNominal();
  if (!NTD)
    return true;
  if (!shouldIndex(NTD, /*IsRef=*/false))
    return true;

  IndexSymbol Info;
  if (initIndexSymbol(D, NTD, Loc, Info))
    return true;

  if (!startEntity(D, Info, /*IsRef=*/false))
    return false;

  if (!reportRelatedRef(NTD, Loc, /*isImplicit=*/false,
                        (SymbolRoleSet)SymbolRole::RelationExtendedBy, D))
      return false;
  if (!reportInheritedTypeRefs(D->getInherited(), D))
      return false;

  return true;
}

bool IndexSwiftASTWalker::report(ValueDecl *D) {
  if (startEntityDecl(D)) {
    // Pass accessors.
    if (auto StoreD = dyn_cast<AbstractStorageDecl>(D)) {
      bool usedPseudoAccessors = false;
      if (isa<VarDecl>(D) &&
          !StoreD->getParsedAccessor(AccessorKind::Get) &&
          !StoreD->getParsedAccessor(AccessorKind::Set)) {
        usedPseudoAccessors = true;
        auto VarD = cast<VarDecl>(D);
        // No actual getter or setter, pass 'pseudo' accessors.
        // We create accessor entities so we can implement the functionality
        // of libclang, which reports implicit method property accessor
        // declarations, invocations, and overrides for properties.
        // Note that an ObjC class subclassing from a Swift class, may still
        // be able to override its non-computed-property-accessors via a
        // method.
        if (!reportPseudoGetterDecl(VarD))
          return false;
        if (!reportPseudoSetterDecl(VarD))
          return false;
      }

      for (auto accessor : StoreD->getAllAccessors()) {
        // Don't include the implicit getter and setter if we added pseudo
        // accessors above.
        if (usedPseudoAccessors &&
            (accessor->getAccessorKind() == AccessorKind::Get ||
             accessor->getAccessorKind() == AccessorKind::Set))
          continue;

        ManuallyVisitedAccessorStack.push_back(accessor);
        SourceEntityWalker::walk(cast<Decl>(accessor));
        ManuallyVisitedAccessorStack.pop_back();
        if (Cancelled)
          return false;
      }
    } else if (auto NTD = dyn_cast<NominalTypeDecl>(D)) {
      if (!reportInheritedTypeRefs(NTD->getInherited(), NTD))
        return false;
    }
  } else {
    // Even if we don't record a local property we still need to walk its
    // accessor bodies.
    if (auto StoreD = dyn_cast<AbstractStorageDecl>(D)) {
      StoreD->visitParsedAccessors([&](AccessorDecl *accessor) {
        if (Cancelled)
          return;
        ManuallyVisitedAccessorStack.push_back(accessor);
        SourceEntityWalker::walk(cast<Decl>(accessor));
        ManuallyVisitedAccessorStack.pop_back();
      });
    }
  }

  return !Cancelled;
}

static bool hasUsefulRoleInSystemModule(SymbolRoleSet roles) {
  return roles & ((SymbolRoleSet)SymbolRole::Definition |
  (SymbolRoleSet)SymbolRole::Declaration |
  (SymbolRoleSet)SymbolRole::RelationChildOf |
  (SymbolRoleSet)SymbolRole::RelationBaseOf |
  (SymbolRoleSet)SymbolRole::RelationOverrideOf |
  (SymbolRoleSet)SymbolRole::RelationExtendedBy |
  (SymbolRoleSet)SymbolRole::RelationAccessorOf |
  (SymbolRoleSet)SymbolRole::RelationIBTypeOf);
}

bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
                                    IndexSymbol &Info,
                                    Optional<AccessKind> AccKind) {
  if (!shouldIndex(D, /*IsRef=*/true))
    return true; // keep walking

  if (isa<AbstractFunctionDecl>(D)) {
    if (initFuncRefIndexSymbol(D, Loc, Info))
      return true;
  } else if (isa<AbstractStorageDecl>(D)) {
    if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info, AccKind))
      return true;
  } else {
    if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
      return true;
  }

  if (isSystemModule && !hasUsefulRoleInSystemModule(Info.roles))
    return true;

  if (!startEntity(D, Info, /*IsRef=*/true))
    return true;

  // Report the accessors that were utilized.
  if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
    bool UsesGetter = Info.roles & (SymbolRoleSet)SymbolRole::Read;
    bool UsesSetter = Info.roles & (SymbolRoleSet)SymbolRole::Write;

    if (UsesGetter)
      if (!reportPseudoAccessor(ASD, AccessorKind::Get, /*IsRef=*/true,
                                Loc))
        return false;
    if (UsesSetter)
      if (!reportPseudoAccessor(ASD, AccessorKind::Set, /*IsRef=*/true,
                                Loc))
        return false;
  }

  return finishCurrentEntity();
}

bool IndexSwiftASTWalker::reportImplicitConformance(ValueDecl *witness, ValueDecl *requirement,
                                                    Decl *container) {
  if (!shouldIndex(witness, /*IsRef=*/true))
    return true; // keep walking

  SourceLoc loc;
  if (auto *extD = dyn_cast<ExtensionDecl>(container))
    loc = getLocForExtension(extD);
  else
    loc = container->getLoc();

  IndexSymbol info;
  if (initIndexSymbol(witness, loc, /*IsRef=*/true, info))
    return true;
  if (addRelation(info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, requirement))
    return true;
  if (addRelation(info, (SymbolRoleSet) SymbolRole::RelationContainedBy, container))
    return true;
  // Remove the 'ref' role that \c initIndexSymbol introduces. This isn't
  // actually a 'reference', but an 'implicit' override.
  info.roles &= ~(SymbolRoleSet)SymbolRole::Reference;
  info.roles |= (SymbolRoleSet)SymbolRole::Implicit;

  if (!startEntity(witness, info, /*IsRef=*/true))
    return true;
  return finishCurrentEntity();
}

bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
                                          bool IsRef, IndexSymbol &Info) {
  assert(D);
  if (auto *VD = dyn_cast<VarDecl>(D)) {
    // Always base the symbol information on the canonical VarDecl
    D = VD->getCanonicalVarDecl();
  }

  Info.decl = D;
  Info.symInfo = getSymbolInfoForDecl(D);
  if (Info.symInfo.Kind == SymbolKind::Unknown)
    return true;

  // Cannot be extension, which is not a ValueDecl.

  if (IsRef) {
    Info.roles |= (unsigned)SymbolRole::Reference;
    if (auto Container = getContainingDecl())
      addRelation(Info, (unsigned)SymbolRole::RelationContainedBy, Container);
  } else {
    Info.roles |= (unsigned)SymbolRole::Definition;
    if (D->isImplicit())
      Info.roles |= (unsigned)SymbolRole::Implicit;
  }

  if (getNameAndUSR(D, /*ExtD=*/nullptr, Info.name, Info.USR))
    return true;

  std::tie(Info.line, Info.column, Info.offset) = getLineColAndOffset(Loc);
  if (!IsRef) {
    if (auto Group = D->getGroupName())
      Info.group = Group.getValue();
  }
  return false;
}

bool IndexSwiftASTWalker::initIndexSymbol(ExtensionDecl *ExtD, ValueDecl *ExtendedD,
                                          SourceLoc Loc, IndexSymbol &Info) {
  assert(ExtD && ExtendedD);
  Info.decl = ExtendedD;
  Info.symInfo = getSymbolInfoForDecl(ExtD);
  if (Info.symInfo.Kind == SymbolKind::Unknown)
    return true;

  Info.roles |= (unsigned)SymbolRole::Definition;

  if (getNameAndUSR(ExtendedD, ExtD, Info.name, Info.USR))
    return true;

  std::tie(Info.line, Info.column, Info.offset) = getLineColAndOffset(Loc);
  if (auto Group = ExtD->getGroupName())
    Info.group = Group.getValue();
  return false;
}

static NominalTypeDecl *getNominalParent(ValueDecl *D) {
  return D->getDeclContext()->getSelfNominalTypeDecl();
}

bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
                                                  IndexSymbol &Info) {
  if (initIndexSymbol(D, D->getLoc(), /*IsRef=*/false, Info))
    return true;

  if (isDynamicVarAccessorOrFunc(D, Info.symInfo)) {
    Info.roles |= (SymbolRoleSet)SymbolRole::Dynamic;
  }

  if (D->hasImplicitSelfDecl()) {
    // If this is an @IBAction or @IBSegueAction method, find the sender
    // parameter (if present) and relate the method to its type.
    ParamDecl *senderParam = nullptr;

    auto paramList = D->getParameters();
    if (D->getAttrs().hasAttribute<IBActionAttr>()) {
      if (paramList->size() > 0)
        senderParam = paramList->get(0);
    } else if (D->getAttrs().hasAttribute<IBSegueActionAttr>()) {
      if (paramList->size() > 1)
        senderParam = paramList->get(1);
    }

    if (senderParam)
      if (auto nominal = senderParam->getType()->getAnyNominal())
        addRelation(Info, (SymbolRoleSet) SymbolRole::RelationIBTypeOf,
                    nominal);
  }

  if (auto Group = D->getGroupName())
    Info.group = Group.getValue();
  return false;
}

static bool isSuperRefExpr(Expr *E) {
  if (!E)
    return false;
  if (isa<SuperRefExpr>(E))
    return true;
  if (auto LoadE = dyn_cast<LoadExpr>(E))
    return isSuperRefExpr(LoadE->getSubExpr());
  return false;
}

static bool isDynamicCall(Expr *BaseE, ValueDecl *D) {
  // The call is 'dynamic' if the method is not of a struct/enum and the
  // receiver is not 'super'. Note that if the receiver is 'super' that
  // does not mean that the call is statically determined (an extension
  // method may have injected itself in the super hierarchy).
  // For our purposes 'dynamic' means that the method call cannot invoke
  // a method in a subclass.
  auto TyD = getNominalParent(D);
  if (!TyD)
    return false;
  if (isa<StructDecl>(TyD) || isa<EnumDecl>(TyD))
    return false;
  if (isSuperRefExpr(BaseE))
    return false;
  if (BaseE->getType()->is<MetatypeType>())
    return false;

  return true;
}

static bool isBeingCalled(Expr *Target, Expr *Parent, Expr *GrandParent) {
    if (!Target || !Parent || !isa<ApplyExpr>(Parent))
      return false;

    if (!isa<SelfApplyExpr>(Parent))
      return cast<ApplyExpr>(Parent)->getFn() == Target;

  return GrandParent && isa<CallExpr>(GrandParent) &&
    cast<CallExpr>(GrandParent)->getFn() == Parent;
}

bool IndexSwiftASTWalker::initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc,
                                                 IndexSymbol &Info) {

  if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
    return true;

  Expr *CurrentE = getCurrentExpr();
  if (!CurrentE)
    return false;

  Expr *ParentE = getParentExpr();

  if (!isa<AbstractStorageDecl>(D) &&
      !isBeingCalled(CurrentE, ParentE, getContainingExpr(2)))
    return false;

  Info.roles |= (unsigned)SymbolRole::Call;
  if (auto *Caller = dyn_cast_or_null<AbstractFunctionDecl>(getParentDecl())) {
    if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationCalledBy, Caller))
      return true;
  }

  Expr *BaseE = nullptr;
  if (auto DotE = dyn_cast_or_null<DotSyntaxCallExpr>(ParentE))
    BaseE = DotE->getBase();
  else if (auto MembE = dyn_cast<MemberRefExpr>(CurrentE))
    BaseE = MembE->getBase();
  else if (auto SubsE = dyn_cast<SubscriptExpr>(CurrentE))
    BaseE = SubsE->getBase();

  if (!BaseE || BaseE == CurrentE)
    return false;

  if (Type ReceiverTy = BaseE->getType()) {
    if (auto LVT = ReceiverTy->getAs<LValueType>())
      ReceiverTy = LVT->getObjectType();
    else if (auto MetaT = ReceiverTy->getAs<MetatypeType>())
      ReceiverTy = MetaT->getInstanceType();

    if (auto TyD = ReceiverTy->getAnyNominal()) {
      if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationReceivedBy, TyD))
        return true;
      if (isDynamicCall(BaseE, D))
        Info.roles |= (unsigned)SymbolRole::Dynamic;
    }
  }

  return false;
}

bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D,
                                                 SourceLoc Loc, IndexSymbol &Info,
                                                 Optional<AccessKind> AccKind) {

  if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
    return true;

  if (!CurrentE)
    return false;

  AccessKind Kind = AccKind.hasValue() ? *AccKind : AccessKind::Read;
  switch (Kind) {
  case swift::AccessKind::Read:
    Info.roles |= (unsigned)SymbolRole::Read;
    break;
  case swift::AccessKind::ReadWrite:
    Info.roles |= (unsigned)SymbolRole::Read;
    LLVM_FALLTHROUGH;
  case swift::AccessKind::Write:
    Info.roles |= (unsigned)SymbolRole::Write;
  }

  return false;
}

bool IndexSwiftASTWalker::indexComment(const Decl *D) {
  // FIXME: Workaround for getting tag locations. We should enhance cmark to
  // keep track of node offsets in the original comment text.
  struct TagLoc {
    StringRef Text;
    SourceLoc Loc;
  };
  SmallVector<TagLoc, 3> tagLocs;
  for (const auto &single : D->getRawComment().Comments) {
    size_t idx = single.RawText.find("- Tag:");
    if (idx != StringRef::npos) {
      tagLocs.push_back(TagLoc{single.RawText,
                               single.Range.getStart().getAdvancedLoc(idx)});
    }
  }
  if (tagLocs.empty())
    return true;

  swift::markup::MarkupContext MC;
  auto DC = getSingleDocComment(MC, D);
  if (!DC)
    return true;
  for (StringRef tagName : DC->getTags()) {
    tagName = tagName.trim();
    if (tagName.empty())
      continue;
    SourceLoc loc;
    for (const auto &tagLoc : tagLocs) {
      if (tagLoc.Text.contains(tagName)) {
        loc = tagLoc.Loc;
        break;
      }
    }
    if (loc.isInvalid())
      continue;
    IndexSymbol Info;
    Info.decl = nullptr;
    Info.symInfo = SymbolInfo{ SymbolKind::CommentTag, SymbolSubKind::None,
      SymbolLanguage::Swift, SymbolPropertySet() };
    Info.roles |= (unsigned)SymbolRole::Definition;
    Info.name = StringRef();
    SmallString<128> storage;
    {
      llvm::raw_svector_ostream OS(storage);
      OS << "t:" << tagName;
      Info.USR = stringStorage.copyString(OS.str());
    }
    std::tie(Info.line, Info.column, Info.offset) = getLineColAndOffset(loc);
    if (!IdxConsumer.startSourceEntity(Info) || !IdxConsumer.finishSourceEntity(Info.symInfo, Info.roles)) {
      Cancelled = true;
      break;
    }
  }
  return !Cancelled;
}

void IndexSwiftASTWalker::getRecursiveModuleImports(
    ModuleDecl &Mod, SmallVectorImpl<ModuleDecl *> &Imports) {
  auto It = ImportsMap.find(&Mod);
  if (It != ImportsMap.end()) {
    Imports.append(It->second.begin(), It->second.end());
    return;
  }

  llvm::SmallPtrSet<ModuleDecl *, 16> Visited;
  collectRecursiveModuleImports(Mod, Visited);
  Visited.erase(&Mod);

  warn([&Imports](llvm::raw_ostream &OS) {
    std::for_each(Imports.begin(), Imports.end(), [&OS](ModuleDecl *M) {
      if (M->getModuleFilename().empty()) {
        std::string Info = "swift::ModuleDecl with empty file name!! \nDetails: \n";
        Info += "  name: ";
        Info += M->getName().get();
        Info += "\n";

        auto Files = M->getFiles();
        std::for_each(Files.begin(), Files.end(), [&](FileUnit *FU) {
          Info += "  file unit: ";

          switch (FU->getKind()) {
          case FileUnitKind::Builtin:
            Info += "builtin";
            break;
          case FileUnitKind::Source:
            Info += "source, file=\"";
            Info += cast<SourceFile>(FU)->getFilename();
            Info += "\"";
            break;
          case FileUnitKind::SerializedAST:
            Info += "serialized ast, file=\"";
            Info += cast<LoadedFile>(FU)->getFilename();
            Info += "\"";
            break;
          case FileUnitKind::ClangModule:
          case FileUnitKind::DWARFModule:
            Info += "clang module, file=\"";
            Info += cast<LoadedFile>(FU)->getFilename();
            Info += "\"";
          }

          Info += "\n";
        });

        OS << "swift::ModuleDecl with empty file name! " << Info << "\n";
      }
    });
  });

  Imports.append(Visited.begin(), Visited.end());
  std::sort(Imports.begin(), Imports.end(), [](ModuleDecl *LHS, ModuleDecl *RHS) {
    return LHS->getModuleFilename() < RHS->getModuleFilename();
  });

  // Cache it.
  ImportsMap[&Mod].append(Imports.begin(), Imports.end());
}

void IndexSwiftASTWalker::collectRecursiveModuleImports(
    ModuleDecl &TopMod, llvm::SmallPtrSetImpl<ModuleDecl *> &Visited) {

  bool IsNew = Visited.insert(&TopMod).second;
  if (!IsNew)
    return;

  // Pure Clang modules are tied to their dependencies, no need to look into its
  // imports.
  // FIXME: What happens if the clang module imports a swift module ? So far
  // the assumption is that the path to the swift module will be fixed, so no
  // need to hash the clang module.
  // FIXME: This is a bit of a hack.
  if (TopMod.getFiles().size() == 1)
    if (TopMod.getFiles().front()->getKind() == FileUnitKind::ClangModule ||
        TopMod.getFiles().front()->getKind() == FileUnitKind::DWARFModule)
      return;

  auto It = ImportsMap.find(&TopMod);
  if (It != ImportsMap.end()) {
    Visited.insert(It->second.begin(), It->second.end());
    return;
  }

  ModuleDecl::ImportFilter ImportFilter;
  ImportFilter |= ModuleDecl::ImportFilterKind::Public;
  ImportFilter |= ModuleDecl::ImportFilterKind::Private;
  SmallVector<ModuleDecl::ImportedModule, 8> Imports;
  TopMod.getImportedModules(Imports);

  for (auto Import : Imports) {
    collectRecursiveModuleImports(*Import.second, Visited);
  }
}

//===----------------------------------------------------------------------===//
// Indexing entry points
//===----------------------------------------------------------------------===//

void index::indexDeclContext(DeclContext *DC, IndexDataConsumer &consumer) {
  assert(DC);
  unsigned bufferId = DC->getParentSourceFile()->getBufferID().getValue();
  IndexSwiftASTWalker walker(consumer, DC->getASTContext(), bufferId);
  walker.visitDeclContext(DC);
  consumer.finish();
}

void index::indexSourceFile(SourceFile *SF, IndexDataConsumer &consumer) {
  assert(SF);
  unsigned bufferID = SF->getBufferID().getValue();
  IndexSwiftASTWalker walker(consumer, SF->getASTContext(), bufferID);
  walker.visitModule(*SF->getParentModule());
  consumer.finish();
}

void index::indexModule(ModuleDecl *module, IndexDataConsumer &consumer) {
  assert(module);
  IndexSwiftASTWalker walker(consumer, module->getASTContext());
  walker.visitModule(*module);
  consumer.finish();
}
