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

@@ -72,6 +72,8 @@ ERROR(super_class_removed,none,"%0 has removed its super class %1", (StringRef,
ERROR(super_class_changed,none,"%0 has changed its super class from %1 to %2", (StringRef, StringRef, StringRef))
ERROR(nominal_type_kind_changed,none,"%0 has been changed to a %1", (StringRef, StringRef))
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG

View File

@@ -91,3 +91,6 @@ public protocol RequiementChanges {
}
public class SuperClassRemoval: C3 {}
public class ClassToStruct {}
public protocol ProtocolToEnum {}

View File

@@ -98,3 +98,6 @@ public protocol RequiementChanges {
}
public class SuperClassRemoval {}
public struct ClassToStruct {}
public enum ProtocolToEnum {}

View File

@@ -16,6 +16,8 @@ cake1: Var RemoveSetters.Value has removed its setter
cake1: Var RequiementChanges.removedVar has been removed
/* Moved Decls */
cake1: Class ClassToStruct has been changed to a Struct
cake1: Protocol ProtocolToEnum has been changed to a Enum
/* Renamed Decls */
cake1: Func S1.foo5(x:y:) has been renamed to Func S1.foo5(x:y:z:)

View File

@@ -16,6 +16,8 @@ cake1: Var RemoveSetters.Value has removed its setter
cake1: Var RequiementChanges.removedVar has been removed
/* Moved Decls */
cake1: Class ClassToStruct has been changed to a Struct
cake1: Protocol ProtocolToEnum has been changed to a Enum
/* Renamed Decls */
cake1: Func S1.foo5(x:y:) has been renamed to Func S1.foo5(x:y:z:)

View File

@@ -764,6 +764,9 @@ bool SDKNode::operator==(const SDKNode &Other) const {
if (Left->getSuperClassName() != Right->getSuperClassName()) {
return false;
}
if (Left->getDeclKind() != Right->getDeclKind()) {
return false;
}
}
LLVM_FALLTHROUGH;
}

View File

@@ -36,6 +36,7 @@ static StringRef getCategoryName(uint32_t ID) {
case LocalDiagID::removed_setter:
return "/* Removed Decls */";
case LocalDiagID::moved_decl:
case LocalDiagID::nominal_type_kind_changed:
return "/* Moved Decls */";
case LocalDiagID::renamed_decl:
return "/* Renamed Decls */";

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,14 +695,15 @@ 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;
}
case DeclKind::Class: {
auto LSuperClass = L->getSuperClassName();
auto RSuperClass = R->getSuperClassName();
if (!LSuperClass.empty() && LSuperClass != RSuperClass) {
@@ -707,6 +717,11 @@ static void diagnoseNominalTypeDeclChange(SDKNodeDeclType *L, SDKNodeDeclType *R
LSuperClass, RSuperClass);
}
}
break;
}
default:
break;
}
}
static void detectDeclChange(NodePtr L, NodePtr R, SDKContext &Ctx) {