[SymbolGraphGen] Un-revert #78959 and clean up usage of DenseMap (#79124)

* Revert "Revert "[SymbolGraphGen] synthesize child symbols for type aliases of private…" (#79062)"

This reverts commit cac82978bc.

* clean up use of DenseMap in SymbolGraphGen

rdar://143865173
This commit is contained in:
QuietMisdreavus
2025-02-06 08:34:16 -07:00
committed by GitHub
parent 8daf94c195
commit 57450f5d18
8 changed files with 226 additions and 62 deletions

View File

@@ -233,6 +233,18 @@ void SymbolGraph::recordEdge(Symbol Source,
void SymbolGraph::recordMemberRelationship(Symbol S) {
const auto *DC = S.getLocalSymbolDecl()->getDeclContext();
const ValueDecl *ParentDecl = DC->getSelfNominalTypeDecl();
if (!ParentDecl) {
// If we couldn't look up the type the member is declared on (e.g.
// because the member is declared in an extension whose extended type
// doesn't exist), don't record a memberOf relationship.
return;
}
if (const auto *PublicDecl = Walker.PublicPrivateTypeAliases.lookup(ParentDecl)) {
// If our member target is a private type that has a public type alias,
// point the membership to that type alias instead.
ParentDecl = PublicDecl;
}
switch (DC->getContextKind()) {
case DeclContextKind::GenericTypeDecl:
case DeclContextKind::ExtensionDecl:
@@ -251,13 +263,6 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
return;
}
if (DC->getSelfNominalTypeDecl() == nullptr) {
// If we couldn't look up the type the member is declared on (e.g.
// because the member is declared in an extension whose extended type
// doesn't exist), don't record a memberOf relationship.
return;
}
// If this is an extension to an external type, we use the extension
// symbol itself as the target.
if (auto const *Extension =
@@ -269,8 +274,7 @@ void SymbolGraph::recordMemberRelationship(Symbol S) {
}
}
return recordEdge(S,
Symbol(this, DC->getSelfNominalTypeDecl(), nullptr),
return recordEdge(S, Symbol(this, ParentDecl, nullptr),
RelationshipKind::MemberOf());
case swift::DeclContextKind::AbstractClosureExpr:
case swift::DeclContextKind::SerializedAbstractClosure:
@@ -323,7 +327,16 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
bool dropSynthesizedMembers = !Walker.Options.EmitSynthesizedMembers ||
Walker.Options.SkipProtocolImplementations;
const auto D = S.getLocalSymbolDecl();
const auto *D = S.getLocalSymbolDecl();
// If this symbol is a public type alias to a private symbol, collect
// synthesized members for the underlying type.
if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
const auto *NTD = TD->getUnderlyingType()->getAnyNominal();
if (NTD && Walker.PublicPrivateTypeAliases.lookup(NTD) == D)
D = NTD;
}
const NominalTypeDecl *OwningNominal = nullptr;
if (const auto *ThisNominal = dyn_cast<NominalTypeDecl>(D)) {
OwningNominal = ThisNominal;
@@ -376,9 +389,11 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
// that protocol would otherwise be hidden.
if (auto *Nominal = Info.Ext->getExtendedNominal()) {
if (dropSynthesizedMembers &&
!isImplicitlyPrivate(
Nominal, /*IgnoreContext =*/Nominal->getModuleContext() ==
StdlibModule))
!isImplicitlyPrivate(Nominal, /*IgnoreContext =*/
[&](const Decl *P) {
return Nominal->getModuleContext() ==
StdlibModule;
}))
continue;
} else if (dropSynthesizedMembers) {
continue;
@@ -393,10 +408,12 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
// There can be synthesized members on effectively private
// protocols or things that conform to them. We don't want to
// include those.
if (isImplicitlyPrivate(SynthMember,
/*IgnoreContext =*/
SynthMember->getModuleContext() ==
StdlibModule)) {
if (isImplicitlyPrivate(
SynthMember,
/*IgnoreContext =*/
[&](const Decl *P) {
return SynthMember->getModuleContext() == StdlibModule;
})) {
continue;
}
@@ -405,7 +422,11 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
continue;
}
Symbol Source(this, SynthMember, OwningNominal);
const ValueDecl *BaseDecl = OwningNominal;
if (const auto *PublicDecl = Walker.PublicPrivateTypeAliases.lookup(BaseDecl))
BaseDecl = PublicDecl;
Symbol Source(this, SynthMember, BaseDecl);
if (auto *InheritedDecl = Source.getInheritedDecl()) {
if (auto *ParentDecl =
@@ -413,14 +434,17 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
if (dropSynthesizedMembers &&
!isImplicitlyPrivate(
ParentDecl,
/*IgnoreContext =*/ParentDecl->getModuleContext() ==
StdlibModule)) {
/*IgnoreContext =*/
[&](const Decl *P) {
return ParentDecl->getModuleContext() ==
StdlibModule;
})) {
continue;
}
}
}
auto ExtendedSG = Walker.getModuleSymbolGraph(OwningNominal);
auto ExtendedSG = Walker.getModuleSymbolGraph(BaseDecl);
ExtendedSG->Nodes.insert(Source);
@@ -433,7 +457,15 @@ void SymbolGraph::recordConformanceSynthesizedMemberRelationships(Symbol S) {
void
SymbolGraph::recordInheritanceRelationships(Symbol S) {
const auto D = S.getLocalSymbolDecl();
const auto *D = S.getLocalSymbolDecl();
// If this is a public type alias for a private symbol, gather inheritance
// for the underlying type instead.
if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
const auto *NTD = TD->getUnderlyingType()->getAnyNominal();
if (NTD && Walker.PublicPrivateTypeAliases.lookup(NTD) == D)
D = NTD;
}
ClassDecl *Super = nullptr;
if (auto *CD = dyn_cast<ClassDecl>(D))
@@ -442,8 +474,7 @@ SymbolGraph::recordInheritanceRelationships(Symbol S) {
Super = PD->getSuperclassDecl();
if (Super) {
recordEdge(Symbol(this, cast<ValueDecl>(D), nullptr),
Symbol(this, Super, nullptr),
recordEdge(S, Symbol(this, Super, nullptr),
RelationshipKind::InheritsFrom());
}
}
@@ -522,7 +553,16 @@ void SymbolGraph::recordOptionalRequirementRelationships(Symbol S) {
}
void SymbolGraph::recordConformanceRelationships(Symbol S) {
const auto D = S.getLocalSymbolDecl();
const auto *D = S.getLocalSymbolDecl();
// If this is a public type alias for a private symbol, gather conformances
// for the underlying type instead.
if (const auto *TD = dyn_cast<TypeAliasDecl>(D)) {
const auto *NTD = TD->getUnderlyingType()->getAnyNominal();
if (NTD && Walker.PublicPrivateTypeAliases.lookup(NTD) == D)
D = NTD;
}
if (const auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
for (auto *inherited : PD->getAllInheritedProtocols()) {
@@ -700,8 +740,8 @@ const ValueDecl *getProtocolRequirement(const ValueDecl *VD) {
}
bool SymbolGraph::isImplicitlyPrivate(const Decl *D,
bool IgnoreContext) const {
bool SymbolGraph::isImplicitlyPrivate(
const Decl *D, llvm::function_ref<bool(const Decl *)> IgnoreContext) const {
// Don't record unconditionally private declarations
if (D->isPrivateSystemDecl(/*treatNonBuiltinProtocolsAsPublic=*/false)) {
return true;
@@ -809,16 +849,15 @@ bool SymbolGraph::isImplicitlyPrivate(const Decl *D,
if (IsGlobalSIMDType) {
return true;
}
if (IgnoreContext) {
return false;
}
}
// Check up the parent chain. Anything inside a privately named
// thing is also private. We could be looking at the `B` of `_A.B`.
if (const auto *DC = D->getDeclContext()) {
if (const auto *Parent = DC->getAsDecl()) {
if (IgnoreContext && IgnoreContext(Parent))
return false;
// Exception: Children of underscored protocols should be considered
// public, even though the protocols themselves aren't. This way,
// synthesized copies of those symbols are correctly added to the public
@@ -851,7 +890,11 @@ bool SymbolGraph::isUnconditionallyUnavailableOnAllPlatforms(const Decl *D) cons
}
/// Returns `true` if the symbol should be included as a node in the graph.
bool SymbolGraph::canIncludeDeclAsNode(const Decl *D) const {
bool SymbolGraph::canIncludeDeclAsNode(const Decl *D,
const Decl *PublicAncestorDecl) const {
if (PublicAncestorDecl && D == PublicAncestorDecl)
return true;
// If this decl isn't in this module or module that this module imported with `@_exported`, don't record it,
// as it will appear elsewhere in its module's symbol graph.
@@ -873,6 +916,8 @@ bool SymbolGraph::canIncludeDeclAsNode(const Decl *D) const {
} else {
return false;
}
return !isImplicitlyPrivate(cast<ValueDecl>(D))
&& !isUnconditionallyUnavailableOnAllPlatforms(cast<ValueDecl>(D));
return !isImplicitlyPrivate(
cast<ValueDecl>(D), /*IgnoreContext=*/
[&](const Decl *P) { return P == PublicAncestorDecl; }) &&
!isUnconditionallyUnavailableOnAllPlatforms(cast<ValueDecl>(D));
}