mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
swift-api-digester: add specific logic to detect optional dictionary's key changes.
We've also seen type changes in the frameworks from "[String: Any]?" to "[StringRepresentable: Any]?". This patch adds specific logic and attribute for this kind of change on the top of nonnull dictionary changes.
This commit is contained in:
@@ -75,6 +75,7 @@ NODE_ANNOTATION(NowMutating)
|
||||
NODE_ANNOTATION(StaticChange)
|
||||
NODE_ANNOTATION(OwnershipChange)
|
||||
NODE_ANNOTATION(DictionaryKeyUpdate)
|
||||
NODE_ANNOTATION(OptionalDictionaryKeyUpdate)
|
||||
|
||||
DECL_ATTR(deprecated)
|
||||
DECL_ATTR(fixedLayout)
|
||||
|
||||
@@ -20,4 +20,5 @@ extern int ANTGlobalValue;
|
||||
|
||||
@interface AnimalStatusDescriptor
|
||||
- (nonnull AnimalStatusDescriptor *)animalStatusDescriptorByAddingAttributes:(nonnull NSDictionary<NSString*, id> *)attributes;
|
||||
- (nonnull AnimalStatusDescriptor *)animalStatusDescriptorByAddingOptionalAttributes:(nullable NSDictionary<NSString*, id> *)attributes;
|
||||
@end
|
||||
|
||||
@@ -20,4 +20,5 @@ typedef NSString * AnimalAttributeName NS_STRING_ENUM;
|
||||
|
||||
@interface AnimalStatusDescriptor
|
||||
- (nonnull AnimalStatusDescriptor *)animalStatusDescriptorByAddingAttributes:(nonnull NSDictionary<AnimalAttributeName, id> *)attributes;
|
||||
- (nonnull AnimalStatusDescriptor *)animalStatusDescriptorByAddingOptionalAttributes:(nullable NSDictionary<AnimalAttributeName, id> *)attributes;
|
||||
@end
|
||||
|
||||
@@ -10,5 +10,6 @@ APINotesTest(APINotesTest.h): TypeAlias AnimalAttributeName(NSString) is now Str
|
||||
|
||||
/* Type Changes */
|
||||
APINotesTest(APINotesTest.h): Func AnimalStatusDescriptor.addingAttributes(_:) has parameter 0 type change from [String : Any] to [AnimalAttributeName : Any]
|
||||
APINotesTest(APINotesTest.h): Func AnimalStatusDescriptor.addingOptionalAttributes(_:) has parameter 0 type change from [String : Any]? to [AnimalAttributeName : Any]?
|
||||
|
||||
/* Decl Attribute changes */
|
||||
|
||||
@@ -14,5 +14,6 @@ APINotesTest(APINotesTest.h): Var OldType.oldMember has been renamed to Var NewT
|
||||
|
||||
/* Type Changes */
|
||||
APINotesTest(APINotesTest.h): Func AnimalStatusDescriptor.addingAttributes(_:) has parameter 0 type change from [String : Any] to [AnimalAttributeName : Any]
|
||||
APINotesTest(APINotesTest.h): Func AnimalStatusDescriptor.addingOptionalAttributes(_:) has parameter 0 type change from [String : Any]? to [AnimalAttributeName : Any]?
|
||||
|
||||
/* Decl Attribute changes */
|
||||
|
||||
@@ -43,6 +43,50 @@
|
||||
"RightComment": "AnimalAttributeName",
|
||||
"ModuleName": "APINotesTest"
|
||||
},
|
||||
{
|
||||
"DiffItemKind": "CommonDiffItem",
|
||||
"NodeKind": "Function",
|
||||
"NodeAnnotation": "TypeRewritten",
|
||||
"ChildIndex": "1:0:0",
|
||||
"LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
|
||||
"LeftComment": "String",
|
||||
"RightUsr": "",
|
||||
"RightComment": "AnimalAttributeName",
|
||||
"ModuleName": "APINotesTest"
|
||||
},
|
||||
{
|
||||
"DiffItemKind": "CommonDiffItem",
|
||||
"NodeKind": "Function",
|
||||
"NodeAnnotation": "OptionalDictionaryKeyUpdate",
|
||||
"ChildIndex": "1",
|
||||
"LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
|
||||
"LeftComment": "",
|
||||
"RightUsr": "",
|
||||
"RightComment": "AnimalAttributeName",
|
||||
"ModuleName": "APINotesTest"
|
||||
},
|
||||
{
|
||||
"DiffItemKind": "CommonDiffItem",
|
||||
"NodeKind": "Function",
|
||||
"NodeAnnotation": "TypeRewritten",
|
||||
"ChildIndex": "1:0:0",
|
||||
"LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
|
||||
"LeftComment": "String",
|
||||
"RightUsr": "",
|
||||
"RightComment": "AnimalAttributeName",
|
||||
"ModuleName": "APINotesTest"
|
||||
},
|
||||
{
|
||||
"DiffItemKind": "CommonDiffItem",
|
||||
"NodeKind": "Function",
|
||||
"NodeAnnotation": "OptionalDictionaryKeyUpdate",
|
||||
"ChildIndex": "1",
|
||||
"LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
|
||||
"LeftComment": "",
|
||||
"RightUsr": "",
|
||||
"RightComment": "AnimalAttributeName",
|
||||
"ModuleName": "APINotesTest"
|
||||
},
|
||||
{
|
||||
"DiffItemKind": "CommonDiffItem",
|
||||
"NodeKind": "Function",
|
||||
|
||||
@@ -409,7 +409,7 @@ public:
|
||||
ArrayRef<SDKNode*> getChildren() const;
|
||||
bool hasSameChildren(const SDKNode &Other) const;
|
||||
unsigned getChildIndex(NodePtr Child) const;
|
||||
const SDKNode* getOnlyChild() const;
|
||||
SDKNode* getOnlyChild() const;
|
||||
SDKContext &getSDKContext() const { return Ctx; }
|
||||
SDKNodeRoot *getRootNode() const;
|
||||
template <typename T> const T *getAs() const;
|
||||
@@ -575,7 +575,7 @@ unsigned SDKNode::getChildIndex(NodePtr Child) const {
|
||||
return std::find(Children.begin(), Children.end(), Child) - Children.begin();
|
||||
}
|
||||
|
||||
const SDKNode* SDKNode::getOnlyChild() const {
|
||||
SDKNode* SDKNode::getOnlyChild() const {
|
||||
assert(Children.size() == 1 && "more that one child.");
|
||||
return *Children.begin();
|
||||
}
|
||||
@@ -2693,12 +2693,11 @@ class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
|
||||
if (!IsVisitingLeft)
|
||||
return false;
|
||||
static StringRef detectDictionaryKeyChangeInternal(SDKNodeType *L,
|
||||
SDKNodeType *R) {
|
||||
if (L->getTypeKind() != KnownTypeKind::Dictionary ||
|
||||
R->getTypeKind() != KnownTypeKind::Dictionary)
|
||||
return false;
|
||||
return StringRef();
|
||||
auto *Left = dyn_cast<SDKNodeTypeNominal>(L);
|
||||
auto *Right = dyn_cast<SDKNodeTypeNominal>(R);
|
||||
assert(Left && Right);
|
||||
@@ -2707,20 +2706,45 @@ class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
|
||||
auto* LKey = dyn_cast<SDKNodeTypeNominal>(*Left->getChildBegin());
|
||||
auto* RKey = dyn_cast<SDKNodeTypeNominal>(*Right->getChildBegin());
|
||||
if (!LKey || !RKey)
|
||||
return false;
|
||||
return StringRef();
|
||||
if (LKey->getTypeKind() != KnownTypeKind::String)
|
||||
return false;
|
||||
return StringRef();
|
||||
auto Results = RKey->getRootNode()->getDescendantsByUsr(RKey->getUsr());
|
||||
if (Results.empty())
|
||||
return false;
|
||||
return StringRef();
|
||||
if (auto DT = dyn_cast<SDKNodeDeclType>(Results.front())) {
|
||||
if (DT->isConformingTo(KnownProtocolKind::RawRepresentable)) {
|
||||
L->annotate(NodeAnnotation::DictionaryKeyUpdate);
|
||||
L->annotate(NodeAnnotation::TypeRewrittenRight,
|
||||
DT->getFullyQualifiedName());
|
||||
return true;
|
||||
return DT->getFullyQualifiedName();
|
||||
}
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
|
||||
if (!IsVisitingLeft)
|
||||
return false;
|
||||
|
||||
// We only care if this the top-level type node.
|
||||
if (!isa<SDKNodeDecl>(L->getParent()) || !isa<SDKNodeDecl>(R->getParent()))
|
||||
return false;
|
||||
StringRef KeyChangedTo;
|
||||
if (L->getTypeKind() == KnownTypeKind::Optional &&
|
||||
R->getTypeKind() == KnownTypeKind::Optional) {
|
||||
// Detect [String: Any]? to [StringRepresentableStruct: Any]? Chnage
|
||||
KeyChangedTo =
|
||||
detectDictionaryKeyChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
R->getOnlyChild()->getAs<SDKNodeType>());
|
||||
} else {
|
||||
// Detect [String: Any] to [StringRepresentableStruct: Any] Chnage
|
||||
KeyChangedTo = detectDictionaryKeyChangeInternal(L, R);
|
||||
}
|
||||
if (!KeyChangedTo.empty()) {
|
||||
L->annotate(L->getTypeKind() == KnownTypeKind::Optional ?
|
||||
NodeAnnotation::OptionalDictionaryKeyUpdate :
|
||||
NodeAnnotation::DictionaryKeyUpdate);
|
||||
L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2864,6 +2888,7 @@ class DiffItemEmitter : public SDKNodeVisitor {
|
||||
static StringRef getRightComment(NodePtr Node, NodeAnnotation Anno) {
|
||||
switch (Anno) {
|
||||
case NodeAnnotation::DictionaryKeyUpdate:
|
||||
case NodeAnnotation::OptionalDictionaryKeyUpdate:
|
||||
case NodeAnnotation::TypeRewritten:
|
||||
return Node->getAnnotateComment(NodeAnnotation::TypeRewrittenRight);
|
||||
case NodeAnnotation::ModernizeEnum:
|
||||
@@ -2922,6 +2947,7 @@ class DiffItemEmitter : public SDKNodeVisitor {
|
||||
NodeAnnotation::Rename,
|
||||
NodeAnnotation::NowThrowing,
|
||||
NodeAnnotation::DictionaryKeyUpdate,
|
||||
NodeAnnotation::OptionalDictionaryKeyUpdate,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user