Skip to content

swift-api-digester: serialize and de-serialize whether a parameter has a default argument. #14866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/swift/IDE/DigesterEnums.def
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ KEY(declKind)
KEY(ownership)
KEY(superclassUsr)
KEY(parentExtensionReqs)
KEY(hasDefaultArg)

KNOWN_TYPE(Optional)
KNOWN_TYPE(ImplicitlyUnwrappedOptional)
Expand Down
5 changes: 4 additions & 1 deletion test/api-digester/Inputs/cake.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ public extension C0 where T1 == S1, T2 == S1, T3 == S1 {

public extension C0 {
func unconditionalFooExt() {}
}
}

public func foo1(_ a: Int = 1, b: S1) {}
public func foo2(_ a: Int = #line, b: S1) {}
54 changes: 54 additions & 0 deletions test/api-digester/Outputs/cake.json
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,60 @@
]
}
]
},
{
"kind": "Function",
"name": "foo1",
"printedName": "foo1(_:b:)",
"declKind": "Func",
"usr": "s:4cake4foo1_1bySi_AA2S1VtF",
"location": "",
"moduleName": "cake",
"children": [
{
"kind": "TypeNominal",
"name": "Void",
"printedName": "()"
},
{
"kind": "TypeNominal",
"name": "Int",
"printedName": "Int",
"hasDefaultArg": true
},
{
"kind": "TypeNominal",
"name": "S1",
"printedName": "S1"
}
]
},
{
"kind": "Function",
"name": "foo2",
"printedName": "foo2(_:b:)",
"declKind": "Func",
"usr": "s:4cake4foo2_1bySi_AA2S1VtF",
"location": "",
"moduleName": "cake",
"children": [
{
"kind": "TypeNominal",
"name": "Void",
"printedName": "()"
},
{
"kind": "TypeNominal",
"name": "Int",
"printedName": "Int",
"hasDefaultArg": true
},
{
"kind": "TypeNominal",
"name": "S1",
"printedName": "S1"
}
]
}
]
}
97 changes: 61 additions & 36 deletions tools/swift-api-digester/swift-api-digester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,14 @@ class ParentExtensionInfo {
ArrayRef<StringRef> getGenericRequirements() const { return Requirements; }
};

/// The additional information we need to create a type node.
struct TypeInitInfo {
bool IsImplicitlyUnwrappedOptional = false;
/// When this type node represents a function parameter, this boolean value
/// indicates whether the parameter has default argument.
bool hasDefaultArgument = false;
};

struct SDKNodeInitInfo {
SDKContext &Ctx;
StringRef Name;
Expand All @@ -325,11 +333,11 @@ struct SDKNodeInitInfo {
std::vector<TypeAttrKind> TypeAttrs;
StringRef SuperclassUsr;
ParentExtensionInfo *ExtInfo = nullptr;
TypeInitInfo TypeInfo;

SDKNodeInitInfo(SDKContext &Ctx) : Ctx(Ctx) {}
SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD);
SDKNodeInitInfo(SDKContext &Ctx, Type Ty,
bool IsImplicitlyUnwrappedOptional =false);
SDKNodeInitInfo(SDKContext &Ctx, Type Ty, TypeInitInfo Info = TypeInitInfo());
SDKNode* createSDKNode(SDKNodeKind Kind);
};

