//===--- UnqualifiedLookup.cpp - Swift Name Lookup Routines ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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
//
//===----------------------------------------------------------------------===//
///
/// This file implements the construction of an UnqualifiedLookup, which entails
/// performing the lookup.
///
//===----------------------------------------------------------------------===//

#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/DebuggerClient.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/ImportCache.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/ModuleNameLookup.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ReferencedNameTracker.h"
#include "swift/AST/SourceFile.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "namelookup"

using namespace swift;
using namespace swift::namelookup;


namespace {
  
  /// Determine whether unqualified lookup should look at the members of the
  /// given nominal type or extension, vs. only looking at type parameters.
  template <typename D> bool shouldLookupMembers(D *decl, SourceLoc loc) {
    // Only look at members of this type (or its inherited types) when
    // inside the body or a protocol's top-level 'where' clause. (Why the
    // 'where' clause? Because that's where you put constraints on
    // inherited associated types.)
    
    // When we have no source-location information, we have to perform member
    // lookup.
    if (loc.isInvalid() || decl->getBraces().isInvalid())
      return true;
    
    // Within the braces, always look for members.
    auto &ctx = decl->getASTContext();
    auto braces = decl->getBraces();
    if (braces.Start != braces.End &&
        ctx.SourceMgr.rangeContainsTokenLoc(braces, loc))
      return true;
    
    // Within 'where' clause, we can also look for members.
    if (auto *whereClause = decl->getTrailingWhereClause()) {
      SourceRange whereClauseRange = whereClause->getSourceRange();
      if (whereClauseRange.isValid() &&
          ctx.SourceMgr.rangeContainsTokenLoc(whereClauseRange, loc)) {
        return true;
      }
    }
    
    // Don't look at the members.
    return false;
  }
} // end anonymous namespace

namespace {
  /// Because UnqualifiedLookup does all of its work in the constructor,
  /// a factory class is needed to hold all of the inputs and outputs so
  /// that the construction code can be decomposed into bite-sized pieces.
  
  class UnqualifiedLookupFactory {

    friend class ASTScopeDeclConsumerForUnqualifiedLookup;

  public:
    using Flags = UnqualifiedLookup::Flags;
    using Options = UnqualifiedLookup::Options;
    using ResultsVector = UnqualifiedLookup::ResultsVector;
    
  private:
    struct ContextAndResolvedIsCascadingUse {
      DeclContext *const DC;
      const bool isCascadingUse;
    };
    
    /// Finds lookup results based on the types that self conforms to.
    /// For instance, self always conforms to a struct, enum or class.
    /// But in addition, self could conform to any number of protocols.
    /// For example, when there's a protocol extension, e.g. extension P where
    /// self: P2, self also conforms to P2 so P2 must be searched.
    class ResultFinderForTypeContext {
      UnqualifiedLookupFactory *const factory;
      /// Nontypes are formally members of the base type, i.e. the dynamic type
      /// of the activation record.
      DeclContext *const dynamicContext;
      /// Types are formally members of the metatype, i.e. the static type of the
      /// activation record.
      DeclContext *const staticContext;
      using SelfBounds = SmallVector<NominalTypeDecl *, 2>;
      SelfBounds selfBounds;
      
    public:
      /// \p staticContext is also the context from which to derive the self types
      ResultFinderForTypeContext(UnqualifiedLookupFactory *factory,
                                 DeclContext *dynamicContext,
                                 DeclContext *staticContext);
      
      void dump() const;
      
    private:
      SelfBounds findSelfBounds(DeclContext *dc);
      
      // Classify this declaration.
      // Types are formally members of the metatype.
      DeclContext *whereValueIsMember(const ValueDecl *const member) const {
        return isa<TypeDecl>(member) ? staticContext : dynamicContext;
      }
      
    public:
      /// Do the lookups and add matches to results.
      void findResults(const DeclName &Name, bool isCascadingUse,
                       NLOptions baseNLOptions, DeclContext *contextForLookup,
                       SmallVectorImpl<LookupResultEntry> &results) const;
    };
    
    enum class AddGenericParameters { Yes, No };

#ifndef NDEBUG
    /// A consumer for debugging that lets the UnqualifiedLookupFactory know when
    /// finding something.
    class InstrumentedNamedDeclConsumer : public NamedDeclConsumer {
      virtual void anchor() override;
      UnqualifiedLookupFactory *factory;
      
    public:
      InstrumentedNamedDeclConsumer(UnqualifiedLookupFactory *factory,
                                    DeclName name,
                                    SmallVectorImpl<LookupResultEntry> &results,
                                    bool isTypeLookup)
      : NamedDeclConsumer(name, results, isTypeLookup), factory(factory) {}
      
      virtual void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason,
                             DynamicLookupInfo dynamicLookupInfo = {}) override {
        unsigned before = results.size();
        NamedDeclConsumer::foundDecl(VD, Reason, dynamicLookupInfo);
        unsigned after = results.size();
        if (after > before)
          factory->addedResult(results.back());
      }
    };
#endif
    // Inputs
    const DeclName Name;
    DeclContext *const DC;
    ModuleDecl &M;
    const ASTContext &Ctx;
    const SourceLoc Loc;
    const SourceManager &SM;
    
    /// Used to find the file-local names.
    DebuggerClient *const DebugClient;
    
    const Options options;
    const bool isOriginallyTypeLookup;
    const NLOptions baseNLOptions;
    // Transputs
#ifndef NDEBUG
    InstrumentedNamedDeclConsumer Consumer;
#else
    NamedDeclConsumer Consumer;
#endif
    // Outputs
    SmallVectorImpl<LookupResultEntry> &Results;
    size_t &IndexOfFirstOuterResult;
    ResultsVector UnavailableInnerResults;

#ifndef NDEBUG
    static unsigned lookupCounter;
    static const unsigned targetLookup;
#endif

  public: // for exp debugging
    SourceFile const *recordedSF = nullptr;
    bool recordedIsCascadingUse = false;
    unsigned resultsSizeBeforeLocalsPass = ~0;
    
  public:
    // clang-format off
    UnqualifiedLookupFactory(DeclName Name,
                             DeclContext *const DC,
                             SourceLoc Loc,
                             Options options,
                             UnqualifiedLookup &lookupToBeCreated);
    
    UnqualifiedLookupFactory(DeclName Name,
                             DeclContext *const DC,
                             SourceLoc Loc,
                             Options options,
                             SmallVectorImpl<LookupResultEntry> &Results,
                             size_t &IndexOfFirstOuterResult);
    // clang-format on
    
    void performUnqualifiedLookup();
    
  private:
    struct ContextAndUnresolvedIsCascadingUse {
      DeclContext *whereToLook;
      Optional<bool> isCascadingUse;
      ContextAndResolvedIsCascadingUse resolve(const bool resolution) const {
        return ContextAndResolvedIsCascadingUse{
          whereToLook, isCascadingUse.getValueOr(resolution)};
      }
    };

    bool useASTScopesForLookup() const;

