//===--- CompletionLookup.cpp ---------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 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/IDE/CompletionLookup.h"
#include "CodeCompletionResultBuilder.h"
#include "ExprContextAnalysis.h"
#include "swift/AST/ConformanceLookup.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/SourceFile.h"
#include "swift/Basic/Assertions.h"
#include "swift/IDE/CodeCompletionStringPrinter.h"

using namespace swift;
using namespace swift::ide;

namespace {

static bool SwiftKeyPathFilter(ValueDecl *decl, DeclVisibilityKind) {
  switch (decl->getKind()) {
  case DeclKind::Var:
  case DeclKind::Subscript:
    return true;
  default:
    return false;
  }
}

static bool isTopLevelSubcontext(const DeclContext *DC) {
  for (; DC && DC->isLocalContext(); DC = DC->getParent()) {
    switch (DC->getContextKind()) {
    case DeclContextKind::TopLevelCodeDecl:
      return true;
    case DeclContextKind::AbstractFunctionDecl:
    case DeclContextKind::SubscriptDecl:
    case DeclContextKind::EnumElementDecl:
      return false;
    default:
      continue;
    }
  }
  return false;
}

static KnownProtocolKind
protocolForLiteralKind(CodeCompletionLiteralKind kind) {
  switch (kind) {
  case CodeCompletionLiteralKind::ArrayLiteral:
    return KnownProtocolKind::ExpressibleByArrayLiteral;
  case CodeCompletionLiteralKind::BooleanLiteral:
    return KnownProtocolKind::ExpressibleByBooleanLiteral;
  case CodeCompletionLiteralKind::ColorLiteral:
    return KnownProtocolKind::ExpressibleByColorLiteral;
  case CodeCompletionLiteralKind::ImageLiteral:
    return KnownProtocolKind::ExpressibleByImageLiteral;
  case CodeCompletionLiteralKind::DictionaryLiteral:
    return KnownProtocolKind::ExpressibleByDictionaryLiteral;
  case CodeCompletionLiteralKind::IntegerLiteral:
    return KnownProtocolKind::ExpressibleByIntegerLiteral;
  case CodeCompletionLiteralKind::NilLiteral:
    return KnownProtocolKind::ExpressibleByNilLiteral;
  case CodeCompletionLiteralKind::StringLiteral:
    return KnownProtocolKind::ExpressibleByUnicodeScalarLiteral;
  case CodeCompletionLiteralKind::Tuple:
    llvm_unreachable("no such protocol kind");
  }

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

static Type defaultTypeLiteralKind(CodeCompletionLiteralKind kind,
                                   ASTContext &Ctx) {
  switch (kind) {
  case CodeCompletionLiteralKind::BooleanLiteral:
    return Ctx.getBoolType();
  case CodeCompletionLiteralKind::IntegerLiteral:
    return Ctx.getIntType();
  case CodeCompletionLiteralKind::StringLiteral:
    return Ctx.getStringType();
  case CodeCompletionLiteralKind::ArrayLiteral:
    if (!Ctx.getArrayDecl())
      return Type();
    return Ctx.getArrayDecl()->getDeclaredInterfaceType();
  case CodeCompletionLiteralKind::DictionaryLiteral:
    if (!Ctx.getDictionaryDecl())
      return Type();
    return Ctx.getDictionaryDecl()->getDeclaredInterfaceType();
  case CodeCompletionLiteralKind::NilLiteral:
  case CodeCompletionLiteralKind::ColorLiteral:
  case CodeCompletionLiteralKind::ImageLiteral:
  case CodeCompletionLiteralKind::Tuple:
    return Type();
  }

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

/// Whether the provided type has a single argument (not including defaulted
/// arguments) that is of type () -> ().
static bool hasTrivialTrailingClosure(const ValueDecl *VD, Type type) {
  if (!VD->hasParameterList())
    return false;

  auto *funcType = type->getAs<AnyFunctionType>();
  if (!funcType)
    return false;

  ParameterListInfo paramInfo(funcType->getParams(), VD,
                              /*skipCurriedSelf*/ VD->hasCurriedSelf());

  if (paramInfo.size() - paramInfo.numNonDefaultedParameters() == 1) {
    auto param = funcType->getParams().back();
    if (!param.isAutoClosure()) {
      if (auto Fn = param.getOldType()->getAs<AnyFunctionType>()) {
        return Fn->getParams().empty() && Fn->getResult()->isVoid();
      }
    }
  }

  return false;
}
} // end anonymous namespace

bool swift::ide::DefaultFilter(ValueDecl *VD, DeclVisibilityKind Kind,
                               DynamicLookupInfo dynamicLookupInfo) {
  return true;
}

bool swift::ide::KeyPathFilter(ValueDecl *decl, DeclVisibilityKind,
                               DynamicLookupInfo dynamicLookupInfo) {
  return isa<TypeDecl>(decl) ||
         (isa<VarDecl>(decl) && decl->getDeclContext()->isTypeContext());
}

bool swift::ide::MacroFilter(ValueDecl *decl, DeclVisibilityKind,
                             DynamicLookupInfo dynamicLookupInfo) {
  return isa<MacroDecl>(decl);
}

bool swift::ide::isCodeCompletionAtTopLevel(const DeclContext *DC) {
  if (DC->isModuleScopeContext())
    return true;

  // CC token at top-level is parsed as an expression. If the only element
  // body of the TopLevelCodeDecl is a CodeCompletionExpr without a base
  // expression, the user might be writing a top-level declaration.
  if (const TopLevelCodeDecl *TLCD = dyn_cast<const TopLevelCodeDecl>(DC)) {
    auto body = TLCD->getBody();
    if (!body || body->empty())
      return true;
    if (body->getElements().size() > 1)
      return false;
    auto expr = body->getFirstElement().dyn_cast<Expr *>();
    if (!expr)
      return false;
    if (CodeCompletionExpr *CCExpr = dyn_cast<CodeCompletionExpr>(expr)) {
      if (CCExpr->getBase() == nullptr)
        return true;
    }
  }

  return false;
}

bool swift::ide::isCompletionDeclContextLocalContext(DeclContext *DC) {
  if (!DC->isLocalContext())
    return false;
  if (isCodeCompletionAtTopLevel(DC))
    return false;
  return true;
}

/// Returns \c true if \p DC can handles async call.
bool swift::ide::canDeclContextHandleAsync(const DeclContext *DC) {
  if (auto *func = dyn_cast<AbstractFunctionDecl>(DC))
    return func->isAsyncContext();

  if (auto *closure = dyn_cast<ClosureExpr>(DC)) {
    // See if the closure has 'async' function type.
    if (auto closureType = closure->getType())
      if (auto fnType = closureType->getAs<AnyFunctionType>())
        if (fnType->isAsync())
          return true;

    // If the closure doesn't contain any async call in the body, closure itself
    // doesn't have 'async' type even if 'async' closure is expected.
    //   func foo(fn: () async -> Void)
    //   foo { <HERE> }
    // In this case, the closure is wrapped with a 'FunctionConversionExpr'
    // which has 'async' function type.
    struct AsyncClosureChecker : public ASTWalker {
      const ClosureExpr *Target;
      bool Result = false;

      /// Walk everything in a macro.
      MacroWalking getMacroWalkingBehavior() const override {
        return MacroWalking::ArgumentsAndExpansion;
      }

      AsyncClosureChecker(const ClosureExpr *Target) : Target(Target) {}

      PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
        if (E == Target)
          return Action::SkipNode(E);

        if (auto conversionExpr = dyn_cast<FunctionConversionExpr>(E)) {
          if (conversionExpr->getSubExpr() == Target) {
            if (conversionExpr->getType()->is<AnyFunctionType>() &&
                conversionExpr->getType()->castTo<AnyFunctionType>()->isAsync())
              Result = true;
            return Action::SkipNode(E);
          }
        }
        return Action::Continue(E);
      }
    } checker(closure);
    closure->getParent()->walkContext(checker);
    return checker.Result;
  }

  return false;
}

/// Return \c true if the completion happens at top-level of a library file.
bool swift::ide::isCodeCompletionAtTopLevelOfLibraryFile(
    const DeclContext *DC) {
  if (DC->getParentSourceFile()->isScriptMode())
    return false;
  return isCodeCompletionAtTopLevel(DC);
}

// MARK: - CompletionLookup

void CompletionLookup::foundFunction(const AbstractFunctionDecl *AFD) {
  FoundFunctionCalls = true;
  const DeclName Name = AFD->getName();
  auto ArgNames = Name.getArgumentNames();
  if (ArgNames.empty())
    return;
  if (ArgNames[0].empty())
    FoundFunctionsWithoutFirstKeyword = true;
}

void CompletionLookup::foundFunction(const AnyFunctionType *AFT) {
  FoundFunctionCalls = true;
  auto Params = AFT->getParams();
  if (Params.empty())
    return;
  if (Params.size() == 1 && !Params[0].hasLabel()) {
    FoundFunctionsWithoutFirstKeyword = true;
    return;
  }
  if (!Params[0].hasLabel())
    FoundFunctionsWithoutFirstKeyword = true;
}

bool CompletionLookup::canBeUsedAsRequirementFirstType(Type selfTy,
                                                       TypeAliasDecl *TAD) {
  if (TAD->hasGenericParamList())
    return false;

  auto T = TAD->getDeclaredInterfaceType();
  auto subMap = selfTy->getContextSubstitutionMap(TAD->getDeclContext());

  return T.subst(subMap)->is<ArchetypeType>();
}

CompletionLookup::CompletionLookup(CodeCompletionResultSink &Sink,
                                   ASTContext &Ctx,
                                   const DeclContext *CurrDeclContext,
                                   CodeCompletionContext *CompletionContext)
    : Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
      CurrModule(CurrDeclContext ? CurrDeclContext->getParentModule()
                                 : nullptr),
      Importer(static_cast<ClangImporter *>(
          CurrDeclContext->getASTContext().getClangModuleLoader())),
      CompletionContext(CompletionContext) {
  // Determine if we are doing code completion inside a static method.
  if (CurrDeclContext) {
    CurrentMethod = CurrDeclContext->getInnermostMethodContext();
    if (auto *FD = dyn_cast_or_null<FuncDecl>(CurrentMethod))
      InsideStaticMethod = FD->isStatic();
    CanCurrDeclContextHandleAsync = canDeclContextHandleAsync(CurrDeclContext);
  }
}

void CompletionLookup::addSubModuleNames(
    std::vector<std::pair<std::string, bool>> &SubModuleNameVisibilityPairs) {
  for (auto &Pair : SubModuleNameVisibilityPairs) {
    CodeCompletionResultBuilder Builder = makeResultBuilder(
        CodeCompletionResultKind::Declaration, SemanticContextKind::None);
    auto *MD = ModuleDecl::createEmpty(Ctx.getIdentifier(Pair.first), Ctx);
    Builder.setAssociatedDecl(MD);
    Builder.addBaseName(MD->getNameStr());
    Builder.addTypeAnnotation("Module");
    if (Pair.second)
      Builder.setContextualNotRecommended(
          ContextualNotRecommendedReason::RedundantImport);
  }
}

void CompletionLookup::collectImportedModules(
    llvm::StringSet<> &directImportedModules,
    llvm::StringSet<> &allImportedModules) {
  SmallVector<ImportedModule, 16> Imported;
  SmallVector<ImportedModule, 16> FurtherImported;
  CurrDeclContext->getParentSourceFile()->getImportedModules(
      Imported, ModuleDecl::getImportFilterLocal());

  for (ImportedModule &imp : Imported)
    directImportedModules.insert(imp.importedModule->getNameStr());

  while (!Imported.empty()) {
    ModuleDecl *MD = Imported.back().importedModule;
    Imported.pop_back();
    if (!allImportedModules.insert(MD->getNameStr()).second)
      continue;
    FurtherImported.clear();
    MD->getImportedModules(FurtherImported,
                           ModuleDecl::ImportFilterKind::Exported);
    Imported.append(FurtherImported.begin(), FurtherImported.end());
  }
}

void CompletionLookup::addModuleName(
    ModuleDecl *MD, std::optional<ContextualNotRecommendedReason> R) {

  // Don't add underscored cross-import overlay modules.
  if (MD->getDeclaringModuleIfCrossImportOverlay())
    return;

  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Declaration, SemanticContextKind::None);
  Builder.setAssociatedDecl(MD);
  auto moduleName = MD->getName();

  // This checks if module aliasing was used. For example, when editing
  // `import ...`, and `-module-alias Foo=Bar` was passed, we want to show
  // Foo as an option to import, instead of Bar (name of the binary), as
  // Foo is the name that should appear in source files.
  auto aliasedName = Ctx.getRealModuleName(
      moduleName, ASTContext::ModuleAliasLookupOption::aliasFromRealName);
  if (aliasedName != moduleName && // check if module aliasing was applied
      !aliasedName.empty()) { // check an alias mapped to the binary name exists
    moduleName = aliasedName; // if so, use the aliased name
  }
  Builder.addBaseName(moduleName.str());
  Builder.addTypeAnnotation("Module");
  if (R)
    Builder.setContextualNotRecommended(*R);
}

void CompletionLookup::addImportModuleNames() {
  SmallVector<Identifier, 0> ModuleNames;
  Ctx.getVisibleTopLevelModuleNames(ModuleNames);

  llvm::StringSet<> directImportedModules;
  llvm::StringSet<> allImportedModules;
  collectImportedModules(directImportedModules, allImportedModules);

  auto mainModuleName = CurrModule->getName();
  for (auto ModuleName : ModuleNames) {
    if (ModuleName == mainModuleName || isHiddenModuleName(ModuleName))
      continue;

    auto *MD = ModuleDecl::createEmpty(ModuleName, Ctx);

    std::optional<ContextualNotRecommendedReason> Reason = std::nullopt;

    // Imported modules are not recommended.
    if (directImportedModules.contains(MD->getNameStr())) {
      Reason = ContextualNotRecommendedReason::RedundantImport;
    } else if (allImportedModules.contains(MD->getNameStr())) {
      Reason = ContextualNotRecommendedReason::RedundantImportIndirect;
    }

    addModuleName(MD, Reason);
  }
}

void CompletionLookup::addUsingSpecifiers() {
  for (unsigned i = 0,
                n = static_cast<unsigned>(UsingSpecifier::LastSpecifier) + 1;
       i != n; ++i) {
    CodeCompletionResultBuilder Builder = makeResultBuilder(
        CodeCompletionResultKind::Keyword, SemanticContextKind::None);
    switch (static_cast<UsingSpecifier>(i)) {
    case UsingSpecifier::MainActor:
      Builder.addTextChunk("@MainActor");
      break;
    case UsingSpecifier::Nonisolated:
      Builder.addTextChunk("nonisolated");
      break;
    }
  }
}

