@@ -747,6 +747,15 @@ void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
747
747
if (AFD->hasAsync ()) {
748
748
addAsyncFunctionPointerSymbol (SILDeclRef (AFD));
749
749
}
750
+
751
+ // Skip non objc compatible methods or non-public methods.
752
+ if (isa<DestructorDecl>(AFD) || !AFD->isObjC () ||
753
+ AFD->getFormalAccess () != AccessLevel::Public)
754
+ return ;
755
+ if (auto *CD = dyn_cast<ClassDecl>(AFD->getDeclContext ()))
756
+ recorder.addObjCMethod (CD, SILDeclRef (AFD));
757
+ else if (auto *ED = dyn_cast<ExtensionDecl>(AFD->getDeclContext ()))
758
+ recorder.addObjCMethod (ED, SILDeclRef (AFD));
750
759
}
751
760
752
761
void TBDGenVisitor::visitFuncDecl (FuncDecl *FD) {
@@ -956,30 +965,9 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
956
965
}
957
966
958
967
TBD.addMethodDescriptor (method);
959
-
960
- if (auto methodOrCtorOrDtor = method.getDecl ()) {
961
- // Skip non objc compatible methods or non-public methods.
962
- if (!methodOrCtorOrDtor->isObjC () ||
963
- methodOrCtorOrDtor->getFormalAccess () != AccessLevel::Public)
964
- return ;
965
-
966
- // only handle FuncDecl here. Initializers are handled in
967
- // visitConstructorDecl.
968
- if (isa<FuncDecl>(methodOrCtorOrDtor))
969
- recorder.addObjCMethod (CD, method);
970
- }
971
968
}
972
969
973
- void addMethodOverride (SILDeclRef baseRef, SILDeclRef derivedRef) {
974
- if (auto methodOrCtorOrDtor = derivedRef.getDecl ()) {
975
- if (!methodOrCtorOrDtor->isObjC () ||
976
- methodOrCtorOrDtor->getFormalAccess () != AccessLevel::Public)
977
- return ;
978
-
979
- if (isa<FuncDecl>(methodOrCtorOrDtor))
980
- recorder.addObjCMethod (CD, derivedRef);
981
- }
982
- }
970
+ void addMethodOverride (SILDeclRef baseRef, SILDeclRef derivedRef) {}
983
971
984
972
void addPlaceholder (MissingMemberDecl *) {}
985
973
@@ -1001,10 +989,6 @@ void TBDGenVisitor::visitConstructorDecl(ConstructorDecl *CD) {
1001
989
addAsyncFunctionPointerSymbol (
1002
990
SILDeclRef (CD, SILDeclRef::Kind::Initializer));
1003
991
}
1004
- if (auto parentClass = CD->getParent ()->getSelfClassDecl ()) {
1005
- if (parentClass->isObjC () || CD->isObjC ())
1006
- recorder.addObjCMethod (parentClass, SILDeclRef (CD));
1007
- }
1008
992
}
1009
993
1010
994
visitAbstractFunctionDecl (CD);
@@ -1399,8 +1383,11 @@ class APIGenRecorder final : public APIRecorder {
1399
1383
addOrGetObjCInterface (decl);
1400
1384
}
1401
1385
1402
- void addObjCMethod (const ClassDecl *cls,
1403
- SILDeclRef method) override {
1386
+ void addObjCCategory (const ExtensionDecl *decl) override {
1387
+ addOrGetObjCCategory (decl);
1388
+ }
1389
+
1390
+ void addObjCMethod (const GenericContext *ctx, SILDeclRef method) override {
1404
1391
SmallString<128 > buffer;
1405
1392
StringRef name = getSelectorName (method, buffer);
1406
1393
apigen::APIAvailability availability;
@@ -1415,12 +1402,23 @@ class APIGenRecorder final : public APIRecorder {
1415
1402
access = apigen::APIAccess::Private;
1416
1403
}
1417
1404
1418
- auto *clsRecord = addOrGetObjCInterface (cls);
1419
- api.addObjCMethod (clsRecord, name, moduleLoc, access, isInstanceMethod,
1420
- false , availability);
1405
+ apigen::ObjCContainerRecord *record = nullptr ;
1406
+ if (auto *cls = dyn_cast<ClassDecl>(ctx))
1407
+ record = addOrGetObjCInterface (cls);
1408
+ else if (auto *ext = dyn_cast<ExtensionDecl>(ctx))
1409
+ record = addOrGetObjCCategory (ext);
1410
+
1411
+ if (record)
1412
+ api.addObjCMethod (record, name, moduleLoc, access, isInstanceMethod,
1413
+ false , availability);
1421
1414
}
1422
1415
1423
1416
private:
1417
+ // / Follow the naming schema that IRGen uses for Categories (see
1418
+ // / ClassDataBuilder).
1419
+ using CategoryNameKey = std::pair<const ClassDecl *, const ModuleDecl *>;
1420
+ llvm::DenseMap<CategoryNameKey, unsigned > CategoryCounts;
1421
+
1424
1422
apigen::APIAvailability getAvailability (const Decl *decl) {
1425
1423
bool unavailable = false ;
1426
1424
std::string introduced, obsoleted;
@@ -1477,11 +1475,46 @@ class APIGenRecorder final : public APIRecorder {
1477
1475
return cls;
1478
1476
}
1479
1477
1478
+ void buildCategoryName (const ExtensionDecl *ext, const ClassDecl *cls,
1479
+ SmallVectorImpl<char > &s) {
1480
+ llvm::raw_svector_ostream os (s);
1481
+ ModuleDecl *module = ext->getParentModule ();
1482
+ os << module ->getName ();
1483
+ unsigned categoryCount = CategoryCounts[{cls, module }]++;
1484
+ if (categoryCount > 0 )
1485
+ os << categoryCount;
1486
+ }
1487
+
1488
+ apigen::ObjCCategoryRecord *addOrGetObjCCategory (const ExtensionDecl *decl) {
1489
+ auto entry = categoryMap.find (decl);
1490
+ if (entry != categoryMap.end ())
1491
+ return entry->second ;
1492
+
1493
+ SmallString<128 > interfaceBuffer;
1494
+ SmallString<128 > nameBuffer;
1495
+ ClassDecl *cls = decl->getSelfClassDecl ();
1496
+ auto interface = cls->getObjCRuntimeName (interfaceBuffer);
1497
+ buildCategoryName (decl, cls, nameBuffer);
1498
+ apigen::APIAvailability availability = getAvailability (decl);
1499
+ apigen::APIAccess access =
1500
+ decl->isSPI () ? apigen::APIAccess::Private : apigen::APIAccess::Public;
1501
+ apigen::APILinkage linkage =
1502
+ decl->getMaxAccessLevel () == AccessLevel::Public
1503
+ ? apigen::APILinkage::Exported
1504
+ : apigen::APILinkage::Internal;
1505
+ auto category = api.addObjCCategory (nameBuffer, linkage, moduleLoc, access,
1506
+ availability, interface);
1507
+ categoryMap.try_emplace (decl, category);
1508
+ return category;
1509
+ }
1510
+
1480
1511
apigen::API &api;
1481
1512
ModuleDecl *module ;
1482
1513
apigen::APILoc moduleLoc;
1483
1514
1484
1515
llvm::DenseMap<const ClassDecl*, apigen::ObjCInterfaceRecord*> classMap;
1516
+ llvm::DenseMap<const ExtensionDecl *, apigen::ObjCCategoryRecord *>
1517
+ categoryMap;
1485
1518
};
1486
1519
1487
1520
apigen::API APIGenRequest::evaluate (Evaluator &evaluator,
0 commit comments