    /// For testing, assume this lookup is enabled:
    bool useASTScopesForLookupIfEnabled() const;

    void lookUpTopLevelNamesInModuleScopeContext(DeclContext *);

    void lookInASTScopes();

    /// Can lookup stop searching for results, assuming hasn't looked for outer
    /// results yet?
    bool isFirstResultEnough() const;
    
    /// Every time lookup finishes searching a scope, call me
    /// to record the dividing line between results from first fruitful scope and
    /// the result.
    void recordCompletionOfAScope();
    
    template <typename Fn> void ifNotDoneYet(Fn fn) {
      recordCompletionOfAScope();
      if (!isFirstResultEnough())
        fn();
    }
    
    template <typename Fn1, typename Fn2> void ifNotDoneYet(Fn1 fn1, Fn2 fn2) {
      ifNotDoneYet(fn1);
      ifNotDoneYet(fn2);
    }
    
#pragma mark context-based lookup declarations
    
    void lookupOperatorInDeclContexts(ContextAndUnresolvedIsCascadingUse);
    
    void lookupNamesIntroducedBy(const ContextAndUnresolvedIsCascadingUse);
    
    void finishLookingInContext(
                                AddGenericParameters addGenericParameters,
                                DeclContext *lookupContextForThisContext,
                                Optional<ResultFinderForTypeContext> &&resultFinderForTypeContext,
                                Optional<bool> isCascadingUse);
    
    void lookupInModuleScopeContext(DeclContext *, Optional<bool> isCascadingUse);
    
    void lookupNamesIntroducedByPatternBindingInitializer(
                                                          PatternBindingInitializer *PBI, Optional<bool> isCascadingUse);
    
    void
    lookupNamesIntroducedByLazyVariableInitializer(PatternBindingInitializer *PBI,
                                                   ParamDecl *selfParam,
                                                   Optional<bool> isCascadingUse);
    
    void lookupNamesIntroducedByInitializerOfStoredPropertyOfAType(
                                                                   PatternBindingInitializer *PBI, Optional<bool> isCascadingUse);
    
    /// An initializer of a global name, or a function-likelocal name.
    void lookupNamesIntroducedByInitializerOfGlobalOrLocal(
                                                           PatternBindingInitializer *PBI, Optional<bool> isCascadingUse);
    
    void lookupNamesIntroducedByFunctionDecl(AbstractFunctionDecl *AFD,
                                             Optional<bool> isCascadingUse);
    
    void lookupNamesIntroducedByMemberFunction(AbstractFunctionDecl *AFD,
                                               bool isCascadingUse);
    
    void lookupNamesIntroducedByPureFunction(AbstractFunctionDecl *AFD,
                                             bool isCascadingUse);
    
    void lookupNamesIntroducedByClosure(AbstractClosureExpr *ACE,
                                        Optional<bool> isCascadingUse);
    
    template <typename NominalTypeDeclOrExtensionDecl>
    void lookupNamesIntroducedByNominalTypeOrExtension(
                                                       NominalTypeDeclOrExtensionDecl *D, Optional<bool> isCascadingUse);
    
    void lookupNamesIntroducedByDefaultArgumentInitializer(
                                                           DefaultArgumentInitializer *I, Optional<bool> isCascadingUse);
    
    void lookupNamesIntroducedByMiscContext(DeclContext *dc,
                                            Optional<bool> isCascadingUse);
    
    void lookForLocalVariablesIn(AbstractFunctionDecl *AFD,
                                 Optional<bool> isCascadingUse);
    void lookForLocalVariablesIn(ClosureExpr *);
    void lookForLocalVariablesIn(SourceFile *);
    
    bool isOutsideBodyOfFunction(const AbstractFunctionDecl *const AFD) const;
    
    void addGenericParametersForContext(DeclContext *dc);
    void addGenericParametersForContext(GenericParamList *);
    
    /// Consume generic parameters
    void addGenericParametersForFunction(AbstractFunctionDecl *AFD);
    
    static GenericParamList *getGenericParams(const DeclContext *const dc);
    
    /// For diagnostic purposes, move aside the unavailables, and put
    /// them back as a last-ditch effort.
    /// Could be cleaner someday with a richer interface to UnqualifiedLookup.
    void setAsideUnavailableResults(size_t firstPossiblyUnavailableResult);
    
    void recordDependencyOnTopLevelName(DeclContext *topLevelContext,
                                        DeclName name, bool isCascadingUse);
    
    void addImportedResults(DeclContext *const dc);
    
    void addNamesKnownToDebugClient(DeclContext *dc);
    
    void addUnavailableInnerResults();
    
    void lookForAModuleWithTheGivenName(DeclContext *const dc);
    
#pragma mark common helper declarations
    static NLOptions
    computeBaseNLOptions(const UnqualifiedLookup::Options options,
                         const bool isOriginallyTypeLookup);

    Optional<bool> getInitialIsCascadingUse() const {
      return options.contains(Flags::KnownPrivate) ? Optional<bool>(false)
                                                   : None;
    }

    static bool resolveIsCascadingUse(const DeclContext *const dc,
                                      Optional<bool> isCascadingUse,
                                      bool onlyCareAboutFunctionBody) {
      return isCascadingUse.getValueOr(dc->isCascadingContextForLookup(
                                                                       /*functionsAreNonCascading=*/onlyCareAboutFunctionBody));
    }
    
    static bool resolveIsCascadingUse(ContextAndUnresolvedIsCascadingUse x,
                                      bool onlyCareAboutFunctionBody) {
      return resolveIsCascadingUse(x.whereToLook, x.isCascadingUse,
                                   onlyCareAboutFunctionBody);
    }
    
    void findResultsAndSaveUnavailables(
                                        DeclContext *lookupContextForThisContext,
                                        ResultFinderForTypeContext &&resultFinderForTypeContext,
                                        bool isCascadingUse, NLOptions baseNLOptions);
    
  public:
    void dump() const;
    void dumpScopes() const;
    void print(raw_ostream &OS) const;
    
    void dumpResults() const;
    
    bool verifyEqualTo(const UnqualifiedLookupFactory &&, const char *thisLabel,
                       const char *otherLabel) const;
    
    /// Legacy lookup is wrong here; we should NOT find this symbol.
    bool shouldDiffer() const;
    StringRef getSourceFileName() const;

#ifndef NDEBUG
    bool isTargetLookup() const;
    void stopForDebuggingIfStartingTargetLookup(bool isASTScopeLookup) const;
    void stopForDebuggingIfDuringTargetLookup(bool isASTScopeLookup) const;
    void
    stopForDebuggingIfAddingTargetLookupResult(const LookupResultEntry &) const;
    void addedResult(const LookupResultEntry &) const;
#endif
  };

} // namespace

namespace {
  /// Used to gather lookup results
class ASTScopeDeclConsumerForUnqualifiedLookup
    : public AbstractASTScopeDeclConsumer {
  UnqualifiedLookupFactory &factory;

public:
  ASTScopeDeclConsumerForUnqualifiedLookup(UnqualifiedLookupFactory &factory)
      : factory(factory) {}

  virtual ~ASTScopeDeclConsumerForUnqualifiedLookup() = default;

  bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
               NullablePtr<DeclContext> baseDC = nullptr) override;

