From 4475b0761337b3a379d0a88561a659c9c6d946db Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Thu, 27 Oct 2016 11:55:17 -0700 Subject: [PATCH] swift-api-digester: teach the tool to keep track of ownership attributes. --- test/api-digester/Inputs/cake.swift | 2 + test/api-digester/Outputs/cake.json | 142 ++++++++++++++++++ tools/swift-api-digester/DigesterEnums.def | 1 + .../swift-api-digester/swift-api-digester.cpp | 39 ++++- 4 files changed, 176 insertions(+), 8 deletions(-) diff --git a/test/api-digester/Inputs/cake.swift b/test/api-digester/Inputs/cake.swift index 80f6d23d92cee..a61ac20ef0c14 100644 --- a/test/api-digester/Inputs/cake.swift +++ b/test/api-digester/Inputs/cake.swift @@ -8,4 +8,6 @@ public struct S1 { public class C1 { open class func foo1() {} + public weak var Ins : C1? + public unowned var Ins2 : C1 = C1() } \ No newline at end of file diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json index c29c3385058cf..e783b94080b96 100644 --- a/test/api-digester/Outputs/cake.json +++ b/test/api-digester/Outputs/cake.json @@ -90,6 +90,148 @@ } ] }, + { + "kind": "Var", + "name": "Ins", + "printedName": "Ins", + "declKind": "Var", + "usr": "s:vC4cake2C13InsXwGSqS0__", + "location": "", + "moduleName": "cake", + "ownership": 1, + "children": [ + { + "kind": "TypeNominal", + "name": "WeakStorage", + "printedName": "C1?" + }, + { + "kind": "Getter", + "name": "_", + "printedName": "_()", + "declKind": "Func", + "usr": "s:FC4cake2C1g3InsXwGSqS0__", + "location": "", + "moduleName": "cake", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "C1?", + "children": [ + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + } + ] + }, + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + } + ] + }, + { + "kind": "Setter", + "name": "_", + "printedName": "_()", + "declKind": "Func", + "usr": "s:FC4cake2C1s3InsXwGSqS0__", + "location": "", + "moduleName": "cake", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "C1?", + "children": [ + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + } + ] + } + ] + } + ] + }, + { + "kind": "Var", + "name": "Ins2", + "printedName": "Ins2", + "declKind": "Var", + "usr": "s:vC4cake2C14Ins2XoS0_", + "location": "", + "moduleName": "cake", + "ownership": 2, + "children": [ + { + "kind": "TypeNominal", + "name": "UnownedStorage", + "printedName": "C1" + }, + { + "kind": "Getter", + "name": "_", + "printedName": "_()", + "declKind": "Func", + "usr": "s:FC4cake2C1g4Ins2XoS0_", + "location": "", + "moduleName": "cake", + "children": [ + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + }, + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + } + ] + }, + { + "kind": "Setter", + "name": "_", + "printedName": "_()", + "declKind": "Func", + "usr": "s:FC4cake2C1s4Ins2XoS0_", + "location": "", + "moduleName": "cake", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + }, + { + "kind": "TypeNominal", + "name": "C1", + "printedName": "C1" + } + ] + } + ] + }, { "kind": "Constructor", "name": "init", diff --git a/tools/swift-api-digester/DigesterEnums.def b/tools/swift-api-digester/DigesterEnums.def index b123d2ffed479..2e8ef29657e00 100644 --- a/tools/swift-api-digester/DigesterEnums.def +++ b/tools/swift-api-digester/DigesterEnums.def @@ -73,6 +73,7 @@ KEY(static) KEY(typeAttributes) KEY(declAttributes) KEY(declKind) +KEY(ownership) KNOWN_TYPE(Optional) KNOWN_TYPE(ImplicitlyUnwrappedOptional) diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp index c0679452806d3..eefef8fcbf381 100644 --- a/tools/swift-api-digester/swift-api-digester.cpp +++ b/tools/swift-api-digester/swift-api-digester.cpp @@ -228,23 +228,23 @@ static StringRef getKeyContent(KeyKind Kind) { } // The node kind appearing in the tree that describes the content of the SDK -enum class SDKNodeKind { +enum class SDKNodeKind: uint8_t { #define NODE_KIND(NAME) NAME, #include "DigesterEnums.def" }; -enum class NodeAnnotation { +enum class NodeAnnotation: uint8_t{ #define NODE_ANNOTATION(NAME) NAME, #include "DigesterEnums.def" }; -enum class KnownTypeKind { +enum class KnownTypeKind: uint8_t { #define KNOWN_TYPE(NAME) NAME, #include "DigesterEnums.def" Unknown, }; -enum class SDKDeclAttrKind { +enum class SDKDeclAttrKind: uint8_t { #define DECL_ATTR(Name) DAK_##Name, #include "DigesterEnums.def" }; @@ -283,6 +283,7 @@ struct SDKNodeInitInfo { bool IsMutating = false; bool IsStatic = false; Optional SelfIndex; + Ownership Ownership = Ownership::Strong; std::vector DeclAttrs; std::vector TypeAttrs; SDKNodeInitInfo() = default; @@ -344,13 +345,14 @@ class SDKNodeDecl : public SDKNode { StringRef ModuleName; std::vector DeclAttributes; bool IsStatic; + uint8_t Ownership; bool hasDeclAttribute(SDKDeclAttrKind DAKind) const; protected: SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind) : SDKNode(Info, Kind), DKind(Info.DKind), Usr(Info.USR), Location(Info.Location), ModuleName(Info.ModuleName), DeclAttributes(Info.DeclAttrs), - IsStatic(Info.IsStatic) {} + IsStatic(Info.IsStatic), Ownership(uint8_t(Info.Ownership)) {} public: StringRef getUsr() const { return Usr; } @@ -358,6 +360,7 @@ class SDKNodeDecl : public SDKNode { StringRef getModuleName() const {return ModuleName;} void addDeclAttribute(SDKDeclAttrKind DAKind); ArrayRef getDeclAttributes() const; + swift::Ownership getOwnership() const { return swift::Ownership(Ownership); } bool isObjc() const { return Usr.startswith("c:"); } static bool classof(const SDKNode *N); DeclKind getDeclKind() const { return DKind; } @@ -762,6 +765,10 @@ NodeUniquePtr SDKNode::constructSDKNode(llvm::yaml::MappingNode *Node) { auto WithQuote = cast(N)->getRawValue(); return WithQuote.substr(1, WithQuote.size() - 2); }; + + static auto getAsInt = [&](llvm::yaml::Node *N) -> int { + return std::stoi(cast(N)->getRawValue()); + }; SDKNodeKind Kind; SDKNodeInitInfo Info; NodeOwnedVector Children; @@ -778,8 +785,7 @@ NodeUniquePtr SDKNode::constructSDKNode(llvm::yaml::MappingNode *Node) { Info.Name = GetScalarString(Pair.getValue()); break; case KeyKind::KK_selfIndex: - Info.SelfIndex = std::stoi(cast(Pair.getValue())-> - getRawValue()); + Info.SelfIndex = getAsInt(Pair.getValue()); break; case KeyKind::KK_usr: Info.USR = GetScalarString(Pair.getValue()); @@ -808,6 +814,10 @@ NodeUniquePtr SDKNode::constructSDKNode(llvm::yaml::MappingNode *Node) { case KeyKind::KK_static: Info.IsStatic = true; break; + case KeyKind::KK_ownership: + Info.Ownership = swift::Ownership(getAsInt(Pair.getValue())); + assert(Info.Ownership != swift::Ownership::Strong && "Stong is implied."); + break; case KeyKind::KK_typeAttributes: { auto *Seq = cast(Pair.getValue()); @@ -1013,6 +1023,13 @@ static Optional getSelfIndex(ValueDecl *VD) { return None; } +static Ownership getOwnership(ValueDecl *VD) { + if (auto OA = VD->getAttrs().getAttribute()) { + return OA->get(); + } + return Ownership::Strong; +} + SDKNodeInitInfo::SDKNodeInitInfo(Type Ty) : Name(getTypeName(Ty)), PrintedName(getPrintedName(Ty)) { if (isFunctionTypeNoEscape(Ty)) @@ -1025,7 +1042,8 @@ SDKNodeInitInfo::SDKNodeInitInfo(ValueDecl *VD) : USR(calculateUsr(VD)), Location(calculateLocation(VD)), ModuleName(VD->getModuleContext()->getName().str()), IsThrowing(isFuncThrowing(VD)), IsMutating(isFuncMutating(VD)), - IsStatic(VD->isStatic()), SelfIndex(getSelfIndex(VD)) { + IsStatic(VD->isStatic()), SelfIndex(getSelfIndex(VD)), + Ownership(getOwnership(VD)) { if (VD->getAttrs().getDeprecated(VD->getASTContext())) DeclAttrs.push_back(SDKDeclAttrKind::DAK_deprecated); } @@ -1383,6 +1401,11 @@ namespace swift { if (!Attributes.empty()) out.mapRequired(getKeyContent(KeyKind::KK_declAttributes).data(), Attributes); + // Strong reference is implied, no need for serialization. + if (D->getOwnership() != Ownership::Strong) { + uint8_t Raw = uint8_t(D->getOwnership()); + out.mapRequired(getKeyContent(KeyKind::KK_ownership).data(), Raw); + } } else if (auto T = dyn_cast(value.get())) { auto Attributes = T->getTypeAttributes(); if (!Attributes.empty())