[NFC] Add @objc to imported ObjC categories

This contains the category name, if there is one.
This commit is contained in:
Becca Royal-Gordon
2024-04-24 20:17:19 -07:00
parent c3225b066e
commit 07b2b9a01f
3 changed files with 34 additions and 30 deletions

View File

@@ -3707,6 +3707,29 @@ void ValueDecl::setIsObjC(bool value) {
LazySemanticInfo.isObjC = value;
}
Identifier ExtensionDecl::getObjCCategoryName() const {
// If there's an @objc attribute, it's authoritative. (ClangImporter
// attaches one automatically.)
if (auto objcAttr = getAttrs().getAttribute<ObjCAttr>(/*AllowInvalid*/true)) {
if (objcAttr->hasName() && objcAttr->getName()->getNumArgs() == 0)
return objcAttr->getName()->getSimpleName();
return Identifier();
}
// Fall back to @_objcImplementation attribute.
if (auto attr =
getAttrs().getAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true)) {
if (!attr->isCategoryNameInvalid())
return attr->CategoryName;
return Identifier();
}
// Not a category, evidently.
return Identifier();
}
bool ValueDecl::isSemanticallyFinal() const {
// Actor types are semantically final.
if (auto classDecl = dyn_cast<ClassDecl>(this)) {

View File

@@ -5969,32 +5969,6 @@ struct OrderDecls {
};
}
Identifier ExtensionDecl::getObjCCategoryName() const {
// Could it be an imported category?
if (!hasClangNode()) {
// Nope, not imported. Is it an @implementation extension?
auto attr = getAttrs()
.getAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true);
if (attr && !attr->isCategoryNameInvalid())
return attr->CategoryName;
return Identifier();
}
auto category = dyn_cast<clang::ObjCCategoryDecl>(getClangDecl());
if (!category)
// Nope, not a category.
return Identifier();
// We'll look for an implementation with this category name.
auto clangCategoryName = category->getName();
if (clangCategoryName.empty())
// Class extension (has an empty name).
return Identifier();
return getASTContext().getIdentifier(clangCategoryName);
}
static ObjCInterfaceAndImplementation
constructResult(const llvm::TinyPtrVector<Decl *> &interfaces,
llvm::TinyPtrVector<Decl *> &impls,

View File

@@ -4132,14 +4132,16 @@ namespace {
/// selector.
///
/// The importer should use this rather than adding the attribute directly.
void addObjCAttribute(ValueDecl *decl, std::optional<ObjCSelector> name) {
void addObjCAttribute(Decl *decl, std::optional<ObjCSelector> name) {
auto &ctx = Impl.SwiftContext;
if (name) {
decl->getAttrs().add(ObjCAttr::create(ctx, name,
/*implicitName=*/true));
}
decl->setIsObjC(true);
decl->setIsDynamic(true);
if (auto VD = dyn_cast<ValueDecl>(decl)) {
VD->setIsObjC(true);
VD->setIsDynamic(true);
}
// If the declaration we attached the 'objc' attribute to is within a
// type, record it in the type.
@@ -4157,7 +4159,7 @@ namespace {
/// selector.
///
/// The importer should use this rather than adding the attribute directly.
void addObjCAttribute(ValueDecl *decl, Identifier name) {
void addObjCAttribute(Decl *decl, Identifier name) {
addObjCAttribute(decl, ObjCSelector(Impl.SwiftContext, 0, name));
}
@@ -4778,6 +4780,11 @@ namespace {
objcClass->getDeclaredType());
Impl.SwiftContext.evaluator.cacheOutput(ExtendedNominalRequest{result},
std::move(objcClass));
Identifier categoryName;
if (!decl->getName().empty())
categoryName = Impl.SwiftContext.getIdentifier(decl->getName());
addObjCAttribute(result, categoryName);
// Create the extension declaration and record it.
objcClass->addExtension(result);