@@ -232,6 +232,18 @@ void SymbolGraph::recordEdge(Symbol Source,
232
232
233
233
void SymbolGraph::recordMemberRelationship (Symbol S) {
234
234
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
+ }
235
247
switch (DC->getContextKind ()) {
236
248
case DeclContextKind::GenericTypeDecl:
237
249
case DeclContextKind::ExtensionDecl:
@@ -250,13 +262,6 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
250
262
return ;
251
263
}
252
264
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
-
260
265
// If this is an extension to an external type, we use the extension
261
266
// symbol itself as the target.
262
267
if (auto const *Extension =
@@ -268,8 +273,7 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
268
273
}
269
274
}
270
275
271
- return recordEdge (S,
272
- Symbol (this , DC->getSelfNominalTypeDecl (), nullptr ),
276
+ return recordEdge (S, Symbol (this , ParentDecl, nullptr ),
273
277
RelationshipKind::MemberOf ());
274
278
case swift::DeclContextKind::AbstractClosureExpr:
275
279
case swift::DeclContextKind::SerializedAbstractClosure:
@@ -322,7 +326,16 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
322
326
bool dropSynthesizedMembers = !Walker.Options .EmitSynthesizedMembers ||
323
327
Walker.Options .SkipProtocolImplementations ;
324
328
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
+
326
339
const NominalTypeDecl *OwningNominal = nullptr ;
327
340
if (const auto *ThisNominal = dyn_cast<NominalTypeDecl>(D)) {
328
341
OwningNominal = ThisNominal;
@@ -375,9 +388,11 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
375
388
// that protocol would otherwise be hidden.
376
389
if (auto *Nominal = Info.Ext ->getExtendedNominal ()) {
377
390
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
+ }))
381
396
continue ;
382
397
} else if (dropSynthesizedMembers) {
383
398
continue ;
@@ -392,10 +407,12 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
392
407
// There can be synthesized members on effectively private
393
408
// protocols or things that conform to them. We don't want to
394
409
// 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
+ })) {
399
416
continue ;
400
417
}
401
418
@@ -404,22 +421,29 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
404
421
continue ;
405
422
}
406
423
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);
408
429
409
430
if (auto *InheritedDecl = Source.getInheritedDecl ()) {
410
431
if (auto *ParentDecl =
411
432
InheritedDecl->getDeclContext ()->getAsDecl ()) {
412
433
if (dropSynthesizedMembers &&
413
434
!isImplicitlyPrivate (
414
435
ParentDecl,
415
- /* IgnoreContext =*/ ParentDecl->getModuleContext () ==
416
- StdlibModule)) {
436
+ /* IgnoreContext =*/
437
+ [&](const Decl *P) {
438
+ return ParentDecl->getModuleContext () ==
439
+ StdlibModule;
440
+ })) {
417
441
continue ;
418
442
}
419
443
}
420
444
}
421
445
422
- auto ExtendedSG = Walker.getModuleSymbolGraph (OwningNominal );
446
+ auto ExtendedSG = Walker.getModuleSymbolGraph (BaseDecl );
423
447
424
448
ExtendedSG->Nodes .insert (Source);
425
449
@@ -432,7 +456,15 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
432
456
433
457
void
434
458
SymbolGraph::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
+ }
436
468
437
469
ClassDecl *Super = nullptr ;
438
470
if (auto *CD = dyn_cast<ClassDecl>(D))
@@ -441,8 +473,7 @@ SymbolGraph::recordInheritanceRelationships(Symbol S) {
441
473
Super = PD->getSuperclassDecl ();
442
474
443
475
if (Super) {
444
- recordEdge (Symbol (this , cast<ValueDecl>(D), nullptr ),
445
- Symbol (this , Super, nullptr ),
476
+ recordEdge (S, Symbol (this , Super, nullptr ),
446
477
RelationshipKind::InheritsFrom ());
447
478
}
448
479
}
@@ -521,7 +552,16 @@ void SymbolGraph::recordOptionalRequirementRelationships(Symbol S) {
521
552
}
522
553
523
554
void 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
+
525
565
if (const auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
526
566
if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
527
567
for (auto *inherited : PD->getAllInheritedProtocols ()) {
@@ -699,8 +739,8 @@ const ValueDecl *getProtocolRequirement(const ValueDecl *VD) {
699
739
700
740
}
701
741
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 {
704
744
// Don't record unconditionally private declarations
705
745
if (D->isPrivateSystemDecl (/* treatNonBuiltinProtocolsAsPublic=*/ false )) {
706
746
return true ;
@@ -808,16 +848,15 @@ bool SymbolGraph::isImplicitlyPrivate(const Decl *D,
808
848
if (IsGlobalSIMDType) {
809
849
return true ;
810
850
}
811
-
812
- if (IgnoreContext) {
813
- return false ;
814
- }
815
851
}
816
852
817
853
// Check up the parent chain. Anything inside a privately named
818
854
// thing is also private. We could be looking at the `B` of `_A.B`.
819
855
if (const auto *DC = D->getDeclContext ()) {
820
856
if (const auto *Parent = DC->getAsDecl ()) {
857
+ if (IgnoreContext && IgnoreContext (Parent))
858
+ return false ;
859
+
821
860
// Exception: Children of underscored protocols should be considered
822
861
// public, even though the protocols themselves aren't. This way,
823
862
// synthesized copies of those symbols are correctly added to the public
@@ -850,7 +889,11 @@ bool SymbolGraph::isUnconditionallyUnavailableOnAllPlatforms(const Decl *D) cons
850
889
}
851
890
852
891
// / 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
+
854
897
// If this decl isn't in this module or module that this module imported with `@_exported`, don't record it,
855
898
// as it will appear elsewhere in its module's symbol graph.
856
899
if (D->getModuleContext ()->getName () != M.getName () && !Walker.isConsideredExportedImported (D)) {
@@ -864,6 +907,8 @@ bool SymbolGraph::canIncludeDeclAsNode(const Decl *D) const {
864
907
} else {
865
908
return false ;
866
909
}
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));
869
914
}
0 commit comments