void ModuleFile::lookupVisibleDecls(Module::AccessPathTy accessPath, VisibleDeclConsumer &consumer, NLKind lookupKind) { PrettyModuleFileDeserialization stackEntry(*this); assert(accessPath.size() <= 1 && "can only refer to top-level decls"); if (!TopLevelDecls) return; if (!accessPath.empty()) { auto iter = TopLevelDecls->find(accessPath.front().first); if (iter == TopLevelDecls->end()) return; for (auto item : *iter) consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)), DeclVisibilityKind::VisibleAtTopLevel); return; } for (auto entry : TopLevelDecls->data()) { for (auto item : entry) consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)), DeclVisibilityKind::VisibleAtTopLevel); } }
void ModuleFile::lookupClassMembers(Module::AccessPathTy accessPath, VisibleDeclConsumer &consumer) { PrettyModuleFileDeserialization stackEntry(*this); assert(accessPath.size() <= 1 && "can only refer to top-level decls"); if (!ClassMembersByName) return; if (!accessPath.empty()) { for (const auto &list : ClassMembersByName->data()) { for (auto item : list) { auto vd = cast<ValueDecl>(getDecl(item.second)); auto dc = vd->getDeclContext(); while (!dc->getParent()->isModuleScopeContext()) dc = dc->getParent(); if (auto nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext()) if (nominal->getName() == accessPath.front().first) consumer.foundDecl(vd, DeclVisibilityKind::DynamicLookup); } } return; } for (const auto &list : ClassMembersByName->data()) { for (auto item : list) consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)), DeclVisibilityKind::DynamicLookup); } }
static void lookupDeclsFromProtocolsBeingConformedTo( Type BaseTy, VisibleDeclConsumer &Consumer, LookupState LS, const DeclContext *FromContext, DeclVisibilityKind Reason, LazyResolver *TypeResolver, VisitedSet &Visited) { NominalTypeDecl *CurrNominal = BaseTy->getAnyNominal(); if (!CurrNominal) return; for (auto Conformance : CurrNominal->getAllConformances()) { auto Proto = Conformance->getProtocol(); if (!Proto->isAccessibleFrom(FromContext)) continue; DeclVisibilityKind ReasonForThisProtocol; if (Reason == DeclVisibilityKind::MemberOfCurrentNominal) ReasonForThisProtocol = DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal; else ReasonForThisProtocol = getReasonForSuper(Reason); auto NormalConformance = Conformance->getRootNormalConformance(); for (auto Member : Proto->getMembers()) { if (auto *ATD = dyn_cast<AssociatedTypeDecl>(Member)) { // Skip type decls if they aren't visible, or any type that has a // witness. This cuts down on duplicates. if (areTypeDeclsVisibleInLookupMode(LS) && !NormalConformance->hasTypeWitness(ATD)) { Consumer.foundDecl(ATD, ReasonForThisProtocol); } continue; } if (auto *VD = dyn_cast<ValueDecl>(Member)) { if (TypeResolver) { TypeResolver->resolveDeclSignature(VD); if (!NormalConformance->hasWitness(VD) && (Conformance->getDeclContext()->getParentSourceFile() != FromContext->getParentSourceFile())) TypeResolver->resolveWitness(NormalConformance, VD); } // Skip value requirements that have corresponding witnesses. This cuts // down on duplicates. if (!NormalConformance->hasWitness(VD) || !NormalConformance->getWitness(VD, nullptr) || NormalConformance->getWitness(VD, nullptr).getDecl()->getFullName() != VD->getFullName()) { Consumer.foundDecl(VD, ReasonForThisProtocol); } } } // Add members from any extensions. SmallVector<ValueDecl *, 2> FoundDecls; doGlobalExtensionLookup(BaseTy, Proto->getDeclaredType(), FoundDecls, FromContext, LS, ReasonForThisProtocol, TypeResolver); for (auto *VD : FoundDecls) Consumer.foundDecl(VD, ReasonForThisProtocol); } }
/// \brief Enumerate all members in \c BaseTy (including members of extensions, /// superclasses and implemented protocols), as seen from the context \c CurrDC. /// /// This operation corresponds to a standard "dot" lookup operation like "a.b" /// where 'self' is the type of 'a'. This operation is only valid after name /// binding. static void lookupVisibleMemberDecls( Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) { OverrideFilteringConsumer ConsumerWrapper(BaseTy, CurrDC); VisitedSet Visited; lookupVisibleMemberDeclsImpl(BaseTy, ConsumerWrapper, CurrDC, LS, Reason, TypeResolver, Visited); // Report the declarations we found to the real consumer. for (const auto &DeclAndReason : ConsumerWrapper.DeclsToReport) Consumer.foundDecl(DeclAndReason.D, DeclAndReason.Reason); }
/// \brief Enumerate all members in \c BaseTy (including members of extensions, /// superclasses and implemented protocols), as seen from the context \c CurrDC. /// /// This operation corresponds to a standard "dot" lookup operation like "a.b" /// where 'self' is the type of 'a'. This operation is only valid after name /// binding. static void lookupVisibleMemberDecls( Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver, GenericSignatureBuilder *GSB) { OverrideFilteringConsumer overrideConsumer(BaseTy, CurrDC, TypeResolver); RestateFilteringConsumer restateConsumer(BaseTy, CurrDC, TypeResolver); VisitedSet Visited; lookupVisibleMemberDeclsImpl(BaseTy, restateConsumer, CurrDC, LS, Reason, TypeResolver, GSB, Visited); // Report the declarations we found to the real consumer. restateConsumer.feedResultsToConsumer(overrideConsumer); for (const auto &DeclAndReason : overrideConsumer.DeclsToReport) Consumer.foundDecl(DeclAndReason.D, DeclAndReason.Reason); }
/// \brief Enumerate immediate members of the type \c LookupType and its /// extensions, as seen from the context \c CurrDC. /// /// Don't do lookup into superclasses or implemented protocols. Uses /// \p BaseType as the underlying type when checking any constraints on the /// extensions. static void lookupTypeMembers(Type BaseType, Type LookupType, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) { NominalTypeDecl *D = LookupType->getAnyNominal(); assert(D && "should have a nominal type"); bool LookupFromChildDeclContext = false; const DeclContext *TempDC = CurrDC; while (!TempDC->isModuleContext()) { if (TempDC == D) { LookupFromChildDeclContext = true; break; } TempDC = TempDC->getParent(); } SmallVector<ValueDecl*, 2> FoundDecls; if (LookupFromChildDeclContext) { // Current decl context is contained inside 'D', so generic parameters // are visible. if (D->getGenericParams()) for (auto Param : *D->getGenericParams()) if (isDeclVisibleInLookupMode(Param, LS, CurrDC, TypeResolver)) FoundDecls.push_back(Param); } for (Decl *Member : D->getMembers()) { if (auto *VD = dyn_cast<ValueDecl>(Member)) if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver)) FoundDecls.push_back(VD); } doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason, TypeResolver); // Report the declarations we found to the consumer. for (auto *VD : FoundDecls) Consumer.foundDecl(VD, Reason); }
/// Enumerate immediate members of the type \c LookupType and its /// extensions, as seen from the context \c CurrDC. /// /// Don't do lookup into superclasses or implemented protocols. Uses /// \p BaseType as the underlying type when checking any constraints on the /// extensions. static void lookupTypeMembers(Type BaseType, Type LookupType, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) { NominalTypeDecl *D = LookupType->getAnyNominal(); assert(D && "should have a nominal type"); SmallVector<ValueDecl*, 2> FoundDecls; for (Decl *Member : D->getMembers()) { if (auto *VD = dyn_cast<ValueDecl>(Member)) if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver)) FoundDecls.push_back(VD); } doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason, TypeResolver); // Report the declarations we found to the consumer. for (auto *VD : FoundDecls) Consumer.foundDecl(VD, Reason); }
void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer, const DeclContext *DC, LazyResolver *TypeResolver, bool IncludeTopLevel, SourceLoc Loc) { const ModuleDecl &M = *DC->getParentModule(); const SourceManager &SM = DC->getASTContext().SourceMgr; auto Reason = DeclVisibilityKind::MemberOfCurrentNominal; // If we are inside of a method, check to see if there are any ivars in scope, // and if so, whether this is a reference to one of them. while (!DC->isModuleScopeContext()) { const ValueDecl *BaseDecl = nullptr; Type ExtendedType; auto LS = LookupState::makeUnqualified(); // Skip initializer contexts, we will not find any declarations there. if (isa<Initializer>(DC)) { DC = DC->getParent(); LS = LS.withOnMetatype(); } GenericParamList *GenericParams = DC->getGenericParamsOfContext(); if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) { // Look for local variables; normally, the parser resolves these // for us, but it can't do the right thing inside local types. // FIXME: when we can parse and typecheck the function body partially for // code completion, AFD->getBody() check can be removed. if (Loc.isValid() && AFD->getBody()) { namelookup::FindLocalVal(SM, Loc, Consumer).visit(AFD->getBody()); } for (auto *P : AFD->getParameterLists()) namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P); // Constructors and destructors don't have 'self' in parameter patterns. if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) if (auto *selfParam = AFD->getImplicitSelfDecl()) Consumer.foundDecl(const_cast<ParamDecl*>(selfParam), DeclVisibilityKind::FunctionParameter); if (AFD->getDeclContext()->isTypeContext()) { ExtendedType = AFD->getDeclContext()->getSelfTypeInContext(); BaseDecl = AFD->getImplicitSelfDecl(); DC = DC->getParent(); if (auto *FD = dyn_cast<FuncDecl>(AFD)) if (FD->isStatic()) ExtendedType = MetatypeType::get(ExtendedType); } } else if (auto CE = dyn_cast<ClosureExpr>(DC)) { if (Loc.isValid()) { namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody()); if (auto P = CE->getParameters()) { namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P); } } } else if (auto ED = dyn_cast<ExtensionDecl>(DC)) { ExtendedType = ED->getExtendedType(); if (ExtendedType) BaseDecl = ExtendedType->getNominalOrBoundGenericNominal(); } else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) { ExtendedType = ND->getDeclaredTypeInContext(); BaseDecl = ND; } if (BaseDecl && ExtendedType) { ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, Reason, TypeResolver, nullptr); } // Check any generic parameters for something with the given name. namelookup::FindLocalVal(SM, Loc, Consumer) .checkGenericParams(GenericParams); DC = DC->getParent(); Reason = DeclVisibilityKind::MemberOfOutsideNominal; } SmallVector<ModuleDecl::ImportedModule, 8> extraImports; if (auto SF = dyn_cast<SourceFile>(DC)) { if (Loc.isValid()) { // Look for local variables in top-level code; normally, the parser // resolves these for us, but it can't do the right thing for // local types. namelookup::FindLocalVal(SM, Loc, Consumer).checkSourceFile(*SF); } if (IncludeTopLevel) { auto &cached = SF->getCachedVisibleDecls(); if (!cached.empty()) { for (auto result : cached) Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel); return; } SF->getImportedModules(extraImports, ModuleDecl::ImportFilter::Private); } } if (IncludeTopLevel) { using namespace namelookup; SmallVector<ValueDecl *, 0> moduleResults; auto &mutableM = const_cast<ModuleDecl&>(M); lookupVisibleDeclsInModule(&mutableM, {}, moduleResults, NLKind::UnqualifiedLookup, ResolutionKind::Overloadable, TypeResolver, DC, extraImports); for (auto result : moduleResults) Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel); if (auto SF = dyn_cast<SourceFile>(DC)) SF->cacheVisibleDecls(std::move(moduleResults)); } }
static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer, const DeclContext *DC, LazyResolver *TypeResolver, bool IncludeTopLevel, SourceLoc Loc) { const ModuleDecl &M = *DC->getParentModule(); const SourceManager &SM = DC->getASTContext().SourceMgr; auto Reason = DeclVisibilityKind::MemberOfCurrentNominal; // If we are inside of a method, check to see if there are any ivars in scope, // and if so, whether this is a reference to one of them. while (!DC->isModuleScopeContext()) { GenericParamList *GenericParams = nullptr; Type ExtendedType; auto LS = LookupState::makeUnqualified(); // Skip initializer contexts, we will not find any declarations there. if (isa<Initializer>(DC)) { DC = DC->getParent(); LS = LS.withOnMetatype(); } // We don't look for generic parameters if we are in the context of a // nominal type: they will be looked up anyways via `lookupVisibleMemberDecls`. if (DC && !isa<NominalTypeDecl>(DC)) { if (auto *decl = DC->getAsDecl()) { if (auto GC = decl->getAsGenericContext()) { auto params = GC->getGenericParams(); namelookup::FindLocalVal(SM, Loc, Consumer).checkGenericParams(params); } } } if (auto *SE = dyn_cast<SubscriptDecl>(DC)) { ExtendedType = SE->getDeclContext()->getSelfTypeInContext(); DC = DC->getParent(); } else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) { // Look for local variables; normally, the parser resolves these // for us, but it can't do the right thing inside local types. // FIXME: when we can parse and typecheck the function body partially for // code completion, AFD->getBody() check can be removed. if (Loc.isValid() && AFD->getBody()) { namelookup::FindLocalVal(SM, Loc, Consumer).visit(AFD->getBody()); } if (auto *P = AFD->getImplicitSelfDecl()) { namelookup::FindLocalVal(SM, Loc, Consumer).checkValueDecl( const_cast<ParamDecl *>(P), DeclVisibilityKind::FunctionParameter); } namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList( AFD->getParameters()); GenericParams = AFD->getGenericParams(); if (AFD->getDeclContext()->isTypeContext()) { ExtendedType = AFD->getDeclContext()->getSelfTypeInContext(); DC = DC->getParent(); if (auto *FD = dyn_cast<FuncDecl>(AFD)) if (FD->isStatic()) ExtendedType = MetatypeType::get(ExtendedType); } } else if (auto CE = dyn_cast<ClosureExpr>(DC)) { if (Loc.isValid()) { namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody()); if (auto P = CE->getParameters()) { namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P); } } } else if (auto ED = dyn_cast<ExtensionDecl>(DC)) { ExtendedType = ED->getSelfTypeInContext(); } else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) { ExtendedType = ND->getSelfTypeInContext(); } // If we're inside a function context, we've already moved to // the parent DC, so we have to check the function's generic // parameters first. if (GenericParams) { namelookup::FindLocalVal localVal(SM, Loc, Consumer); localVal.checkGenericParams(GenericParams); } // Check the generic parameters of our context. GenericParamList *dcGenericParams = nullptr; if (auto nominal = dyn_cast<NominalTypeDecl>(DC)) dcGenericParams = nominal->getGenericParams(); else if (auto ext = dyn_cast<ExtensionDecl>(DC)) dcGenericParams = ext->getGenericParams(); else if (auto subscript = dyn_cast<SubscriptDecl>(DC)) dcGenericParams = subscript->getGenericParams(); while (dcGenericParams) { namelookup::FindLocalVal localVal(SM, Loc, Consumer); localVal.checkGenericParams(dcGenericParams); dcGenericParams = dcGenericParams->getOuterParameters(); } if (ExtendedType) ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, Reason, TypeResolver, nullptr); DC = DC->getParent(); Reason = DeclVisibilityKind::MemberOfOutsideNominal; } SmallVector<ModuleDecl::ImportedModule, 8> extraImports; if (auto SF = dyn_cast<SourceFile>(DC)) { if (Loc.isValid()) { // Look for local variables in top-level code; normally, the parser // resolves these for us, but it can't do the right thing for // local types. namelookup::FindLocalVal(SM, Loc, Consumer).checkSourceFile(*SF); } if (IncludeTopLevel) { auto &cached = SF->getCachedVisibleDecls(); if (!cached.empty()) { for (auto result : cached) Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel); return; } SF->getImportedModules(extraImports, ModuleDecl::ImportFilter::Private); } } if (IncludeTopLevel) { using namespace namelookup; SmallVector<ValueDecl *, 0> moduleResults; auto &mutableM = const_cast<ModuleDecl&>(M); lookupVisibleDeclsInModule(&mutableM, {}, moduleResults, NLKind::UnqualifiedLookup, ResolutionKind::Overloadable, TypeResolver, DC, extraImports); for (auto result : moduleResults) Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel); if (auto SF = dyn_cast<SourceFile>(DC)) SF->cacheVisibleDecls(std::move(moduleResults)); } }
void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) { if (isUsableValue(VD, Reason)) Consumer.foundDecl(VD, Reason); }
void feedResultsToConsumer(VisibleDeclConsumer &Consumer) const { for (const auto entry: declsToReport) Consumer.foundDecl(entry.first, entry.second); }