text: //===--- SemaFixture.cpp - Helper for setting up Sema context --------------===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2020 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 "SemaFixture.h"
  #include "swift/AST/Decl.h"
  #include "swift/AST/Import.h"
  #include "swift/AST/Module.h"
  #include "swift/AST/ParseRequests.h"
  #include "swift/AST/SourceFile.h"
  #include "swift/AST/Type.h"
  #include "swift/AST/Types.h"
  #include "swift/Basic/LLVMInitialize.h"
  #include "swift/ClangImporter/ClangImporter.h"
  #include "swift/Serialization/SerializedModuleLoader.h"
  #include "swift/Subsystems.h"
  #include "llvm/ADT/DenseMap.h"
  
  using namespace swift;
  using namespace swift::unittest;
  
  SemaTest::SemaTest()
      : Context(*ASTContext::get(LangOpts, TypeCheckerOpts, SearchPathOpts,
                                 ClangImporterOpts, SourceMgr, Diags)) {
    INITIALIZE_LLVM();
  
    registerParseRequestFunctions(Context.evaluator);
    registerTypeCheckerRequestFunctions(Context.evaluator);
  
    Context.addModuleLoader(ImplicitSerializedModuleLoader::create(Context));
    Context.addModuleLoader(ClangImporter::create(Context), /*isClang=*/true);
  
    auto *stdlib = Context.getStdlibModule(/*loadIfAbsent=*/true);
    assert(stdlib && "Failed to load standard library");
  
    auto *module =
        ModuleDecl::create(Context.getIdentifier("SemaTests"), Context);
  
    MainFile = new (Context) SourceFile(*module, SourceFileKind::Main,
                                        /*buffer=*/None);
  
    AttributedImport<ImportedModule> stdlibImport{{ImportPath::Access(), stdlib},
                                                  /*options=*/{}};
  
    MainFile->setImports(stdlibImport);
    module->addFile(*MainFile);
  
    DC = module;
  }
  
  Type SemaTest::getStdlibType(StringRef name) const {
    auto typeName = Context.getIdentifier(name);
  
    auto *stdlib = Context.getStdlibModule();
  
    llvm::SmallVector<ValueDecl *, 4> results;
    stdlib->lookupValue(typeName, NLKind::UnqualifiedLookup, results);
  
    if (results.size() != 1)
      return Type();
  
    if (auto *decl = dyn_cast<TypeDecl>(results.front())) {
      if (auto *NTD = dyn_cast<NominalTypeDecl>(decl))
        return NTD->getDeclaredType();
      return decl->getDeclaredInterfaceType();
    }
  
    return Type();
  }
  
  NominalTypeDecl *SemaTest::getStdlibNominalTypeDecl(StringRef name) const {
    auto typeName = Context.getIdentifier(name);
  
    auto *stdlib = Context.getStdlibModule();
  
    llvm::SmallVector<ValueDecl *, 4> results;
    stdlib->lookupValue(typeName, NLKind::UnqualifiedLookup, results);
  
    if (results.size() != 1)
      return nullptr;
  
    return dyn_cast<NominalTypeDecl>(results.front());
  }
  
  VarDecl *SemaTest::addExtensionVarMember(NominalTypeDecl *decl,
                                           StringRef name, Type type) const {
    auto *ext = ExtensionDecl::create(Context, SourceLoc(), nullptr, { }, DC,
                                      nullptr);
    decl->addExtension(ext);
    ext->setExtendedNominal(decl);
  
    auto *VD = new (Context) VarDecl(/*isStatic=*/ true, VarDecl::Introducer::Var,
                                     /*nameLoc=*/ SourceLoc(),
                                     Context.getIdentifier(name), ext);
  
    ext->addMember(VD);
    auto *pat = new (Context) NamedPattern(VD);
    VD->setNamingPattern(pat);
    pat->setType(type);
  
    return VD;
  }
  
  ProtocolType *SemaTest::createProtocol(llvm::StringRef protocolName,
                                         Type parent) {
    auto *PD = new (Context)
        ProtocolDecl(DC, SourceLoc(), SourceLoc(),
                     Context.getIdentifier(protocolName), /*Inherited=*/{},
                     /*trailingWhere=*/nullptr);
    PD->setImplicit();
  
    return ProtocolType::get(PD, parent, Context);
  }
  
  ConstraintSystem::PotentialBindings
  SemaTest::inferBindings(ConstraintSystem &cs, TypeVariableType *typeVar) {
    llvm::SmallDenseMap<TypeVariableType *, ConstraintSystem::PotentialBindings>
        cache;
  
    for (auto *typeVar : cs.getTypeVariables()) {
      if (!typeVar->getImpl().hasRepresentativeOrFixed())
        cache.insert({typeVar, cs.inferBindingsFor(typeVar, /*finalize=*/false)});
    }
  
    for (auto *typeVar : cs.getTypeVariables()) {
      auto cachedBindings = cache.find(typeVar);
      if (cachedBindings == cache.end())
        continue;
  
      auto &bindings = cachedBindings->getSecond();
      bindings.finalize(cache);
    }
  
    auto result = cache.find(typeVar);
    assert(result != cache.end());
    return result->second;
  }
  