mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
swift-api-digester: Eliminate false positives introduced by moving a member declaration to super classes.
We shouldn't report these moved declarations as source breaking changes. rdar://32778228
This commit is contained in:
@@ -306,6 +306,8 @@ struct SDKNodeInitInfo {
|
||||
SDKNode* createSDKNode(SDKNodeKind Kind);
|
||||
};
|
||||
|
||||
class SDKNodeRoot;
|
||||
|
||||
class SDKNode {
|
||||
typedef std::vector<SDKNode*>::iterator ChildIt;
|
||||
SDKContext &Ctx;
|
||||
@@ -352,6 +354,7 @@ public:
|
||||
unsigned getChildIndex(NodePtr Child) const;
|
||||
const SDKNode* getOnlyChild() const;
|
||||
SDKContext &getSDKContext() const { return Ctx; }
|
||||
SDKNodeRoot *getRootNode() const;
|
||||
template <typename T> const T *getAs() const;
|
||||
template <typename T> T *getAs();
|
||||
};
|
||||
@@ -389,6 +392,27 @@ public:
|
||||
bool isStatic() const { return IsStatic; };
|
||||
};
|
||||
|
||||
class SDKNodeRoot :public SDKNode {
|
||||
/// This keeps track of all decl descendants with USRs.
|
||||
llvm::StringMap<SDKNodeDecl*> DescendantDeclTable;
|
||||
|
||||
public:
|
||||
SDKNodeRoot(SDKNodeInitInfo Info) : SDKNode(Info, SDKNodeKind::Root) {}
|
||||
static SDKNode *getInstance(SDKContext &Ctx);
|
||||
static bool classof(const SDKNode *N);
|
||||
void registerDescendant(SDKNode *D) {
|
||||
if (auto DD = dyn_cast<SDKNodeDecl>(D)) {
|
||||
assert(!DD->getUsr().empty());
|
||||
DescendantDeclTable[DD->getUsr()] = DD;
|
||||
}
|
||||
}
|
||||
Optional<SDKNodeDecl*> getDescendantByUsr(StringRef Usr) {
|
||||
if (DescendantDeclTable.count(Usr))
|
||||
return DescendantDeclTable[Usr];
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
NodePtr UpdatedNodesMap::findUpdateCounterpart(const SDKNode *Node) const {
|
||||
assert(Node->isAnnotatedAs(NodeAnnotation::Updated) && "Not update operation.");
|
||||
auto FoundPair = std::find_if(MapImpl.begin(), MapImpl.end(),
|
||||
@@ -475,9 +499,27 @@ const SDKNode* SDKNode::getOnlyChild() const {
|
||||
return *Children.begin();
|
||||
}
|
||||
|
||||
SDKNodeRoot *SDKNode::getRootNode() const {
|
||||
for (auto *Root = const_cast<SDKNode*>(this); ; Root = Root->getParent()) {
|
||||
if (auto Result = dyn_cast<SDKNodeRoot>(Root))
|
||||
return Result;
|
||||
}
|
||||
llvm_unreachable("Unhandled SDKNodeKind in switch.");
|
||||
}
|
||||
|
||||
void SDKNode::addChild(SDKNode *Child) {
|
||||
Child->Parent = this;
|
||||
Children.push_back(Child);
|
||||
if (auto *Root = dyn_cast<SDKNodeRoot>(this)) {
|
||||
struct DeclCollector: public SDKNodeVisitor {
|
||||
SDKNodeRoot &Root;
|
||||
DeclCollector(SDKNodeRoot &Root): Root(Root) {}
|
||||
void visit(NodePtr Node) override {
|
||||
Root.registerDescendant(Node);
|
||||
}
|
||||
} Collector(*Root);
|
||||
SDKNode::preorderVisit(Child, Collector);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayRef<SDKNode*> SDKNode::getChildren() const {
|
||||
@@ -602,13 +644,6 @@ bool SDKNodeType::hasTypeAttribute(TypeAttrKind DAKind) const {
|
||||
TypeAttributes.end();
|
||||
}
|
||||
|
||||
class SDKNodeRoot : public SDKNode {
|
||||
public:
|
||||
SDKNodeRoot(SDKNodeInitInfo Info) : SDKNode(Info, SDKNodeKind::Root) {}
|
||||
static SDKNode *getInstance(SDKContext &Ctx);
|
||||
static bool classof(const SDKNode *N);
|
||||
};
|
||||
|
||||
SDKNode *SDKNodeRoot::getInstance(SDKContext &Ctx) {
|
||||
SDKNodeInitInfo Info(Ctx);
|
||||
Info.Name = Ctx.buffer("TopLevel");
|
||||
@@ -690,6 +725,27 @@ public:
|
||||
SuperclassUsr(Info.SuperclassUsr) {}
|
||||
static bool classof(const SDKNode *N);
|
||||
StringRef getSuperClassUsr() const { return SuperclassUsr; }
|
||||
|
||||
Optional<SDKNodeTypeDecl*> getSuperclass() const {
|
||||
if (SuperclassUsr.empty())
|
||||
return None;
|
||||
return (*getRootNode()->getDescendantByUsr(SuperclassUsr))->
|
||||
getAs<SDKNodeTypeDecl>();
|
||||
}
|
||||
|
||||
/// Finding the node through all children, including the inheritted ones,
|
||||
/// whose printed name matches with the given name.
|
||||
Optional<SDKNodeDecl*> lookupChildByPrintedName(StringRef Name) const {
|
||||
for (auto C : getChildren()) {
|
||||
if (C->getPrintedName() == Name)
|
||||
return C->getAs<SDKNodeDecl>();
|
||||
}
|
||||
// Finding from the inheritance chain.
|
||||
if (auto Super = getSuperclass()) {
|
||||
return (*Super)->lookupChildByPrintedName(Name);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
class SDKNodeTypeAlias : public SDKNodeDecl {
|
||||
@@ -2795,6 +2851,22 @@ void DiagnosisEmitter::handle(const SDKNodeDecl *Node, NodeAnnotation Anno) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We should exlude those declarations that are pulled up to the super classes.
|
||||
bool FoundInSuperclass = false;
|
||||
if (auto PD = dyn_cast<SDKNodeDecl>(Node->getParent())) {
|
||||
if (PD->isAnnotatedAs(NodeAnnotation::Updated)) {
|
||||
// Get the updated counterpart of the parent decl.
|
||||
if (auto RTD = dyn_cast<SDKNodeTypeDecl>(UpdateMap.
|
||||
findUpdateCounterpart(PD))) {
|
||||
// Look up by the printed name in the counterpart.
|
||||
FoundInSuperclass =
|
||||
RTD->lookupChildByPrintedName(Node->getPrintedName()).hasValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FoundInSuperclass)
|
||||
return;
|
||||
RemovedDecls.Diags.emplace_back(Node->getDeclKind(),
|
||||
Node->getFullyQualifiedName(),
|
||||
Node->isDeprecated());
|
||||
|
||||
Reference in New Issue
Block a user