SemanticContextKind
CompletionLookup::getSemanticContext(const Decl *D, DeclVisibilityKind Reason,
                                     DynamicLookupInfo dynamicLookupInfo) {
  if (ForcedSemanticContext)
    return *ForcedSemanticContext;

  switch (Reason) {
  case DeclVisibilityKind::LocalDecl:
  case DeclVisibilityKind::FunctionParameter:
  case DeclVisibilityKind::GenericParameter:
    return SemanticContextKind::Local;

  case DeclVisibilityKind::MemberOfCurrentNominal:
    return SemanticContextKind::CurrentNominal;

  case DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal:
  case DeclVisibilityKind::MemberOfSuper:
    return SemanticContextKind::Super;

  case DeclVisibilityKind::MemberOfOutsideNominal:
    return SemanticContextKind::OutsideNominal;

  case DeclVisibilityKind::VisibleAtTopLevel:
    if (CurrDeclContext && D->getModuleContext() == CurrModule) {
      // Treat global variables from the same source file as local when
      // completing at top-level.
      if (isa<VarDecl>(D) && isTopLevelSubcontext(CurrDeclContext) &&
          D->getDeclContext()->getParentSourceFile() ==
              CurrDeclContext->getParentSourceFile()) {
        return SemanticContextKind::Local;
      } else {
        return SemanticContextKind::CurrentModule;
      }
    } else {
      return SemanticContextKind::OtherModule;
    }

  case DeclVisibilityKind::DynamicLookup:
    switch (dynamicLookupInfo.getKind()) {
    case DynamicLookupInfo::None:
      llvm_unreachable("invalid DynamicLookupInfo::Kind for dynamic lookup");

    case DynamicLookupInfo::AnyObject:
      // AnyObject results can come from different modules, including the
      // current module, but we always assign them the OtherModule semantic
      // context.  These declarations are uniqued by signature, so it is
      // totally random (determined by the hash function) which of the
      // equivalent declarations (across multiple modules) we will get.
      return SemanticContextKind::OtherModule;

    case DynamicLookupInfo::KeyPathDynamicMember:
      // Use the visibility of the underlying declaration.
      // FIXME: KeyPath<AnyObject, U> !?!?
      assert(dynamicLookupInfo.getKeyPathDynamicMember().originalVisibility !=
             DeclVisibilityKind::DynamicLookup);
      return getSemanticContext(
          D, dynamicLookupInfo.getKeyPathDynamicMember().originalVisibility,
          {});
    }

  case DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal:
    llvm_unreachable("should not see this kind");
  }
  llvm_unreachable("unhandled kind");
}

bool CompletionLookup::isUnresolvedMemberIdealType(Type Ty) {
  assert(Ty);
  if (!IsUnresolvedMember)
    return false;
  Type idealTy = expectedTypeContext.getIdealType();
  if (!idealTy)
    return false;
  /// Consider optional object type is the ideal.
  /// For example:
  ///   enum MyEnum { case foo, bar }
  ///   func foo(_: MyEnum?)
  ///   fooo(.<HERE>)
  /// Prefer '.foo' and '.bar' over '.some' and '.none'.
  idealTy = idealTy->lookThroughAllOptionalTypes();
  return idealTy->isEqual(Ty);
}

CodeCompletionResultBuilder
CompletionLookup::makeResultBuilder(CodeCompletionResultKind kind,
                                    SemanticContextKind semanticContext) const {
  CodeCompletionResultBuilder builder(Sink, kind, semanticContext);
  builder.setTypeContext(expectedTypeContext, CurrDeclContext);
  return builder;
}

void CompletionLookup::addValueBaseName(CodeCompletionResultBuilder &Builder,
                                        DeclBaseName Name) {
  Builder.addValueBaseName(Name, /*IsMember=*/bool(ExprType));
}

void CompletionLookup::addIdentifier(CodeCompletionResultBuilder &Builder,
                                     Identifier Name) {
  if (Name.mustAlwaysBeEscaped()) {
    SmallString<16> buffer;
    Builder.addBaseName(Builder.escapeWithBackticks(Name.str(), buffer));
  } else {
    Builder.addBaseName(Name.str());
  }
}

void CompletionLookup::addLeadingDot(CodeCompletionResultBuilder &Builder) {
  if (NeedOptionalUnwrap) {
    Builder.setNumBytesToErase(NumBytesToEraseForOptionalUnwrap);
    Builder.addQuestionMark();
    Builder.addLeadingDot();
    return;
  }
  if (needDot())
    Builder.addLeadingDot();
}

void CompletionLookup::addTypeAnnotation(CodeCompletionResultBuilder &Builder,
                                         Type T, GenericSignature genericSig) {
  Builder.addTypeAnnotation(T, CurrDeclContext, genericSig);
  Builder.setResultTypes(T);
}

void CompletionLookup::addTypeAnnotationForImplicitlyUnwrappedOptional(
    CodeCompletionResultBuilder &Builder, Type T, GenericSignature genericSig,
    bool dynamicOrOptional) {
  Builder.addTypeAnnotationForImplicitlyUnwrappedOptional(
      T, CurrDeclContext, genericSig, dynamicOrOptional);
  Builder.setResultTypes(T);
  Builder.setTypeContext(expectedTypeContext, CurrDeclContext);
}

Type CompletionLookup::getTypeOfMember(const ValueDecl *VD,
                                       DynamicLookupInfo dynamicLookupInfo) {
  switch (dynamicLookupInfo.getKind()) {
  case DynamicLookupInfo::None:
    return getTypeOfMember(VD, getMemberBaseType());
  case DynamicLookupInfo::AnyObject:
    return getTypeOfMember(VD, Type());
  case DynamicLookupInfo::KeyPathDynamicMember: {
    auto &keyPathInfo = dynamicLookupInfo.getKeyPathDynamicMember();

    // Map the result of VD to keypath member lookup results.
    // Given:
    //   struct Wrapper<T> {
    //     subscript<U>(dynamicMember: KeyPath<T, U>) -> Wrapped<U> { get }
    //   }
    //   struct Circle {
    //     var center: Point { get }
    //     var radius: Length { get }
    //   }
    //
    // Consider 'Wrapper<Circle>.center'.
    //   'VD' is 'Circle.center' decl.
    //   'keyPathInfo.subscript' is 'Wrapper<T>.subscript' decl.
    //   'keyPathInfo.baseType' is 'Wrapper<Circle>' type.

    // FIXME: Handle nested keypath member lookup.
    // i.e. cases where 'ExprType' != 'keyPathInfo.baseType'.

    auto *SD = keyPathInfo.subscript;
    const auto elementTy = SD->getElementInterfaceType();
    if (!elementTy->hasTypeParameter())
      return elementTy;

    // Map is:
    //   { τ_0_0(T) => Circle
    //     τ_1_0(U) => U }
    auto subs = keyPathInfo.baseType->getMemberSubstitutions(SD);

    // FIXME: The below should use substitution map substitution.

    // If the keyPath result type has type parameters, that might affect the
    // subscript result type.
    auto keyPathResultTy = getResultTypeOfKeypathDynamicMember(SD);
    if (keyPathResultTy->hasTypeParameter()) {
      auto keyPathRootTy = getRootTypeOfKeypathDynamicMember(SD).subst(
          QueryTypeSubstitutionMap{subs},
          LookUpConformanceInModule());

      // The result type of the VD.
      // i.e. 'Circle.center' => 'Point'.
      auto innerResultTy = getTypeOfMember(VD, keyPathRootTy);

      if (auto paramTy = keyPathResultTy->getAs<GenericTypeParamType>()) {
        // Replace keyPath result type in the map with the inner result type.
        // i.e. Make the map as:
        //   { τ_0_0(T) => Circle
        //     τ_1_0(U) => Point }
        auto key = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
        subs[key] = innerResultTy;
      } else {
        // FIXME: Handle the case where the KeyPath result is generic.
        // e.g. 'subscript<U>(dynamicMember: KeyPath<T, Box<U>>) -> Bag<U>'
        // For now, just return the inner type.
        return innerResultTy;
      }
    }

    // Substitute the element type of the subscript using modified map.
    // i.e. 'Wrapped<U>' => 'Wrapped<Point>'.
    return elementTy.subst(QueryTypeSubstitutionMap{subs},
                           LookUpConformanceInModule());
  }
  }
  llvm_unreachable("Unhandled DynamicLookupInfo Kind in switch");
}

Type CompletionLookup::getTypeOfMember(const ValueDecl *VD, Type ExprType) {
  Type T;
  if (auto *TD = dyn_cast<TypeDecl>(VD)) {
    // For a type decl we're interested in the declared interface type, i.e
    // we don't want a metatype.
    T = TD->getDeclaredInterfaceType();
  } else {
    T = VD->getInterfaceType();
  }
  assert(!T.isNull());

  if (ExprType) {
    Type ContextTy = VD->getDeclContext()->getDeclaredInterfaceType();
    if (ContextTy) {
      // Look through lvalue types and metatypes
      Type MaybeNominalType = ExprType->getRValueType();

      if (auto Metatype = MaybeNominalType->getAs<MetatypeType>())
        MaybeNominalType = Metatype->getInstanceType();

      if (auto SelfType = MaybeNominalType->getAs<DynamicSelfType>())
        MaybeNominalType = SelfType->getSelfType();

      // For optional protocol requirements and dynamic dispatch,
      // strip off optionality from the base type, but only if
      // we're not actually completing a member of Optional.
      if (!ContextTy->getOptionalObjectType() &&
          MaybeNominalType->getOptionalObjectType())
        MaybeNominalType = MaybeNominalType->getOptionalObjectType();

      // For dynamic lookup don't substitute in the base type.
      if (MaybeNominalType->isAnyObject())
        return T;

      // FIXME: Sometimes ExprType is the type of the member here,
      // and not the type of the base. That is inconsistent and
      // should be cleaned up.
      if (!MaybeNominalType->mayHaveMembers())
        return T;

      // We can't do anything if the base type has unbound generic parameters.
      if (MaybeNominalType->hasUnboundGenericType())
        return T;

      // If we are doing implicit member lookup on a protocol and we have found
      // a declaration in a constrained extension, use the extension's `Self`
      // type for the generic substitution.
      // Eg in the following, the `Self` type returned by `qux` is
      // `MyGeneric<Int>`, not `MyProto` because of the `Self` type restriction.
      // ```
      // protocol MyProto {}
      // struct MyGeneric<T>: MyProto {}
      // extension MyProto where Self == MyGeneric<Int> {
      //   static func qux() -> Self { .init() }
      // }
      // func takeMyProto(_: any MyProto)  {}
      // func test() {
      //   takeMyProto(.#^COMPLETE^#)
      // }
      // ```
      if (MaybeNominalType->isExistentialType()) {
        Type SelfType;
        if (auto *ED = dyn_cast<ExtensionDecl>(VD->getDeclContext())) {
          if (ED->getSelfProtocolDecl() && ED->isConstrainedExtension()) {
            auto Sig = ED->getGenericSignature();
            SelfType = Sig->getConcreteType(ED->getSelfInterfaceType());
          }
        }
        if (SelfType) {
          MaybeNominalType = SelfType;
        } else {
          return T;
        }
      }

      // For everything else, substitute in the base type.
      auto Subs = MaybeNominalType->getMemberSubstitutionMap(VD);

      // For a GenericFunctionType, we only want to substitute the
      // param/result types, as otherwise we might end up with a bad generic
      // signature if there are ErrorTypes present in the base type. Note
      // we pass in DesugarMemberTypes so that we see the actual concrete type
      // witnesses instead of type alias types.
      if (auto *GFT = T->getAs<GenericFunctionType>()) {
        T = GFT->substGenericArgs(Subs, SubstFlags::DesugarMemberTypes);
      } else {
        T = T.subst(Subs, SubstFlags::DesugarMemberTypes);
      }
    }
  }

  return T;
}

Type CompletionLookup::getAssociatedTypeType(const AssociatedTypeDecl *ATD) {
  Type BaseTy = getMemberBaseType();
  if (!BaseTy && CurrDeclContext)
    BaseTy =
        CurrDeclContext->getInnermostTypeContext()->getDeclaredTypeInContext();
  if (BaseTy) {
    BaseTy = BaseTy->getInOutObjectType()->getMetatypeInstanceType();
    if (BaseTy->getAnyNominal()) {
      auto Conformance = lookupConformance(BaseTy, ATD->getProtocol());
      if (Conformance.isConcrete()) {
        return Conformance.getConcrete()->getTypeWitness(
            const_cast<AssociatedTypeDecl *>(ATD));
      }
    }
  }
  return Type();
}

void CompletionLookup::analyzeActorIsolation(
    const ValueDecl *VD, Type T, bool &implicitlyAsync,
    std::optional<ContextualNotRecommendedReason> &NotRecommended) {
  auto isolation = getActorIsolation(const_cast<ValueDecl *>(VD));

  switch (isolation.getKind()) {
  case ActorIsolation::ActorInstance: {
    // TODO: implicitlyThrowing here for distributed
    if (IsCrossActorReference) {
      implicitlyAsync = true;
      // TODO: 'NotRecommended' if this is a r-value reference.
    }
    break;
  }
  case ActorIsolation::GlobalActor: {
    // For "preconcurrency" global actor isolation, automatic 'async' only happens
    // if the context has adopted concurrency.
    if (isolation.preconcurrency() &&
        !CanCurrDeclContextHandleAsync &&
        !completionContextUsesConcurrencyFeatures(CurrDeclContext)) {
      return;
    }

    auto getClosureActorIsolation = [this](AbstractClosureExpr *CE) {
      // Prefer solution-specific actor-isolations and fall back to the one
      // recorded in the AST.
      auto isolation = ClosureActorIsolations.find(CE);
      if (isolation != ClosureActorIsolations.end()) {
        return isolation->second;
      } else {
        return CE->getActorIsolation();
      }
    };
    auto contextIsolation = getActorIsolationOfContext(
        const_cast<DeclContext *>(CurrDeclContext), getClosureActorIsolation);
    if (contextIsolation != isolation) {
      implicitlyAsync = true;
    }
    break;
  }
  case ActorIsolation::Erased:
    implicitlyAsync = true;
    break;
  case ActorIsolation::Unspecified:
  case ActorIsolation::Nonisolated:
  case ActorIsolation::CallerIsolationInheriting:
  case ActorIsolation::NonisolatedUnsafe:
    return;
  }
}

void CompletionLookup::addVarDeclRef(const VarDecl *VD,
                                     DeclVisibilityKind Reason,
                                     DynamicLookupInfo dynamicLookupInfo) {
  if (!VD->hasName())
    return;

  const Identifier Name = VD->getName();
  assert(!Name.empty() && "name should not be empty");

  Type VarType;
  auto SolutionSpecificType = SolutionSpecificVarTypes.find(VD);
  if (SolutionSpecificType != SolutionSpecificVarTypes.end()) {
    assert(!VarType && "Type recorded in the AST and is also solution-specific?");
    VarType = SolutionSpecificType->second;
  } else if (VD->hasInterfaceType()) {
    VarType = getTypeOfMember(VD, dynamicLookupInfo);
  }

  std::optional<ContextualNotRecommendedReason> NotRecommended;
  // "not recommended" in its own getter.
  if (Kind == LookupKind::ValueInDeclContext) {
    if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
      if (accessor->getStorage() == VD && accessor->isGetter())
        NotRecommended =
            ContextualNotRecommendedReason::VariableUsedInOwnDefinition;
    }
  }
  bool implicitlyAsync = false;
  analyzeActorIsolation(VD, VarType, implicitlyAsync, NotRecommended);
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(VD, Reason, dynamicLookupInfo));
  Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
  Builder.setAssociatedDecl(VD);
  addLeadingDot(Builder);
  addValueBaseName(Builder, Name);

  if (NotRecommended)
    Builder.setContextualNotRecommended(*NotRecommended);

  if (!VarType)
    return;

  if (auto *PD = dyn_cast<ParamDecl>(VD)) {
    if (Name != Ctx.Id_self && PD->isInOut()) {
      // It is useful to show inout for function parameters.
      // But for 'self' it is just noise.
      VarType = InOutType::get(VarType);
    }
  }
  auto DynamicOrOptional =
      IsDynamicLookup || VD->getAttrs().hasAttribute<OptionalAttr>();
  if (DynamicOrOptional) {
    // Values of properties that were found on a AnyObject have
    // Optional<T> type.  Same applies to optional members.
    VarType = OptionalType::get(VarType);
  }

  auto genericSig =
      VD->getInnermostDeclContext()->getGenericSignatureOfContext();
  if (VD->isImplicitlyUnwrappedOptional())
    addTypeAnnotationForImplicitlyUnwrappedOptional(
        Builder, VarType, genericSig, DynamicOrOptional);
  else
    addTypeAnnotation(Builder, VarType, genericSig);

  if (implicitlyAsync)
    Builder.addAnnotatedAsync();

  if (isUnresolvedMemberIdealType(VarType))
    Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific);

  if (auto Accessor = VD->getEffectfulGetAccessor()) {
    if (auto AFT = getTypeOfMember(Accessor, dynamicLookupInfo)->getAs<AnyFunctionType>()) {
      if (Accessor->hasImplicitSelfDecl()) {
        AFT = AFT->getResult()->getAs<AnyFunctionType>();
        assert(AFT);
      }
      Builder.addEffectsSpecifiers(AFT, Accessor);
    }
  }
}

