Skip to content

Commit b2c4375

Browse files
committed
swift-api-digester: teach the tool to detect [String:Any] changes to [StringRepresentable:Any].
This allows us to migrate string enum changes from the frameworks.
1 parent 08c7391 commit b2c4375

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

include/swift/IDE/DigesterEnums.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
#define KNOWN_TYPE(NAME)
1919
#endif
2020

21+
#ifndef KNOWN_PROTOCOL
22+
#define KNOWN_PROTOCOL(NAME)
23+
#endif
24+
2125
#ifndef DIFF_ITEM_KIND
2226
#define DIFF_ITEM_KIND(NAME)
2327
#endif
@@ -70,6 +74,7 @@ NODE_ANNOTATION(NowThrowing)
7074
NODE_ANNOTATION(NowMutating)
7175
NODE_ANNOTATION(StaticChange)
7276
NODE_ANNOTATION(OwnershipChange)
77+
NODE_ANNOTATION(DictionaryKeyUpdate)
7378

7479
DECL_ATTR(deprecated)
7580
DECL_ATTR(fixedLayout)
@@ -100,6 +105,10 @@ KNOWN_TYPE(ImplicitlyUnwrappedOptional)
100105
KNOWN_TYPE(Void)
101106
KNOWN_TYPE(Unmanaged)
102107
KNOWN_TYPE(Function)
108+
KNOWN_TYPE(Dictionary)
109+
KNOWN_TYPE(String)
110+
111+
KNOWN_PROTOCOL(RawRepresentable)
103112

104113
DIFF_ITEM_KIND(CommonDiffItem)
105114
DIFF_ITEM_KIND(TypeMemberDiffItem)
@@ -149,6 +158,7 @@ SPECIAL_CASE_ID(ToUIntMax)
149158
#undef DIFF_ITEM_KEY_KIND
150159
#undef DIFF_ITEM_KIND
151160
#undef KNOWN_TYPE
161+
#undef KNOWN_PROTOCOL
152162
#undef KEY
153163
#undef DECL_ATTR
154164
#undef NODE_ANNOTATION

