mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Add lookupClassMembers for use in id-style dynamic lookup.
With this, we can now get a list of all class members* available in the current translation unit, which will be necessary for doing id-style dynamic lookup (inferring which method you're referring to when the base type is some magic "dynamic lookup" type). * Including members of protocols, since a class we don't know about could have implemented the protocol. Since there is no code currently using this, I've added a new mode to swift-ide-test to just dump all class members -- what will eventually happen when you code complete on a dynamic lookup type. This mode will go away once the other pieces of id-style lookup are in place. Swift SVN r7287
This commit is contained in:
@@ -85,12 +85,17 @@ void BuiltinModuleCache::lookupValue(Identifier Name, NLKind LookupKind,
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
/// TUModuleCache - This is the type of the cache for the TranslationUnit.
|
||||
/// This is lazily created on its first use an hangs off
|
||||
/// This is the type of the cache for the TranslationUnit.
|
||||
///
|
||||
/// This is lazily created on its first use and hangs off
|
||||
/// Module::LookupCachePimpl.
|
||||
class TUModuleCache {
|
||||
llvm::DenseMap<Identifier, TinyPtrVector<ValueDecl*>> TopLevelValues;
|
||||
llvm::DenseMap<Identifier, TinyPtrVector<ValueDecl*>> ClassMembers;
|
||||
bool MemberCachePopulated = false;
|
||||
void doPopulateCache(ArrayRef<Decl*> decls, bool onlyOperators);
|
||||
void addToMemberCache(ArrayRef<Decl*> decls);
|
||||
void populateMemberCache(const TranslationUnit &TU);
|
||||
public:
|
||||
typedef Module::AccessPathTy AccessPathTy;
|
||||
|
||||
@@ -104,6 +109,10 @@ namespace {
|
||||
VisibleDeclConsumer &Consumer,
|
||||
NLKind LookupKind,
|
||||
const TranslationUnit &TU);
|
||||
|
||||
void lookupClassMembers(AccessPathTy AccessPath,
|
||||
VisibleDeclConsumer &consumer,
|
||||
const TranslationUnit &TU);
|
||||
|
||||
SmallVector<ValueDecl *, 0> AllVisibleValues;
|
||||
};
|
||||
@@ -134,6 +143,30 @@ void TUModuleCache::doPopulateCache(ArrayRef<Decl*> decls, bool onlyOperators) {
|
||||
}
|
||||
}
|
||||
|
||||
void TUModuleCache::populateMemberCache(const TranslationUnit &TU) {
|
||||
for (const Decl *D : TU.Decls) {
|
||||
if (const NominalTypeDecl *NTD = dyn_cast<NominalTypeDecl>(D)) {
|
||||
if (isa<ClassDecl>(NTD) || isa<ProtocolDecl>(NTD))
|
||||
addToMemberCache(NTD->getMembers());
|
||||
} else if (const ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D)) {
|
||||
Type baseTy = ED->getExtendedType();
|
||||
assert(baseTy && "cannot use this before type-checking");
|
||||
if (auto baseNominal = baseTy->getAnyNominal())
|
||||
if (isa<ClassDecl>(baseNominal) || isa<ProtocolDecl>(baseNominal))
|
||||
addToMemberCache(ED->getMembers());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TUModuleCache::addToMemberCache(ArrayRef<Decl*> decls) {
|
||||
for (Decl *D : decls) {
|
||||
auto VD = dyn_cast<ValueDecl>(D);
|
||||
if (!VD || !VD->canBeAccessedByDynamicLookup())
|
||||
continue;
|
||||
ClassMembers[VD->getName()].push_back(VD);
|
||||
}
|
||||
}
|
||||
|
||||
/// Populate our cache on the first name lookup.
|
||||
TUModuleCache::TUModuleCache(const TranslationUnit &TU) {
|
||||
doPopulateCache(TU.Decls, false);
|
||||
@@ -179,14 +212,36 @@ void TUModuleCache::lookupVisibleDecls(AccessPathTy AccessPath,
|
||||
}
|
||||
}
|
||||
|
||||
void TUModuleCache::lookupClassMembers(AccessPathTy accessPath,
|
||||
VisibleDeclConsumer &consumer,
|
||||
const TranslationUnit &TU) {
|
||||
if (!MemberCachePopulated)
|
||||
populateMemberCache(TU);
|
||||
|
||||
assert(accessPath.size() <= 1 && "can only refer to top-level decls");
|
||||
|
||||
if (!accessPath.empty()) {
|
||||
for (auto &member : ClassMembers) {
|
||||
for (ValueDecl *vd : member.second) {
|
||||
Type ty = vd->getDeclContext()->getDeclaredTypeOfContext();
|
||||
if (auto nominal = ty->getAnyNominal())
|
||||
if (nominal->getName() == accessPath.front().first)
|
||||
consumer.foundDecl(vd);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &member : ClassMembers) {
|
||||
for (ValueDecl *vd : member.second)
|
||||
consumer.foundDecl(vd);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Module Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// lookupValue - Look up a (possibly overloaded) value set at top-level scope
|
||||
/// (but with the specified access path, which may come from an import decl)
|
||||
/// within the current module. This does a simple local lookup, not
|
||||
/// recursively looking through imports.
|
||||
void Module::lookupValue(AccessPathTy AccessPath, Identifier Name,
|
||||
NLKind LookupKind,
|
||||
SmallVectorImpl<ValueDecl*> &Result) {
|
||||
@@ -206,8 +261,6 @@ void Module::lookupValue(AccessPathTy AccessPath, Identifier Name,
|
||||
Result);
|
||||
}
|
||||
|
||||
/// lookupVisibleDecls - Find ValueDecls in the module and pass them to the
|
||||
/// given consumer object.
|
||||
void Module::lookupVisibleDecls(AccessPathTy AccessPath,
|
||||
VisibleDeclConsumer &Consumer,
|
||||
NLKind LookupKind) const {
|
||||
@@ -226,6 +279,21 @@ void Module::lookupVisibleDecls(AccessPathTy AccessPath,
|
||||
LookupKind);
|
||||
}
|
||||
|
||||
void Module::lookupClassMembers(AccessPathTy accessPath,
|
||||
VisibleDeclConsumer &consumer) const {
|
||||
if (isa<BuiltinModule>(this)) {
|
||||
// The Builtin module defines no classes.
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto TU = dyn_cast<TranslationUnit>(this)) {
|
||||
return getTUCachePimpl(LookupCachePimpl, *TU)
|
||||
.lookupClassMembers(accessPath, consumer, *TU);
|
||||
}
|
||||
|
||||
return cast<LoadedModule>(this)->lookupClassMembers(accessPath, consumer);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Returns Nothing on error, Optional(nullptr) if no operator decl found, or
|
||||
// Optional(decl) if decl was found.
|
||||
@@ -475,6 +543,11 @@ void LoadedModule::lookupVisibleDecls(AccessPathTy accessPath,
|
||||
return getOwner().lookupVisibleDecls(this, accessPath, consumer, lookupKind);
|
||||
}
|
||||
|
||||
void LoadedModule::lookupClassMembers(AccessPathTy accessPath,
|
||||
VisibleDeclConsumer &consumer) const {
|
||||
return getOwner().lookupClassMembers(this, accessPath, consumer);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ModuleLoader Implementation
|
||||
|
||||
Reference in New Issue
Block a user