bool CompletionLookup::shouldAddItemWithoutDefaultArgs(
    const AbstractFunctionDecl *func) {
  if (!func || !Sink.addCallWithNoDefaultArgs)
    return false;
  for (auto param : *func->getParameters()) {
    if (hasInterestingDefaultValue(param))
      return true;
  }
  return false;
}

void CompletionLookup::addPoundAvailable(std::optional<StmtKind> ParentKind) {
  if (ParentKind != StmtKind::If && ParentKind != StmtKind::Guard)
    return;
  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword,
      // FIXME: SemanticContextKind::Local is not correct.
      // Use 'None' (and fix prioritization) or introduce a new context.
      SemanticContextKind::Local);
  Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific);
  Builder.addBaseName("available");
  Builder.addLeftParen();
  Builder.addSimpleTypedParameter("Platform", /*IsVarArg=*/true);
  Builder.addComma();
  Builder.addTextChunk("*");
  Builder.addRightParen();
}

void CompletionLookup::addPoundSelector(bool needPound) {
  // #selector is only available when the Objective-C runtime is.
  if (!Ctx.LangOpts.EnableObjCInterop)
    return;

  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword, SemanticContextKind::None);
  if (needPound)
    Builder.addTextChunk("#selector");
  else
    Builder.addTextChunk("selector");
  Builder.addLeftParen();
  Builder.addSimpleTypedParameter("@objc method", /*IsVarArg=*/false);
  Builder.addRightParen();
  Builder.addTypeAnnotation("Selector");
  // This function is called only if the context type is 'Selector'.
  Builder.setResultTypes(Ctx.getSelectorType());
  Builder.setTypeContext(expectedTypeContext, CurrDeclContext);
}

void CompletionLookup::addPoundKeyPath(bool needPound) {
  // #keyPath is only available when the Objective-C runtime is.
  if (!Ctx.LangOpts.EnableObjCInterop)
    return;

  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword, SemanticContextKind::None);
  if (needPound)
    Builder.addTextChunk("#keyPath");
  else
    Builder.addTextChunk("keyPath");
  Builder.addLeftParen();
  Builder.addSimpleTypedParameter("@objc property sequence",
                                  /*IsVarArg=*/false);
  Builder.addRightParen();
  Builder.addTypeAnnotation("String");
  Builder.setResultTypes(Ctx.getStringType());
  Builder.setTypeContext(expectedTypeContext, CurrDeclContext);
}

SemanticContextKind
CompletionLookup::getSemanticContextKind(const ValueDecl *VD) {
  // FIXME: to get the corect semantic context we need to know how lookup
  // would have found the VD. For now, just infer a reasonable semantics.

  if (!VD)
    return SemanticContextKind::CurrentModule;

  DeclContext *calleeDC = VD->getDeclContext();

  if (calleeDC->isTypeContext())
    // FIXME: We should distinguish CurrentNominal and Super. We need to
    // propagate the base type to do that.
    return SemanticContextKind::CurrentNominal;

  if (calleeDC->isLocalContext())
    return SemanticContextKind::Local;
  if (calleeDC->getParentModule() == CurrModule)
    return SemanticContextKind::CurrentModule;

  return SemanticContextKind::OtherModule;
}

void CompletionLookup::addSubscriptCallPattern(
    const AnyFunctionType *AFT, const SubscriptDecl *SD,
    const std::optional<SemanticContextKind> SemanticContext) {
  foundFunction(AFT);
  GenericSignature genericSig;
  if (SD)
    genericSig = SD->getGenericSignatureOfContext();

  CodeCompletionResultBuilder Builder = makeResultBuilder(
      SD ? CodeCompletionResultKind::Declaration
         : CodeCompletionResultKind::Pattern,
      SemanticContext ? *SemanticContext : getSemanticContextKind(SD));
  if (SD)
    Builder.setAssociatedDecl(SD);
  if (!HaveLParen) {
    Builder.addLeftBracket();
  } else {
    // Add 'ArgumentLabels' only if it has '['. Without existing '[',
    // consider it suggesting 'subscript' itself, not call arguments for it.
    Builder.addFlair(CodeCompletionFlairBit::ArgumentLabels);
    Builder.addAnnotatedLeftBracket();
  }
  ArrayRef<const ParamDecl *> declParams;
  if (SD)
    declParams = SD->getIndices()->getArray();
  Builder.addCallArgumentPatterns(AFT->getParams(), declParams, CurrDeclContext,
                                  genericSig);
  if (!HaveLParen)
    Builder.addRightBracket();
  else
    Builder.addAnnotatedRightBracket();
  if (SD && SD->isImplicitlyUnwrappedOptional())
    addTypeAnnotationForImplicitlyUnwrappedOptional(Builder, AFT->getResult(),
                                                    genericSig);
  else
    addTypeAnnotation(Builder, AFT->getResult(), genericSig);
}

void CompletionLookup::addFunctionCallPattern(
    const AnyFunctionType *AFT, const AbstractFunctionDecl *AFD,
    const std::optional<SemanticContextKind> SemanticContext) {
  GenericSignature genericSig;
  if (AFD)
    genericSig = AFD->getGenericSignatureOfContext();

  // Add the pattern, possibly including any default arguments.
  auto addPattern = [&](ArrayRef<const ParamDecl *> declParams = {},
                        DefaultArgumentOutputMode defaultArgsMode =
                            DefaultArgumentOutputMode::Interesting) {
    CodeCompletionResultBuilder Builder = makeResultBuilder(
        AFD ? CodeCompletionResultKind::Declaration
            : CodeCompletionResultKind::Pattern,
        SemanticContext ? *SemanticContext : getSemanticContextKind(AFD));
    Builder.addFlair(CodeCompletionFlairBit::ArgumentLabels);
    if (DotLoc) {
      Builder.setNumBytesToErase(Ctx.SourceMgr.getByteDistance(
          DotLoc, Ctx.SourceMgr.getIDEInspectionTargetLoc()));
    }
    if (AFD)
      Builder.setAssociatedDecl(AFD);

    if (!HaveLParen)
      Builder.addLeftParen();
    else
      Builder.addAnnotatedLeftParen();

    Builder.addCallArgumentPatterns(AFT->getParams(), declParams,
                                    CurrDeclContext, genericSig,
                                    defaultArgsMode);

    // The rparen matches the lparen here so that we insert both or neither.
    if (!HaveLParen)
      Builder.addRightParen();
    else
      Builder.addAnnotatedRightParen();

    Builder.addEffectsSpecifiers(AFT, AFD);

    if (AFD && AFD->isImplicitlyUnwrappedOptional())
      addTypeAnnotationForImplicitlyUnwrappedOptional(Builder, AFT->getResult(),
                                                      genericSig);
    else
      addTypeAnnotation(Builder, AFT->getResult(), genericSig);

    Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
  };

  if (!AFD || !AFD->getInterfaceType()->is<AnyFunctionType>()) {
    // Probably, calling closure type expression.
    foundFunction(AFT);
    addPattern();
    return;
  } else {
    // Calling function or method.
    foundFunction(AFD);

    // FIXME: Hack because we don't know we are calling instance
    // method or not. There's invariant that funcTy is derived from AFD.
    // Only if we are calling instance method on meta type, AFT is still
    // curried. So we should be able to detect that by comparing curried level
    // of AFT and the interface type of AFD.
    auto getCurriedLevel = [](const AnyFunctionType *funcTy) -> unsigned {
      unsigned level = 0;
      while ((funcTy = funcTy->getResult()->getAs<AnyFunctionType>()))
        ++level;
      return level;
    };
    bool isImplicitlyCurriedInstanceMethod =
        (AFD->hasImplicitSelfDecl() &&
         getCurriedLevel(AFT) ==
             getCurriedLevel(
                 AFD->getInterfaceType()->castTo<AnyFunctionType>()) &&
         // NOTE: shouldn't be necessary, but just in case curried level check
         // is insufficient.
         AFT->getParams().size() == 1 &&
         AFT->getParams()[0].getLabel().empty());

    if (isImplicitlyCurriedInstanceMethod) {
      addPattern({AFD->getImplicitSelfDecl()},
                 DefaultArgumentOutputMode::Interesting);
    } else {
      if (shouldAddItemWithoutDefaultArgs(AFD))
        addPattern(AFD->getParameters()->getArray(),
                   DefaultArgumentOutputMode::None);
      addPattern(AFD->getParameters()->getArray(),
                 DefaultArgumentOutputMode::Interesting);
    }
  }
}

bool CompletionLookup::isImplicitlyCurriedInstanceMethod(
    const AbstractFunctionDecl *FD) {
  if (FD->isStatic())
    return false;

  switch (Kind) {
  case LookupKind::ValueExpr:
  case LookupKind::StoredProperty:
    return ExprType->is<AnyMetatypeType>();
  case LookupKind::ValueInDeclContext:
    if (InsideStaticMethod)
      return FD->getDeclContext() == CurrentMethod->getDeclContext();
    if (auto Init = dyn_cast<Initializer>(CurrDeclContext)) {
      if (auto PatInit = dyn_cast<PatternBindingInitializer>(Init)) {
        if (PatInit->getInitializedLazyVar())
          return false;
      }
      return FD->getDeclContext() == Init->getInnermostTypeContext();
    }
    return false;
  case LookupKind::EnumElement:
  case LookupKind::Type:
  case LookupKind::TypeInDeclContext:
  case LookupKind::GenericRequirement:
    llvm_unreachable("cannot have a method call while doing a "
                     "type completion");
  case LookupKind::ImportFromModule:
    return false;
  }

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

void CompletionLookup::addMethodCall(const FuncDecl *FD,
                                     DeclVisibilityKind Reason,
                                     DynamicLookupInfo dynamicLookupInfo) {
  if (FD->getBaseIdentifier().empty())
    return;
  foundFunction(FD);

  const Identifier Name = FD->getBaseIdentifier();
  assert(!Name.empty() && "name should not be empty");

  Type FunctionType = getTypeOfMember(FD, dynamicLookupInfo);
  assert(FunctionType);

  auto AFT = FunctionType->getAs<AnyFunctionType>();

  bool IsImplicitlyCurriedInstanceMethod = false;
  if (FD->hasImplicitSelfDecl()) {
    IsImplicitlyCurriedInstanceMethod = isImplicitlyCurriedInstanceMethod(FD);

    // Strip off '(_ self: Self)' if needed.
    if (AFT && !IsImplicitlyCurriedInstanceMethod) {
      AFT = AFT->getResult()->getAs<AnyFunctionType>();

      // Check for duplicates with the adjusted type too.
      if (isDuplicate(FD, AFT))
        return;
    }
  }

  bool trivialTrailingClosure = false;
  if (AFT && !IsImplicitlyCurriedInstanceMethod)
    trivialTrailingClosure = hasTrivialTrailingClosure(FD, AFT);

  std::optional<ContextualNotRecommendedReason> NotRecommended;
  bool implictlyAsync = false;
  analyzeActorIsolation(FD, AFT, implictlyAsync, NotRecommended);

  // Add the method, possibly including any default arguments.
  auto addMethodImpl = [&](DefaultArgumentOutputMode defaultArgsMode =
                               DefaultArgumentOutputMode::Interesting,
                           bool trivialTrailingClosure = false) {
    CodeCompletionResultBuilder Builder =
        makeResultBuilder(CodeCompletionResultKind::Declaration,
                          getSemanticContext(FD, Reason, dynamicLookupInfo));
    Builder.setHasAsyncAlternative(
        FD->getAsyncAlternative() &&
        !FD->getAsyncAlternative()->shouldHideFromEditor());
    Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
    Builder.setAssociatedDecl(FD);

    if (IsSuperRefExpr && CurrentMethod &&
        CurrentMethod->getOverriddenDecl() == FD)
      Builder.addFlair(CodeCompletionFlairBit::SuperChain);

    if (NotRecommended)
      Builder.setContextualNotRecommended(*NotRecommended);

    addLeadingDot(Builder);
    addValueBaseName(Builder, Name);
    if (IsDynamicLookup)
      Builder.addDynamicLookupMethodCallTail();
    else if (FD->getAttrs().hasAttribute<OptionalAttr>())
      Builder.addOptionalMethodCallTail();

    if (!AFT) {
      addTypeAnnotation(Builder, FunctionType,
                        FD->getGenericSignatureOfContext());
      return;
    }
    if (IsImplicitlyCurriedInstanceMethod) {
      Builder.addLeftParen();
      Builder.addCallArgumentPatterns(
          AFT->getParams(), {FD->getImplicitSelfDecl()}, CurrDeclContext,
          FD->getGenericSignatureOfContext(), defaultArgsMode);
      Builder.addRightParen();
    } else if (trivialTrailingClosure) {
      Builder.addBraceStmtWithCursor(" { code }");
      Builder.addEffectsSpecifiers(AFT, FD, implictlyAsync);
    } else {
      Builder.addLeftParen();
      Builder.addCallArgumentPatterns(AFT, FD->getParameters(), CurrDeclContext,
                                      FD->getGenericSignatureOfContext(),
                                      defaultArgsMode);
      Builder.addRightParen();
      Builder.addEffectsSpecifiers(AFT, FD, implictlyAsync);
    }

    // Build type annotation.
    Type ResultType = AFT->getResult();
    // As we did with parameters in addParamPatternFromFunction,
    // for regular methods we'll print '!' after implicitly
    // unwrapped optional results.
    bool IsIUO = !IsImplicitlyCurriedInstanceMethod &&
                 FD->isImplicitlyUnwrappedOptional();

    NonRecursivePrintOptions nrOptions;
    if (IsIUO)
      nrOptions |= NonRecursivePrintOption::ImplicitlyUnwrappedOptional;

    PrintOptions PO;
    PO.OpaqueReturnTypePrinting =
        PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
    if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
      PO.setBaseType(typeContext->getDeclaredTypeInContext());
    Type AnnotationTy =
        eraseArchetypes(ResultType, FD->getGenericSignatureOfContext());
    if (Builder.shouldAnnotateResults()) {
      Builder.withNestedGroup(
          CodeCompletionString::Chunk::ChunkKind::TypeAnnotationBegin, [&] {
            CodeCompletionStringPrinter printer(Builder);
            auto TL = TypeLoc::withoutLoc(AnnotationTy);
            printer.printTypePre(TL);
            if (IsImplicitlyCurriedInstanceMethod) {
              auto *FnType = AnnotationTy->castTo<AnyFunctionType>();
              AnyFunctionType::printParams(FnType->getParams(), printer,
                                           PrintOptions());
              AnnotationTy = FnType->getResult();
              printer.printText(" -> ");
            }

            // What's left is the result type.
            if (AnnotationTy->isVoid())
              AnnotationTy = Ctx.getVoidDecl()->getDeclaredInterfaceType();
            AnnotationTy.print(printer, PO, nrOptions);
            printer.printTypePost(TL);
          });
    } else {
      llvm::SmallString<32> TypeStr;
      llvm::raw_svector_ostream OS(TypeStr);
      if (IsImplicitlyCurriedInstanceMethod) {
        auto *FnType = AnnotationTy->castTo<AnyFunctionType>();
        AnyFunctionType::printParams(FnType->getParams(), OS);
        AnnotationTy = FnType->getResult();
        OS << " -> ";
      }

      // What's left is the result type.
      if (AnnotationTy->isVoid())
        AnnotationTy = Ctx.getVoidDecl()->getDeclaredInterfaceType();
      AnnotationTy.print(OS, PO, nrOptions);
      Builder.addTypeAnnotation(TypeStr);
    }

    Builder.setResultTypes(ResultType);
    Builder.setTypeContext(expectedTypeContext, CurrDeclContext);

    if (isUnresolvedMemberIdealType(ResultType))
      Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific);
  };

  // Do not add imported C++ methods that are treated as unsafe in Swift.
  if (Importer->isUnsafeCXXMethod(FD))
    return;

  if (!AFT || IsImplicitlyCurriedInstanceMethod) {
    addMethodImpl();
  } else {
    if (trivialTrailingClosure)
      addMethodImpl(DefaultArgumentOutputMode::None,
                    /*trivialTrailingClosure=*/true);
    if (shouldAddItemWithoutDefaultArgs(FD))
      addMethodImpl(DefaultArgumentOutputMode::None);
    addMethodImpl(DefaultArgumentOutputMode::Interesting);
  }
}

