@@ -233,6 +233,18 @@ void SymbolGraph::recordEdge(Symbol Source,
233
233
234
234
void SymbolGraph::recordMemberRelationship (Symbol S) {
235
235
const auto *DC = S.getLocalSymbolDecl ()->getDeclContext ();
236
+ const ValueDecl *ParentDecl = DC->getSelfNominalTypeDecl ();
237
+ if (!ParentDecl) {
238
+ // If we couldn't look up the type the member is declared on (e.g.
239
+ // because the member is declared in an extension whose extended type
240
+ // doesn't exist), don't record a memberOf relationship.
241
+ return ;
242
+ }
243
+ if (const auto *PublicDecl = Walker.PublicPrivateTypeAliases .lookup (ParentDecl)) {
244
+ // If our member target is a private type that has a public type alias,
245
+ // point the membership to that type alias instead.
246
+ ParentDecl = PublicDecl;
247
+ }
236
248
switch (DC->getContextKind ()) {
237
249
case DeclContextKind::GenericTypeDecl:
238
250
case DeclContextKind::ExtensionDecl:
@@ -251,13 +263,6 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
251
263
return ;
252
264
}
253
265
254
- if (DC->getSelfNominalTypeDecl () == nullptr ) {
255
- // If we couldn't look up the type the member is declared on (e.g.
256
- // because the member is declared in an extension whose extended type
257
- // doesn't exist), don't record a memberOf relationship.
258
- return ;
259
- }
260
-
261
266
// If this is an extension to an external type, we use the extension
262
267
// symbol itself as the target.
263
268
if (auto const *Extension =
@@ -269,8 +274,7 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
269
274
}
270
275
}
271
276
272
- return recordEdge (S,
273
- Symbol (this , DC->getSelfNominalTypeDecl (), nullptr ),
277
+ return recordEdge (S, Symbol (this , ParentDecl, nullptr ),
274
278
RelationshipKind::MemberOf ());
275
279
case swift::DeclContextKind::AbstractClosureExpr:
276
280
case swift::DeclContextKind::SerializedAbstractClosure:
@@ -323,7 +327,16 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
323
327
bool dropSynthesizedMembers = !Walker.Options .EmitSynthesizedMembers ||
324
328
Walker.Options .SkipProtocolImplementations ;
325
329
326
- const auto D = S.getLocalSymbolDecl ();
330
+ const auto *D = S.getLocalSymbolDecl ();
331
+
332
+ // If this symbol is a public type alias to a private symbol, collect
333
+ // synthesized members for the underlying type.
334
+ if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
335
+ const auto *NTD = TD->getUnderlyingType ()->getAnyNominal ();
336
+ if (NTD && Walker.PublicPrivateTypeAliases .lookup (NTD) == D)
337
+ D = NTD;
338
+ }
339
+
327
340
const NominalTypeDecl *OwningNominal = nullptr ;
328
341
if (const auto *ThisNominal = dyn_cast<NominalTypeDecl>(D)) {
329
342
OwningNominal = ThisNominal;
@@ -376,9 +389,11 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
376
389
// that protocol would otherwise be hidden.
377
390
if (auto *Nominal = Info.Ext ->getExtendedNominal ()) {
378
391
if (dropSynthesizedMembers &&
379
- !isImplicitlyPrivate (
380
- Nominal, /* IgnoreContext =*/ Nominal->getModuleContext () ==
381
- StdlibModule))
392
+ !isImplicitlyPrivate (Nominal, /* IgnoreContext =*/
393
+ [&](const Decl *P) {
394
+ return Nominal->getModuleContext () ==
395
+ StdlibModule;
396
+ }))
382
397
continue ;
383
398
} else if (dropSynthesizedMembers) {
384
399
continue ;
@@ -393,10 +408,12 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
393
408
// There can be synthesized members on effectively private
394
409
// protocols or things that conform to them. We don't want to
395
410
// include those.
396
- if (isImplicitlyPrivate (SynthMember,
397
- /* IgnoreContext =*/
398
- SynthMember->getModuleContext () ==
399
- StdlibModule)) {
411
+ if (isImplicitlyPrivate (
412
+ SynthMember,
413
+ /* IgnoreContext =*/
414
+ [&](const Decl *P) {
415
+ return SynthMember->getModuleContext () == StdlibModule;
416
+ })) {
400
417
continue ;
401
418
}
402
419
@@ -405,22 +422,29 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
405
422
continue ;
406
423
}
407
424
408
- Symbol Source (this , SynthMember, OwningNominal);
425
+ const ValueDecl *BaseDecl = OwningNominal;
426
+ if (const auto *PublicDecl = Walker.PublicPrivateTypeAliases .lookup (BaseDecl))
427
+ BaseDecl = PublicDecl;
428
+
429
+ Symbol Source (this , SynthMember, BaseDecl);
409
430
410
431
if (auto *InheritedDecl = Source.getInheritedDecl ()) {
411
432
if (auto *ParentDecl =
412
433
InheritedDecl->getDeclContext ()->getAsDecl ()) {
413
434
if (dropSynthesizedMembers &&
414
435
!isImplicitlyPrivate (
415
436
ParentDecl,
416
- /* IgnoreContext =*/ ParentDecl->getModuleContext () ==
417
- StdlibModule)) {
437
+ /* IgnoreContext =*/
438
+ [&](const Decl *P) {
439
+ return ParentDecl->getModuleContext () ==
440
+ StdlibModule;
441
+ })) {
418
442
continue ;
419
443
}
420
444
}
421
445
}
422
446
423
- auto ExtendedSG = Walker.getModuleSymbolGraph (OwningNominal );
447
+ auto ExtendedSG = Walker.getModuleSymbolGraph (BaseDecl );
424
448
425
449
ExtendedSG->Nodes .insert (Source);
426
450
@@ -433,7 +457,15 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
433
457
434
458
void
435
459
SymbolGraph::recordInheritanceRelationships (Symbol S) {
436
- const auto D = S.getLocalSymbolDecl ();
460
+ const auto *D = S.getLocalSymbolDecl ();
461
+
462
+ // If this is a public type alias for a private symbol, gather inheritance
463
+ // for the underlying type instead.
464
+ if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
465
+ const auto *NTD = TD->getUnderlyingType ()->getAnyNominal ();
466
+ if (NTD && Walker.PublicPrivateTypeAliases .lookup (NTD) == D)
467
+ D = NTD;
468
+ }
437
469
438
470
ClassDecl *Super = nullptr ;
439
471
if (auto *CD = dyn_cast<ClassDecl>(D))
@@ -442,8 +474,7 @@ SymbolGraph::recordInheritanceRelationships(Symbol S) {
442
474
Super = PD->getSuperclassDecl ();
443
475
444
476
if (Super) {
445
- recordEdge (Symbol (this , cast<ValueDecl>(D), nullptr ),
446
- Symbol (this , Super, nullptr ),
477
+ recordEdge (S, Symbol (this , Super, nullptr ),
447
478
RelationshipKind::InheritsFrom ());
448
479
}
449
480
}
@@ -522,7 +553,16 @@ void SymbolGraph::recordOptionalRequirementRelationships(Symbol S) {
522
553
}
523
554
524
555
void SymbolGraph::recordConformanceRelationships (Symbol S) {
525
- const auto D = S.getLocalSymbolDecl ();
556
+ const auto *D = S.getLocalSymbolDecl ();
557
+
558
+ // If this is a public type alias for a private symbol, gather conformances
559
+ // for the underlying type instead.
560
+ if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
561
+ const auto *NTD = TD->getUnderlyingType ()->getAnyNominal ();
562
+ if (NTD && Walker.PublicPrivateTypeAliases .lookup (NTD) == D)
563
+ D = NTD;
564
+ }
565
+
526
566
if (const auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
527
567
if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
528
568
for (auto *inherited : PD->getAllInheritedProtocols ()) {
@@ -700,8 +740,8 @@ const ValueDecl *getProtocolRequirement(const ValueDecl *VD) {
700
740
701
741
}
702
742
703
- bool SymbolGraph::isImplicitlyPrivate (const Decl *D,
704
- bool IgnoreContext) const {
743
+ bool SymbolGraph::isImplicitlyPrivate (
744
+ const Decl *D, llvm::function_ref< bool ( const Decl *)> IgnoreContext) const {
705
745
// Don't record unconditionally private declarations
706
746
if (D->isPrivateSystemDecl (/* treatNonBuiltinProtocolsAsPublic=*/ false )) {
707
747
return true ;
@@ -809,16 +849,15 @@ bool SymbolGraph::isImplicitlyPrivate(const Decl *D,
809
849
if (IsGlobalSIMDType) {
810
850
return true ;
811
851
}
812
-
813
- if (IgnoreContext) {
814
- return false ;
815
- }
816
852
}
817
853
818
854
// Check up the parent chain. Anything inside a privately named
819
855
// thing is also private. We could be looking at the `B` of `_A.B`.
820
856
if (const auto *DC = D->getDeclContext ()) {
821
857
if (const auto *Parent = DC->getAsDecl ()) {
858
+ if (IgnoreContext && IgnoreContext (Parent))
859
+ return false ;
860
+
822
861
// Exception: Children of underscored protocols should be considered
823
862
// public, even though the protocols themselves aren't. This way,
824
863
// synthesized copies of those symbols are correctly added to the public
@@ -851,7 +890,11 @@ bool SymbolGraph::isUnconditionallyUnavailableOnAllPlatforms(const Decl *D) cons
851
890
}
852
891
853
892
// / Returns `true` if the symbol should be included as a node in the graph.
854
- bool SymbolGraph::canIncludeDeclAsNode (const Decl *D) const {
893
+ bool SymbolGraph::canIncludeDeclAsNode (const Decl *D,
894
+ const Decl *PublicAncestorDecl) const {
895
+ if (PublicAncestorDecl && D == PublicAncestorDecl)
896
+ return true ;
897
+
855
898
// If this decl isn't in this module or module that this module imported with `@_exported`, don't record it,
856
899
// as it will appear elsewhere in its module's symbol graph.
857
900
@@ -873,6 +916,8 @@ bool SymbolGraph::canIncludeDeclAsNode(const Decl *D) const {
873
916
} else {
874
917
return false ;
875
918
}
876
- return !isImplicitlyPrivate (cast<ValueDecl>(D))
877
- && !isUnconditionallyUnavailableOnAllPlatforms (cast<ValueDecl>(D));
919
+ return !isImplicitlyPrivate (
920
+ cast<ValueDecl>(D), /* IgnoreContext=*/
921
+ [&](const Decl *P) { return P == PublicAncestorDecl; }) &&
922
+ !isUnconditionallyUnavailableOnAllPlatforms (cast<ValueDecl>(D));
878
923
}
0 commit comments