  /// returns true if finished and new value for isCascadingUse
  bool lookInMembers(NullablePtr<DeclContext> selfDC,
                     DeclContext *const scopeDC, NominalTypeDecl *const nominal,
                     function_ref<bool(Optional<bool>)>) override;

#ifndef NDEBUG
  void startingNextLookupStep() override {
    factory.stopForDebuggingIfDuringTargetLookup(true);
  }
  bool isTargetLookup() const override { return factory.isTargetLookup(); }

  void finishingLookup(std::string msg) const override {
    if (isTargetLookup())
      llvm::errs() << "Finishing lookup: " << msg << "\n";
  }
#endif
  };
} // namespace

#pragma mark UnqualifiedLookupFactory functions

// clang-format off
UnqualifiedLookupFactory::UnqualifiedLookupFactory(
                            DeclName Name,
                            DeclContext *const DC,
                            SourceLoc Loc,
                            Options options,
                            UnqualifiedLookup &lookupToBeCreated)
: UnqualifiedLookupFactory(Name, DC, Loc, options,
    lookupToBeCreated.Results,
    lookupToBeCreated.IndexOfFirstOuterResult)

{}

UnqualifiedLookupFactory::UnqualifiedLookupFactory(
                            DeclName Name,
                            DeclContext *const DC,
                            SourceLoc Loc,
                            Options options,
                            SmallVectorImpl<LookupResultEntry> &Results,
                            size_t &IndexOfFirstOuterResult)
:
  Name(Name),
  DC(DC),
  M(*DC->getParentModule()),
  Ctx(M.getASTContext()),
  Loc(Loc),
  SM(Ctx.SourceMgr),
  DebugClient(M.getDebugClient()),
  options(options),
  isOriginallyTypeLookup(options.contains(Flags::TypeLookup)),
  baseNLOptions(computeBaseNLOptions(options, isOriginallyTypeLookup)),
  #ifdef NDEBUG
  Consumer(Name, Results, isOriginallyTypeLookup),
  #else
  Consumer(this, Name, Results, isOriginallyTypeLookup),
  #endif
  Results(Results),
  IndexOfFirstOuterResult(IndexOfFirstOuterResult)
{}
// clang-format on

void UnqualifiedLookupFactory::performUnqualifiedLookup() {
#ifndef NDEBUG
  ++lookupCounter;
  auto localCounter = lookupCounter;
  (void)localCounter; // for debugging
#endif
  FrontendStatsTracer StatsTracer(Ctx.Stats, "performUnqualifedLookup",
                                  DC->getParentSourceFile());

  const Optional<bool> initialIsCascadingUse = getInitialIsCascadingUse();

  ContextAndUnresolvedIsCascadingUse contextAndIsCascadingUse{
      DC, initialIsCascadingUse};
  const bool crosscheckUnqualifiedLookup =
      Ctx.LangOpts.CrosscheckUnqualifiedLookup;
  if (useASTScopesForLookup()) {
    static bool haveWarned = false;
    if (!haveWarned && Ctx.LangOpts.WarnIfASTScopeLookup) {
      haveWarned = true;
      llvm::errs() << "WARNING: TRYING Scope exclusively\n";
    }
    lookInASTScopes();
  } else {
#ifndef NDEBUG
    stopForDebuggingIfStartingTargetLookup(false);
#endif

    if (Name.isOperator())
      lookupOperatorInDeclContexts(contextAndIsCascadingUse);
    else
      lookupNamesIntroducedBy(contextAndIsCascadingUse);
  }

  if (crosscheckUnqualifiedLookup && useASTScopesForLookupIfEnabled()) {
    ResultsVector results;
    size_t indexOfFirstOuterResult = 0;
    UnqualifiedLookupFactory altLookup(Name, DC, Loc, options, results,
                                       indexOfFirstOuterResult);
    if (!useASTScopesForLookup())
      altLookup.lookInASTScopes();
    else if (Name.isOperator())
      altLookup.lookupOperatorInDeclContexts(contextAndIsCascadingUse);
    else
      altLookup.lookupNamesIntroducedBy(contextAndIsCascadingUse);

    assert(
        verifyEqualTo(std::move(altLookup), "main lookup", "alternate lookup"));
  }
}

void UnqualifiedLookupFactory::lookUpTopLevelNamesInModuleScopeContext(
    DeclContext *DC) {
  // TODO: Does the debugger client care about compound names?
  if (Name.isSimpleName() && !Name.isSpecial() && DebugClient &&
      DebugClient->lookupOverrides(Name.getBaseName(), DC, Loc,
                                   isOriginallyTypeLookup, Results))
    return;

  addImportedResults(DC);
  addNamesKnownToDebugClient(DC);
  if (Results.empty()) {
    // If we still haven't found anything, but we do have some
    // declarations that are "unavailable in the current Swift", drop
    // those in.
    addUnavailableInnerResults();
    if (Results.empty())
      lookForAModuleWithTheGivenName(DC);
  }
  recordCompletionOfAScope();
}

bool UnqualifiedLookupFactory::useASTScopesForLookup() const {
  return Ctx.LangOpts.EnableASTScopeLookup && useASTScopesForLookupIfEnabled();
}

bool UnqualifiedLookupFactory::useASTScopesForLookupIfEnabled() const {
  if (!Loc.isValid())
    return false;
  const auto *const SF = DC->getParentSourceFile();
  return SF && SF->isSuitableForASTScopes();
}

#pragma mark context-based lookup definitions

void UnqualifiedLookupFactory::lookupOperatorInDeclContexts(
    const ContextAndUnresolvedIsCascadingUse contextAndUseArg) {
  ContextAndResolvedIsCascadingUse contextAndResolvedIsCascadingUse{
      // Operators are global
      contextAndUseArg.whereToLook->getModuleScopeContext(),
      resolveIsCascadingUse(contextAndUseArg,
                            /*onlyCareAboutFunctionBody*/ true)};
  lookupInModuleScopeContext(contextAndResolvedIsCascadingUse.DC,
                             contextAndResolvedIsCascadingUse.isCascadingUse);
}