void CompletionLookup::addConstructorCall(const ConstructorDecl *CD,
                                          DeclVisibilityKind Reason,
                                          DynamicLookupInfo dynamicLookupInfo,
                                          std::optional<Type> BaseType,
                                          std::optional<Type> Result,
                                          bool IsOnType, Identifier addName) {
  foundFunction(CD);
  Type MemberType = getTypeOfMember(CD, BaseType.value_or(ExprType));
  AnyFunctionType *ConstructorType = nullptr;
  if (auto MemberFuncType = MemberType->getAs<AnyFunctionType>())
    ConstructorType = MemberFuncType->getResult()->castTo<AnyFunctionType>();

  bool needInit = false;
  if (!IsOnType) {
    assert(addName.empty());
    needInit = true;
  } else if (addName.empty() && HaveDot) {
    needInit = true;
  }

  // If we won't be able to provide a result, bail out.
  if (!ConstructorType && addName.empty() && !needInit)
    return;

  // Add the constructor, possibly including any default arguments.
  auto addConstructorImpl = [&](DefaultArgumentOutputMode defaultArgsMode) {
    CodeCompletionResultBuilder Builder =
        makeResultBuilder(CodeCompletionResultKind::Declaration,
                          getSemanticContext(CD, Reason, dynamicLookupInfo));
    Builder.setAssociatedDecl(CD);

    if (IsSuperRefExpr && CurrentMethod &&
        CurrentMethod->getOverriddenDecl() == CD)
      Builder.addFlair(CodeCompletionFlairBit::SuperChain);

    if (needInit) {
      assert(addName.empty());
      addLeadingDot(Builder);
      Builder.addBaseName("init");
    } else if (!addName.empty()) {
      addIdentifier(Builder, addName);
    } else {
      Builder.addFlair(CodeCompletionFlairBit::ArgumentLabels);
    }

    if (!ConstructorType) {
      addTypeAnnotation(Builder, MemberType,
                        CD->getGenericSignatureOfContext());
      return;
    }

    if (!HaveLParen)
      Builder.addLeftParen();
    else
      Builder.addAnnotatedLeftParen();

    Builder.addCallArgumentPatterns(
        ConstructorType, CD->getParameters(), CurrDeclContext,
        CD->getGenericSignatureOfContext(), defaultArgsMode);

    // The rparen matches the lparen here so that we insert both or neither.
    if (!HaveLParen)
      Builder.addRightParen();
    else
      Builder.addAnnotatedRightParen();

    Builder.addEffectsSpecifiers(ConstructorType, CD);

    if (!Result.has_value())
      Result = ConstructorType->getResult();
    if (CD->isImplicitlyUnwrappedOptional()) {
      addTypeAnnotationForImplicitlyUnwrappedOptional(
          Builder, *Result, CD->getGenericSignatureOfContext());
    } else {
      addTypeAnnotation(Builder, *Result, CD->getGenericSignatureOfContext());
    }

    Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
  };

  if (ConstructorType && shouldAddItemWithoutDefaultArgs(CD))
    addConstructorImpl(DefaultArgumentOutputMode::None);
  addConstructorImpl(DefaultArgumentOutputMode::Interesting);
}

void CompletionLookup::addConstructorCallsForType(
    Type type, Identifier name, DeclVisibilityKind Reason,
    DynamicLookupInfo dynamicLookupInfo) {
  if (!Sink.addInitsToTopLevel)
    return;

  // Existential types cannot be instantiated. e.g. 'MyProtocol()'.
  if (type->isExistentialType())
    return;

  // 'AnyObject' is not initializable.
  // FIXME: Should we do this in 'AnyObjectLookupRequest'?
  if (type->isAnyObject())
    return;

  assert(CurrDeclContext);

  auto results =
      swift::lookupSemanticMember(const_cast<DeclContext *>(CurrDeclContext),
                                  type, DeclBaseName::createConstructor());
  for (const auto &entry : results.allResults()) {
    auto *init = cast<ConstructorDecl>(entry.getValueDecl());
    if (init->shouldHideFromEditor())
      continue;
    addConstructorCall(cast<ConstructorDecl>(init), Reason, dynamicLookupInfo,
                       type, std::nullopt,
                       /*IsOnType=*/true, name);
  }
}

void CompletionLookup::addSubscriptCall(const SubscriptDecl *SD,
                                        DeclVisibilityKind Reason,
                                        DynamicLookupInfo dynamicLookupInfo) {
  // Don't add subscript call to unqualified completion.
  if (!ExprType)
    return;

  // Subscript after '.' is valid only after type part of Swift keypath
  // expression. (e.g. '\TyName.SubTy.[0])
  if (HaveDot && !IsAfterSwiftKeyPathRoot)
    return;

  auto subscriptType =
      getTypeOfMember(SD, dynamicLookupInfo)->getAs<AnyFunctionType>();
  if (!subscriptType)
    return;

  std::optional<ContextualNotRecommendedReason> NotRecommended;
  bool implictlyAsync = false;
  analyzeActorIsolation(SD, subscriptType, implictlyAsync, NotRecommended);

  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(SD, Reason, dynamicLookupInfo));
  Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
  Builder.setAssociatedDecl(SD);

  if (NotRecommended)
    Builder.setContextualNotRecommended(*NotRecommended);

  // '\TyName#^TOKEN^#' requires leading dot.
  if (!HaveDot && IsAfterSwiftKeyPathRoot)
    Builder.addLeadingDot();

  if (NeedOptionalUnwrap) {
    Builder.setNumBytesToErase(NumBytesToEraseForOptionalUnwrap);
    Builder.addQuestionMark();
  }

  Builder.addLeftBracket();
  Builder.addCallArgumentPatterns(subscriptType, SD->getIndices(),
                                  CurrDeclContext,
                                  SD->getGenericSignatureOfContext(),
                                  DefaultArgumentOutputMode::Interesting);
  Builder.addRightBracket();

  // Add a type annotation.
  Type resultTy = subscriptType->getResult();
  if (IsDynamicLookup) {
    // Values of properties that were found on a AnyObject have
    // std::optional<T> type.
    resultTy = OptionalType::get(resultTy);
  }

  if (implictlyAsync)
    Builder.addAnnotatedAsync();

  addTypeAnnotation(Builder, resultTy, SD->getGenericSignatureOfContext());
}

static StringRef getTypeAnnotationString(const NominalTypeDecl *NTD,
                                         SmallVectorImpl<char> &stash) {
  SmallVector<StringRef, 1> attrRoleStrs;
  if (NTD->getAttrs().hasAttribute<PropertyWrapperAttr>())
    attrRoleStrs.push_back("Property Wrapper");
  if (NTD->getAttrs().hasAttribute<ResultBuilderAttr>())
    attrRoleStrs.push_back("Result Builder");
  if (NTD->isGlobalActor())
    attrRoleStrs.push_back("Global Actor");

  if (attrRoleStrs.empty())
    return StringRef();
  if (attrRoleStrs.size() == 1)
    return attrRoleStrs[0];

  assert(stash.empty());
  llvm::raw_svector_ostream OS(stash);
  llvm::interleave(attrRoleStrs, OS, ", ");
  return {stash.data(), stash.size()};
}

void CompletionLookup::addNominalTypeRef(const NominalTypeDecl *NTD,
                                         DeclVisibilityKind Reason,
                                         DynamicLookupInfo dynamicLookupInfo) {
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(NTD, Reason, dynamicLookupInfo));
  Builder.setAssociatedDecl(NTD);
  addLeadingDot(Builder);
  addValueBaseName(Builder, NTD->getBaseName());

  // Substitute the base type for a nested type if needed.
  auto nominalTy = getTypeOfMember(NTD, dynamicLookupInfo);

  // "Fake" annotation for custom attribute types.
  SmallVector<char, 0> stash;
  StringRef customAttributeAnnotation = getTypeAnnotationString(NTD, stash);
  if (!customAttributeAnnotation.empty()) {
    Builder.addTypeAnnotation(customAttributeAnnotation);
  } else {
    addTypeAnnotation(Builder, nominalTy);
  }

  // Override the type relation for NominalTypes. Use the better relation
  // for the metatypes and the instance type. For example,
  //
  //   func receiveInstance(_: Int) {}
  //   func receiveMetatype(_: Int.Type) {}
  //
  // We want to suggest 'Int' as 'Identical' for both arguments.
  Builder.setResultTypes({MetatypeType::get(nominalTy), nominalTy});
  Builder.setTypeContext(expectedTypeContext, CurrDeclContext);
}

Type CompletionLookup::getTypeAliasType(const TypeAliasDecl *TAD,
                                        DynamicLookupInfo dynamicLookupInfo) {
  // Substitute the base type for a nested typealias if needed.
  auto ty = getTypeOfMember(TAD, dynamicLookupInfo);
  auto *typeAliasTy = dyn_cast<TypeAliasType>(ty.getPointer());
  if (!typeAliasTy)
    return ty;

  // If the underlying type has an error, prefer to print the full typealias,
  // otherwise get the underlying type. We only want the direct underlying type,
  // not the full desugared type, since that more faithfully reflects what's
  // written in source.
  Type underlyingTy = typeAliasTy->getSinglyDesugaredType();
  if (underlyingTy->hasError())
    return ty;

  // The underlying type might be unbound for e.g:
  //
  // struct S<T> {}
  // typealias X = S
  //
  // Introduce type parameters such that we print the underlying type as
  // 'S<T>'. We only expect unbound generics at the top-level of a type-alias,
  // they are rejected by type resolution in any other position.
  //
  // FIXME: This is a hack – using the declared interface type isn't correct
  // since the generic parameters ought to be introduced at a higher depth,
  // i.e we should be treating it as `typealias X<T> = S<T>`. Ideally this would
  // be fixed by desugaring the unbound typealias during type resolution. For
  // now this is fine though since we only use the resulting type for printing
  // the type annotation; the type relation logic currently skips type
  // parameters.
  if (auto *UGT = underlyingTy->getAs<UnboundGenericType>())
    underlyingTy = UGT->getDecl()->getDeclaredInterfaceType();

  ASSERT(!underlyingTy->hasUnboundGenericType());
  return underlyingTy;
}

void CompletionLookup::addTypeAliasRef(const TypeAliasDecl *TAD,
                                       DeclVisibilityKind Reason,
                                       DynamicLookupInfo dynamicLookupInfo) {
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(TAD, Reason, dynamicLookupInfo));
  Builder.setAssociatedDecl(TAD);
  addLeadingDot(Builder);
  addValueBaseName(Builder, TAD->getBaseName());
  addTypeAnnotation(Builder, getTypeAliasType(TAD, dynamicLookupInfo));
}

void CompletionLookup::addGenericTypeParamRef(
    const GenericTypeParamDecl *GP, DeclVisibilityKind Reason,
    DynamicLookupInfo dynamicLookupInfo) {
  assert(!GP->getName().empty());
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(GP, Reason, dynamicLookupInfo));
  Builder.setAssociatedDecl(GP);
  addLeadingDot(Builder);
  addValueBaseName(Builder, GP->getBaseName());
  addTypeAnnotation(Builder, GP->getDeclaredInterfaceType());
}

void CompletionLookup::addAssociatedTypeRef(
    const AssociatedTypeDecl *AT, DeclVisibilityKind Reason,
    DynamicLookupInfo dynamicLookupInfo) {
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(AT, Reason, dynamicLookupInfo));
  Builder.setAssociatedDecl(AT);
  addLeadingDot(Builder);
  addValueBaseName(Builder, AT->getBaseName());
  if (Type T = getAssociatedTypeType(AT))
    addTypeAnnotation(Builder, T);
}

void CompletionLookup::addPrecedenceGroupRef(PrecedenceGroupDecl *PGD) {
  auto semanticContext =
      getSemanticContext(PGD, DeclVisibilityKind::VisibleAtTopLevel, {});
  CodeCompletionResultBuilder builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration, semanticContext);

  addIdentifier(builder, PGD->getName());
  builder.setAssociatedDecl(PGD);
}

void CompletionLookup::addBuiltinMemberRef(StringRef Name,
                                           Type TypeAnnotation) {
  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Pattern, SemanticContextKind::CurrentNominal);
  addLeadingDot(Builder);
  Builder.addBaseName(Name);
  addTypeAnnotation(Builder, TypeAnnotation);
}

void CompletionLookup::addEnumElementRef(const EnumElementDecl *EED,
                                         DeclVisibilityKind Reason,
                                         DynamicLookupInfo dynamicLookupInfo,
                                         bool HasTypeContext) {
  if (!EED->hasName() || !EED->isAccessibleFrom(CurrDeclContext) ||
      EED->shouldHideFromEditor())
    return;

  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(EED, Reason, dynamicLookupInfo));
  Builder.setAssociatedDecl(EED);

  addLeadingDot(Builder);
  addValueBaseName(Builder, EED->getBaseIdentifier());

  // Enum element is of function type; (Self.type) -> Self or
  // (Self.Type) -> (Args...) -> Self.
  Type EnumType = getTypeOfMember(EED, dynamicLookupInfo);
  if (EnumType->is<AnyFunctionType>())
    EnumType = EnumType->castTo<AnyFunctionType>()->getResult();

  if (EnumType->is<FunctionType>()) {
    Builder.addLeftParen();
    Builder.addCallArgumentPatterns(EnumType->castTo<FunctionType>(),
                                    EED->getParameterList(), CurrDeclContext,
                                    EED->getGenericSignatureOfContext());
    Builder.addRightParen();

    // Extract result as the enum type.
    EnumType = EnumType->castTo<FunctionType>()->getResult();
  }

  addTypeAnnotation(Builder, EnumType, EED->getGenericSignatureOfContext());

  if (isUnresolvedMemberIdealType(EnumType))
    Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific);
}

static StringRef getTypeAnnotationString(const MacroDecl *MD,
                                         SmallVectorImpl<char> &stash) {
  auto roles = MD->getMacroRoles();
  SmallVector<StringRef, 1> roleStrs;
  for (auto role : getAllMacroRoles()) {
    if (!roles.contains(role))
      continue;

    switch (role) {
    case MacroRole::Accessor:
      roleStrs.push_back("Accessor Macro");
      break;
    case MacroRole::CodeItem:
      roleStrs.push_back("Code Item Macro");
      break;
    case MacroRole::Conformance:
      roleStrs.push_back("Conformance Macro");
      break;
    case MacroRole::Declaration:
      roleStrs.push_back("Declaration Macro");
      break;
    case MacroRole::Expression:
      roleStrs.push_back("Expression Macro");
      break;
    case MacroRole::Extension:
      roleStrs.push_back("Extension Macro");
      break;
    case MacroRole::Member:
      roleStrs.push_back("Member Macro");
      break;
    case MacroRole::MemberAttribute:
      roleStrs.push_back("Member Attribute Macro");
      break;
    case MacroRole::Peer:
      roleStrs.push_back("Peer Macro");
      break;
    case MacroRole::Preamble:
      roleStrs.push_back("Preamble Macro");
      break;
    case MacroRole::Body:
      roleStrs.push_back("Body Macro");
      break;
    }
  }

  if (roleStrs.empty())
    return "Macro";
  if (roleStrs.size() == 1)
    return roleStrs[0];

  assert(stash.empty());
  llvm::raw_svector_ostream OS(stash);
  llvm::interleave(roleStrs, OS, ", ");
  return {stash.data(), stash.size()};
}

