@@ -67,7 +67,9 @@ namespace {
67
67
DumpSwiftModules,
68
68
CompareSDKs,
69
69
DiagnoseSDKs,
70
+ // The following two are for testing purposes
70
71
DeserializeDiffItems,
72
+ DeserializeSDK,
71
73
};
72
74
} // end anonymous namespace
73
75
@@ -135,7 +137,10 @@ Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
135
137
" Diagnose SDK content in JSON file" ),
136
138
clEnumValN(ActionType::DeserializeDiffItems,
137
139
" deserialize-diff" ,
138
- " Deserialize diff items in a JSON file" )));
140
+ " Deserialize diff items in a JSON file" ),
141
+ clEnumValN(ActionType::DeserializeSDK,
142
+ " deserialize-sdk" ,
143
+ " Deserialize sdk digester in a JSON file" )));
139
144
140
145
static llvm::cl::list<std::string>
141
146
SDKJsonPaths (" input-paths" ,
@@ -287,6 +292,22 @@ static raw_ostream &operator<<(raw_ostream &Out, const DeclKind Value) {
287
292
llvm_unreachable (" Unhandled DeclKind in switch." );
288
293
}
289
294
295
+ // / We don't dump individual extension declaration in the digester. However,
296
+ // / we still want to detect whether an extension's applicability changes. Therefore,
297
+ // / by using ParentExtensionInfo, we keep track of extension's information in
298
+ // / each member of the extension.
299
+ class ParentExtensionInfo {
300
+ friend struct SDKNodeInitInfo ;
301
+ friend class SDKNode ;
302
+ std::vector<StringRef> Requirements;
303
+
304
+ void *operator new (size_t Bytes, SDKContext &C) {
305
+ return C.allocator ().Allocate <ParentExtensionInfo>();
306
+ }
307
+ public:
308
+ ArrayRef<StringRef> getGenericRequirements () const { return Requirements; }
309
+ };
310
+
290
311
struct SDKNodeInitInfo {
291
312
SDKContext &Ctx;
292
313
StringRef Name;
@@ -303,6 +324,8 @@ struct SDKNodeInitInfo {
303
324
std::vector<SDKDeclAttrKind> DeclAttrs;
304
325
std::vector<TypeAttrKind> TypeAttrs;
305
326
StringRef SuperclassUsr;
327
+ ParentExtensionInfo *ExtInfo = nullptr ;
328
+
306
329
SDKNodeInitInfo (SDKContext &Ctx) : Ctx(Ctx) {}
307
330
SDKNodeInitInfo (SDKContext &Ctx, ValueDecl *VD);
308
331
SDKNodeInitInfo (SDKContext &Ctx, Type Ty,
@@ -372,12 +395,15 @@ class SDKNodeDecl : public SDKNode {
372
395
bool IsStatic;
373
396
uint8_t Ownership;
374
397
bool hasDeclAttribute (SDKDeclAttrKind DAKind) const ;
398
+ // Non-null ExtInfo implies this decl is defined in an type extension.
399
+ ParentExtensionInfo *ExtInfo;
375
400
376
401
protected:
377
402
SDKNodeDecl (SDKNodeInitInfo Info, SDKNodeKind Kind) : SDKNode(Info, Kind),
378
403
DKind (Info.DKind), Usr(Info.USR), Location(Info.Location),
379
404
ModuleName(Info.ModuleName), DeclAttributes(Info.DeclAttrs),
380
- IsStatic(Info.IsStatic), Ownership(uint8_t (Info.Ownership)) {}
405
+ IsStatic(Info.IsStatic), Ownership(uint8_t (Info.Ownership)),
406
+ ExtInfo(Info.ExtInfo) {}
381
407
382
408
public:
383
409
StringRef getUsr () const { return Usr; }
@@ -395,6 +421,11 @@ class SDKNodeDecl : public SDKNode {
395
421
bool isSDKPrivate () const ;
396
422
bool isDeprecated () const ;
397
423
bool isStatic () const { return IsStatic; };
424
+ bool isFromExtension () const { return ExtInfo; }
425
+ const ParentExtensionInfo& getExtensionInfo () const {
426
+ assert (isFromExtension ());
427
+ return *ExtInfo;
428
+ }
398
429
};
399
430
400
431
StringRef SDKNodeDecl::getHeaderName () const {
@@ -893,6 +924,14 @@ SDKNode* SDKNode::constructSDKNode(SDKContext &Ctx,
893
924
cast<llvm::yaml::MappingNode>(&Mapping)));
894
925
}
895
926
break ;
927
+ case KeyKind::KK_parentExtensionReqs: {
928
+ assert (!Info.ExtInfo );
929
+ Info.ExtInfo = new (Ctx) ParentExtensionInfo ();
930
+ for (auto &Req : *cast<llvm::yaml::SequenceNode>(Pair.getValue ())) {
931
+ Info.ExtInfo ->Requirements .push_back (GetScalarString (&Req));
932
+ }
933
+ break ;
934
+ }
896
935
case KeyKind::KK_printedName:
897
936
Info.PrintedName = GetScalarString (Pair.getValue ());
898
937
break ;
@@ -1194,7 +1233,7 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD) : Ctx(Ctx),
1194
1233
ModuleName(VD->getModuleContext ()->getName().str()),
1195
1234
IsThrowing(isFuncThrowing(VD)), IsMutating(isFuncMutating(VD)),
1196
1235
IsStatic(VD->isStatic ()), SelfIndex(getSelfIndex(VD)),
1197
- Ownership(getOwnership(VD)) {
1236
+ Ownership(getOwnership(VD)), ExtInfo( nullptr ) {
1198
1237
1199
1238
// Calculate usr for its super class.
1200
1239
if (auto *CD = dyn_cast_or_null<ClassDecl>(VD)) {
@@ -1203,6 +1242,18 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD) : Ctx(Ctx),
1203
1242
}
1204
1243
if (VD->getAttrs ().getDeprecated (VD->getASTContext ()))
1205
1244
DeclAttrs.push_back (SDKDeclAttrKind::DAK_deprecated);
1245
+
1246
+ // If the decl is declared in an extension, calculate the extension info.
1247
+ if (auto *Ext = dyn_cast_or_null<ExtensionDecl>(VD->getDeclContext ())) {
1248
+ ExtInfo = new (Ctx) ParentExtensionInfo ();
1249
+ // Print each generic requirement to the extension info.
1250
+ for (auto Req: Ext->getGenericRequirements ()) {
1251
+ llvm::SmallString<32 > Result;
1252
+ llvm::raw_svector_ostream OS (Result);
1253
+ Req.print (OS, PrintOptions::printInterface ());
1254
+ ExtInfo->Requirements .emplace_back (Ctx.buffer (OS.str ()));
1255
+ }
1256
+ }
1206
1257
}
1207
1258
1208
1259
SDKNode *SDKNodeInitInfo::createSDKNode (SDKNodeKind Kind) {
@@ -1576,6 +1627,15 @@ namespace swift {
1576
1627
Super);
1577
1628
}
1578
1629
}
1630
+ if (D->isFromExtension ()) {
1631
+ // Even if we don't have any requirements on this parent extension,
1632
+ // we still want to have this key present to indicate the member
1633
+ // is from an extension.
1634
+ auto Reqs = D->getExtensionInfo ().getGenericRequirements ();
1635
+ out.mapRequired (getKeyContent (Ctx,
1636
+ KeyKind::KK_parentExtensionReqs).data (),
1637
+ Reqs);
1638
+ }
1579
1639
auto Attributes = D->getDeclAttributes ();
1580
1640
if (!Attributes.empty ())
1581
1641
out.mapRequired (getKeyContent (Ctx, KeyKind::KK_declAttributes).data (),
@@ -1630,6 +1690,16 @@ namespace swift {
1630
1690
return const_cast <SDKDeclAttrKind&>(seq[index]);
1631
1691
}
1632
1692
};
1693
+ template <>
1694
+ struct ArrayTraits <ArrayRef<StringRef>> {
1695
+ static size_t size (Output &out, ArrayRef<StringRef> &seq) {
1696
+ return seq.size ();
1697
+ }
1698
+ static StringRef& element (Output &, ArrayRef<StringRef> &seq,
1699
+ size_t index) {
1700
+ return const_cast <StringRef&>(seq[index]);
1701
+ }
1702
+ };
1633
1703
} // namespace json
1634
1704
} // namespace swift
1635
1705
@@ -3497,6 +3567,23 @@ static int deserializeDiffItems(StringRef DiffPath, StringRef OutputPath) {
3497
3567
return 0 ;
3498
3568
}
3499
3569
3570
+ // / Mostly for testing purposes, this function de-serializes the SDK dump in
3571
+ // / dumpPath and re-serialize them to OutputPath. If the tool performs correctly,
3572
+ // / the contents in dumpPath and OutputPath should be identical.
3573
+ static int deserializeSDKDump (StringRef dumpPath, StringRef OutputPath) {
3574
+ std::error_code EC;
3575
+ llvm::raw_fd_ostream FS (OutputPath, EC, llvm::sys::fs::F_None);
3576
+ if (!fs::exists (dumpPath)) {
3577
+ llvm::errs () << dumpPath << " does not exist\n " ;
3578
+ return 1 ;
3579
+ }
3580
+ SDKContext Ctx;
3581
+ SwiftDeclCollector Collector (Ctx);
3582
+ Collector.deSerialize (dumpPath);
3583
+ Collector.serialize (OutputPath);
3584
+ return 0 ;
3585
+ }
3586
+
3500
3587
int main (int argc, char *argv[]) {
3501
3588
INITIALIZE_LLVM (argc, argv);
3502
3589
@@ -3532,12 +3619,16 @@ int main(int argc, char *argv[]) {
3532
3619
else
3533
3620
return diagnoseModuleChange (options::SDKJsonPaths[0 ],
3534
3621
options::SDKJsonPaths[1 ]);
3622
+ case ActionType::DeserializeSDK:
3535
3623
case ActionType::DeserializeDiffItems: {
3536
3624
if (options::SDKJsonPaths.size () != 1 ) {
3537
3625
llvm::cl::PrintHelpMessage ();
3538
3626
return 1 ;
3539
3627
}
3540
- return deserializeDiffItems (options::SDKJsonPaths[0 ], options::OutputFile);
3628
+ if (options::Action == ActionType::DeserializeDiffItems)
3629
+ return deserializeDiffItems (options::SDKJsonPaths[0 ], options::OutputFile);
3630
+ else
3631
+ return deserializeSDKDump (options::SDKJsonPaths[0 ], options::OutputFile);
3541
3632
}
3542
3633
case ActionType::None:
3543
3634
llvm::errs () << " Action required\n " ;
0 commit comments