@@ -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);
@@ -1397,8 +1381,11 @@ class APIGenRecorder final : public APIRecorder {
1397
1381
addOrGetObjCInterface (decl);
1398
1382
}
1399
1383
1400
- void addObjCMethod (const ClassDecl *cls,
1401
- SILDeclRef method) override {
1384
+ void addObjCCategory (const ExtensionDecl *decl) override {
1385
+ addOrGetObjCCategory (decl);
1386
+ }
1387
+
1388
+ void addObjCMethod (const GenericContext *ctx, SILDeclRef method) override {
1402
1389
SmallString<128 > buffer;
1403
1390
StringRef name = getSelectorName (method, buffer);
1404
1391
apigen::APIAvailability availability;
@@ -1413,12 +1400,23 @@ class APIGenRecorder final : public APIRecorder {
1413
1400
access = apigen::APIAccess::Private;
1414
1401
}
1415
1402
1416
- auto *clsRecord = addOrGetObjCInterface (cls);
1417
- api.addObjCMethod (clsRecord, name, moduleLoc, access , isInstanceMethod,
1418
- false , availability);
1403
+ apigen::ObjCContainerRecord *record = nullptr ;
1404
+ if (auto *cls = dyn_cast<ClassDecl>(ctx))
1405
+ record = addOrGetObjCInterface (cls);
1406
+ else if (auto *ext = dyn_cast<ExtensionDecl>(ctx))
1407
+ record = addOrGetObjCCategory (ext);
1408
+
1409
+ if (record)
1410
+ api.addObjCMethod (record, name, moduleLoc, access , isInstanceMethod,
1411
+ false , availability);
1419
1412
}
1420
1413
1421
1414
private:
1415
+ // / Follow the naming schema that IRGen uses for Categories (see
1416
+ // / ClassDataBuilder).
1417
+ using CategoryNameKey = std::pair<const ClassDecl *, const ModuleDecl *>;
1418
+ llvm::DenseMap<CategoryNameKey, unsigned > CategoryCounts;
1419
+
1422
1420
apigen::APIAvailability getAvailability (const Decl *decl) {
1423
1421
bool unavailable = false ;
1424
1422
std::string introduced, obsoleted;
@@ -1475,11 +1473,46 @@ class APIGenRecorder final : public APIRecorder {
1475
1473
return cls;
1476
1474
}
1477
1475
1476
+ void buildCategoryName (const ExtensionDecl *ext, const ClassDecl *cls,
1477
+ SmallVectorImpl<char > &s) {
1478
+ llvm::raw_svector_ostream os (s);
1479
+ ModuleDecl *module = ext->getParentModule ();
1480
+ os << module->getName ();
1481
+ unsigned categoryCount = CategoryCounts[{cls, module}]++;
1482
+ if (categoryCount > 0 )
1483
+ os << categoryCount;
1484
+ }
1485
+
1486
+ apigen::ObjCCategoryRecord *addOrGetObjCCategory (const ExtensionDecl *decl) {
1487
+ auto entry = categoryMap.find (decl);
1488
+ if (entry != categoryMap.end ())
1489
+ return entry->second ;
1490
+
1491
+ SmallString<128 > interfaceBuffer;
1492
+ SmallString<128 > nameBuffer;
1493
+ ClassDecl *cls = decl->getSelfClassDecl ();
1494
+ auto interface = cls->getObjCRuntimeName (interfaceBuffer);
1495
+ buildCategoryName (decl, cls, nameBuffer);
1496
+ apigen::APIAvailability availability = getAvailability (decl);
1497
+ apigen::APIAccess access =
1498
+ decl->isSPI () ? apigen::APIAccess::Private : apigen::APIAccess::Public;
1499
+ apigen::APILinkage linkage =
1500
+ decl->getMaxAccessLevel () == AccessLevel::Public
1501
+ ? apigen::APILinkage::Exported
1502
+ : apigen::APILinkage::Internal;
1503
+ auto category = api.addObjCCategory (nameBuffer, linkage, moduleLoc, access ,
1504
+ availability, interface);
1505
+ categoryMap.try_emplace (decl, category);
1506
+ return category;
1507
+ }
1508
+
1478
1509
apigen::API &api;
1479
1510
ModuleDecl *module;
1480
1511
apigen::APILoc moduleLoc;
1481
1512
1482
1513
llvm::DenseMap<const ClassDecl*, apigen::ObjCInterfaceRecord*> classMap;
1514
+ llvm::DenseMap<const ExtensionDecl *, apigen::ObjCCategoryRecord *>
1515
+ categoryMap;
1483
1516
};
1484
1517
1485
1518
apigen::API APIGenRequest::evaluate (Evaluator &evaluator,
0 commit comments