void CompletionLookup::addMacroCallArguments(const MacroDecl *MD,
                                             DeclVisibilityKind Reason,
                                             bool forTrivialTrailingClosure) {
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(MD, Reason, DynamicLookupInfo()));
  Builder.setAssociatedDecl(MD);

  addValueBaseName(Builder, MD->getBaseIdentifier());

  if (forTrivialTrailingClosure) {
    Builder.addBraceStmtWithCursor(" { code }");
  } else if (MD->parameterList && MD->parameterList->size() > 0) {
    auto *macroTy = MD->getInterfaceType()->castTo<AnyFunctionType>();
    Builder.addLeftParen();
    Builder.addCallArgumentPatterns(macroTy, MD->parameterList, CurrDeclContext,
                                    MD->getGenericSignature());
    Builder.addRightParen();
  }

  auto roles = MD->getMacroRoles();
  if (roles.containsOnly(MacroRole::Expression)) {
    addTypeAnnotation(Builder, MD->getResultInterfaceType(),
                      MD->getGenericSignature());
  } else {
    llvm::SmallVector<char, 0> stash;
    Builder.addTypeAnnotation(getTypeAnnotationString(MD, stash));
  }
}

void CompletionLookup::addMacroExpansion(const MacroDecl *MD,
                                         DeclVisibilityKind Reason) {
  if (!MD->hasName() || !MD->isAccessibleFrom(CurrDeclContext) ||
      MD->shouldHideFromEditor())
    return;

  OptionSet<CustomAttributeKind> expectedKinds =
      expectedTypeContext.getExpectedCustomAttributeKinds();
  if (expectedKinds) {
    CodeCompletionMacroRoles expectedRoles =
        getCompletionMacroRoles(expectedKinds);
    CodeCompletionMacroRoles roles = getCompletionMacroRoles(MD);
    if (!(roles & expectedRoles))
      return;
  }

  if (hasTrivialTrailingClosure(MD, MD->getInterfaceType()))
    addMacroCallArguments(MD, Reason, /*forTrivialTrailingClosure*/ true);

  addMacroCallArguments(MD, Reason);
}

void CompletionLookup::addKeyword(StringRef Name, Type TypeAnnotation,
                                  SemanticContextKind SK,
                                  CodeCompletionKeywordKind KeyKind,
                                  unsigned NumBytesToErase) {
  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Keyword, SK);
  addLeadingDot(Builder);
  Builder.addKeyword(Name);
  Builder.setKeywordKind(KeyKind);
  if (TypeAnnotation)
    addTypeAnnotation(Builder, TypeAnnotation);
  if (NumBytesToErase > 0)
    Builder.setNumBytesToErase(NumBytesToErase);
}

void CompletionLookup::addKeyword(StringRef Name, StringRef TypeAnnotation,
                                  CodeCompletionKeywordKind KeyKind,
                                  CodeCompletionFlair flair) {
  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword, SemanticContextKind::None);
  Builder.addFlair(flair);
  addLeadingDot(Builder);
  Builder.addKeyword(Name);
  Builder.setKeywordKind(KeyKind);
  if (!TypeAnnotation.empty())
    Builder.addTypeAnnotation(TypeAnnotation);
}

void CompletionLookup::addDeclAttrParamKeyword(StringRef Name,
                                               ArrayRef<StringRef> Parameters,
                                               StringRef Annotation,
                                               bool NeedSpecify) {
  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword, SemanticContextKind::None);
  Builder.addDeclAttrParamKeyword(Name, Parameters, Annotation, NeedSpecify);
}

void CompletionLookup::addDeclAttrKeyword(StringRef Name,
                                          StringRef Annotation) {
  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword, SemanticContextKind::None);
  Builder.addDeclAttrKeyword(Name, Annotation);
}

/// Add the compound function name for the given function.
/// Returns \c true if the compound function name is actually used.
bool CompletionLookup::addCompoundFunctionNameIfDesiable(
    AbstractFunctionDecl *AFD, DeclVisibilityKind Reason,
    DynamicLookupInfo dynamicLookupInfo) {
  auto funcTy =
      getTypeOfMember(AFD, dynamicLookupInfo)->getAs<AnyFunctionType>();
  bool dropCurryLevel = funcTy && AFD->getDeclContext()->isTypeContext() &&
                        !isImplicitlyCurriedInstanceMethod(AFD);
  if (dropCurryLevel)
    funcTy = funcTy->getResult()->getAs<AnyFunctionType>();

  bool useFunctionReference = PreferFunctionReferencesToCalls;
  if (!useFunctionReference && funcTy) {
    // We know that the CodeCompletionResultType is AST-based so we can pass
    // nullptr for USRTypeContext.
    auto maxFuncTyRel = CodeCompletionResultType(funcTy).calculateTypeRelation(
        &expectedTypeContext, CurrDeclContext, /*USRTypeContext=*/nullptr);
    auto maxResultTyRel = CodeCompletionResultType(funcTy->getResult()).calculateTypeRelation(
        &expectedTypeContext, CurrDeclContext, /*USRTypeContext=*/nullptr);
    useFunctionReference = maxFuncTyRel > maxResultTyRel;
  }
  if (!useFunctionReference)
    return false;

  // Check for duplicates with the adjusted type too.
  if (dropCurryLevel && isDuplicate(AFD, funcTy))
    return true;

  CodeCompletionResultBuilder Builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration,
                        getSemanticContext(AFD, Reason, dynamicLookupInfo));
  Builder.setAssociatedDecl(AFD);

  // Base name
  addLeadingDot(Builder);
  addValueBaseName(Builder, AFD->getBaseName());

  // Add the argument labels.
  const auto ArgLabels = AFD->getName().getArgumentNames();
  if (!ArgLabels.empty()) {
    if (!HaveLParen)
      Builder.addLeftParen();
    else
      Builder.addAnnotatedLeftParen();

    for (auto ArgLabel : ArgLabels) {
      if (ArgLabel.empty())
        Builder.addTextChunk("_");
      else
        Builder.addTextChunk(ArgLabel.str());
      Builder.addTextChunk(":");
    }

    Builder.addRightParen();
  }

  if (funcTy)
    addTypeAnnotation(Builder, funcTy, AFD->getGenericSignatureOfContext());

  return true;
}

void CompletionLookup::onLookupNominalTypeMembers(NominalTypeDecl *NTD,
                                                  DeclVisibilityKind Reason) {

  // Remember the decl name to
  SmallString<32> buffer;
  llvm::raw_svector_ostream OS(buffer);
  PrintOptions PS = PrintOptions::printDocInterface();
  PS.FullyQualifiedTypes = true;
  NTD->getDeclaredType()->print(OS, PS);
  NullTerminatedStringRef qualifiedName(
      buffer, *CompletionContext->getResultSink().Allocator);
  CompletionContext->LookedupNominalTypeNames.push_back(qualifiedName);
}

Type CompletionLookup::normalizeTypeForDuplicationCheck(Type Ty) {
  return Ty.transformRec([](Type T) -> std::optional<Type> {
    if (auto opaque = T->getAs<OpaqueTypeArchetypeType>()) {
      /// Opaque type has a _invisible_ substitution map. Since IDE can't
      /// differentiate them, replace it with empty substitution map.
      return Type(OpaqueTypeArchetypeType::get(opaque->getDecl(),
                                               opaque->getInterfaceType(),
                                               /*Substitutions=*/{}));
    }
    return std::nullopt;
  });
}

void CompletionLookup::foundDecl(ValueDecl *D, DeclVisibilityKind Reason,
                                 DynamicLookupInfo dynamicLookupInfo) {
  assert(Reason !=
             DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal &&
         "Including derived requirement in non-override lookup");

  if (D->shouldHideFromEditor())
    return;

  if (IsKeyPathExpr && !KeyPathFilter(D, Reason, dynamicLookupInfo))
    return;

  if (IsSwiftKeyPathExpr && !SwiftKeyPathFilter(D, Reason))
    return;

  // If we've seen this decl+type before (possible when multiple lookups are
  // performed e.g. because of ambiguous base types), bail.
  if (isDuplicate(D, dynamicLookupInfo))
    return;

  // FIXME(InterfaceTypeRequest): Remove this.
  (void)D->getInterfaceType();
  switch (Kind) {
  case LookupKind::ValueExpr:
    if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
      // Do we want compound function names here?
      if (addCompoundFunctionNameIfDesiable(CD, Reason, dynamicLookupInfo))
        return;

      if (auto MT = ExprType->getAs<AnyMetatypeType>()) {
        Type Ty = MT->getInstanceType();
        assert(Ty && "Cannot find instance type.");

        // If instance type is type alias, show users that the constructed
        // type is the typealias instead of the underlying type of the alias.
        std::optional<Type> Result = std::nullopt;
        if (!CD->getInterfaceType()->is<ErrorType>() &&
            isa<TypeAliasType>(Ty.getPointer()) &&
            Ty->getDesugaredType() ==
                CD->getResultInterfaceType().getPointer()) {
          Result = Ty;
        }
        // If the expression type is not a static metatype or an archetype, the
        // base is not a type. Direct call syntax is illegal on values, so we
        // only add initializer completions if we do not have a left parenthesis
        // and either the initializer is required, the base type's instance type
        // is not a class, or this is a 'self' or 'super' reference.
        if (IsStaticMetatype || IsUnresolvedMember || Ty->is<ArchetypeType>())
          addConstructorCall(CD, Reason, dynamicLookupInfo, std::nullopt,
                             Result,
                             /*isOnType*/ true);
        else if ((IsSelfRefExpr || IsSuperRefExpr || !Ty->is<ClassType>() ||
                  CD->isRequired()) &&
                 !HaveLParen)
          addConstructorCall(CD, Reason, dynamicLookupInfo, std::nullopt,
                             Result,
                             /*isOnType*/ false);
        return;
      }
      if (!HaveLParen) {
        auto CDC = dyn_cast<ConstructorDecl>(CurrDeclContext);
        if (!CDC)
          return;

        // For classes, we do not want 'init' completions for 'self' in
        // non-convenience initializers and for 'super' in convenience
        // initializers.
        if (ExprType->is<ClassType>()) {
          if ((IsSelfRefExpr && !CDC->isConvenienceInit()) ||
              (IsSuperRefExpr && CDC->isConvenienceInit()))
            return;
        }
        if (IsSelfRefExpr || IsSuperRefExpr)
          addConstructorCall(CD, Reason, dynamicLookupInfo, std::nullopt,
                             std::nullopt,
                             /*IsOnType=*/false);
      }
      return;
    }

    if (HaveLParen)
      return;

    LLVM_FALLTHROUGH;

  case LookupKind::ValueInDeclContext:
  case LookupKind::ImportFromModule:
    if (auto *VD = dyn_cast<VarDecl>(D)) {
      addVarDeclRef(VD, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *FD = dyn_cast<FuncDecl>(D)) {
      // We cannot call operators with a postfix parenthesis syntax.
      if (FD->isBinaryOperator() || FD->isUnaryOperator())
        return;

      // We cannot call accessors.  We use VarDecls and SubscriptDecls to
      // produce completions that refer to getters and setters.
      if (isa<AccessorDecl>(FD))
        return;

      // Do we want compound function names here?
      if (addCompoundFunctionNameIfDesiable(FD, Reason, dynamicLookupInfo))
        return;

      addMethodCall(FD, Reason, dynamicLookupInfo);

      // SE-0253: Callable values of user-defined nominal types.
      if (FD->isCallAsFunctionMethod() && !HaveDot &&
          (!ExprType || !ExprType->is<AnyMetatypeType>())) {
        Type funcType = getTypeOfMember(FD, dynamicLookupInfo)
                            ->castTo<AnyFunctionType>()
                            ->getResult();

        // Check for duplicates with the adjusted type too.
        if (isDuplicate(FD, funcType))
          return;

        addFunctionCallPattern(
            funcType->castTo<AnyFunctionType>(), FD,
            getSemanticContext(FD, Reason, dynamicLookupInfo));
      }
      return;
    }

    if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
      addNominalTypeRef(NTD, Reason, dynamicLookupInfo);
      addConstructorCallsForType(NTD->getDeclaredInterfaceType(),
                                 NTD->getName(), Reason, dynamicLookupInfo);
      return;
    }

    if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
      addTypeAliasRef(TAD, Reason, dynamicLookupInfo);
      auto type = TAD->mapTypeIntoEnvironment(TAD->getDeclaredInterfaceType());
      if (type->mayHaveMembers())
        addConstructorCallsForType(type, TAD->getName(), Reason,
                                   dynamicLookupInfo);
      return;
    }

    if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
      addGenericTypeParamRef(GP, Reason, dynamicLookupInfo);
      auto type =
          CurrDeclContext->mapTypeIntoEnvironment(GP->getDeclaredInterfaceType());
      addConstructorCallsForType(type, GP->getName(), Reason,
                                 dynamicLookupInfo);
      return;
    }

    if (auto *AT = dyn_cast<AssociatedTypeDecl>(D)) {
      addAssociatedTypeRef(AT, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *EED = dyn_cast<EnumElementDecl>(D)) {
      addEnumElementRef(EED, Reason, dynamicLookupInfo,
                        /*HasTypeContext=*/false);
      return;
    }

    // Swift key path allows .[0]
    if (auto *SD = dyn_cast<SubscriptDecl>(D)) {
      addSubscriptCall(SD, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *MD = dyn_cast<MacroDecl>(D)) {
      addMacroExpansion(MD, Reason);
      return;
    }
    return;

  case LookupKind::EnumElement:
    handleEnumElement(D, Reason, dynamicLookupInfo);
    return;

  case LookupKind::Type:
  case LookupKind::TypeInDeclContext:
    if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
      addNominalTypeRef(NTD, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
      addGenericTypeParamRef(GP, Reason, dynamicLookupInfo);
      return;
    }

    LLVM_FALLTHROUGH;
  case LookupKind::GenericRequirement:

    if (TypeAliasDecl *TAD = dyn_cast<TypeAliasDecl>(D)) {
      if (Kind == LookupKind::GenericRequirement &&
          !canBeUsedAsRequirementFirstType(BaseType, TAD))
        return;
      addTypeAliasRef(TAD, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *AT = dyn_cast<AssociatedTypeDecl>(D)) {
      addAssociatedTypeRef(AT, Reason, dynamicLookupInfo);
      return;
    }

    return;
  case LookupKind::StoredProperty:
    if (auto *VD = dyn_cast<VarDecl>(D)) {
      if (VD->hasStorage()) {
        addVarDeclRef(VD, Reason, dynamicLookupInfo);
      }
      return;
    }
  }
}

bool CompletionLookup::handleEnumElement(ValueDecl *D,
                                         DeclVisibilityKind Reason,
                                         DynamicLookupInfo dynamicLookupInfo) {
  if (auto *EED = dyn_cast<EnumElementDecl>(D)) {
    addEnumElementRef(EED, Reason, dynamicLookupInfo,
                      /*HasTypeContext=*/true);
    return true;
  } else if (auto *ED = dyn_cast<EnumDecl>(D)) {
    for (auto *Ele : ED->getAllElements()) {
      addEnumElementRef(Ele, Reason, dynamicLookupInfo,
                        /*HasTypeContext=*/true);
    }
    return true;
  }
  return false;
}

bool CompletionLookup::tryTupleExprCompletions(Type ExprType) {
  auto *TT = ExprType->getAs<TupleType>();
  if (!TT)
    return false;

  unsigned Index = 0;
  for (auto TupleElt : TT->getElements()) {
    auto Ty = TupleElt.getType();
    if (TupleElt.hasName()) {
      addBuiltinMemberRef(TupleElt.getName().str(), Ty);
    } else {
      llvm::SmallString<4> IndexStr;
      {
        llvm::raw_svector_ostream OS(IndexStr);
        OS << Index;
      }
      addBuiltinMemberRef(IndexStr, Ty);
    }
    ++Index;
  }
  return true;
}

void CompletionLookup::tryFunctionIsolationCompletion(Type ExprType) {
  auto *FT = ExprType->getAs<FunctionType>();
  if (!FT || !FT->getIsolation().isErased())
    return;

  // The type of `.isolation` is `(any Actor)?`
  auto *actorProto = Ctx.getProtocol(KnownProtocolKind::Actor);
  auto memberTy = OptionalType::get(actorProto->getDeclaredExistentialType());

  addBuiltinMemberRef(Ctx.Id_isolation.str(), memberTy);
}

bool CompletionLookup::tryFunctionCallCompletions(
    Type ExprType, const ValueDecl *VD,
    std::optional<SemanticContextKind> SemanticContext) {
  ExprType = ExprType->getRValueType();
  if (auto AFT = ExprType->getAs<AnyFunctionType>()) {
    if (auto *AFD = dyn_cast_or_null<AbstractFunctionDecl>(VD)) {
      addFunctionCallPattern(AFT, AFD, SemanticContext);
    } else {
      addFunctionCallPattern(AFT);
    }
    return true;
  }
  return false;
}

bool CompletionLookup::tryModuleCompletions(Type ExprType,
                                            CodeCompletionFilter Filter) {
  if (auto MT = ExprType->getAs<ModuleType>()) {
    ModuleDecl *M = MT->getModule();

    // Only lookup this module's symbols from the cache if it is not the
    // current module.
    if (M == CurrModule)
      return false;

    // If the module is shadowed by a separately imported overlay(s), look up
    // the symbols from the overlay(s) instead.
    SmallVector<ModuleDecl *, 1> ShadowingOrOriginal;
    CurrDeclContext->getSeparatelyImportedOverlays(M, ShadowingOrOriginal);
    if (ShadowingOrOriginal.empty())
      ShadowingOrOriginal.push_back(M);
    for (ModuleDecl *M : ShadowingOrOriginal) {
      RequestedResultsTy Request =
          RequestedResultsTy::fromModule(M, Filter).needLeadingDot(needDot());
      RequestedCachedResults.insert(Request);
    }
    return true;
  }
  return false;
}

bool CompletionLookup::tryUnwrappedCompletions(Type ExprType, bool isIUO) {
  // FIXME: consider types convertible to T?.

  ExprType = ExprType->getRValueType();
  // FIXME: We don't always pass down whether a type is from an
  // unforced IUO.
  if (isIUO) {
    if (Type Unwrapped = ExprType->getOptionalObjectType()) {
      lookupVisibleMemberDecls(*this, Unwrapped, DotLoc, CurrDeclContext,
                               IncludeInstanceMembers,
                               /*includeDerivedRequirements*/ false,
                               /*includeProtocolExtensionMembers*/ true);
      return true;
    }
    assert(IsUnwrappedOptional &&
           "IUOs should be optional if not bound/forced");
    return false;
  }

  if (Type Unwrapped = ExprType->getOptionalObjectType()) {
    llvm::SaveAndRestore<bool> ChangeNeedOptionalUnwrap(NeedOptionalUnwrap,
                                                        true);
    if (DotLoc.isValid()) {
      // Let's not erase the dot if the completion is after a swift key path
      // root because \A?.?.member is the correct way to access wrapped type
      // member from an optional key path root.
      auto loc = IsAfterSwiftKeyPathRoot ? DotLoc.getAdvancedLoc(1) : DotLoc;
      NumBytesToEraseForOptionalUnwrap = Ctx.SourceMgr.getByteDistance(
          loc, Ctx.SourceMgr.getIDEInspectionTargetLoc());
    } else {
      NumBytesToEraseForOptionalUnwrap = 0;
    }
    if (NumBytesToEraseForOptionalUnwrap <=
        CodeCompletionResult::MaxNumBytesToErase) {
      // Add '.isolation' to @isolated(any) functions.
      tryFunctionIsolationCompletion(Unwrapped);

      if (!tryTupleExprCompletions(Unwrapped)) {
        lookupVisibleMemberDecls(*this, Unwrapped, DotLoc,
                                 CurrDeclContext,
                                 IncludeInstanceMembers,
                                 /*includeDerivedRequirements*/ false,
                                 /*includeProtocolExtensionMembers*/ true);
      }
    }
    return true;
  }
  return false;
}

void CompletionLookup::getPostfixKeywordCompletions(Type ExprType,
                                                    Expr *ParsedExpr) {
  if (IsSuperRefExpr)
    return;

  NeedLeadingDot = !HaveDot;

  if (!ExprType->getAs<ModuleType>()) {
    addKeyword(getTokenText(tok::kw_self), ExprType->getRValueType(),
               SemanticContextKind::CurrentNominal,
               CodeCompletionKeywordKind::kw_self);
  }

  if (isa<TypeExpr>(ParsedExpr)) {
    if (auto *T = ExprType->getAs<AnyMetatypeType>()) {
      auto instanceTy = T->getInstanceType();
      if (instanceTy->isAnyExistentialType()) {
        addKeyword("Protocol", MetatypeType::get(instanceTy),
                   SemanticContextKind::CurrentNominal);
        addKeyword("Type", ExistentialMetatypeType::get(instanceTy),
                   SemanticContextKind::CurrentNominal);
      } else {
        addKeyword("Type", MetatypeType::get(instanceTy),
                   SemanticContextKind::CurrentNominal);
      }
    }
  }
}

void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD,
                                               bool IsDeclUnapplied) {
  Kind = LookupKind::ValueExpr;
  NeedLeadingDot = !HaveDot;

  ExprType = ExprType->getRValueType();
  assert(!ExprType->hasTypeParameter());

  this->ExprType = ExprType;

  // Open existential types, so that lookupVisibleMemberDecls() can properly
  // substitute them.
  bool WasOptional = false;
  if (auto OptionalType = ExprType->getOptionalObjectType()) {
    ExprType = OptionalType;
    WasOptional = true;
  }

  if (!ExprType->getMetatypeInstanceType()->isAnyObject()) {
    if (ExprType->isAnyExistentialType()) {
      ExprType = ExistentialArchetypeType::getAny(ExprType->getCanonicalType());
    }
  }
  if (!IsSelfRefExpr && !IsSuperRefExpr && ExprType->getAnyNominal() &&
      ExprType->getAnyNominal()->isActor()) {
    IsCrossActorReference = true;
  }

  if (WasOptional)
    ExprType = OptionalType::get(ExprType);

  // Handle special cases

  // Add '.isolation' to @isolated(any) functions.
  tryFunctionIsolationCompletion(ExprType);

  bool isIUO = VD && VD->isImplicitlyUnwrappedOptional();
  if (tryFunctionCallCompletions(ExprType, IsDeclUnapplied ? VD : nullptr))
    return;
  if (tryModuleCompletions(ExprType, {CodeCompletionFilterFlag::Expr,
                                      CodeCompletionFilterFlag::Type}))
    return;
  if (tryTupleExprCompletions(ExprType))
    return;
  // Don't check/return so we still add the members of Optional itself below
  tryUnwrappedCompletions(ExprType, isIUO);

  lookupVisibleMemberDecls(*this, ExprType, DotLoc, CurrDeclContext,
                           IncludeInstanceMembers,
                           /*includeDerivedRequirements*/ false,
                           /*includeProtocolExtensionMembers*/ true);
}

