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(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 #ifndef DIAG_NO_UNDEF
# if defined(DIAG) # if defined(DIAG)
# undef DIAG # undef DIAG

View File

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

View File

@@ -98,3 +98,6 @@ public protocol RequiementChanges {
} }
public class SuperClassRemoval {} 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 cake1: Var RequiementChanges.removedVar has been removed
/* Moved Decls */ /* Moved Decls */
cake1: Class ClassToStruct has been changed to a Struct
cake1: Protocol ProtocolToEnum has been changed to a Enum
/* Renamed Decls */ /* Renamed Decls */
cake1: Func S1.foo5(x:y:) has been renamed to Func S1.foo5(x:y:z:) 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 cake1: Var RequiementChanges.removedVar has been removed
/* Moved Decls */ /* Moved Decls */
cake1: Class ClassToStruct has been changed to a Struct
cake1: Protocol ProtocolToEnum has been changed to a Enum
/* Renamed Decls */ /* Renamed Decls */
cake1: Func S1.foo5(x:y:) has been renamed to Func S1.foo5(x:y:z:) 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()) { if (Left->getSuperClassName() != Right->getSuperClassName()) {
return false; return false;
} }
if (Left->getDeclKind() != Right->getDeclKind()) {
return false;
}
} }
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
} }

View File

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

View File

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