Skip to content

Commit

Permalink
[SymbolGraph] Track conditional conformance
Browse files Browse the repository at this point in the history
Requirements on extensions were only being gathered indirectly. This adds a new
optional field to `conformsTo` relationship edges, `swiftConstraints`, which
provides the requirements there.

rdar://60091161
  • Loading branch information
bitjammer committed Mar 10, 2020
1 parent 97d8c99 commit 7ce6753
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 115 deletions.
9 changes: 9 additions & 0 deletions lib/SymbolGraphGen/Edge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,14 @@ void Edge::serialize(llvm::json::OStream &OS) const {
Target.printPath(PathOS);
OS.attribute("targetFallback", Scratch.str());
}

if (ConformanceExtension &&
!ConformanceExtension->getGenericRequirements().empty()) {
OS.attributeArray("swiftConstraints", [&](){
for (const auto &Req : ConformanceExtension->getGenericRequirements()) {
::serialize(Req, OS);
}
});
}
});
}
15 changes: 13 additions & 2 deletions lib/SymbolGraphGen/Edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ struct Edge {

/// The precise identifier of the target symbol node.
Symbol Target;

/// If this is a conformsTo relationship, the extension that defined
/// the conformance.
const ExtensionDecl *ConformanceExtension;

void serialize(llvm::json::OStream &OS) const;
};
Expand All @@ -137,13 +141,15 @@ namespace llvm {
using SymbolGraph = swift::symbolgraphgen::SymbolGraph;
using Symbol = swift::symbolgraphgen::Symbol;
using Edge = swift::symbolgraphgen::Edge;
using ExtensionDecl = swift::ExtensionDecl;
template <> struct DenseMapInfo<Edge> {
static inline Edge getEmptyKey() {
return {
DenseMapInfo<SymbolGraph *>::getEmptyKey(),
{ "Empty" },
DenseMapInfo<Symbol>::getEmptyKey(),
DenseMapInfo<Symbol>::getEmptyKey()
DenseMapInfo<Symbol>::getEmptyKey(),
DenseMapInfo<const ExtensionDecl *>::getEmptyKey(),
};
}
static inline Edge getTombstoneKey() {
Expand All @@ -152,19 +158,24 @@ template <> struct DenseMapInfo<Edge> {
{ "Tombstone" },
DenseMapInfo<Symbol>::getTombstoneKey(),
DenseMapInfo<Symbol>::getTombstoneKey(),
DenseMapInfo<const ExtensionDecl *>::getTombstoneKey(),
};
}
static unsigned getHashValue(const Edge E) {
unsigned H = 0;
H ^= DenseMapInfo<StringRef>::getHashValue(E.Kind.Name);
H ^= DenseMapInfo<Symbol>::getHashValue(E.Source);
H ^= DenseMapInfo<Symbol>::getHashValue(E.Target);
H ^= DenseMapInfo<const ExtensionDecl *>::
getHashValue(E.ConformanceExtension);
return H;
}
static bool isEqual(const Edge LHS, const Edge RHS) {
return LHS.Kind == RHS.Kind &&
DenseMapInfo<Symbol>::isEqual(LHS.Source, RHS.Source) &&
DenseMapInfo<Symbol>::isEqual(LHS.Target, RHS.Target);
DenseMapInfo<Symbol>::isEqual(LHS.Target, RHS.Target) &&
DenseMapInfo<const ExtensionDecl *>::isEqual(LHS.ConformanceExtension,
RHS.ConformanceExtension);
}
};
} // end namespace llvm
Expand Down
46 changes: 46 additions & 0 deletions lib/SymbolGraphGen/JSON.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// Adds Symbol Graph JSON serialization to other types.
//===----------------------------------------------------------------------===//

#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "JSON.h"

void swift::symbolgraphgen::serialize(const llvm::VersionTuple &VT,
Expand Down Expand Up @@ -55,3 +57,47 @@ void swift::symbolgraphgen::serialize(const llvm::Triple &T,
});
});
}

void swift::symbolgraphgen::serialize(const ExtensionDecl *Extension,
llvm::json::OStream &OS) {
OS.attributeObject("swiftExtension", [&](){
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
if (const auto *ExtendedModule = ExtendedNominal->getModuleContext()) {
OS.attribute("extendedModule", ExtendedModule->getNameStr());
}
}
auto Generics = Extension->getGenericSignature();
if (Generics && !Generics->getRequirements().empty()) {
OS.attributeArray("constraints", [&](){
for (const auto &Requirement : Generics->getRequirements()) {
serialize(Requirement, OS);
}
}); // end constraints:
}
}); // end swiftExtension:
}