void CompletionLookup::getStoredPropertyCompletions(const NominalTypeDecl *D) {
  Kind = LookupKind::StoredProperty;
  NeedLeadingDot = false;

  lookupVisibleMemberDecls(*this, D->getDeclaredInterfaceType(),
                           /*DotLoc=*/SourceLoc(), CurrDeclContext,
                           /*IncludeInstanceMembers*/ true,
                           /*includeDerivedRequirements*/ false,
                           /*includeProtocolExtensionMembers*/ false);
}

void CompletionLookup::collectOperators(
    SmallVectorImpl<OperatorDecl *> &results) {
  assert(CurrDeclContext);
  for (auto import : namelookup::getAllImports(CurrDeclContext))
    import.importedModule->getOperatorDecls(results);
}

void CompletionLookup::addPostfixBang(Type resultType) {
  CodeCompletionResultBuilder builder = makeResultBuilder(
      CodeCompletionResultKind::BuiltinOperator, SemanticContextKind::None);
  // FIXME: we can't use the exclamation mark chunk kind, or it isn't
  // included in the completion name.
  builder.addTextChunk("!");
  assert(resultType);
  addTypeAnnotation(builder, resultType);
}

void CompletionLookup::addPostfixOperatorCompletion(OperatorDecl *op,
                                                    Type resultType) {
  // FIXME: we should get the semantic context of the function, not the
  // operator decl.
  auto semanticContext =
      getSemanticContext(op, DeclVisibilityKind::VisibleAtTopLevel, {});
  CodeCompletionResultBuilder builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration, semanticContext);

  // FIXME: handle variable amounts of space.
  if (HaveLeadingSpace)
    builder.setNumBytesToErase(1);
  builder.setAssociatedDecl(op);
  builder.addBaseName(op->getName().str());
  assert(resultType);
  addTypeAnnotation(builder, resultType);
}

void CompletionLookup::addAssignmentOperator(Type RHSType) {
  CodeCompletionResultBuilder builder = makeResultBuilder(
      CodeCompletionResultKind::BuiltinOperator, SemanticContextKind::None);

  if (HaveLeadingSpace)
    builder.addAnnotatedWhitespace(" ");
  else
    builder.addWhitespace(" ");
  builder.addEqual();
  builder.addWhitespace(" ");
  assert(RHSType);
  Type contextTy;
  if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
    contextTy = typeContext->getDeclaredTypeInContext();
  builder.addCallArgument(Identifier(), RHSType, contextTy,
                          /*IsForOperator=*/true);
}

void CompletionLookup::addInfixOperatorCompletion(OperatorDecl *op,
                                                  Type resultType,
                                                  Type RHSType) {
  // FIXME: we should get the semantic context of the function, not the
  // operator decl.
  auto semanticContext =
      getSemanticContext(op, DeclVisibilityKind::VisibleAtTopLevel, {});
  CodeCompletionResultBuilder builder =
      makeResultBuilder(CodeCompletionResultKind::Declaration, semanticContext);
  builder.setAssociatedDecl(op);

  if (HaveLeadingSpace)
    builder.addAnnotatedWhitespace(" ");
  else
    builder.addWhitespace(" ");
  builder.addBaseName(op->getName().str());
  builder.addWhitespace(" ");
  if (RHSType) {
    Type contextTy;
    if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
      contextTy = typeContext->getDeclaredTypeInContext();
    builder.addCallArgument(Identifier(), RHSType, contextTy,
                            /*IsForOperator=*/true);
  }
  if (resultType)
    addTypeAnnotation(builder, resultType);
}

void CompletionLookup::addTypeRelationFromProtocol(
    CodeCompletionResultBuilder &builder, CodeCompletionLiteralKind kind) {
  Type literalType;

  // The literal can produce any type that conforms to its ExpressibleBy
  // protocol. Figure out as which type we want to show it in code completion.
  auto *PD = Ctx.getProtocol(protocolForLiteralKind(kind));
  for (auto T : expectedTypeContext.getPossibleTypes()) {
    if (!T)
      continue;

    // Convert through optional types unless we're looking for a protocol
    // that Optional itself conforms to.
    if (kind != CodeCompletionLiteralKind::NilLiteral) {
      if (auto optionalObjT = T->getOptionalObjectType()) {
        T = optionalObjT;
      }
    }

    // Check for conformance to the literal protocol.
    if (T->getAnyNominal()) {
      if (lookupConformance(T, PD)) {
        literalType = T;
        break;
      }
    }
  }

  // Fallback to showing the default type.
  if (!literalType) {
    literalType = defaultTypeLiteralKind(kind, Ctx);
  }
  if (literalType) {
    addTypeAnnotation(builder, literalType);
    builder.setResultTypes(literalType);
    builder.setTypeContext(expectedTypeContext, CurrDeclContext);
  }
}

void CompletionLookup::addValueLiteralCompletions() {
  auto &context = CurrDeclContext->getASTContext();

  CodeCompletionFlair flair;
  if (isCodeCompletionAtTopLevelOfLibraryFile(CurrDeclContext))
    flair |= CodeCompletionFlairBit::ExpressionAtNonScriptOrMainFileScope;

  auto addFromProto =
      [&](CodeCompletionLiteralKind kind,
          llvm::function_ref<void(CodeCompletionResultBuilder &)> consumer,
          bool isKeyword = false) {
        CodeCompletionResultBuilder builder = makeResultBuilder(
            CodeCompletionResultKind::Literal, SemanticContextKind::None);
        builder.setLiteralKind(kind);
        builder.addFlair(flair);

        consumer(builder);
        addTypeRelationFromProtocol(builder, kind);
      };

  // FIXME: the pedantically correct way is to resolve Swift.*LiteralType.

  using LK = CodeCompletionLiteralKind;
  using Builder = CodeCompletionResultBuilder;

  // Add literal completions that conform to specific protocols.
  addFromProto(LK::IntegerLiteral,
               [](Builder &builder) { builder.addTextChunk("0"); });
  addFromProto(
      LK::BooleanLiteral, [](Builder &builder) { builder.addBaseName("true"); },
      /*isKeyword=*/true);
  addFromProto(
      LK::BooleanLiteral,
      [](Builder &builder) { builder.addBaseName("false"); },
      /*isKeyword=*/true);
  addFromProto(
      LK::NilLiteral, [](Builder &builder) { builder.addBaseName("nil"); },
      /*isKeyword=*/true);
  addFromProto(LK::StringLiteral, [&](Builder &builder) {
    builder.addTextChunk("\"");
    builder.addSimpleNamedParameter("abc");
    builder.addTextChunk("\"");
  });
  addFromProto(LK::ArrayLiteral, [&](Builder &builder) {
    builder.addLeftBracket();
    builder.addSimpleNamedParameter("values");
    builder.addRightBracket();
  });
  addFromProto(LK::DictionaryLiteral, [&](Builder &builder) {
    builder.addLeftBracket();
    builder.addSimpleNamedParameter("key");
    builder.addTextChunk(": ");
    builder.addSimpleNamedParameter("value");
    builder.addRightBracket();
  });

  // Optionally add object literals.
  if (Sink.includeObjectLiterals) {
    auto floatType = context.getFloatType();
    addFromProto(LK::ColorLiteral, [&](Builder &builder) {
      builder.addBaseName("#colorLiteral");
      builder.addLeftParen();
      builder.addCallArgument(context.getIdentifier("red"), floatType);
      builder.addComma();
      builder.addCallArgument(context.getIdentifier("green"), floatType);
      builder.addComma();
      builder.addCallArgument(context.getIdentifier("blue"), floatType);
      builder.addComma();
      builder.addCallArgument(context.getIdentifier("alpha"), floatType);
      builder.addRightParen();
    });

    auto stringType = context.getStringType();
    addFromProto(LK::ImageLiteral, [&](Builder &builder) {
      builder.addBaseName("#imageLiteral");
      builder.addLeftParen();
      builder.addCallArgument(context.getIdentifier("resourceName"),
                              stringType);
      builder.addRightParen();
    });
  }

  // Add tuple completion (item, item).
  {
    CodeCompletionResultBuilder builder = makeResultBuilder(
        CodeCompletionResultKind::Literal, SemanticContextKind::None);
    builder.setLiteralKind(LK::Tuple);
    builder.addFlair(flair);

    builder.addLeftParen();
    builder.addSimpleNamedParameter("values");
    builder.addRightParen();
    for (auto T : expectedTypeContext.getPossibleTypes()) {
      if (T && T->is<TupleType>() && !T->isVoid()) {
        addTypeAnnotation(builder, T);
        builder.setResultTypes(T);
        builder.setTypeContext(expectedTypeContext, CurrDeclContext);
        break;
      }
    }
  }
}