// TODO: Unify with LookupVisibleDecls.cpp::lookupVisibleDeclsImpl
void UnqualifiedLookupFactory::lookupNamesIntroducedBy(
    const ContextAndUnresolvedIsCascadingUse contextAndIsCascadingUseArg) {
#ifndef NDEBUG
  stopForDebuggingIfDuringTargetLookup(false);
#endif
  DeclContext *const dc = contextAndIsCascadingUseArg.whereToLook;
  const auto isCascadingUseSoFar = contextAndIsCascadingUseArg.isCascadingUse;
  if (dc->isModuleScopeContext())
    lookupInModuleScopeContext(dc, isCascadingUseSoFar);
  else if (auto *PBI = dyn_cast<PatternBindingInitializer>(dc))
    lookupNamesIntroducedByPatternBindingInitializer(PBI, isCascadingUseSoFar);
  else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(dc))
    lookupNamesIntroducedByFunctionDecl(AFD, isCascadingUseSoFar);
  else if (auto *ACE = dyn_cast<AbstractClosureExpr>(dc))
    lookupNamesIntroducedByClosure(ACE, isCascadingUseSoFar);
  else if (auto *ED = dyn_cast<ExtensionDecl>(dc))
    lookupNamesIntroducedByNominalTypeOrExtension(ED, isCascadingUseSoFar);
  else if (auto *ND = dyn_cast<NominalTypeDecl>(dc))
    lookupNamesIntroducedByNominalTypeOrExtension(ND, isCascadingUseSoFar);
  else if (auto I = dyn_cast<DefaultArgumentInitializer>(dc))
    lookupNamesIntroducedByDefaultArgumentInitializer(I, isCascadingUseSoFar);
  else
    lookupNamesIntroducedByMiscContext(dc, isCascadingUseSoFar);
}

void UnqualifiedLookupFactory::lookupInModuleScopeContext(
    DeclContext *dc, Optional<bool> isCascadingUse) {
  if (auto SF = dyn_cast<SourceFile>(dc)) {
    resultsSizeBeforeLocalsPass = Results.size();
    lookForLocalVariablesIn(SF);
  }
  ifNotDoneYet([&] {
    // If no result has been found yet, the dependency must be on a top-level
    // name, since up to now, the search has been for non-top-level names.
    recordDependencyOnTopLevelName(dc, Name, isCascadingUse.getValueOr(true));
    lookUpTopLevelNamesInModuleScopeContext(dc);
  });
}

void UnqualifiedLookupFactory::lookupNamesIntroducedByPatternBindingInitializer(
    PatternBindingInitializer *PBI, Optional<bool> isCascadingUse) {
  // Lazy variable initializer contexts have a 'self' parameter for
  // instance member lookup.
  if (auto *selfParam = PBI->getImplicitSelfDecl())
    lookupNamesIntroducedByLazyVariableInitializer(PBI, selfParam,
                                                   isCascadingUse);
  else if (PBI->getParent()->isTypeContext())
    lookupNamesIntroducedByInitializerOfStoredPropertyOfAType(PBI,
                                                              isCascadingUse);
  else
    lookupNamesIntroducedByInitializerOfGlobalOrLocal(PBI, isCascadingUse);
}

  void UnqualifiedLookupFactory::lookupNamesIntroducedByLazyVariableInitializer(
      PatternBindingInitializer *PBI, ParamDecl *selfParam,
      Optional<bool> isCascadingUse) {
    Consumer.foundDecl(selfParam, DeclVisibilityKind::FunctionParameter);
    ifNotDoneYet([&] {
      DeclContext *const patternContainer = PBI->getParent();
      // clang-format off
    finishLookingInContext(
      AddGenericParameters::Yes,
      patternContainer,
      ResultFinderForTypeContext(this, PBI, patternContainer),
      resolveIsCascadingUse(PBI, isCascadingUse,
                           /*onlyCareAboutFunctionBody=*/false));
      // clang-format on
    });
}

void UnqualifiedLookupFactory::
    lookupNamesIntroducedByInitializerOfStoredPropertyOfAType(
        PatternBindingInitializer *PBI, Optional<bool> isCascadingUse) {
  // Initializers for stored properties of types perform static
  // lookup into the surrounding context.
  DeclContext *const storedPropertyContainer = PBI->getParent();
  // clang-format off
  finishLookingInContext(
    AddGenericParameters::Yes,
    storedPropertyContainer,
    ResultFinderForTypeContext(
      this, storedPropertyContainer, storedPropertyContainer),
    resolveIsCascadingUse(storedPropertyContainer, None,
                          /*onlyCareAboutFunctionBody=*/false));
  // clang-format on
}

void UnqualifiedLookupFactory::
    lookupNamesIntroducedByInitializerOfGlobalOrLocal(
        PatternBindingInitializer *PBI, Optional<bool> isCascadingUse) {
  // There's not much to find here, we'll keep going up to a parent
  // context.
  // clang-format off
  finishLookingInContext(
                         AddGenericParameters::Yes,
                         PBI,
                         None, // not looking in the partic type
                         resolveIsCascadingUse(PBI, isCascadingUse,
                                               /*onlyCareAboutFunctionBody=*/false));
  // clang-format on
}

void UnqualifiedLookupFactory::lookupNamesIntroducedByFunctionDecl(
    AbstractFunctionDecl *AFD, Optional<bool> isCascadingUseArg) {

  // DOUG: how does this differ from isOutsideBodyOfFunction below?
  const bool isCascadingUse =
      AFD->isCascadingContextForLookup(false) &&
      (isCascadingUseArg.getValueOr(
          Loc.isInvalid() || AFD->getBodySourceRange().isInvalid() ||
          !SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc)));

  if (AFD->getDeclContext()->isTypeContext())
    lookupNamesIntroducedByMemberFunction(AFD, isCascadingUse);
  else
    lookupNamesIntroducedByPureFunction(AFD, isCascadingUse);
}

void UnqualifiedLookupFactory::lookupNamesIntroducedByMemberFunction(
    AbstractFunctionDecl *AFD, bool isCascadingUse) {
  lookForLocalVariablesIn(AFD, isCascadingUse);
  ifNotDoneYet(
      [&] {
        // If we're inside a function context, we're about to move to
        // the parent DC, so we have to check the function's generic
        // parameters first.
        // Cannot start here in finishLookingInContext because AFD's
        // getOuterParameters may be null even when AFD's parent has generics.
        addGenericParametersForFunction(AFD);
      },
      [&] {
        DeclContext *const fnDeclContext = AFD->getDeclContext();
        // If we're not in the body of the function (for example, we
        // might be type checking a default argument expression and
        // performing name lookup from there), the base declaration
        // is the nominal type, not 'self'.
        DeclContext *const BaseDC =
            isOutsideBodyOfFunction(AFD) ? fnDeclContext : AFD;
        // If we are inside of a method, check to see if there are any ivars in
        // scope, and if so, whether this is a reference to one of them.
        // FIXME: We should persist this information between lookups.
        // clang-format off
      finishLookingInContext(
        AddGenericParameters::Yes,
        AFD->getParent(),
        ResultFinderForTypeContext(this, BaseDC, fnDeclContext),
        isCascadingUse);
        // clang-format on
      });
}

void UnqualifiedLookupFactory::lookupNamesIntroducedByPureFunction(
    AbstractFunctionDecl *AFD, bool isCascadingUse) {
  lookForLocalVariablesIn(AFD, isCascadingUse);
  ifNotDoneYet([&] {
    // clang-format off
    finishLookingInContext(
                           AddGenericParameters::Yes,
                           AFD,
                           None,
                           isCascadingUse);
  });
}