Expand Down Expand Up @@ -465,17 +473,23 @@ NodePtr UpdatedNodesMap::findUpdateCounterpart(const SDKNode *Node) const {

class SDKNodeType : public SDKNode {
std::vector<TypeAttrKind> TypeAttributes;
bool HasDefaultArg;

protected:
bool hasTypeAttribute(TypeAttrKind DAKind) const;
SDKNodeType(SDKNodeInitInfo Info, SDKNodeKind Kind) : SDKNode(Info, Kind),
TypeAttributes(Info.TypeAttrs) {}
TypeAttributes(Info.TypeAttrs),
HasDefaultArg(Info.TypeInfo.hasDefaultArgument) {}

public:
KnownTypeKind getTypeKind() const;
void addTypeAttribute(TypeAttrKind AttrKind);
ArrayRef<TypeAttrKind> getTypeAttributes() const;
SDKNodeDecl *getClosestParentDecl() const;

// When the type node represents a function parameter, this function returns
// whether the parameter has a default value.
bool hasDefaultArgument() const { return HasDefaultArg; }
static bool classof(const SDKNode *N);
};

Expand Down Expand Up @@ -947,6 +961,9 @@ SDKNode* SDKNode::constructSDKNode(SDKContext &Ctx,
case KeyKind::KK_mutating:
Info.IsMutating = true;
break;
case KeyKind::KK_hasDefaultArg:
Info.TypeInfo.hasDefaultArgument = true;
break;
case KeyKind::KK_static:
Info.IsStatic = true;
break;
Expand Down Expand Up @@ -1219,9 +1236,10 @@ static Ownership getOwnership(ValueDecl *VD) {
}

SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Type Ty,
bool IsImplicitlyUnwrappedOptional) :
Ctx(Ctx), Name(getTypeName(Ctx, Ty, IsImplicitlyUnwrappedOptional)),
PrintedName(getPrintedName(Ctx, Ty, IsImplicitlyUnwrappedOptional)) {
TypeInitInfo TypeInfo) :
Ctx(Ctx), Name(getTypeName(Ctx, Ty, TypeInfo.IsImplicitlyUnwrappedOptional)),
PrintedName(getPrintedName(Ctx, Ty, TypeInfo.IsImplicitlyUnwrappedOptional)),
TypeInfo(TypeInfo) {
if (isFunctionTypeNoEscape(Ty))
TypeAttrs.push_back(TypeAttrKind::TAK_noescape);
}
Expand Down Expand Up @@ -1270,8 +1288,8 @@ case SDKNodeKind::X: \
// Recursively construct a node that represents a type, for instance,
// representing the return value type of a function decl.
static SDKNode *constructTypeNode(SDKContext &Ctx, Type T,
bool IsImplicitlyUnwrappedOptional =false) {
SDKNode* Root = SDKNodeInitInfo(Ctx, T, IsImplicitlyUnwrappedOptional)
TypeInitInfo InitInfo = TypeInitInfo()) {
SDKNode* Root = SDKNodeInitInfo(Ctx, T, InitInfo)
.createSDKNode(SDKNodeKind::TypeNominal);

if (auto NAT = dyn_cast<NameAliasType>(T.getPointer())) {
Expand Down Expand Up @@ -1313,42 +1331,46 @@ static SDKNode *constructTypeNode(SDKContext &Ctx, Type T,
return Root;
}

static std::vector<SDKNode*>
createParameterNodes(SDKContext &Ctx, ArrayRef<ParameterList*> AllParamLists) {
std::vector<SDKNode*> Result;
for (auto PL: AllParamLists) {
for (auto param: *PL) {
if (param->isSelfParameter())
continue;
TypeInitInfo TypeInfo;
TypeInfo.IsImplicitlyUnwrappedOptional = param->getAttrs().
hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
TypeInfo.hasDefaultArgument = param->getDefaultArgumentKind() !=
DefaultArgumentKind::None;
Result.push_back(constructTypeNode(Ctx, param->getInterfaceType(),
TypeInfo));
}
}
return Result;
}

// Construct a node for a function decl. The first child of the function decl
// is guaranteed to be the return value type of this function.
// We sometimes skip the first parameter because it can be metatype of dynamic
// this if the function is a member function.
static SDKNode *constructFunctionNode(SDKContext &Ctx, FuncDecl* FD,
SDKNodeKind Kind) {
auto Func = SDKNodeInitInfo(Ctx, FD).createSDKNode(Kind);
bool resultIsImplicitlyUnwrappedOptional = false;
if (FD->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
resultIsImplicitlyUnwrappedOptional = true;
Func->addChild(constructTypeNode(Ctx, FD->getResultInterfaceType(),
resultIsImplicitlyUnwrappedOptional));
for (auto *paramList : FD->getParameterLists()) {
for (auto param : *paramList) {
bool paramIsImplicitlyUnwrappedOptional = false;
if (param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
paramIsImplicitlyUnwrappedOptional = true;

if (!param->isSelfParameter())
Func->addChild(constructTypeNode(Ctx, param->getInterfaceType(),
paramIsImplicitlyUnwrappedOptional));
}
}
TypeInitInfo TypeInfo;
TypeInfo.IsImplicitlyUnwrappedOptional = FD->getAttrs().
hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
Func->addChild(constructTypeNode(Ctx, FD->getResultInterfaceType(), TypeInfo));
for (auto *Node : createParameterNodes(Ctx, FD->getParameterLists()))
Func->addChild(Node);
return Func;
}

static SDKNode* constructInitNode(SDKContext &Ctx, ConstructorDecl *CD) {
auto Func = SDKNodeInitInfo(Ctx, CD).createSDKNode(SDKNodeKind::Constructor);
Func->addChild(constructTypeNode(Ctx, CD->getResultInterfaceType()));
for (auto *paramList : CD->getParameterLists()) {
for (auto param : *paramList)
Func->addChild(constructTypeNode(Ctx, param->getInterfaceType()));
}

// Always remove the first parameter in init.
Func->removeChild(Func->getChildBegin() + 1);
for (auto *Node : createParameterNodes(Ctx, CD->getParameterLists()))
Func->addChild(Node);
return Func;
}

Expand Down Expand Up @@ -1405,11 +1427,10 @@ static SDKNode *constructTypeDeclNode(SDKContext &Ctx, NominalTypeDecl *NTD) {

static SDKNode *constructVarNode(SDKContext &Ctx, ValueDecl *VD) {
auto Var = SDKNodeInitInfo(Ctx, VD).createSDKNode(SDKNodeKind::Var);
auto isImplicitlyUnwrappedOptional = false;
if (VD->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
isImplicitlyUnwrappedOptional = true;
Var->addChild(constructTypeNode(Ctx, VD->getInterfaceType(),
isImplicitlyUnwrappedOptional));
TypeInitInfo TypeInfo;
TypeInfo.IsImplicitlyUnwrappedOptional = VD->getAttrs().
hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
Var->addChild(constructTypeNode(Ctx, VD->getInterfaceType(), TypeInfo));
if (auto VAD = dyn_cast<AbstractStorageDecl>(VD)) {
if (auto Getter = VAD->getGetter())
Var->addChild(constructFunctionNode(Ctx, Getter, SDKNodeKind::Getter));
Expand Down Expand Up @@ -1650,6 +1671,10 @@ namespace swift {
if (!Attributes.empty())
out.mapRequired(getKeyContent(Ctx, KeyKind::KK_typeAttributes).data(),
Attributes);
if (bool HasDefault = T->hasDefaultArgument()) {
out.mapRequired(getKeyContent(Ctx, KeyKind::KK_hasDefaultArg).data(),
HasDefault);
}
}
if (!value->isLeaf()) {
ArrayRef<SDKNode *> Children = value->getChildren();
Expand Down