void CompletionLookup::addObjCPoundKeywordCompletions(bool needPound) {
  if (!Ctx.LangOpts.EnableObjCInterop)
    return;

  // If the expected type is ObjectiveC.Selector, add #selector. If
  // it's String, add #keyPath.
  bool addedSelector = false;
  bool addedKeyPath = false;

  for (auto T : expectedTypeContext.getPossibleTypes()) {
    T = T->lookThroughAllOptionalTypes();
    if (auto structDecl = T->getStructOrBoundGenericStruct()) {
      if (!addedSelector && structDecl->getName() == Ctx.Id_Selector &&
          structDecl->getParentModule()->getName() == Ctx.Id_ObjectiveC) {
        addPoundSelector(needPound);
        if (addedKeyPath)
          break;
        addedSelector = true;
        continue;
      }
    }

    if (!addedKeyPath && T->isString()) {
      addPoundKeyPath(needPound);
      if (addedSelector)
        break;
      addedKeyPath = true;
      continue;
    }
  }
}

void CompletionLookup::getMacroCompletions(CodeCompletionMacroRoles roles) {
  RequestedCachedResults.insert(
      RequestedResultsTy::topLevelResults(getCompletionFilter(roles)));
}

void CompletionLookup::getValueCompletionsInDeclContext(SourceLoc Loc,
                                                        DeclFilter Filter,
                                                        bool LiteralCompletions,
                                                        bool ModuleQualifier) {
  ExprType = Type();
  Kind = LookupKind::ValueInDeclContext;
  NeedLeadingDot = false;

  AccessFilteringDeclConsumer AccessFilteringConsumer(CurrDeclContext, *this);
  FilteredDeclConsumer FilteringConsumer(AccessFilteringConsumer, Filter);

  lookupVisibleDecls(FilteringConsumer, Loc, CurrDeclContext,
                     /*IncludeTopLevel=*/false);

  CodeCompletionFilter filter{CodeCompletionFilterFlag::Expr,
                              CodeCompletionFilterFlag::Type};
  if (ModuleQualifier) {
    filter |= CodeCompletionFilterFlag::Module;
  }
  RequestedCachedResults.insert(RequestedResultsTy::topLevelResults(filter));

  if (CompletionContext) {
    // FIXME: this is an awful simplification that says all and only enums can
    // use implicit member syntax (leading dot). Computing the accurate answer
    // using lookup (e.g. getUnresolvedMemberCompletions) is too expensive,
    // and for some clients this approximation is good enough.
    CompletionContext->MayUseImplicitMemberExpr =
        llvm::any_of(expectedTypeContext.getPossibleTypes(), [](Type T) {
          if (auto *NTD = T->getAnyNominal())
            return isa<EnumDecl>(NTD);
          return false;
        });
  }

  if (LiteralCompletions) {
    addValueLiteralCompletions();
  }

  addObjCPoundKeywordCompletions(/*needPound=*/true);
}

bool CompletionLookup::isInitializerOnOptional(Type T, ValueDecl *VD) {
  bool IsOptionalType = false;
  IsOptionalType |= static_cast<bool>(T->getOptionalObjectType());
  if (auto *NTD = T->getAnyNominal()) {
    IsOptionalType |= NTD->getBaseIdentifier() ==
                      VD->getASTContext().Id_OptionalNilComparisonType;
  }
  if (IsOptionalType && VD->getModuleContext()->isStdlibModule() &&
      isa<ConstructorDecl>(VD)) {
    return true;
  } else {
    return false;
  }
}

void CompletionLookup::getUnresolvedMemberCompletions(Type T) {
  if (!T->mayHaveMembers())
    return;

  NeedLeadingDot = !HaveDot;

  if (auto objT = T->getOptionalObjectType()) {
    // Add 'nil' keyword with erasing '.' instruction.
    unsigned bytesToErase = 0;
    auto &SM = CurrDeclContext->getASTContext().SourceMgr;
    if (DotLoc.isValid())
      bytesToErase = SM.getByteDistance(DotLoc, SM.getIDEInspectionTargetLoc());
    addKeyword("nil", T, SemanticContextKind::None,
               CodeCompletionKeywordKind::kw_nil, bytesToErase);
  }

  // We can only say .foo where foo is a static member of the contextual
  // type and has the same type (or if the member is a function, then the
  // same result type) as the contextual type.
  FilteredDeclConsumer consumer(*this,
                                [=](ValueDecl *VD, DeclVisibilityKind Reason,
                                    DynamicLookupInfo dynamicLookupInfo) {
                                  // In optional context, ignore
                                  // '.init(<some>)', 'init(nilLiteral:)',
                                  return !isInitializerOnOptional(T, VD);
                                });

  auto baseType = MetatypeType::get(T);
  llvm::SaveAndRestore<LookupKind> SaveLook(Kind, LookupKind::ValueExpr);
  llvm::SaveAndRestore<Type> SaveType(ExprType, baseType);
  llvm::SaveAndRestore<bool> SaveUnresolved(IsUnresolvedMember, true);
  lookupVisibleMemberDecls(consumer, baseType, DotLoc, CurrDeclContext,
                           /*includeInstanceMembers=*/false,
                           /*includeDerivedRequirements*/ false,
                           /*includeProtocolExtensionMembers*/ true);
}

void CompletionLookup::getEnumElementPatternCompletions(Type T) {
  if (!isa_and_nonnull<EnumDecl>(T->getAnyNominal()))
    return;

  auto baseType = MetatypeType::get(T);
  llvm::SaveAndRestore<LookupKind> SaveLook(Kind, LookupKind::EnumElement);
  llvm::SaveAndRestore<Type> SaveType(ExprType, baseType);
  llvm::SaveAndRestore<bool> SaveUnresolved(IsUnresolvedMember, true);
  lookupVisibleMemberDecls(*this, baseType, DotLoc, CurrDeclContext,
                           /*includeInstanceMembers=*/false,
                           /*includeDerivedRequirements=*/false,
                           /*includeProtocolExtensionMembers=*/true);
}

void CompletionLookup::getUnresolvedMemberCompletions(ArrayRef<Type> Types) {
  NeedLeadingDot = !HaveDot;

  SmallPtrSet<CanType, 4> seenTypes;
  for (auto T : Types) {
    if (!T || !seenTypes.insert(T->getCanonicalType()).second)
      continue;

    if (auto objT = T->getOptionalObjectType()) {
      // If this is optional type, perform completion for the object type.
      // i.e. 'let _: Enum??? = .enumMember' is legal.
      objT = objT->lookThroughAllOptionalTypes();
      if (seenTypes.insert(objT->getCanonicalType()).second)
        getUnresolvedMemberCompletions(objT);
    }
    getUnresolvedMemberCompletions(T);
  }
}

void CompletionLookup::addCallArgumentCompletionResults(
    ArrayRef<PossibleParamInfo> ParamInfos, bool isLabeledTrailingClosure) {
  Type ContextType;
  if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
    ContextType = typeContext->getDeclaredTypeInContext();

  for (auto Info : ParamInfos) {
    const auto *Arg = Info.Param;
    if (!Arg)
      continue;
    CodeCompletionResultBuilder Builder = makeResultBuilder(
        CodeCompletionResultKind::Pattern,
        // FIXME: SemanticContextKind::Local is not correct.
        // Use 'None' (and fix prioritization) or introduce a new context.
        SemanticContextKind::Local);
    Builder.addCallArgument(Arg->getLabel(), Identifier(), Arg->getPlainType(),
                            ContextType, Arg->isVariadic(), Arg->isInOut(),
                            /*IsIUO=*/false, Arg->isAutoClosure(),
                            isLabeledTrailingClosure,
                            /*IsForOperator=*/false,
                            /*HasDefault=*/false);
    Builder.addFlair(CodeCompletionFlairBit::ArgumentLabels);
    auto Ty = Arg->getPlainType();
    if (Arg->isInOut()) {
      Ty = InOutType::get(Ty);
    } else if (Arg->isAutoClosure()) {
      // 'Ty' may be ErrorType.
      if (auto funcTy = Ty->getAs<FunctionType>())
        Ty = funcTy->getResult();
    }
    // The type annotation is the argument type. But the argument label itself
    // does not produce an expression with a result type so we set the result
    // type as being not applicable.
    addTypeAnnotation(Builder, Ty);
    Builder.setResultTypeNotApplicable();
  }
}

void CompletionLookup::getTypeCompletions(Type BaseType) {
  if (tryModuleCompletions(BaseType, CodeCompletionFilterFlag::Type))
    return;
  Kind = LookupKind::Type;
  this->BaseType = BaseType;
  NeedLeadingDot = !HaveDot;
  lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType), DotLoc,
                           CurrDeclContext, IncludeInstanceMembers,
                           /*includeDerivedRequirements*/ false,
                           /*includeProtocolExtensionMembers*/ false);
  if (BaseType->isAnyExistentialType()) {
    addKeyword("Protocol", MetatypeType::get(BaseType));
    addKeyword("Type", ExistentialMetatypeType::get(BaseType));
  } else if (!BaseType->is<ModuleType>()) {
    addKeyword("Type", MetatypeType::get(BaseType));
  }
}

void CompletionLookup::getInvertedTypeCompletions() {
  Kind = LookupKind::Type;

  auto addCompletion = [&](InvertibleProtocolKind invertableKind) {
    auto *P = Ctx.getProtocol(getKnownProtocolKind(invertableKind));
    if (!P)
      return;

    addNominalTypeRef(P, DeclVisibilityKind::VisibleAtTopLevel,
                      DynamicLookupInfo());
  };
#define INVERTIBLE_PROTOCOL(Name, Bit)         \
  addCompletion(InvertibleProtocolKind::Name);
#include "swift/ABI/InvertibleProtocols.def"
}

void CompletionLookup::getGenericRequirementCompletions(
    DeclContext *DC, SourceLoc CodeCompletionLoc) {
  auto genericSig = DC->getGenericSignatureOfContext();
  if (!genericSig)
    return;

  for (auto GPT : genericSig.getGenericParams()) {
    addGenericTypeParamRef(GPT->getDecl(), DeclVisibilityKind::GenericParameter,
                           {});
  }

  // For non-protocol nominal type decls, only suggest generic parameters.
  if (auto D = DC->getAsDecl())
    if (isa<NominalTypeDecl>(D) && !isa<ProtocolDecl>(D))
      return;

  auto typeContext = DC->getInnermostTypeContext();
  if (!typeContext)
    return;

  auto selfTy = typeContext->getSelfTypeInContext();
  Kind = LookupKind::GenericRequirement;
  this->BaseType = selfTy;
  NeedLeadingDot = false;
  lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy), DotLoc,
                           CurrDeclContext, IncludeInstanceMembers,
                           /*includeDerivedRequirements*/ false,
                           /*includeProtocolExtensionMembers*/ true);
  // We not only allow referencing nested types/typealiases directly, but also
  // qualified by the current type, as long as it's a top-level type (nested
  // types need to be qualified). Thus also suggest current self type so the
  // user can do a memberwise lookup on it.
  if (auto *NTD = typeContext->getSelfNominalTypeDecl()) {
    if (!NTD->getDeclContext()->isTypeContext()) {
      addNominalTypeRef(NTD, DeclVisibilityKind::LocalDecl,
                        DynamicLookupInfo());
    }
  }

  // Self is also valid in all cases in which it can be used in function
  // bodies. Suggest it if applicable.
  getSelfTypeCompletionInDeclContext(CodeCompletionLoc,
                                     /*isForResultType=*/false);
}

bool CompletionLookup::canUseAttributeOnDecl(DeclAttrKind DAK, bool IsInSil,
                                             const LangOptions &langOpts,
                                             std::optional<DeclKind> DK,
                                             StringRef Name) {
  if (DeclAttribute::isUserInaccessible(DAK))
    return false;
  if (DeclAttribute::isDeclModifier(DAK))
    return false;
  if (DeclAttribute::shouldBeRejectedByParser(DAK))
    return false;
  if (!IsInSil && DeclAttribute::isSilOnly(DAK))
    return false;
  if (!langOpts.EnableExperimentalConcurrency
        && DeclAttribute::isConcurrencyOnly(DAK))
    return false;
  if (auto feature = DeclAttribute::getRequiredFeature(DAK))
    if (!langOpts.hasFeature(*feature))
      return false;
  if (!DK.has_value())
    return true;
  // Hide underscored attributes even if they are not marked as user
  // inaccessible. This can happen for attributes that are an underscored
  // variant of a user-accessible attribute (like @_backDeployed)
  if (Name.empty() || Name[0] == '_')
    return false;
  return DeclAttribute::canAttributeAppearOnDeclKind(DAK, DK.value());
}

