swift-api-digester: de-duplicate protocol conformance entries in the Json output

For some unclear reasons, calling getAllConformances on Int.Words and
UInt.Words returns duplicate entries for conforming to RandomAccessCollection.
Since this isn't the case for swift-5.1-branch, we saw false positives shown
in rdar://49568079.

This patch fixes the ABI/API checker by de-duplicate results collected from
getAllConformances.
This commit is contained in:
Xi Ge
2019-04-09 11:46:09 -07:00
parent 0f1994d288
commit 8225b522d0
3 changed files with 36 additions and 374 deletions

View File

@@ -1024,27 +1024,34 @@ Requirement getCanonicalRequirement(Requirement &Req) {
}
}
static
StringRef printGenericSignature(SDKContext &Ctx, ArrayRef<Requirement> AllReqs) {
llvm::SmallString<32> Result;
llvm::raw_svector_ostream OS(Result);
if (AllReqs.empty())
return StringRef();
OS << "<";
bool First = true;
for (auto Req: AllReqs) {
if (!First) {
OS << ", ";
} else {
First = false;
}
if (Ctx.checkingABI())
getCanonicalRequirement(Req).print(OS, PrintOptions::printInterface());
else
Req.print(OS, PrintOptions::printInterface());
}
OS << ">";
return Ctx.buffer(OS.str());
}
static StringRef printGenericSignature(SDKContext &Ctx, Decl *D) {
llvm::SmallString<32> Result;
llvm::raw_svector_ostream OS(Result);
if (auto *PD = dyn_cast<ProtocolDecl>(D)) {
if (PD->getRequirementSignature().empty())
return StringRef();
OS << "<";
bool First = true;
for (auto Req: PD->getRequirementSignature()) {
if (!First) {
OS << ", ";
} else {
First = false;
}
if (Ctx.checkingABI())
getCanonicalRequirement(Req).print(OS, PrintOptions::printInterface());
else
Req.print(OS, PrintOptions::printInterface());
}
OS << ">";
return Ctx.buffer(OS.str());
return printGenericSignature(Ctx, PD->getRequirementSignature());
}
if (auto *GC = D->getAsGenericContext()) {
@@ -1059,6 +1066,11 @@ static StringRef printGenericSignature(SDKContext &Ctx, Decl *D) {
return StringRef();
}
static
StringRef printGenericSignature(SDKContext &Ctx, ProtocolConformance *Conf) {
return printGenericSignature(Ctx, Conf->getConditionalRequirements());
}
static Optional<uint8_t> getSimilarMemberCount(NominalTypeDecl *NTD,
ValueDecl *VD,
llvm::function_ref<bool(Decl*)> Check) {
@@ -1161,6 +1173,9 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, OperatorDecl *OD):
SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ProtocolConformance *Conform):
SDKNodeInitInfo(Ctx, Conform->getProtocol()) {
// The conformance can be conditional. The generic signature keeps track of
// the requirements.
GenericSig = printGenericSignature(Ctx, Conform);
// Whether this conformance is ABI placeholder depends on the decl context
// of this conformance.
IsABIPlaceholder = isABIPlaceholderRecursive(Conform->getDeclContext()->
@@ -1562,9 +1577,12 @@ SwiftDeclCollector::constructConformanceNode(ProtocolConformance *Conform) {
void swift::ide::api::
SwiftDeclCollector::addConformancesToTypeDecl(SDKNodeDeclType *Root,
NominalTypeDecl *NTD) {
// Avoid adding the same conformance twice.
SmallPtrSet<ProtocolConformance*, 4> Seen;
for (auto &Conf: NTD->getAllConformances()) {
if (!Ctx.shouldIgnore(Conf->getProtocol()))
if (!Ctx.shouldIgnore(Conf->getProtocol()) && !Seen.count(Conf))
Root->addConformance(constructConformanceNode(Conf));
Seen.insert(Conf);
}
}