swift-module-digester: diagnose any decl kind changes for nominal types.

This commit is contained in:
Xi Ge
2018-09-24 14:47:19 -07:00
parent 3b16f34ad4
commit d0cd97e3e5
8 changed files with 45 additions and 14 deletions

View File

@@ -677,6 +677,15 @@ static bool isOwnershipEquivalent(ReferenceOwnership Left,
static void diagnoseNominalTypeDeclChange(SDKNodeDeclType *L, SDKNodeDeclType *R) {
auto &Ctx = L->getSDKContext();
auto &Diags = Ctx.getDiags();
if (L->getDeclKind() != R->getDeclKind()) {
Diags.diagnose(SourceLoc(), diag::nominal_type_kind_changed,
L->getScreenInfo(), getDeclKindStr(R->getDeclKind()));
return;
}
assert(L->getDeclKind() == R->getDeclKind());
auto DKind = L->getDeclKind();
std::vector<StringRef> LeftMinusRight;
std::vector<StringRef> RightMinusLeft;
swift::ide::api::stringSetDifference(L->getAllProtocols(), R->getAllProtocols(),
@@ -686,26 +695,32 @@ static void diagnoseNominalTypeDeclChange(SDKNodeDeclType *L, SDKNodeDeclType *R
Diags.diagnose(SourceLoc(), diag::conformance_removed, L->getScreenInfo(), Name,
isProtocol);
});
// Adding inherited protocols can be API breaking.
if (isProtocol) {
switch (DKind) {
case DeclKind::Protocol: {
std::for_each(RightMinusLeft.begin(), RightMinusLeft.end(), [&](StringRef Name) {
Diags.diagnose(SourceLoc(), diag::conformance_added, L->getScreenInfo(),
Name);
});
break;
}
auto LSuperClass = L->getSuperClassName();
auto RSuperClass = R->getSuperClassName();
if (!LSuperClass.empty() && LSuperClass != RSuperClass) {
if (RSuperClass.empty()) {
Diags.diagnose(SourceLoc(), diag::super_class_removed, L->getScreenInfo(),
LSuperClass);
} else {
// FIXME: This will be a false positive if the new subclass is a subclass
// of the old type.
Diags.diagnose(SourceLoc(), diag::super_class_changed, L->getScreenInfo(),
LSuperClass, RSuperClass);
case DeclKind::Class: {
auto LSuperClass = L->getSuperClassName();
auto RSuperClass = R->getSuperClassName();
if (!LSuperClass.empty() && LSuperClass != RSuperClass) {
if (RSuperClass.empty()) {
Diags.diagnose(SourceLoc(), diag::super_class_removed, L->getScreenInfo(),
LSuperClass);
} else {
// FIXME: This will be a false positive if the new subclass is a subclass
// of the old type.
Diags.diagnose(SourceLoc(), diag::super_class_changed, L->getScreenInfo(),
LSuperClass, RSuperClass);
}
}
break;
}
default:
break;
}
}