void UnqualifiedLookupFactory::lookupNamesIntroducedByClosure(
    AbstractClosureExpr *ACE, Optional<bool> isCascadingUse) {
  if (auto *CE = dyn_cast<ClosureExpr>(ACE))
    lookForLocalVariablesIn(CE);
  ifNotDoneYet([&] {
    // clang-format off
    finishLookingInContext(
      AddGenericParameters::Yes,
      ACE,
      None,
      resolveIsCascadingUse(ACE, isCascadingUse,
                           /*onlyCareAboutFunctionBody=*/false));
    // clang-format on
  });
}

template <typename NominalTypeDeclOrExtensionDecl>
void UnqualifiedLookupFactory::lookupNamesIntroducedByNominalTypeOrExtension(
    NominalTypeDeclOrExtensionDecl *D, Optional<bool> isCascadingUse) {
  // clang-format off
  finishLookingInContext(
    AddGenericParameters::Yes,
    D,
    shouldLookupMembers(D, Loc)
    ? Optional<ResultFinderForTypeContext>(
                ResultFinderForTypeContext(this, D, D))
    : None,
    resolveIsCascadingUse(D, isCascadingUse,
                          /*onlyCareAboutFunctionBody=*/false));

  // clang-format on
}

void UnqualifiedLookupFactory::
    lookupNamesIntroducedByDefaultArgumentInitializer(
        DefaultArgumentInitializer *I, Optional<bool> isCascadingUse) {
  // In a default argument, skip immediately out of both the
  // initializer and the function.
  finishLookingInContext(AddGenericParameters::No, I->getParent(), None, false);
}

void UnqualifiedLookupFactory::lookupNamesIntroducedByMiscContext(
    DeclContext *dc, Optional<bool> isCascadingUse) {
  // clang-format off
  assert(isa<TopLevelCodeDecl>(dc) ||
         isa<Initializer>(dc) ||
         isa<TypeAliasDecl>(dc) ||
         isa<SubscriptDecl>(dc) ||
         isa<EnumElementDecl>(dc));
  finishLookingInContext(
    AddGenericParameters::Yes,
    dc,
    None,
    resolveIsCascadingUse(DC, isCascadingUse,
                          /*onlyCareAboutFunctionBody=*/false));
  // clang-format on
}


void UnqualifiedLookupFactory::finishLookingInContext(
       const AddGenericParameters addGenericParameters,
       DeclContext *const lookupContextForThisContext,
       Optional<ResultFinderForTypeContext> &&resultFinderForTypeContext,
       const Optional<bool> isCascadingUse) {
#ifndef NDEBUG
  stopForDebuggingIfDuringTargetLookup(false);
#endif
  // When a generic has the same name as a member, Swift prioritizes the generic
  // because the member could still be named by qualifying it. But there is no
  // corresponding way to qualify a generic parameter.
  // So, look for generics first.
  if (addGenericParameters == AddGenericParameters::Yes)
    addGenericParametersForContext(lookupContextForThisContext);
  
  ifNotDoneYet(
    [&] {
      if (resultFinderForTypeContext)
        findResultsAndSaveUnavailables(lookupContextForThisContext,
                                      std::move(*resultFinderForTypeContext),
                                      *isCascadingUse, baseNLOptions);
    },
    // Recurse into the next context.
    [&] {
      lookupNamesIntroducedBy(ContextAndUnresolvedIsCascadingUse{
        lookupContextForThisContext->getParentForLookup(), isCascadingUse});
    });
}


void UnqualifiedLookupFactory::lookForLocalVariablesIn(
    AbstractFunctionDecl *AFD, Optional<bool> isCascadingUse) {
  // Look for local variables; normally, the parser resolves these
  // for us, but it can't do the right thing inside local types.
  // FIXME: when we can parse and typecheck the function body partially
  // for code completion, AFD->getBody() check can be removed.

  if (Loc.isInvalid() || AFD->getBodySourceRange().isInvalid() ||
      !SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc) ||
      !AFD->getBody()) {
    return;
  }

  namelookup::FindLocalVal localVal(SM, Loc, Consumer);
  localVal.visit(AFD->getBody());

  ifNotDoneYet([&] {
    if (auto *P = AFD->getImplicitSelfDecl())
      localVal.checkValueDecl(P, DeclVisibilityKind::FunctionParameter);
    localVal.checkParameterList(AFD->getParameters());
  });
}

void UnqualifiedLookupFactory::lookForLocalVariablesIn(ClosureExpr *CE) {
  // Look for local variables; normally, the parser resolves these
  // for us, but it can't do the right thing inside local types.
  if (Loc.isInvalid())
    return;
  namelookup::FindLocalVal localVal(SM, Loc, Consumer);
  if (auto body = CE->getBody())
    localVal.visit(body);
  ifNotDoneYet([&] {
    if (auto params = CE->getParameters())
      localVal.checkParameterList(params);
  });
}

void UnqualifiedLookupFactory::lookForLocalVariablesIn(SourceFile *SF) {
  if (Loc.isInvalid())
    return;
  // Look for local variables in top-level code; normally, the parser
  // resolves these for us, but it can't do the right thing for
  // local types.
  namelookup::FindLocalVal localVal(SM, Loc, Consumer);
  localVal.checkSourceFile(*SF);
}

bool UnqualifiedLookupFactory::isOutsideBodyOfFunction(
    const AbstractFunctionDecl *const AFD) const {
  return !AFD->isImplicit() && Loc.isValid() &&
         AFD->getBodySourceRange().isValid() &&
         !SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc);
}

GenericParamList *
UnqualifiedLookupFactory::getGenericParams(const DeclContext *const dc) {
  if (auto nominal = dyn_cast<NominalTypeDecl>(dc))
    return nominal->getGenericParams();
  if (auto ext = dyn_cast<ExtensionDecl>(dc))
    return ext->getGenericParams();
  if (auto subscript = dyn_cast<SubscriptDecl>(dc))
    return subscript->getGenericParams();
  if (auto func = dyn_cast<AbstractFunctionDecl>(dc))
    return func->getGenericParams();
  return nullptr;
}

void UnqualifiedLookupFactory::addGenericParametersForContext(
    DeclContext *dc) {
  // Generics can be nested, so visit the generic list, innermost first.
  // Cannot use DeclContext::forEachGenericContext because this code breaks out
  // if it finds a match and isFirstResultEnough()
  addGenericParametersForContext(getGenericParams(dc));
}

void UnqualifiedLookupFactory::addGenericParametersForContext(
    GenericParamList *dcGenericParams) {
  if (!dcGenericParams)
    return;
  namelookup::FindLocalVal localVal(SM, Loc, Consumer);
  localVal.checkGenericParams(dcGenericParams);
  ifNotDoneYet([&] {
    addGenericParametersForContext(
        dcGenericParams->getOuterParameters());
  });
}

void UnqualifiedLookupFactory::addGenericParametersForFunction(
    AbstractFunctionDecl *AFD) {
  GenericParamList *GenericParams = AFD->getGenericParams();
  if (GenericParams) {
    namelookup::FindLocalVal localVal(SM, Loc, Consumer);
    localVal.checkGenericParams(GenericParams);
  }
}

