@@ -232,6 +232,18 @@ void SymbolGraph::recordEdge(Symbol Source,
232232
233233void SymbolGraph::recordMemberRelationship (Symbol S) {
234234 const auto *DC = S.getLocalSymbolDecl ()->getDeclContext ();
235+ const ValueDecl *ParentDecl = DC->getSelfNominalTypeDecl ();
236+ if (!ParentDecl) {
237+ // If we couldn't look up the type the member is declared on (e.g.
238+ // because the member is declared in an extension whose extended type
239+ // doesn't exist), don't record a memberOf relationship.
240+ return ;
241+ }
242+ if (const auto *PublicDecl = Walker.PublicPrivateTypeAliases [ParentDecl]) {
243+ // If our member target is a private type that has a public type alias,
244+ // point the membership to that type alias instead.
245+ ParentDecl = PublicDecl;
246+ }
235247 switch (DC->getContextKind ()) {
236248 case DeclContextKind::GenericTypeDecl:
237249 case DeclContextKind::ExtensionDecl:
@@ -250,13 +262,6 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
250262 return ;
251263 }
252264
253- if (DC->getSelfNominalTypeDecl () == nullptr ) {
254- // If we couldn't look up the type the member is declared on (e.g.
255- // because the member is declared in an extension whose extended type
256- // doesn't exist), don't record a memberOf relationship.
257- return ;
258- }
259-
260265 // If this is an extension to an external type, we use the extension
261266 // symbol itself as the target.
262267 if (auto const *Extension =
@@ -268,8 +273,7 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
268273 }
269274 }
270275
271- return recordEdge (S,
272- Symbol (this , DC->getSelfNominalTypeDecl (), nullptr ),
276+ return recordEdge (S, Symbol (this , ParentDecl, nullptr ),
273277 RelationshipKind::MemberOf ());
274278 case swift::DeclContextKind::AbstractClosureExpr:
275279 case swift::DeclContextKind::SerializedAbstractClosure:
@@ -322,7 +326,16 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
322326 bool dropSynthesizedMembers = !Walker.Options .EmitSynthesizedMembers ||
323327 Walker.Options .SkipProtocolImplementations ;
324328
325- const auto D = S.getLocalSymbolDecl ();
329+ const auto *D = S.getLocalSymbolDecl ();
330+
331+ // If this symbol is a public type alias to a private symbol, collect
332+ // synthesized members for the underlying type.
333+ if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
334+ const auto *NTD = TD->getUnderlyingType ()->getAnyNominal ();
335+ if (NTD && Walker.PublicPrivateTypeAliases [NTD] == D)
336+ D = NTD;
337+ }
338+
326339 const NominalTypeDecl *OwningNominal = nullptr ;
327340 if (const auto *ThisNominal = dyn_cast<NominalTypeDecl>(D)) {
328341 OwningNominal = ThisNominal;
@@ -375,9 +388,11 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
375388 // that protocol would otherwise be hidden.
376389 if (auto *Nominal = Info.Ext ->getExtendedNominal ()) {
377390 if (dropSynthesizedMembers &&
378- !isImplicitlyPrivate (
379- Nominal, /* IgnoreContext =*/ Nominal->getModuleContext () ==
380- StdlibModule))
391+ !isImplicitlyPrivate (Nominal, /* IgnoreContext =*/
392+ [&](const Decl *P) {
393+ return Nominal->getModuleContext () ==
394+ StdlibModule;
395+ }))
381396 continue ;
382397 } else if (dropSynthesizedMembers) {
383398 continue ;
@@ -392,10 +407,12 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
392407 // There can be synthesized members on effectively private
393408 // protocols or things that conform to them. We don't want to
394409 // include those.
395- if (isImplicitlyPrivate (SynthMember,
396- /* IgnoreContext =*/
397- SynthMember->getModuleContext () ==
398- StdlibModule)) {
410+ if (isImplicitlyPrivate (
411+ SynthMember,
412+ /* IgnoreContext =*/
413+ [&](const Decl *P) {
414+ return SynthMember->getModuleContext () == StdlibModule;
415+ })) {
399416 continue ;
400417 }
401418
@@ -404,22 +421,29 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
404421 continue ;
405422 }
406423
407- Symbol Source (this , SynthMember, OwningNominal);
424+ const ValueDecl *BaseDecl = OwningNominal;
425+ if (Walker.PublicPrivateTypeAliases .contains (BaseDecl))
426+ BaseDecl = Walker.PublicPrivateTypeAliases [BaseDecl];
427+
428+ Symbol Source (this , SynthMember, BaseDecl);
408429
409430 if (auto *InheritedDecl = Source.getInheritedDecl ()) {
410431 if (auto *ParentDecl =
411432 InheritedDecl->getDeclContext ()->getAsDecl ()) {
412433 if (dropSynthesizedMembers &&
413434 !isImplicitlyPrivate (
414435 ParentDecl,
415- /* IgnoreContext =*/ ParentDecl->getModuleContext () ==
416- StdlibModule)) {
436+ /* IgnoreContext =*/
437+ [&](const Decl *P) {
438+ return ParentDecl->getModuleContext () ==
439+ StdlibModule;
440+ })) {
417441 continue ;
418442 }
419443 }
420444 }
421445
422- auto ExtendedSG = Walker.getModuleSymbolGraph (OwningNominal );
446+ auto ExtendedSG = Walker.getModuleSymbolGraph (BaseDecl );
423447
424448 ExtendedSG->Nodes .insert (Source);
425449
@@ -432,7 +456,15 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
432456
433457void
434458SymbolGraph::recordInheritanceRelationships (Symbol S) {
435- const auto D = S.getLocalSymbolDecl ();
459+ const auto *D = S.getLocalSymbolDecl ();
460+
461+ // If this is a public type alias for a private symbol, gather inheritance
462+ // for the underlying type instead.
463+ if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
464+ const auto *NTD = TD->getUnderlyingType ()->getAnyNominal ();
465+ if (NTD && Walker.PublicPrivateTypeAliases [NTD] == D)
466+ D = NTD;
467+ }
436468
437469 ClassDecl *Super = nullptr ;
438470 if (auto *CD = dyn_cast<ClassDecl>(D))
@@ -441,8 +473,7 @@ SymbolGraph::recordInheritanceRelationships(Symbol S) {
441473 Super = PD->getSuperclassDecl ();
442474
443475 if (Super) {
444- recordEdge (Symbol (this , cast<ValueDecl>(D), nullptr ),
445- Symbol (this , Super, nullptr ),
476+ recordEdge (S, Symbol (this , Super, nullptr ),
446477 RelationshipKind::InheritsFrom ());
447478 }
448479}
@@ -521,7 +552,16 @@ void SymbolGraph::recordOptionalRequirementRelationships(Symbol S) {
521552}
522553
523554void SymbolGraph::recordConformanceRelationships (Symbol S) {
524- const auto D = S.getLocalSymbolDecl ();
555+ const auto *D = S.getLocalSymbolDecl ();
556+
557+ // If this is a public type alias for a private symbol, gather conformances
558+ // for the underlying type instead.
559+ if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
560+ const auto *NTD = TD->getUnderlyingType ()->getAnyNominal ();
561+ if (NTD && Walker.PublicPrivateTypeAliases [NTD] == D)
562+ D = NTD;
563+ }
564+
525565 if (const auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
526566 if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
527567 for (auto *inherited : PD->getAllInheritedProtocols ()) {
@@ -699,8 +739,8 @@ const ValueDecl *getProtocolRequirement(const ValueDecl *VD) {
699739
700740}
701741
702- bool SymbolGraph::isImplicitlyPrivate (const Decl *D,
703- bool IgnoreContext) const {
742+ bool SymbolGraph::isImplicitlyPrivate (
743+ const Decl *D, llvm::function_ref< bool ( const Decl *)> IgnoreContext) const {
704744 // Don't record unconditionally private declarations
705745 if (D->isPrivateSystemDecl (/* treatNonBuiltinProtocolsAsPublic=*/ false )) {
706746 return true ;
@@ -808,16 +848,15 @@ bool SymbolGraph::isImplicitlyPrivate(const Decl *D,
808848 if (IsGlobalSIMDType) {
809849 return true ;
810850 }
811-
812- if (IgnoreContext) {
813- return false ;
814- }
815851 }
816852
817853 // Check up the parent chain. Anything inside a privately named
818854 // thing is also private. We could be looking at the `B` of `_A.B`.
819855 if (const auto *DC = D->getDeclContext ()) {
820856 if (const auto *Parent = DC->getAsDecl ()) {
857+ if (IgnoreContext && IgnoreContext (Parent))
858+ return false ;
859+
821860 // Exception: Children of underscored protocols should be considered
822861 // public, even though the protocols themselves aren't. This way,
823862 // synthesized copies of those symbols are correctly added to the public
@@ -850,7 +889,11 @@ bool SymbolGraph::isUnconditionallyUnavailableOnAllPlatforms(const Decl *D) cons
850889}
851890
852891// / Returns `true` if the symbol should be included as a node in the graph.
853- bool SymbolGraph::canIncludeDeclAsNode (const Decl *D) const {
892+ bool SymbolGraph::canIncludeDeclAsNode (const Decl *D,
893+ const Decl *PublicAncestorDecl) const {
894+ if (PublicAncestorDecl && D == PublicAncestorDecl)
895+ return true ;
896+
854897 // If this decl isn't in this module or module that this module imported with `@_exported`, don't record it,
855898 // as it will appear elsewhere in its module's symbol graph.
856899 if (D->getModuleContext ()->getName () != M.getName () && !Walker.isConsideredExportedImported (D)) {
@@ -864,6 +907,8 @@ bool SymbolGraph::canIncludeDeclAsNode(const Decl *D) const {
864907 } else {
865908 return false ;
866909 }
867- return !isImplicitlyPrivate (cast<ValueDecl>(D))
868- && !isUnconditionallyUnavailableOnAllPlatforms (cast<ValueDecl>(D));
910+ return !isImplicitlyPrivate (
911+ cast<ValueDecl>(D), /* IgnoreContext=*/
912+ [&](const Decl *P) { return P == PublicAncestorDecl; }) &&
913+ !isUnconditionallyUnavailableOnAllPlatforms (cast<ValueDecl>(D));
869914}
0 commit comments