test/api-digester/Outputs/apinotes-migrator-gen.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@
1010
"RightComment": "AnimalAttributeName",
1111
"ModuleName": "APINotesTest"
1212
},
13+
{
14+
"DiffItemKind": "CommonDiffItem",
15+
"NodeKind": "Function",
16+
"NodeAnnotation": "DictionaryKeyUpdate",
17+
"ChildIndex": "1",
18+
"LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
19+
"LeftComment": "",
20+
"RightUsr": "",
21+
"RightComment": "AnimalAttributeName",
22+
"ModuleName": "APINotesTest"
23+
},
1324
{
1425
"DiffItemKind": "CommonDiffItem",
1526
"NodeKind": "Function",
@@ -21,6 +32,17 @@
2132
"RightComment": "AnimalAttributeName",
2233
"ModuleName": "APINotesTest"
2334
},
35+
{
36+
"DiffItemKind": "CommonDiffItem",
37+
"NodeKind": "Function",
38+
"NodeAnnotation": "DictionaryKeyUpdate",
39+
"ChildIndex": "1",
40+
"LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
41+
"LeftComment": "",
42+
"RightUsr": "",
43+
"RightComment": "AnimalAttributeName",
44+
"ModuleName": "APINotesTest"
45+
},
2446
{
2547
"DiffItemKind": "CommonDiffItem",
2648
"NodeKind": "Function",

tools/swift-api-digester/swift-api-digester.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,11 @@ enum class KnownTypeKind: uint8_t {
277277
Unknown,
278278
};
279279

280+
enum class KnownProtocolKind: uint8_t {
281+
#define KNOWN_PROTOCOL(NAME) NAME,
282+
#include "swift/IDE/DigesterEnums.def"
283+
};
284+
280285
enum class SDKDeclAttrKind: uint8_t {
281286
#define DECL_ATTR(Name) DAK_##Name,
282287
#include "swift/IDE/DigesterEnums.def"
@@ -831,6 +836,18 @@ class SDKNodeTypeDecl : public SDKNodeDecl {
831836
}
832837
return None;
833838
}
839+
840+
bool isConformingTo(KnownProtocolKind Kind) const {
841+
StringRef Usr;
842+
switch (Kind) {
843+
#define KNOWN_PROTOCOL(NAME) \
844+
case KnownProtocolKind::NAME: \
845+
return std::find(ConformingProtocols.begin(), \
846+
ConformingProtocols.end(), \
847+
#NAME) != ConformingProtocols.end();
848+
#include "swift/IDE/DigesterEnums.def"
849+
}
850+
}
834851
};
835852

836853
class SDKNodeTypeAlias : public SDKNodeDecl {
@@ -2598,6 +2615,38 @@ class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
25982615
return false;
25992616
}
26002617

2618+
bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
2619+
if (!IsVisitingLeft)
2620+
return false;
2621+
if (L->getTypeKind() != KnownTypeKind::Dictionary ||
2622+
R->getTypeKind() != KnownTypeKind::Dictionary)
2623+
return false;
2624+
auto *Left = dyn_cast<SDKNodeTypeNominal>(L);
2625+
auto *Right = dyn_cast<SDKNodeTypeNominal>(R);
2626+
assert(Left && Right);
2627+
assert(Left->getChildrenCount() == 2);
2628+
assert(Right->getChildrenCount() == 2);
2629+
auto* LKey = dyn_cast<SDKNodeTypeNominal>(*Left->getChildBegin());
2630+
auto* RKey = dyn_cast<SDKNodeTypeNominal>(*Right->getChildBegin());
2631+
if (!LKey || !RKey)
2632+
return false;
2633+
if (LKey->getTypeKind() != KnownTypeKind::String)
2634+
return false;
2635+
auto Results = RKey->getRootNode()->getDescendantsByUsr(RKey->getUsr());
2636+
if (Results.empty())
2637+
return false;
2638+
if (auto DT = dyn_cast<SDKNodeTypeDecl>(Results.front())) {
2639+
if (DT->isConformingTo(KnownProtocolKind::RawRepresentable)) {
2640+
L->annotate(NodeAnnotation::DictionaryKeyUpdate);
2641+
L->annotate(NodeAnnotation::TypeRewrittenRight);
2642+
L->addAnnotateComment(NodeAnnotation::TypeRewrittenRight,
2643+
DT->getFullyQualifiedName());
2644+
return true;
2645+
}
2646+
}
2647+
return false;
2648+
}
2649+
26012650
bool isUnhandledCase(SDKNodeType *Node) {
26022651
auto Counter = UpdateMap.findUpdateCounterpart(Node)->getAs<SDKNodeType>();
26032652
return Node->getTypeKind() == KnownTypeKind::Void ||
@@ -2628,6 +2677,7 @@ class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
26282677
detectOptionalUpdate(Node, Counter)||
26292678
detectWrapImplicitOptional(Node, Counter)||
26302679
detectUnmanagedUpdate(Node, Counter)||
2680+
detectDictionaryKeyChange(Node, Counter) ||
26312681
detectTypeRewritten(Node, Counter);
26322682
(void) Result;
26332683
return;
@@ -2739,6 +2789,7 @@ class DiffItemEmitter : public SDKNodeVisitor {
27392789

27402790
static StringRef getRightComment(NodePtr Node, NodeAnnotation Anno) {
27412791
switch (Anno) {
2792+
case NodeAnnotation::DictionaryKeyUpdate:
27422793
case NodeAnnotation::TypeRewritten:
27432794
return Node->getAnnotateComment(NodeAnnotation::TypeRewrittenRight);
27442795
case NodeAnnotation::ModernizeEnum:
@@ -2795,7 +2846,8 @@ class DiffItemEmitter : public SDKNodeVisitor {
27952846
NodeAnnotation::GetterToProperty,
27962847
NodeAnnotation::ModernizeEnum,
27972848
NodeAnnotation::Rename,
2798-
NodeAnnotation::NowThrowing
2849+
NodeAnnotation::NowThrowing,
2850+
NodeAnnotation::DictionaryKeyUpdate,
27992851
});
28002852
}
28012853

0 commit comments

Comments
 (0)