@@ -780,6 +780,30 @@ void SourceFile::lookupObjCMethods(
780780 results.append (known->second .begin (), known->second .end ());
781781}
782782
783+ bool ModuleDecl::shouldCollectDisplayDecls () const {
784+ for (const FileUnit *file : Files) {
785+ if (!file->shouldCollectDisplayDecls ())
786+ return false ;
787+ }
788+ return true ;
789+ }
790+
791+ static void collectParsedExportedImports (const ModuleDecl *M, SmallPtrSetImpl<ModuleDecl *> &Imports) {
792+ for (const FileUnit *file : M->getFiles ()) {
793+ if (const SourceFile *source = dyn_cast<SourceFile>(file)) {
794+ if (source->hasImports ()) {
795+ for (auto import : source->getImports ()) {
796+ if (import .options .contains (ImportFlags::Exported) &&
797+ !Imports.contains (import .module .importedModule ) &&
798+ import .module .importedModule ->shouldCollectDisplayDecls ()) {
799+ Imports.insert (import .module .importedModule );
800+ }
801+ }
802+ }
803+ }
804+ }
805+ }
806+
783807void ModuleDecl::getLocalTypeDecls (SmallVectorImpl<TypeDecl*> &Results) const {
784808 FORWARD (getLocalTypeDecls, (Results));
785809}
@@ -788,6 +812,24 @@ void ModuleDecl::getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const {
788812 FORWARD (getTopLevelDecls, (Results));
789813}
790814
815+ void ModuleDecl::dumpDisplayDecls () const {
816+ SmallVector<Decl *, 32 > Decls;
817+ getDisplayDecls (Decls);
818+ for (auto *D : Decls) {
819+ D->dump (llvm::errs ());
820+ llvm::errs () << " \n " ;
821+ }
822+ }
823+
824+ void ModuleDecl::dumpTopLevelDecls () const {
825+ SmallVector<Decl *, 32 > Decls;
826+ getTopLevelDecls (Decls);
827+ for (auto *D : Decls) {
828+ D->dump (llvm::errs ());
829+ llvm::errs () << " \n " ;
830+ }
831+ }
832+
791833void ModuleDecl::getExportedPrespecializations (
792834 SmallVectorImpl<Decl *> &Results) const {
793835 FORWARD (getExportedPrespecializations, (Results));
@@ -907,9 +949,34 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
907949 return Result;
908950}
909951
910- void ModuleDecl::getDisplayDecls (SmallVectorImpl<Decl*> &Results) const {
952+ void ModuleDecl::getDisplayDecls (SmallVectorImpl<Decl*> &Results, bool Recursive) const {
953+ if (Recursive && isParsedModule (this )) {
954+ SmallPtrSet<ModuleDecl *, 4 > Modules;
955+ collectParsedExportedImports (this , Modules);
956+ for (const ModuleDecl *import : Modules) {
957+ import ->getDisplayDecls (Results, Recursive);
958+ }
959+ }
911960 // FIXME: Should this do extra access control filtering?
912961 FORWARD (getDisplayDecls, (Results));
962+
963+ #ifndef NDEBUG
964+ if (Recursive) {
965+ llvm::DenseSet<Decl *> visited;
966+ for (auto *D : Results) {
967+ // decls synthesized from implicit clang decls may appear multiple times;
968+ // e.g. if multiple modules with underlying clang modules are re-exported.
969+ // including duplicates of these is harmless, so skip them when counting
970+ // this assertion
971+ if (const auto *CD = D->getClangDecl ()) {
972+ if (CD->isImplicit ()) continue ;
973+ }
974+
975+ auto inserted = visited.insert (D).second ;
976+ assert (inserted && " there should be no duplicate decls" );
977+ }
978+ }
979+ #endif
913980}
914981
915982ProtocolConformanceRef
@@ -3065,6 +3132,22 @@ void FileUnit::getTopLevelDeclsWhereAttributesMatch(
30653132 Results.erase (newEnd, Results.end ());
30663133}
30673134
3135+ void FileUnit::dumpDisplayDecls () const {
3136+ SmallVector<Decl *, 32 > Decls;
3137+ getDisplayDecls (Decls);
3138+ for (auto *D : Decls) {
3139+ D->dump (llvm::errs ());
3140+ }
3141+ }
3142+
3143+ void FileUnit::dumpTopLevelDecls () const {
3144+ SmallVector<Decl *, 32 > Decls;
3145+ getTopLevelDecls (Decls);
3146+ for (auto *D : Decls) {
3147+ D->dump (llvm::errs ());
3148+ }
3149+ }
3150+
30683151void swift::simple_display (llvm::raw_ostream &out, const FileUnit *file) {
30693152 if (!file) {
30703153 out << " (null)" ;
0 commit comments