void CompletionLookup::getAttributeDeclCompletions(bool IsInSil,
                                                   std::optional<DeclKind> DK) {
  // FIXME: also include user-defined attribute keywords
  StringRef TargetName = "Declaration";
  if (DK.has_value()) {
    switch (DK.value()) {
#define DECL(Id, ...)                                                          \
  case DeclKind::Id:                                                           \
    TargetName = #Id;                                                          \
    break;
#include "swift/AST/DeclNodes.def"
    }
  }
  std::string Description = TargetName.str() + " Attribute";
#define DECL_ATTR_ALIAS(KEYWORD, NAME) DECL_ATTR(KEYWORD, NAME, 0, 0)
#define DECL_ATTR(KEYWORD, NAME, ...)                                          \
  if (canUseAttributeOnDecl(DeclAttrKind::NAME, IsInSil, Ctx.LangOpts,         \
                            DK, #KEYWORD))                                     \
    addDeclAttrKeyword(#KEYWORD, Description);
#include "swift/AST/DeclAttr.def"
}

void CompletionLookup::getAttributeDeclParamCompletions(
    ParameterizedDeclAttributeKind AttrKind, int ParamIndex, bool HasLabel) {
  switch (AttrKind) {
  case ParameterizedDeclAttributeKind::Unowned:
    addDeclAttrParamKeyword("safe", /*Parameters=*/{}, "", false);
    addDeclAttrParamKeyword("unsafe", /*Parameters=*/{}, "", false);
    break;
  case ParameterizedDeclAttributeKind::Nonisolated:
    addDeclAttrParamKeyword("unsafe", /*Parameters=*/{}, "", false);
    addDeclAttrParamKeyword("nonsending", /*Parameters=*/{}, "", false);
    break;
  case ParameterizedDeclAttributeKind::InheritActorContext:
    addDeclAttrParamKeyword("always", /*Parameters=*/{}, "", false);
    break;
  case ParameterizedDeclAttributeKind::AccessControl:
    addDeclAttrParamKeyword("set", /*Parameters=*/{}, "", false);
    break;
  case ParameterizedDeclAttributeKind::Available:
    if (ParamIndex == 0) {
      addDeclAttrParamKeyword("*", /*Parameters=*/{}, "Platform", false);

#define AVAILABILITY_PLATFORM(X, PrettyName)                                   \
  addDeclAttrParamKeyword(swift::platformString(PlatformKind::X),              \
                          /*Parameters=*/{}, "Platform", false);
#include "swift/AST/PlatformKinds.def"

    } else {
      addDeclAttrParamKeyword("unavailable", /*Parameters=*/{}, "", false);
      addDeclAttrParamKeyword("message", /*Parameters=*/{}, "Specify message",
                              true);
      addDeclAttrParamKeyword("renamed", /*Parameters=*/{},
                              "Specify replacing name", true);
      addDeclAttrParamKeyword("introduced", /*Parameters=*/{},
                              "Specify version number", true);
      addDeclAttrParamKeyword("deprecated", /*Parameters=*/{},
                              "Specify version number", true);
    }
    break;
  case ParameterizedDeclAttributeKind::FreestandingMacro:
  case ParameterizedDeclAttributeKind::AttachedMacro:
    switch (ParamIndex) {
    case 0:
      for (auto role : getAllMacroRoles()) {
        bool isRoleSupported = isMacroSupported(role, Ctx);
        if (AttrKind == ParameterizedDeclAttributeKind::FreestandingMacro) {
          isRoleSupported &= isFreestandingMacro(role);
        } else if (AttrKind == ParameterizedDeclAttributeKind::AttachedMacro) {
          isRoleSupported &= isAttachedMacro(role);
        }
        if (isRoleSupported) {
          addDeclAttrParamKeyword(getMacroRoleString(role), /*Parameters=*/{},
                                  /*Annotation=*/"", /*NeedsSpecify=*/false);
        }
      }
      break;
    case 1:
      if (HasLabel) {
        for (auto kind : getAllMacroIntroducedDeclNameKinds()) {
          auto name = getMacroIntroducedDeclNameString(kind);
          SmallVector<StringRef, 1> Parameters;
          if (macroIntroducedNameRequiresArgument(kind)) {
            Parameters = {"name"};
          }
          addDeclAttrParamKeyword(name, Parameters, /*Annotation=*/"",
                                  /*NeedsSpecify=*/false);
        }
      } else {
        addDeclAttrParamKeyword("names", /*Parameters=*/{},
                                "Specify declared names",
                                /*NeedsSpecify=*/true);
      }
      break;
    }
    break;
  case ParameterizedDeclAttributeKind::StorageRestrictions: {
    bool suggestInitializesLabel = false;
    bool suggestAccessesLabel = false;
    bool suggestArgument = false;
    switch (static_cast<StorageRestrictionsCompletionKind>(ParamIndex)) {
    case StorageRestrictionsCompletionKind::Label:
      suggestAccessesLabel = true;
      suggestInitializesLabel = true;
      break;
    case StorageRestrictionsCompletionKind::Argument:
      suggestArgument = true;
      break;
    case StorageRestrictionsCompletionKind::ArgumentOrInitializesLabel:
      suggestArgument = true;
      suggestInitializesLabel = true;
      break;
    case StorageRestrictionsCompletionKind::ArgumentOrAccessesLabel:
      suggestArgument = true;
      suggestAccessesLabel = true;
      break;
    }
    if (suggestInitializesLabel) {
      addDeclAttrParamKeyword(
          "initializes", /*Parameters=*/{},
          "Specify stored properties initialized by the accessor", true);
    }
    if (suggestAccessesLabel) {
      addDeclAttrParamKeyword(
          "accesses", /*Parameters=*/{},
          "Specify stored properties accessed by the accessor", true);
    }
    if (suggestArgument) {
      if (auto NT = dyn_cast<NominalTypeDecl>(CurrDeclContext)) {
        getStoredPropertyCompletions(NT);
      }
    }
    break;
  }
  case ParameterizedDeclAttributeKind::Nonexhaustive: {
    addDeclAttrParamKeyword("warn", /*Parameters=*/{}, "", false);
    break;
  }
  }
}

void CompletionLookup::getTypeAttributeKeywordCompletions(
    CompletionKind completionKind) {
  auto addTypeAttr = [&](TypeAttrKind Kind, StringRef Name) {
    if (completionKind != CompletionKind::TypeAttrInheritanceBeginning) {
      switch (Kind) {
      case TypeAttrKind::Retroactive:
      case TypeAttrKind::Preconcurrency:
      case TypeAttrKind::Nonisolated:
      case TypeAttrKind::Unchecked:
      case TypeAttrKind::Unsafe:
        // These attributes are only available in inheritance clasuses.
        return;
      default:
        break;
      }
    }
    CodeCompletionResultBuilder Builder = makeResultBuilder(
        CodeCompletionResultKind::Keyword, SemanticContextKind::None);
    Builder.addAttributeKeyword(Name, "Type Attribute");
  };

  // Add simple user-accessible attributes.
#define SIL_TYPE_ATTR(SPELLING, C)
#define SIMPLE_SIL_TYPE_ATTR(SPELLING, C)
#define SIMPLE_TYPE_ATTR(SPELLING, C)                                          \
  if (!TypeAttribute::isUserInaccessible(TypeAttrKind::C))                     \
    addTypeAttr(TypeAttrKind::C, #SPELLING);
#include "swift/AST/TypeAttr.def"

  // Add non-simple cases.
  addTypeAttr(TypeAttrKind::Convention, "convention(swift)");
  addTypeAttr(TypeAttrKind::Convention, "convention(block)");
  addTypeAttr(TypeAttrKind::Convention, "convention(c)");
  addTypeAttr(TypeAttrKind::Convention, "convention(thin)");
  addTypeAttr(TypeAttrKind::Isolated, "isolated(any)");
}

void CompletionLookup::collectPrecedenceGroups() {
  assert(CurrDeclContext);

  if (CurrModule) {
    for (auto FU : CurrModule->getFiles()) {
      // We are looking through the current module,
      // inspect only source files.
      if (FU->getKind() != FileUnitKind::Source)
        continue;

      llvm::SmallVector<PrecedenceGroupDecl *, 4> results;
      cast<SourceFile>(FU)->getPrecedenceGroups(results);

      for (auto PG : results)
        addPrecedenceGroupRef(PG);
    }
  }
  for (auto Import : namelookup::getAllImports(CurrDeclContext)) {
    auto Module = Import.importedModule;
    if (Module == CurrModule)
      continue;

    RequestedCachedResults.insert(RequestedResultsTy::fromModule(
        Module, CodeCompletionFilterFlag::PrecedenceGroup));
  }
}

void CompletionLookup::getPrecedenceGroupCompletions(
    CodeCompletionCallbacks::PrecedenceGroupCompletionKind SK) {
  switch (SK) {
  case CodeCompletionCallbacks::PrecedenceGroupCompletionKind::Associativity:
    addKeyword(getAssociativitySpelling(Associativity::None));
    addKeyword(getAssociativitySpelling(Associativity::Left));
    addKeyword(getAssociativitySpelling(Associativity::Right));
    return;
  case CodeCompletionCallbacks::PrecedenceGroupCompletionKind::Assignment:
    addKeyword(getTokenText(tok::kw_false), Type(), SemanticContextKind::None,
               CodeCompletionKeywordKind::kw_false);
    addKeyword(getTokenText(tok::kw_true), Type(), SemanticContextKind::None,
               CodeCompletionKeywordKind::kw_true);
    return;
  case CodeCompletionCallbacks::PrecedenceGroupCompletionKind::AttributeList:
    addKeyword("associativity");
    addKeyword("higherThan");
    addKeyword("lowerThan");
    addKeyword("assignment");
    return;
  case CodeCompletionCallbacks::PrecedenceGroupCompletionKind::Relation:
    collectPrecedenceGroups();
    return;
  }
  llvm_unreachable("not a precedencegroup SyntaxKind");
}

void CompletionLookup::getPoundAvailablePlatformCompletions() {

  // The platform names should be identical to those in @available.
  getAttributeDeclParamCompletions(ParameterizedDeclAttributeKind::Available, 0,
                                   /*HasLabel=*/false);
}

void CompletionLookup::getSelfTypeCompletionInDeclContext(
    SourceLoc Loc, bool isForDeclResult) {
  const DeclContext *typeDC = CurrDeclContext->getInnermostTypeContext();
  if (!typeDC)
    return;

  // For protocols, there's a 'Self' generic parameter.
  if (typeDC->getSelfProtocolDecl())
    return;

  Type selfType =
      CurrDeclContext->mapTypeIntoEnvironment(typeDC->getSelfInterfaceType());

  if (typeDC->getSelfClassDecl()) {
    // In classes, 'Self' can be used in result type of func, subscript and
    // computed property, or inside function bodies.
    bool canUseDynamicSelf = false;
    if (isForDeclResult) {
      canUseDynamicSelf = true;
    } else {
      const auto *checkDC = CurrDeclContext;
      if (isa<TypeAliasDecl>(checkDC))
        checkDC = checkDC->getParent();

      if (const auto *AFD = checkDC->getInnermostMethodContext()) {
        canUseDynamicSelf =
            Ctx.SourceMgr.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc);
      }
    }
    if (!canUseDynamicSelf)
      return;
    // 'Self' in class is a dynamic type.
    selfType = DynamicSelfType::get(selfType, Ctx);
  } else {
    // In enums and structs, 'Self' is just an alias for the nominal type,
    // and can be used anywhere.
  }

  CodeCompletionResultBuilder Builder = makeResultBuilder(
      CodeCompletionResultKind::Keyword, SemanticContextKind::CurrentNominal);
  Builder.addKeyword("Self");
  Builder.setKeywordKind(CodeCompletionKeywordKind::kw_Self);
  addTypeAnnotation(Builder, selfType);
}

void CompletionLookup::getTypeCompletionsInDeclContext(SourceLoc Loc,
                                                       bool ModuleQualifier) {
  Kind = LookupKind::TypeInDeclContext;

  AccessFilteringDeclConsumer AccessFilteringConsumer(CurrDeclContext, *this);
  lookupVisibleDecls(AccessFilteringConsumer, Loc, CurrDeclContext,
                     /*IncludeTopLevel=*/false);

  CodeCompletionFilter filter{CodeCompletionFilterFlag::Type};
  if (ModuleQualifier) {
    filter |= CodeCompletionFilterFlag::Module;
  }
  RequestedCachedResults.insert(RequestedResultsTy::topLevelResults(filter));
}

namespace {

/// A \c VisibleDeclConsumer that stores all decls that are found and is able
/// to forward the to another \c VisibleDeclConsumer later.
class StoringDeclConsumer : public VisibleDeclConsumer {
  struct FoundDecl {
    ValueDecl *VD;
    DeclVisibilityKind Reason;
    DynamicLookupInfo DynamicLookupInfo;
  };

  std::vector<FoundDecl> FoundDecls;

  void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason,
                 DynamicLookupInfo DynamicLookupInfo = {}) override {
    FoundDecls.push_back({VD, Reason, DynamicLookupInfo});
  }

public:
  /// Call \c foundDecl for every declaration that this consumer has found.
  void forward(VisibleDeclConsumer &Consumer) {
    for (auto &FoundDecl : FoundDecls) {
      Consumer.foundDecl(FoundDecl.VD, FoundDecl.Reason,
                         FoundDecl.DynamicLookupInfo);
    }
  }
};

} // namespace

void CompletionLookup::getToplevelCompletions(CodeCompletionFilter Filter) {
  Kind = (Filter - CodeCompletionFilterFlag::Module)
                 .containsOnly(CodeCompletionFilterFlag::Type)
             ? LookupKind::TypeInDeclContext
             : LookupKind::ValueInDeclContext;
  NeedLeadingDot = false;

  // If we have 'addinitstotoplevel' enabled, calling `foundDecl` on `this`
  // can cause macros to get expanded, which can then cause new members ot get
  // added to 'TopLevelValues', invalidating iterator over `TopLevelDecls` in
  // `SourceLookupCache::lookupVisibleDecls`.
  //
  // Technically `foundDecl` should not expand macros or discover new top level
  // members in any way because those newly discovered decls will not be added
  // to the code completion results. However, it's preferrable to miss results
  // than to silently invalidate a collection, resulting in hard-to-diagnose
  // crashes.
  // Thus, store all the decls found by `CurrModule->lookupVisibleDecls` in a
  // vector first and only call `this->foundDecl` once we have left the
  // iteration loop over `TopLevelDecls`.
  StoringDeclConsumer StoringConsumer;

  UsableFilteringDeclConsumer UsableFilteringConsumer(
      Ctx.SourceMgr, CurrDeclContext, Ctx.SourceMgr.getIDEInspectionTargetLoc(),
      StoringConsumer);
  AccessFilteringDeclConsumer AccessFilteringConsumer(CurrDeclContext,
                                                      UsableFilteringConsumer);

  CodeCompletionMacroRoles ExpectedRoles = getCompletionMacroRoles(Filter);
  DeclFilter VisibleFilter =
      [ExpectedRoles](ValueDecl *VD, DeclVisibilityKind Kind,
                      DynamicLookupInfo DynamicLookupInfo) {
        CodeCompletionMacroRoles Roles = getCompletionMacroRoles(VD);
        if (!ExpectedRoles)
          return !Roles;
        return (bool)(Roles & ExpectedRoles);
      };

  FilteredDeclConsumer FilteringConsumer(AccessFilteringConsumer,
                                         VisibleFilter);

  CurrModule->lookupVisibleDecls({}, FilteringConsumer,
                                 NLKind::UnqualifiedLookup);

  StoringConsumer.forward(*this);
}

void CompletionLookup::lookupExternalModuleDecls(
    const ModuleDecl *TheModule, ArrayRef<std::string> AccessPath,
    bool ResultsHaveLeadingDot) {
  assert(CurrModule != TheModule && "requested module should be external");

  Kind = LookupKind::ImportFromModule;
  NeedLeadingDot = ResultsHaveLeadingDot;

  ImportPath::Access::Builder builder;
  for (auto Piece : AccessPath) {
    builder.push_back(Ctx.getIdentifier(Piece));
  }

  AccessFilteringDeclConsumer FilteringConsumer(CurrDeclContext, *this);
  TheModule->lookupVisibleDecls(builder.get(), FilteringConsumer,
                                NLKind::UnqualifiedLookup);

  llvm::SmallVector<PrecedenceGroupDecl *, 16> precedenceGroups;
  TheModule->getPrecedenceGroups(precedenceGroups);

  for (auto PGD : precedenceGroups)
    addPrecedenceGroupRef(PGD);
}

void CompletionLookup::getStmtLabelCompletions(SourceLoc Loc, bool isContinue) {
  auto *SF = CurrDeclContext->getParentSourceFile();
  llvm::SmallPtrSet<Identifier, 4> labels;
  for (auto *LS : ASTScope::lookupLabeledStmts(SF, Loc)) {
    if (isContinue && !LS->isPossibleContinueTarget())
      continue;

    auto labelInfo = LS->getLabelInfo();
    if (!labelInfo)
      continue;

    auto label = labelInfo.Name;
    if (!labels.insert(label).second)
      continue;

    CodeCompletionResultBuilder Builder = makeResultBuilder(
        CodeCompletionResultKind::Pattern, SemanticContextKind::Local);
    Builder.addTextChunk(label.str());
  }
}

void CompletionLookup::getOptionalBindingCompletions(SourceLoc Loc) {
  ExprType = Type();
  Kind = LookupKind::ValueInDeclContext;
  NeedLeadingDot = false;

  AccessFilteringDeclConsumer AccessFilteringConsumer(CurrDeclContext, *this);

  // Suggest only 'Optional' type var decls (incl. parameters)
  FilteredDeclConsumer FilteringConsumer(
      AccessFilteringConsumer,
      [&](ValueDecl *VD, DeclVisibilityKind Reason,
          DynamicLookupInfo dynamicLookupInfo) -> bool {
        auto *VarD = dyn_cast<VarDecl>(VD);
        if (!VarD)
          return false;

        auto Ty = getTypeOfMember(VD, dynamicLookupInfo);
        return Ty->isOptional();
      });

  // FIXME: Currently, it doesn't include top level decls for performance
  // reason. Enabling 'IncludeTopLevel' pulls everything including imported
  // modules. For suggesting top level results, we need a way to filter cached
  // results.

  lookupVisibleDecls(FilteringConsumer, Loc, CurrDeclContext,
                     /*IncludeTopLevel=*/false);
}
