Merge pull request #20559 from KitsunebiGames/objc

Objective-C Improvements

Signed-off-by: Dennis <dkorpel@users.noreply.github.com>
Signed-off-by: Nicholas Wilson <thewilsonator@users.noreply.github.com>
Merged-on-behalf-of: Dennis <dkorpel@users.noreply.github.com>
This commit is contained in:
The Dlang Bot 2024-12-15 22:48:39 +01:00 committed by GitHub
commit 059b1ab407
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 160 additions and 12 deletions

View file

@ -93,39 +93,66 @@ struct ObjcSelector
return sel;
}
static const(char)[] toPascalCase(const(char)[] id) {
OutBuffer buf;
char firstChar = id[0];
if (firstChar >= 'a' && firstChar <= 'z')
firstChar = cast(char)(firstChar - 'a' + 'A');
buf.writeByte(firstChar);
buf.writestring(id[1..$]);
return cast(const(char)[])buf.extractSlice(false);
}
extern (C++) static ObjcSelector* create(FuncDeclaration fdecl)
{
OutBuffer buf;
auto ftype = cast(TypeFunction)fdecl.type;
const id = fdecl.ident.toString();
const nparams = ftype.parameterList.length;
// Special case: property setter
if (ftype.isProperty && nparams == 1)
{
// rewrite "identifier" as "setIdentifier"
char firstChar = id[0];
if (firstChar >= 'a' && firstChar <= 'z')
firstChar = cast(char)(firstChar - 'a' + 'A');
buf.writestring("set");
buf.writeByte(firstChar);
buf.write(id[1 .. id.length - 1]);
// Special case: "isXYZ:"
if (id.length >= 2 && id[0..2] == "is")
{
buf.writestring("set");
buf.write(toPascalCase(id[2..$]));
}
else
{
buf.writestring("set");
buf.write(toPascalCase(id));
}
buf.writeByte(':');
goto Lcomplete;
}
// write identifier in selector
buf.write(id[]);
// add mangled type and colon for each parameter
if (nparams)
// To make it easier to match the selectors of objects nicely,
// the implementation has been replaced so that the parameter name followed by a colon
// is used instead.
// eg. void myFunction(int a, int b, int c) would be mangled to a selector as `myFunction:b:c:
if (nparams > 1)
{
buf.writeByte('_');
foreach (i, fparam; ftype.parameterList)
buf.writeByte(':');
foreach(i; 1..nparams)
{
mangleToBuffer(fparam.type, buf);
buf.write(ftype.parameterList[i].ident.toString());
buf.writeByte(':');
}
}
else if (nparams == 1)
{
buf.writeByte(':');
}
Lcomplete:
buf.writeByte('\0');
// the slice is not expected to include a terminating 0
return lookup(cast(const(char)*)buf[].ptr, buf.length - 1, nparams);
}
@ -565,6 +592,16 @@ extern(C++) private final class Supported : Objc
return 0;
});
// Avoid attempting to generate selectors for template instances.
if (fd.parent && fd.parent.isTemplateInstance())
return;
// No selector declared, generate one.
if (fd._linkage == LINK.objc && !fd.objc.selector)
{
fd.objc.selector = ObjcSelector.create(fd);
}
}
override void validateSelector(FuncDeclaration fd)