void UnqualifiedLookupFactory::ResultFinderForTypeContext::findResults(
    const DeclName &Name, bool isCascadingUse, NLOptions baseNLOptions,
    DeclContext *contextForLookup,
    SmallVectorImpl<LookupResultEntry> &results) const {
  // An optimization:
  if (selfBounds.empty())
    return;
  const NLOptions options =
      baseNLOptions | (isCascadingUse ? NL_KnownCascadingDependency
                                      : NL_KnownNonCascadingDependency);

  SmallVector<ValueDecl *, 4> Lookup;
  contextForLookup->lookupQualified(selfBounds, Name, options, Lookup);
  for (auto Result : Lookup) {
    results.push_back(LookupResultEntry(whereValueIsMember(Result), Result));
#ifndef NDEBUG
    factory->addedResult(results.back());
#endif
  }
}

// TODO (someday): Instead of adding unavailable entries to Results,
// then later shunting them aside, just put them in the right place
// to begin with.

void UnqualifiedLookupFactory::setAsideUnavailableResults(
    const size_t firstPossiblyUnavailableResult) {
  // An optimization:
  assert(Results.size() >= firstPossiblyUnavailableResult);
  if (Results.size() == firstPossiblyUnavailableResult)
    return;
  // Predicate that determines whether a lookup result should
  // be unavailable except as a last-ditch effort.
  auto unavailableLookupResult = [&](const LookupResultEntry &result) {
    auto &effectiveVersion = Ctx.LangOpts.EffectiveLanguageVersion;
    return result.getValueDecl()->getAttrs().isUnavailableInSwiftVersion(
        effectiveVersion);
  };

  // If all of the results we found are unavailable, keep looking.
  auto begin = Results.begin() + firstPossiblyUnavailableResult;
  if (std::all_of(begin, Results.end(), unavailableLookupResult)) {
    // better to have more structure in results
    UnavailableInnerResults.append(begin, Results.end());
    Results.erase(begin, Results.end());
    return;
  }
  // The debugger may have a different private discriminator
  // in order to support lookup relative to the place where
  // execution is suspended.
  filterForDiscriminator(Results, DebugClient);
}


void UnqualifiedLookupFactory::recordDependencyOnTopLevelName(
    DeclContext *topLevelContext, DeclName name, bool isCascadingUse) {
  recordLookupOfTopLevelName(topLevelContext, Name, isCascadingUse);
  recordedSF = dyn_cast<SourceFile>(topLevelContext);
  recordedIsCascadingUse = isCascadingUse;
}

void UnqualifiedLookupFactory::addImportedResults(DeclContext *const dc) {
  using namespace namelookup;
  SmallVector<ValueDecl *, 8> CurModuleResults;
  auto resolutionKind = isOriginallyTypeLookup ? ResolutionKind::TypesOnly
                                               : ResolutionKind::Overloadable;
  lookupInModule(dc, Name, CurModuleResults, NLKind::UnqualifiedLookup,
                 resolutionKind, dc);

  // Always perform name shadowing for type lookup.
  if (options.contains(Flags::TypeLookup)) {
    removeShadowedDecls(CurModuleResults, dc);
  }

  for (auto VD : CurModuleResults) {
    Results.push_back(LookupResultEntry(VD));
#ifndef NDEBUG
    addedResult(Results.back());
#endif
  }

  filterForDiscriminator(Results, DebugClient);
}

void UnqualifiedLookupFactory::addNamesKnownToDebugClient(DeclContext *dc) {
  if (Name.isSimpleName() && DebugClient)
    DebugClient->lookupAdditions(Name.getBaseName(), dc, Loc,
                                 isOriginallyTypeLookup, Results);
}

void UnqualifiedLookupFactory::addUnavailableInnerResults() {
  Results = std::move(UnavailableInnerResults);
}

void UnqualifiedLookupFactory::lookForAModuleWithTheGivenName(
    DeclContext *const dc) {
  using namespace namelookup;
  if (!Name.isSimpleName() || Name.isSpecial())
    return;

  // Look for a module with the given name.
  if (Name.isSimpleName(M.getName())) {
    Results.push_back(LookupResultEntry(&M));
#ifndef NDEBUG
    addedResult(Results.back());
#endif
    return;
  }
  ModuleDecl *desiredModule = Ctx.getLoadedModule(Name.getBaseIdentifier());
  if (!desiredModule && Name == Ctx.TheBuiltinModule->getName())
    desiredModule = Ctx.TheBuiltinModule;
  if (desiredModule) {
    // Make sure the desired module is actually visible from the current
    // context.
    if (Ctx.getImportCache().isImportedBy(desiredModule, dc)) {
      Results.push_back(LookupResultEntry(desiredModule));
#ifndef NDEBUG
      addedResult(Results.back());
#endif
    }
  }
}

#pragma mark common helper definitions


void UnqualifiedLookupFactory::findResultsAndSaveUnavailables(
       DeclContext *lookupContextForThisContext,
       ResultFinderForTypeContext &&resultFinderForTypeContext,
       bool isCascadingUse, NLOptions baseNLOptions) {
  auto firstPossiblyUnavailableResult = Results.size();
  resultFinderForTypeContext.findResults(Name, isCascadingUse, baseNLOptions,
                                         lookupContextForThisContext, Results);
  setAsideUnavailableResults(firstPossiblyUnavailableResult);
}


NLOptions UnqualifiedLookupFactory::computeBaseNLOptions(
    const UnqualifiedLookup::Options options,
    const bool isOriginallyTypeLookup) {
  NLOptions baseNLOptions = NL_UnqualifiedDefault;
  if (options.contains(Flags::AllowProtocolMembers))
    baseNLOptions |= NL_ProtocolMembers;
  if (isOriginallyTypeLookup)
    baseNLOptions |= NL_OnlyTypes;
  if (options.contains(Flags::IgnoreAccessControl))
    baseNLOptions |= NL_IgnoreAccessControl;
  return baseNLOptions;
}

bool UnqualifiedLookupFactory::isFirstResultEnough()
    const {
  return !Results.empty() && !options.contains(Flags::IncludeOuterResults);
}

void UnqualifiedLookupFactory::recordCompletionOfAScope() {
  // OK to call (NOOP) if there are more inner results and Results is empty
  if (IndexOfFirstOuterResult == 0)
    IndexOfFirstOuterResult = Results.size();
}

UnqualifiedLookupFactory::ResultFinderForTypeContext::
    ResultFinderForTypeContext(UnqualifiedLookupFactory *factory,
                               DeclContext *dynamicContext,
                               DeclContext *staticContext)
    : factory(factory),
      dynamicContext(dynamicContext), staticContext(staticContext),
      selfBounds(findSelfBounds(staticContext)) {}

