Put UsedDeclEnumerator Back

This abstraction turns out to have hidden dependencies from the dependency verifier. Invert the dependency here and have it use the new enumerators in the DependencyRecorder instead.
This commit is contained in:
Robert Widmann
2020-05-21 18:51:53 -07:00
parent 9a88bef29d
commit bf8d5412e0

View File

@@ -551,24 +551,134 @@ void FrontendSourceFileDepGraphFactory::addAllDefinedDeclsOfAGivenType(
// MARK: FrontendSourceFileDepGraphFactory - adding collections of used Decls
//==============================================================================
namespace {
/// Extracts uses out of a SourceFile
class UsedDeclEnumerator {
SourceFile *SF;
const DependencyTracker &depTracker;
StringRef swiftDeps;
/// Cache these for efficiency
const DependencyKey sourceFileInterface;
const DependencyKey sourceFileImplementation;
const bool includeIntrafileDeps;
function_ref<void(const DependencyKey &, const DependencyKey &)> createDefUse;
public:
UsedDeclEnumerator(
SourceFile *SF, const DependencyTracker &depTracker, StringRef swiftDeps,
bool includeIntrafileDeps,
function_ref<void(const DependencyKey &, const DependencyKey &)>
createDefUse)
: SF(SF), depTracker(depTracker), swiftDeps(swiftDeps),
sourceFileInterface(DependencyKey::createKeyForWholeSourceFile(
DeclAspect::interface, swiftDeps)),
sourceFileImplementation(DependencyKey::createKeyForWholeSourceFile(
DeclAspect::implementation, swiftDeps)),
includeIntrafileDeps(includeIntrafileDeps), createDefUse(createDefUse) {
}
public:
void enumerateAllUses() {
auto &Ctx = SF->getASTContext();
std::unordered_set<std::string> holdersOfCascadingMembers;
Ctx.evaluator.enumerateReferencesInFile(SF, [&](const auto &ref) {
const auto cascades = ref.cascades;
std::string name = ref.name.userFacingName().str();
const auto *nominal = ref.subject;
using Kind = evaluator::DependencyCollector::Reference::Kind;
switch (ref.kind) {
case Kind::Empty:
case Kind::Tombstone:
llvm_unreachable("Cannot enumerate dead reference!");
case Kind::TopLevel:
return enumerateUse<NodeKind::topLevel>("", name, cascades);
case Kind::Dynamic:
return enumerateUse<NodeKind::dynamicLookup>("", name, cascades);
case Kind::PotentialMember: {
std::string context = DependencyKey::computeContextForProvidedEntity<
NodeKind::potentialMember>(nominal);
appendHolderOfCascadingMembers(holdersOfCascadingMembers, nominal,
cascades);
return enumerateUse<NodeKind::potentialMember>(context, "", cascades);
}
case Kind::UsedMember: {
std::string context =
DependencyKey::computeContextForProvidedEntity<NodeKind::member>(
nominal);
appendHolderOfCascadingMembers(holdersOfCascadingMembers, nominal,
cascades);
return enumerateUse<NodeKind::member>(context, name, cascades);
}
}
});
enumerateExternalUses();
enumerateNominalUses(std::move(holdersOfCascadingMembers));
}
private:
template <NodeKind kind>
void enumerateUse(StringRef context, StringRef name, bool isCascadingUse) {
// Assume that what is depended-upon is the interface
createDefUse(
DependencyKey(kind, DeclAspect::interface, context.str(), name.str()),
isCascadingUse ? sourceFileInterface : sourceFileImplementation);
}
void appendHolderOfCascadingMembers(std::unordered_set<std::string> &holders,
const NominalTypeDecl *subject,
bool isCascading) {
bool isPrivate = subject->isPrivateToEnclosingFile();
if (isPrivate && !includeIntrafileDeps)
return;
std::string context =
DependencyKey::computeContextForProvidedEntity<NodeKind::nominal>(
subject);
if (isCascading) {
holders.insert(context);
}
}
void enumerateNominalUses(
const std::unordered_set<std::string> &&holdersOfCascadingMembers) {
auto &Ctx = SF->getASTContext();
Ctx.evaluator.enumerateReferencesInFile(SF, [&](const auto &ref) {
const NominalTypeDecl *subject = ref.subject;
if (!subject) {
return;
}
bool isPrivate = subject->isPrivateToEnclosingFile();
if (isPrivate && !includeIntrafileDeps) {
return;
}
std::string context =
DependencyKey::computeContextForProvidedEntity<NodeKind::nominal>(
subject);
const bool isCascadingUse = holdersOfCascadingMembers.count(context) != 0;
enumerateUse<NodeKind::nominal>(context, "", isCascadingUse);
});
}
void enumerateExternalUses() {
// external dependencies always cascade
for (StringRef s : depTracker.getDependencies())
enumerateUse<NodeKind::externalDepend>("", s, true);
}
};
} // end namespace
void FrontendSourceFileDepGraphFactory::addAllUsedDecls() {
const DependencyKey sourceFileInterface =
DependencyKey::createKeyForWholeSourceFile(DeclAspect::interface,
swiftDeps);
const DependencyKey sourceFileImplementation =
DependencyKey::createKeyForWholeSourceFile(DeclAspect::implementation,
swiftDeps);
SF->getConfiguredReferencedNameTracker()->enumerateAllUses(
includePrivateDeps, depTracker,
[&](const fine_grained_dependencies::NodeKind kind, StringRef context,
StringRef name, const bool isCascadingUse) {
addAUsedDecl(DependencyKey(kind, DeclAspect::interface, context.str(),
name.str()),
isCascadingUse ? sourceFileInterface
: sourceFileImplementation);
});
UsedDeclEnumerator(SF, depTracker, swiftDeps, includePrivateDeps,
[&](const DependencyKey &def, const DependencyKey &use) {
addAUsedDecl(def, use);
})
.enumerateAllUses();
}
//==============================================================================