mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
swift-api-digester: print raw type names for raw representable API changes.
This commit is contained in:
@@ -411,6 +411,7 @@ public:
|
||||
ChildIt getChildBegin() { return Children.begin(); }
|
||||
void annotate(NodeAnnotation Anno) { Annotations.insert(Anno); }
|
||||
void annotate(NodeAnnotation Anno, StringRef Comment);
|
||||
void removeAnnotate(NodeAnnotation Anno);
|
||||
NodePtr getParent() const { return Parent; };
|
||||
unsigned getChildrenCount() const { return Children.size(); }
|
||||
NodePtr childAt(unsigned I) const;
|
||||
@@ -631,11 +632,20 @@ void SDKNode::removeChild(NodePtr C) {
|
||||
|
||||
void SDKNode::annotate(NodeAnnotation Anno, StringRef Comment) {
|
||||
assert(!Comment.empty());
|
||||
assert(!isAnnotatedAs(Anno) || AnnotateComments[Anno] == Comment);
|
||||
if(isAnnotatedAs(Anno))
|
||||
return;
|
||||
annotate(Anno);
|
||||
AnnotateComments[Anno] = Comment;
|
||||
}
|
||||
|
||||
void SDKNode::removeAnnotate(NodeAnnotation Anno) {
|
||||
assert(isAnnotatedAs(Anno));
|
||||
Annotations.erase(Anno);
|
||||
AnnotateComments.erase(Anno);
|
||||
assert(!isAnnotatedAs(Anno));
|
||||
assert(AnnotateComments.count(Anno) == 0);
|
||||
}
|
||||
|
||||
StringRef SDKNode::getAnnotateComment(NodeAnnotation Anno) const {
|
||||
return AnnotateComments.find(Anno)->second;
|
||||
}
|
||||
@@ -2705,12 +2715,29 @@ class InterfaceTypeChangeDetector {
|
||||
return false;
|
||||
}
|
||||
|
||||
static StringRef getStringRepresentableChange(SDKNode *L, SDKNode *R) {
|
||||
auto* LKey = dyn_cast<SDKNodeTypeNominal>(L);
|
||||
auto* RKey = dyn_cast<SDKNodeTypeNominal>(R);
|
||||
if (!LKey || !RKey)
|
||||
static bool isRawType(const SDKNodeType *T, StringRef &Raw) {
|
||||
if (auto Alias = dyn_cast<SDKNodeTypeAlias>(T)) {
|
||||
// In case this type is an alias of the raw type.
|
||||
return isRawType(Alias->getUnderlyingType(), Raw);
|
||||
}
|
||||
switch(T->getTypeKind()) {
|
||||
case KnownTypeKind::String:
|
||||
case KnownTypeKind::Int:
|
||||
Raw = T->getName();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static StringRef getStringRepresentableChange(SDKNode *L, SDKNode *R,
|
||||
StringRef &Raw) {
|
||||
if (!isRawType(L->getAs<SDKNodeType>(), Raw))
|
||||
return StringRef();
|
||||
if (LKey->getTypeKind() != KnownTypeKind::String)
|
||||
auto* RKey = dyn_cast<SDKNodeTypeNominal>(R);
|
||||
if (!RKey)
|
||||
return StringRef();
|
||||
if (Raw.empty())
|
||||
return StringRef();
|
||||
auto Results = RKey->getRootNode()->getDescendantsByUsr(RKey->getUsr());
|
||||
if (Results.empty())
|
||||
@@ -2724,7 +2751,8 @@ class InterfaceTypeChangeDetector {
|
||||
}
|
||||
|
||||
static StringRef detectDictionaryKeyChangeInternal(SDKNodeType *L,
|
||||
SDKNodeType *R) {
|
||||
SDKNodeType *R,
|
||||
StringRef &Raw) {
|
||||
if (L->getTypeKind() != KnownTypeKind::Dictionary ||
|
||||
R->getTypeKind() != KnownTypeKind::Dictionary)
|
||||
return StringRef();
|
||||
@@ -2734,13 +2762,14 @@ class InterfaceTypeChangeDetector {
|
||||
assert(Left->getChildrenCount() == 2);
|
||||
assert(Right->getChildrenCount() == 2);
|
||||
return getStringRepresentableChange(*Left->getChildBegin(),
|
||||
*Right->getChildBegin());
|
||||
*Right->getChildBegin(), Raw);
|
||||
}
|
||||
|
||||
bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
|
||||
// We only care if this the top-level type node.
|
||||
if (!L->isTopLevelType() || !R->isTopLevelType())
|
||||
return false;
|
||||
StringRef Raw;
|
||||
StringRef KeyChangedTo;
|
||||
bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
|
||||
R->getTypeKind() == KnownTypeKind::Optional;
|
||||
@@ -2748,17 +2777,19 @@ class InterfaceTypeChangeDetector {
|
||||
// Detect [String: Any]? to [StringRepresentableStruct: Any]? Chnage
|
||||
KeyChangedTo =
|
||||
detectDictionaryKeyChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
R->getOnlyChild()->getAs<SDKNodeType>());
|
||||
R->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
Raw);
|
||||
} else {
|
||||
// Detect [String: Any] to [StringRepresentableStruct: Any] Chnage
|
||||
KeyChangedTo = detectDictionaryKeyChangeInternal(L, R);
|
||||
KeyChangedTo = detectDictionaryKeyChangeInternal(L, R, Raw);
|
||||
}
|
||||
if (!KeyChangedTo.empty()) {
|
||||
if (IsVisitingLeft) {
|
||||
L->annotate(HasOptional ?
|
||||
NodeAnnotation::OptionalDictionaryKeyUpdate :
|
||||
NodeAnnotation::DictionaryKeyUpdate);
|
||||
L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
|
||||
L->annotate(NodeAnnotation::RawTypeLeft, Raw);
|
||||
L->annotate(NodeAnnotation::RawTypeRight, KeyChangedTo);
|
||||
} else {
|
||||
R->annotate(HasOptional ?
|
||||
NodeAnnotation::RevertOptionalDictionaryKeyUpdate :
|
||||
@@ -2770,7 +2801,7 @@ class InterfaceTypeChangeDetector {
|
||||
}
|
||||
|
||||
static StringRef detectArrayMemberChangeInternal(SDKNodeType *L,
|
||||
SDKNodeType *R) {
|
||||
SDKNodeType *R, StringRef &Raw) {
|
||||
if (L->getTypeKind() != KnownTypeKind::Array ||
|
||||
R->getTypeKind() != KnownTypeKind::Array)
|
||||
return StringRef();
|
||||
@@ -2780,13 +2811,14 @@ class InterfaceTypeChangeDetector {
|
||||
assert(Left->getChildrenCount() == 1);
|
||||
assert(Right->getChildrenCount() == 1);
|
||||
return getStringRepresentableChange(Left->getOnlyChild(),
|
||||
Right->getOnlyChild());
|
||||
Right->getOnlyChild(), Raw);
|
||||
}
|
||||
|
||||
bool detectArrayMemberChange(SDKNodeType* L, SDKNodeType *R) {
|
||||
// We only care if this the top-level type node.
|
||||
if (!L->isTopLevelType() || !R->isTopLevelType())
|
||||
return false;
|
||||
StringRef Raw;
|
||||
StringRef KeyChangedTo;
|
||||
bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
|
||||
R->getTypeKind() == KnownTypeKind::Optional;
|
||||
@@ -2794,17 +2826,19 @@ class InterfaceTypeChangeDetector {
|
||||
// Detect [String]? to [StringRepresentableStruct]? Chnage
|
||||
KeyChangedTo =
|
||||
detectArrayMemberChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
R->getOnlyChild()->getAs<SDKNodeType>());
|
||||
R->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
Raw);
|
||||
} else {
|
||||
// Detect [String] to [StringRepresentableStruct] Chnage
|
||||
KeyChangedTo = detectArrayMemberChangeInternal(L, R);
|
||||
KeyChangedTo = detectArrayMemberChangeInternal(L, R, Raw);
|
||||
}
|
||||
if (!KeyChangedTo.empty()) {
|
||||
if (IsVisitingLeft) {
|
||||
L->annotate(HasOptional ?
|
||||
NodeAnnotation::OptionalArrayMemberUpdate :
|
||||
NodeAnnotation::ArrayMemberUpdate);
|
||||
L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
|
||||
L->annotate(NodeAnnotation::RawTypeLeft, Raw);
|
||||
L->annotate(NodeAnnotation::RawTypeRight, KeyChangedTo);
|
||||
} else {
|
||||
R->annotate(HasOptional ?
|
||||
NodeAnnotation::RevertOptionalArrayMemberUpdate :
|
||||
@@ -2819,20 +2853,23 @@ class InterfaceTypeChangeDetector {
|
||||
if (!L->isTopLevelType() || !R->isTopLevelType())
|
||||
return false;
|
||||
StringRef KeyChangedTo;
|
||||
StringRef Raw;
|
||||
bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
|
||||
R->getTypeKind() == KnownTypeKind::Optional;
|
||||
if (HasOptional) {
|
||||
// Detect String? changes to StringRepresentableStruct? change.
|
||||
KeyChangedTo =
|
||||
getStringRepresentableChange(L->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
R->getOnlyChild()->getAs<SDKNodeType>());
|
||||
R->getOnlyChild()->getAs<SDKNodeType>(),
|
||||
Raw);
|
||||
} else {
|
||||
// Detect String changes to StringRepresentableStruct change.
|
||||
KeyChangedTo = getStringRepresentableChange(L, R);
|
||||
KeyChangedTo = getStringRepresentableChange(L, R, Raw);
|
||||
}
|
||||
if (!KeyChangedTo.empty()) {
|
||||
if (IsVisitingLeft) {
|
||||
L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
|
||||
L->annotate(NodeAnnotation::RawTypeLeft, Raw);
|
||||
L->annotate(NodeAnnotation::RawTypeRight, KeyChangedTo);
|
||||
L->annotate(HasOptional ?
|
||||
NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
|
||||
NodeAnnotation::SimpleStringRepresentableUpdate);
|
||||
@@ -2851,6 +2888,14 @@ class InterfaceTypeChangeDetector {
|
||||
Counter->getTypeKind() == KnownTypeKind::Void;
|
||||
}
|
||||
|
||||
static void clearTypeRewritten(SDKNode *N) {
|
||||
if (!N->isAnnotatedAs(NodeAnnotation::TypeRewritten))
|
||||
return;
|
||||
N->removeAnnotate(NodeAnnotation::TypeRewritten);
|
||||
N->removeAnnotate(NodeAnnotation::TypeRewrittenLeft);
|
||||
N->removeAnnotate(NodeAnnotation::TypeRewrittenRight);
|
||||
}
|
||||
|
||||
public:
|
||||
InterfaceTypeChangeDetector(bool IsVisitingLeft):
|
||||
IsVisitingLeft(IsVisitingLeft) {}
|
||||
@@ -2859,14 +2904,23 @@ public:
|
||||
auto *Counter = dyn_cast<SDKNodeType>(Right);
|
||||
if (!Node || !Counter || isUnhandledCase(Node, Counter))
|
||||
return;
|
||||
bool Result = detectWrapOptional(Node, Counter)||
|
||||
detectOptionalUpdate(Node, Counter)||
|
||||
detectWrapImplicitOptional(Node, Counter)||
|
||||
detectUnmanagedUpdate(Node, Counter)||
|
||||
detectDictionaryKeyChange(Node, Counter) ||
|
||||
detectArrayMemberChange(Node, Counter) ||
|
||||
detectSimpleStringRepresentableUpdate(Node, Counter) ||
|
||||
detectTypeRewritten(Node, Counter);
|
||||
if (detectWrapOptional(Node, Counter) ||
|
||||
detectOptionalUpdate(Node, Counter) ||
|
||||
detectWrapImplicitOptional(Node, Counter) ||
|
||||
detectUnmanagedUpdate(Node, Counter)) {
|
||||
|
||||
// we may have detected type rewritten before (when visiting left),
|
||||
// so clear the annotation here.
|
||||
clearTypeRewritten(Node);
|
||||
clearTypeRewritten(Counter);
|
||||
} else {
|
||||
// Detect type re-written then.
|
||||
detectTypeRewritten(Node, Counter);
|
||||
}
|
||||
// The raw representable changes can co-exist with above attributes.
|
||||
auto Result = detectDictionaryKeyChange(Node, Counter) ||
|
||||
detectArrayMemberChange(Node, Counter) ||
|
||||
detectSimpleStringRepresentableUpdate(Node, Counter);
|
||||
(void) Result;
|
||||
return;
|
||||
}
|
||||
@@ -2992,6 +3046,13 @@ class DiffItemEmitter : public SDKNodeVisitor {
|
||||
|
||||
static StringRef getLeftComment(NodePtr Node, NodeAnnotation Anno) {
|
||||
switch(Anno) {
|
||||
case NodeAnnotation::ArrayMemberUpdate:
|
||||
case NodeAnnotation::OptionalArrayMemberUpdate:
|
||||
case NodeAnnotation::DictionaryKeyUpdate:
|
||||
case NodeAnnotation::OptionalDictionaryKeyUpdate:
|
||||
case NodeAnnotation::SimpleStringRepresentableUpdate:
|
||||
case NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
|
||||
return Node->getAnnotateComment(NodeAnnotation::RawTypeLeft);
|
||||
case NodeAnnotation::TypeRewritten:
|
||||
return Node->getAnnotateComment(NodeAnnotation::TypeRewrittenLeft);
|
||||
case NodeAnnotation::Rename:
|
||||
@@ -3009,6 +3070,7 @@ class DiffItemEmitter : public SDKNodeVisitor {
|
||||
case NodeAnnotation::OptionalDictionaryKeyUpdate:
|
||||
case NodeAnnotation::SimpleStringRepresentableUpdate:
|
||||
case NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
|
||||
return Node->getAnnotateComment(NodeAnnotation::RawTypeRight);
|
||||
case NodeAnnotation::TypeRewritten:
|
||||
return Node->getAnnotateComment(NodeAnnotation::TypeRewrittenRight);
|
||||
case NodeAnnotation::ModernizeEnum:
|
||||
@@ -3025,16 +3087,14 @@ class DiffItemEmitter : public SDKNodeVisitor {
|
||||
|
||||
void handleAnnotations(NodePtr Node, SDKNodeDecl *NonTypeParent,
|
||||
StringRef Index, ArrayRef<NodeAnnotation> Annotations) {
|
||||
for (auto Annotation: Annotations) {
|
||||
if (isInterested(NonTypeParent, Annotation) &&
|
||||
Node->isAnnotatedAs(Annotation)) {
|
||||
for (auto Anno: Annotations) {
|
||||
if (isInterested(NonTypeParent, Anno) && Node->isAnnotatedAs(Anno)) {
|
||||
auto Kind = NonTypeParent->getKind();
|
||||
StringRef LC = getLeftComment(Node, Annotation);
|
||||
StringRef RC = getRightComment(Node, Annotation);
|
||||
AllItems.emplace_back(Kind, Annotation, Index,
|
||||
StringRef LC = getLeftComment(Node, Anno);
|
||||
StringRef RC = getRightComment(Node, Anno);
|
||||
AllItems.emplace_back(Kind, Anno, Index,
|
||||
NonTypeParent->getUsr(), StringRef(), LC, RC,
|
||||
NonTypeParent->getModuleName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user