UnqualifiedLookupFactory::ResultFinderForTypeContext::SelfBounds
UnqualifiedLookupFactory::ResultFinderForTypeContext::findSelfBounds(
    DeclContext *dc) {
  auto nominal = dc->getSelfNominalTypeDecl();
  if (!nominal)
    return {};

  SelfBounds selfBounds;
  selfBounds.push_back(nominal);

  // For a protocol extension, check whether there are additional "Self"
  // constraints that can affect name lookup.
  if (dc->getExtendedProtocolDecl()) {
    auto ext = cast<ExtensionDecl>(dc);
    auto bounds = getSelfBoundsFromWhereClause(ext);
    for (auto bound : bounds.decls)
      selfBounds.push_back(bound);
  }
  return selfBounds;
}

#pragma mark ASTScopeImpl support

void UnqualifiedLookupFactory::lookInASTScopes() {

  ASTScopeDeclConsumerForUnqualifiedLookup consumer(*this);

#ifndef NDEBUG
  stopForDebuggingIfStartingTargetLookup(true);
#endif

  const auto history = ASTScope::unqualifiedLookup(DC->getParentSourceFile(),
                                                   Name, Loc, DC, consumer);

  ifNotDoneYet([&] {
    // Copied from lookupInModuleScopeContext
    // If no result has been found yet, the dependency must be on a top-level
    // name, since up to now, the search has been for non-top-level names.
    auto *const moduleScopeContext = DC->getParentSourceFile();

    const Optional<bool> isCascadingUseAtStartOfLookup =
        !Name.isOperator()
            ? getInitialIsCascadingUse()
            : resolveIsCascadingUse(DC, getInitialIsCascadingUse(),
                                    /*onlyCareAboutFunctionBody*/ true);

    const Optional<bool> isCascadingUseAfterLookup =
        ASTScope::computeIsCascadingUse(history, isCascadingUseAtStartOfLookup);

    recordDependencyOnTopLevelName(moduleScopeContext, Name,
                                   isCascadingUseAfterLookup.getValueOr(true));
    lookUpTopLevelNamesInModuleScopeContext(moduleScopeContext);
  });
}

bool ASTScopeDeclConsumerForUnqualifiedLookup::consume(
    ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
    NullablePtr<DeclContext> baseDC) {
  for (auto *value: values) {
    if (factory.isOriginallyTypeLookup && !isa<TypeDecl>(value))
      continue;
    if (!value->getFullName().matchesRef(factory.Name))
      continue;

    // In order to preserve the behavior of the existing context-based lookup,
    // which finds all results for non-local variables at the top level instead
    // of stopping at the first one, ignore results at the top level that are
    // not local variables. The caller \c lookInASTScopes will
    // then do the appropriate work when the scope lookup fails. In
    // FindLocalVal::visitBraceStmt, it sees PatternBindingDecls, not VarDecls,
    // so a VarDecl at top level would not be found by the context-based lookup.
    if (isa<SourceFile>(value->getDeclContext()) &&
        (vis != DeclVisibilityKind::LocalVariable || isa<VarDecl>(value)))
      return false;

    factory.Results.push_back(LookupResultEntry(value));
#ifndef NDEBUG
    factory.stopForDebuggingIfAddingTargetLookupResult(factory.Results.back());
#endif
  }
  factory.recordCompletionOfAScope();
  return factory.isFirstResultEnough();
}

bool ASTScopeDeclGatherer::consume(ArrayRef<ValueDecl *> valuesArg,
                                   DeclVisibilityKind,
                                   NullablePtr<DeclContext>) {
  for (auto *v: valuesArg)
    values.push_back(v);
  return false;
}

// TODO: in future, migrate this functionality into ASTScopes
bool ASTScopeDeclConsumerForUnqualifiedLookup::lookInMembers(
    NullablePtr<DeclContext> selfDC, DeclContext *const scopeDC,
    NominalTypeDecl *const nominal,
    function_ref<bool(Optional<bool>)> calculateIsCascadingUse) {
  if (selfDC) {
    if (auto *d = selfDC.get()->getAsDecl()) {
      if (auto *afd = dyn_cast<AbstractFunctionDecl>(d))
        assert(!factory.isOutsideBodyOfFunction(afd) && "Should be inside");
    }
  }
  auto resultFinder = UnqualifiedLookupFactory::ResultFinderForTypeContext(
      &factory, selfDC ? selfDC.get() : scopeDC, scopeDC);
  const bool isCascadingUse =
      calculateIsCascadingUse(factory.getInitialIsCascadingUse());
  factory.findResultsAndSaveUnavailables(scopeDC, std::move(resultFinder),
                                         isCascadingUse, factory.baseNLOptions);
  factory.recordCompletionOfAScope();
  return factory.isFirstResultEnough();
}


#pragma mark UnqualifiedLookup functions

// clang-format off
UnqualifiedLookup::UnqualifiedLookup(DeclName Name,
                                     DeclContext *const DC,
                                     SourceLoc Loc,
                                     Options options)
    // clang-format on
    : IndexOfFirstOuterResult(0) {

  auto *stats = DC->getASTContext().Stats;
  if (stats)
    stats->getFrontendCounters().NumUnqualifiedLookup++;

  UnqualifiedLookupFactory factory(Name, DC, Loc, options, *this);
  factory.performUnqualifiedLookup();
}

TypeDecl *UnqualifiedLookup::getSingleTypeResult() const {
  if (Results.size() != 1)
    return nullptr;
  return dyn_cast<TypeDecl>(Results.back().getValueDecl());
}

#pragma mark debugging
#ifndef NDEBUG
void UnqualifiedLookupFactory::InstrumentedNamedDeclConsumer::anchor() {}
#endif

void UnqualifiedLookupFactory::ResultFinderForTypeContext::dump() const {
  (void)factory;
  llvm::errs() << "dynamicContext: ";
  dynamicContext->dumpContext();
  llvm::errs() << "staticContext: ";
  staticContext->dumpContext();
  llvm::errs() << "selfBounds: ";
  for (const auto *D : selfBounds)
    D->dump(llvm::errs(), 1);
  llvm::errs() << "\n";
}

void UnqualifiedLookupFactory::dumpScopes() const {
  llvm::errs() << "\n\nScopes:\n";
  DC->getParentSourceFile()->getScope().print(llvm::errs());
  llvm::errs() << "\n";
}

void UnqualifiedLookupFactory::dump() const { print(llvm::errs()); }

void UnqualifiedLookupFactory::dumpResults() const {
  auto &out = llvm::errs();
  for (auto i : indices(Results)) {
    if (i == resultsSizeBeforeLocalsPass)
      out << "============== next pass ============\n";
    out << i << ": ";
    Results[i].print(out);
    out << "\n";
  }
  if (resultsSizeBeforeLocalsPass == Results.size())
    out << "============== next pass ============\n";
  if (resultsSizeBeforeLocalsPass == ~0u)
    out << "never tried locals\n\n";
}