void swift::symbolgraphgen::serialize(const Requirement &Req,
llvm::json::OStream &OS) {
StringRef Kind;
switch (Req.getKind()) {
case swift::RequirementKind::Conformance:
Kind = "conformance";
break;
case swift::RequirementKind::Superclass:
Kind = "superclass";
break;
case swift::RequirementKind::SameType:
Kind = "sameType";
break;
case swift::RequirementKind::Layout:
return;
}

OS.object([&](){
OS.attribute("kind", Kind);
OS.attribute("lhs", Req.getFirstType()->getString());
OS.attribute("rhs", Req.getSecondType()->getString());
});

}
2 changes: 2 additions & 0 deletions lib/SymbolGraphGen/JSON.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct AttributeRAII {

void serialize(const llvm::VersionTuple &VT, llvm::json::OStream &OS);
void serialize(const llvm::Triple &T, llvm::json::OStream &OS);
void serialize(const ExtensionDecl *Extension, llvm::json::OStream &OS);
void serialize(const Requirement &Req, llvm::json::OStream &OS);

} // end namespace symbolgraphgen
} // end namespace swift
Expand Down
42 changes: 2 additions & 40 deletions lib/SymbolGraphGen/Symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,30 +241,6 @@ void Symbol::serializeGenericParam(const swift::GenericTypeParamType &Param,
});
}

void Symbol::serializeGenericRequirement(const swift::Requirement &Req,
llvm::json::OStream &OS) const {
StringRef Kind;
switch (Req.getKind()) {
case swift::RequirementKind::Conformance:
Kind = "conformance";
break;
case swift::RequirementKind::Superclass:
Kind = "superclass";
break;
case swift::RequirementKind::SameType:
Kind = "sameType";
break;
case swift::RequirementKind::Layout:
return;
}

OS.object([&](){
OS.attribute("kind", Kind);
OS.attribute("lhs", Req.getFirstType()->getString());
OS.attribute("rhs", Req.getSecondType()->getString());
});
}

void Symbol::serializeSwiftGenericMixin(llvm::json::OStream &OS) const {
if (const auto *GC = VD->getAsGenericContext()) {
if (const auto Generics = GC->getGenericSignature()) {
Expand All @@ -286,7 +262,7 @@ void Symbol::serializeSwiftGenericMixin(llvm::json::OStream &OS) const {
if (!Generics->getRequirements().empty()) {
OS.attributeArray("constraints", [&](){
for (const auto &Requirement : Generics->getRequirements()) {
serializeGenericRequirement(Requirement, OS);
::serialize(Requirement, OS);
}
}); // end constraints:
}
Expand All @@ -299,21 +275,7 @@ void Symbol::serializeSwiftGenericMixin(llvm::json::OStream &OS) const {
void Symbol::serializeSwiftExtensionMixin(llvm::json::OStream &OS) const {
if (const auto *Extension
= dyn_cast_or_null<ExtensionDecl>(VD->getInnermostDeclContext())) {
OS.attributeObject("swiftExtension", [&](){
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
if (const auto *ExtendedModule = ExtendedNominal->getModuleContext()) {
OS.attribute("extendedModule", ExtendedModule->getNameStr());
}
}
auto Generics = Extension->getGenericSignature();
if (Generics && !Generics->getRequirements().empty()) {
OS.attributeArray("constraints", [&](){
for (const auto &Requirement : Generics->getRequirements()) {
serializeGenericRequirement(Requirement, OS);
}
}); // end constraints:
}
}); // end swiftExtension:
::serialize(Extension, OS);
}
}

Expand Down
3 changes: 0 additions & 3 deletions lib/SymbolGraphGen/Symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ class Symbol {
void serializeGenericParam(const swift::GenericTypeParamType &Param,
llvm::json::OStream &OS) const;

void serializeGenericRequirement(const swift::Requirement &Req,
llvm::json::OStream &OS) const;

void serializeSwiftGenericMixin(llvm::json::OStream &OS) const;

void serializeSwiftExtensionMixin(llvm::json::OStream &OS) const;
Expand Down
Loading

0 comments on commit 7ce6753

Please sign in to comment.