@@ -241,8 +241,10 @@ bool fine_grained_dependencies::withReferenceDependencies(
241241 const DependencyTracker &depTracker, StringRef outputPath,
242242 bool alsoEmitDotFile,
243243 llvm::function_ref<bool (SourceFileDepGraph &&)> cont) {
244- if (MSF.dyn_cast <ModuleDecl *>()) {
245- llvm_unreachable (" Cannot construct dependency graph for modules!" );
244+ if (auto *MD = MSF.dyn_cast <ModuleDecl *>()) {
245+ SourceFileDepGraph g =
246+ ModuleDepGraphFactory (MD, alsoEmitDotFile).construct ();
247+ return cont (std::move (g));
246248 } else {
247249 auto *SF = MSF.get <SourceFile *>();
248250 SourceFileDepGraph g = FrontendSourceFileDepGraphFactory (
@@ -592,6 +594,9 @@ class UsedDeclEnumerator {
592594 }
593595
594596 void enumerateExternalUses () {
597+ for (StringRef s : depTracker.getIncrementalDependencies ())
598+ enumerateUse<NodeKind::incrementalExternalDepend>(" " , s);
599+
595600 for (StringRef s : depTracker.getDependencies ())
596601 enumerateUse<NodeKind::externalDepend>(" " , s);
597602 }
@@ -632,3 +637,75 @@ FrontendSourceFileDepGraphFactory::getFingerprintIfAny(const Decl *d) {
632637 }
633638 return None;
634639}
640+
641+ // ==============================================================================
642+ // MARK: ModuleDepGraphFactory
643+ // ==============================================================================
644+
645+ ModuleDepGraphFactory::ModuleDepGraphFactory (ModuleDecl *Mod, bool emitDot)
646+ : AbstractSourceFileDepGraphFactory(
647+ /* include private*/ true , Mod->getASTContext ().hadError(),
648+ Mod->getNameStr(), "0xBADBEEF", emitDot, Mod->getASTContext().Diags),
649+ Mod(Mod) {}
650+
651+ void ModuleDepGraphFactory::addAllDefinedDecls () {
652+ // TODO: express the multiple provides and depends streams with variadic
653+ // templates
654+
655+ // Many kinds of Decls become top-level depends.
656+
657+ SmallVector<Decl *, 32 > TopLevelDecls;
658+ Mod->getTopLevelDecls (TopLevelDecls);
659+ DeclFinder declFinder (TopLevelDecls, includePrivateDeps,
660+ [this ](VisibleDeclConsumer &consumer) {
661+ return Mod->lookupClassMembers ({}, consumer);
662+ });
663+
664+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(
665+ declFinder.precedenceGroups );
666+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(
667+ declFinder.memberOperatorDecls );
668+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.operators );
669+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.topNominals );
670+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.topValues );
671+ addAllDefinedDeclsOfAGivenType<NodeKind::nominal>(declFinder.allNominals );
672+ addAllDefinedDeclsOfAGivenType<NodeKind::potentialMember>(
673+ declFinder.potentialMemberHolders );
674+ addAllDefinedDeclsOfAGivenType<NodeKind::member>(
675+ declFinder.valuesInExtensions );
676+ addAllDefinedDeclsOfAGivenType<NodeKind::dynamicLookup>(
677+ declFinder.classMembers );
678+ }
679+
680+ // / Given an array of Decls or pairs of them in \p declsOrPairs
681+ // / create node pairs for context and name
682+ template <NodeKind kind, typename ContentsT>
683+ void ModuleDepGraphFactory::addAllDefinedDeclsOfAGivenType (
684+ std::vector<ContentsT> &contentsVec) {
685+ for (const auto &declOrPair : contentsVec) {
686+ Optional<std::string> fp = getFingerprintIfAny (declOrPair);
687+ addADefinedDecl (
688+ DependencyKey::createForProvidedEntityInterface<kind>(declOrPair),
689+ fp ? StringRef (fp.getValue ()) : Optional<StringRef>());
690+ }
691+ }
692+
693+ // ==============================================================================
694+ // MARK: ModuleDepGraphFactory - adding individual defined Decls
695+ // ==============================================================================
696+
697+ // / At present, only \c NominalTypeDecls have (body) fingerprints
698+ Optional<std::string> ModuleDepGraphFactory::getFingerprintIfAny (
699+ std::pair<const NominalTypeDecl *, const ValueDecl *>) {
700+ return None;
701+ }
702+ Optional<std::string>
703+ ModuleDepGraphFactory::getFingerprintIfAny (const Decl *d) {
704+ if (const auto *idc = dyn_cast<IterableDeclContext>(d)) {
705+ auto result = idc->getBodyFingerprint ();
706+ assert ((!result || !result->empty ()) &&
707+ " Fingerprint should never be empty" );
708+ return result;
709+ }
710+ return None;
711+ }
0 commit comments