@@ -277,6 +277,11 @@ enum class KnownTypeKind: uint8_t {
277
277
Unknown,
278
278
};
279
279
280
+ enum class KnownProtocolKind : uint8_t {
281
+ #define KNOWN_PROTOCOL (NAME ) NAME,
282
+ #include " swift/IDE/DigesterEnums.def"
283
+ };
284
+
280
285
enum class SDKDeclAttrKind : uint8_t {
281
286
#define DECL_ATTR (Name ) DAK_##Name,
282
287
#include " swift/IDE/DigesterEnums.def"
@@ -831,6 +836,18 @@ class SDKNodeTypeDecl : public SDKNodeDecl {
831
836
}
832
837
return None;
833
838
}
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
+ }
834
851
};
835
852
836
853
class SDKNodeTypeAlias : public SDKNodeDecl {
@@ -2598,6 +2615,38 @@ class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
2598
2615
return false ;
2599
2616
}
2600
2617
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
+
2601
2650
bool isUnhandledCase (SDKNodeType *Node) {
2602
2651
auto Counter = UpdateMap.findUpdateCounterpart (Node)->getAs <SDKNodeType>();
2603
2652
return Node->getTypeKind () == KnownTypeKind::Void ||
@@ -2628,6 +2677,7 @@ class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
2628
2677
detectOptionalUpdate (Node, Counter)||
2629
2678
detectWrapImplicitOptional (Node, Counter)||
2630
2679
detectUnmanagedUpdate (Node, Counter)||
2680
+ detectDictionaryKeyChange (Node, Counter) ||
2631
2681
detectTypeRewritten (Node, Counter);
2632
2682
(void ) Result;
2633
2683
return ;
@@ -2739,6 +2789,7 @@ class DiffItemEmitter : public SDKNodeVisitor {
2739
2789
2740
2790
static StringRef getRightComment (NodePtr Node, NodeAnnotation Anno) {
2741
2791
switch (Anno) {
2792
+ case NodeAnnotation::DictionaryKeyUpdate:
2742
2793
case NodeAnnotation::TypeRewritten:
2743
2794
return Node->getAnnotateComment (NodeAnnotation::TypeRewrittenRight);
2744
2795
case NodeAnnotation::ModernizeEnum:
@@ -2795,7 +2846,8 @@ class DiffItemEmitter : public SDKNodeVisitor {
2795
2846
NodeAnnotation::GetterToProperty,
2796
2847
NodeAnnotation::ModernizeEnum,
2797
2848
NodeAnnotation::Rename,
2798
- NodeAnnotation::NowThrowing
2849
+ NodeAnnotation::NowThrowing,
2850
+ NodeAnnotation::DictionaryKeyUpdate,
2799
2851
});
2800
2852
}
2801
2853
0 commit comments