@@ -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 (
@@ -632,3 +634,75 @@ FrontendSourceFileDepGraphFactory::getFingerprintIfAny(const Decl *d) {
632634 }
633635 return None;
634636}
637+
638+ // ==============================================================================
639+ // MARK: ModuleDepGraphFactory
640+ // ==============================================================================
641+
642+ ModuleDepGraphFactory::ModuleDepGraphFactory (ModuleDecl *Mod, bool emitDot)
643+ : AbstractSourceFileDepGraphFactory(
644+ /* include private*/ true , Mod->getASTContext ().hadError(),
645+ Mod->getNameStr(), "0xBADBEEF", emitDot, Mod->getASTContext().Diags),
646+ Mod(Mod) {}
647+
648+ void ModuleDepGraphFactory::addAllDefinedDecls () {
649+ // TODO: express the multiple provides and depends streams with variadic
650+ // templates
651+
652+ // Many kinds of Decls become top-level depends.
653+
654+ SmallVector<Decl *, 32 > TopLevelDecls;
655+ Mod->getTopLevelDecls (TopLevelDecls);
656+ DeclFinder declFinder (TopLevelDecls, includePrivateDeps,
657+ [this ](VisibleDeclConsumer &consumer) {
658+ return Mod->lookupClassMembers ({}, consumer);
659+ });
660+
661+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(
662+ declFinder.precedenceGroups );
663+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(
664+ declFinder.memberOperatorDecls );
665+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.operators );
666+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.topNominals );
667+ addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.topValues );
668+ addAllDefinedDeclsOfAGivenType<NodeKind::nominal>(declFinder.allNominals );
669+ addAllDefinedDeclsOfAGivenType<NodeKind::potentialMember>(
670+ declFinder.potentialMemberHolders );
671+ addAllDefinedDeclsOfAGivenType<NodeKind::member>(
672+ declFinder.valuesInExtensions );
673+ addAllDefinedDeclsOfAGivenType<NodeKind::dynamicLookup>(
674+ declFinder.classMembers );
675+ }
676+
677+ // / Given an array of Decls or pairs of them in \p declsOrPairs
678+ // / create node pairs for context and name
679+ template <NodeKind kind, typename ContentsT>
680+ void ModuleDepGraphFactory::addAllDefinedDeclsOfAGivenType (
681+ std::vector<ContentsT> &contentsVec) {
682+ for (const auto &declOrPair : contentsVec) {
683+ Optional<std::string> fp = getFingerprintIfAny (declOrPair);
684+ addADefinedDecl (
685+ DependencyKey::createForProvidedEntityInterface<kind>(declOrPair),
686+ fp ? StringRef (fp.getValue ()) : Optional<StringRef>());
687+ }
688+ }
689+
690+ // ==============================================================================
691+ // MARK: ModuleDepGraphFactory - adding individual defined Decls
692+ // ==============================================================================
693+
694+ // / At present, only \c NominalTypeDecls have (body) fingerprints
695+ Optional<std::string> ModuleDepGraphFactory::getFingerprintIfAny (
696+ std::pair<const NominalTypeDecl *, const ValueDecl *>) {
697+ return None;
698+ }
699+ Optional<std::string>
700+ ModuleDepGraphFactory::getFingerprintIfAny (const Decl *d) {
701+ if (const auto *idc = dyn_cast<IterableDeclContext>(d)) {
702+ auto result = idc->getBodyFingerprint ();
703+ assert ((!result || !result->empty ()) &&
704+ " Fingerprint should never be empty" );
705+ return result;
706+ }
707+ return None;
708+ }
0 commit comments