void UnqualifiedLookupFactory::print(raw_ostream &OS) const {
  OS << "Look up";
#ifndef NDEBUG
  OS << " (" << lookupCounter << ")";
#endif
  OS << " '" << Name << "' at: ";
  Loc.print(OS, DC->getASTContext().SourceMgr);
  OS << "\nStarting in: ";
  DC->printContext(OS);
  OS << "\n";
}

#pragma mark debugging: output utilities for grepping

static void writeLine(std::string s) {
  llvm::errs() << "\n+-+-+-+-  " << s << "\n";
}

StringRef UnqualifiedLookupFactory::getSourceFileName() const {
  return DC->getParentSourceFile()->getFilename();
}

static void writeFirstLine(const UnqualifiedLookupFactory &ul, StringRef s) {
  std::string line =
      std::string("In file: ") + ul.getSourceFileName().str() + ", " + s.str();
  writeLine(line);
}

static void writeInconsistent(const UnqualifiedLookupFactory &me,
                              const char *thisLabel,
                              const UnqualifiedLookupFactory &other,
                              const char *otherLabel, StringRef s) {
  writeFirstLine(me, s);
  other.dump();
  llvm::errs() << "\n" << thisLabel << " Results:\n";
  me.dumpResults();
  llvm::errs() << "\n" << otherLabel << " Results:\n";
  other.dumpResults();
  me.dumpScopes();
}

#pragma mark comparing results

bool UnqualifiedLookupFactory::verifyEqualTo(
    const UnqualifiedLookupFactory &&other, const char *thisLabel,
    const char *otherLabel) const {
  if (shouldDiffer()) {
     return true;
  }
  auto writeErr = [&](StringRef s) {
    writeInconsistent(*this, thisLabel, other, otherLabel, s);
  };
  if (Results.size() != other.Results.size()) {
    const bool tooMany = Results.size() < other.Results.size();
    writeErr(std::string(tooMany ? "Found too many: " : "Found too few: ") +
             std::to_string(Results.size()) + " vs " +
             std::to_string(other.Results.size()));
    if (tooMany)
      assert(false && "ASTScopeImpl found too many");
    else
      assert(false && "ASTScopeImpl found too few");
  }
  for (size_t i : indices(Results)) {
    const auto &e = Results[i];
    const auto &oe = other.Results[i];
    if (e.getValueDecl() != oe.getValueDecl()) {
      // print_ast_tc_function_bodies.swift generic from subscript vs get fn
      std::string a; llvm::raw_string_ostream as(a);
      std::string b; llvm::raw_string_ostream bs(b);
      e.getValueDecl()->print(as);
      oe.getValueDecl()->print(bs);
      if (a == b)
        llvm::errs() << "ValueDecls differ but print same\n";
      else {
        writeErr(std::string( "ValueDecls differ at ") + std::to_string(i));
        assert(false && "ASTScopeImpl found different Decl");
      }
    }
    if (e.getDeclContext() != oe.getDeclContext()) {
      writeErr((std::string("Contexts differ at ")) + std::to_string(i));
      assert(false && "ASTScopeImpl found different context");
    }
    // unsigned printContext(llvm::raw_ostream &OS, unsigned indent = 0,
    // bool onlyAPartialLine = false) const;
  }
  if (IndexOfFirstOuterResult != other.IndexOfFirstOuterResult) {
    writeErr( std::string("IndexOfFirstOuterResult differs, should be: ")
             + std::to_string(IndexOfFirstOuterResult)
             + std::string( ", is: ")
             + std::to_string(other.IndexOfFirstOuterResult));
    assert(false && "ASTScopeImpl IndexOfFirstOuterResult differs");
  }
  if (recordedSF != other.recordedSF) {
    writeErr(std::string("recordedSF differs: shouldBe: ") +
             (recordedSF ? recordedSF->getFilename().str()
                         : std::string("<no name>")) +
             std::string(" is: ") +
             (other.recordedSF ? other.recordedSF->getFilename().str()
                               : std::string("<no name>")));
    assert(false && "ASTScopeImpl recordedSF differs");
  }
  if (recordedSF && recordedIsCascadingUse != other.recordedIsCascadingUse) {
    writeErr(std::string("recordedIsCascadingUse differs: shouldBe: ") +
             std::to_string(recordedIsCascadingUse) + std::string(" is: ") +
             std::to_string(other.recordedIsCascadingUse));
    assert(false && "ASTScopeImpl recordedIsCascadingUse differs");
  }
  return true;
}

bool UnqualifiedLookupFactory::shouldDiffer() const {
  auto *SF = dyn_cast<SourceFile>(DC->getModuleScopeContext());
  if (!SF)
    return false;
  
  static std::vector<const char*> testsThatShouldDiffer {
    "swift/test/Constraints/diagnostics.swift",
    "swift/test/Constraints/enum_cases.swift",
    "swift/test/Constraints/rdar39401774.swift",
    "swift/test/Constraints/rdar39401774-astscope.swift",
    "swift/test/Interpreter/repl.swift",
    "swift/test/Sema/diag_defer_captures.swift",
    "swift/test/Sema/diag_use_before_declaration.swift",
    "swift/test/SourceKit/CodeFormat/indent-closure.swift",
    "swift/test/TypeCoercion/overload_noncall.swift",
    "swift/test/expr/capture/nested_class.swift",
    "swift/test/expr/capture/order.swift",
    "swift/test/NameBinding/name-binding.swift"
  };
  StringRef fileName = SF->getFilename();
  return llvm::any_of(testsThatShouldDiffer, [&](const char *testFile) {
    return fileName.endswith(testFile);
  });
}

#pragma mark breakpointing
#ifndef NDEBUG

bool UnqualifiedLookupFactory::isTargetLookup() const {
  return lookupCounter == targetLookup;
}

void UnqualifiedLookupFactory::stopForDebuggingIfStartingTargetLookup(
    const bool isASTScopeLookup) const {
  if (!isTargetLookup())
    return;
  if (isASTScopeLookup)
    llvm::errs() << "starting target ASTScopeImpl lookup\n";
  else
    llvm::errs() << "starting target context-based lookup\n";
}

void UnqualifiedLookupFactory::stopForDebuggingIfDuringTargetLookup(
    const bool isASTScopeLookup) const {
  if (!isTargetLookup())
    return;
  if (isASTScopeLookup)
    llvm::errs() << "during target ASTScopeImpl lookup\n";
  else
    llvm::errs() << "during target context-based lookup\n";
}

void UnqualifiedLookupFactory::stopForDebuggingIfAddingTargetLookupResult(
    const LookupResultEntry &e) const {
  if (!isTargetLookup())
    return;
  auto &out = llvm::errs();
  out << "\nresult for Target lookup:\n";
  e.print(out);
  out << "\n";
}

void UnqualifiedLookupFactory::addedResult(const LookupResultEntry &e) const {
  stopForDebuggingIfAddingTargetLookupResult(e);
}

unsigned UnqualifiedLookupFactory::lookupCounter = 0;

// set to ~0 when not debugging
const unsigned UnqualifiedLookupFactory::targetLookup = ~0;

#endif // NDEBUG
