Drekka
1
Hello everyone, I'm developing a macro which needs to identify if a protocol is already implemented on a type. The macro looks like this:
public static func expansion(
of _: AttributeSyntax,
attachedTo _: some DeclGroupSyntax,
providingExtensionsOf type: some TypeSyntaxProtocol,
conformingTo protocols: [TypeSyntax],
in _: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
var newFunctions: [ExtensionDeclSyntax] = []
let identifiers = protocols.compactMap { $0.as(IdentifierTypeSyntax.self) }
if identifiers.contains(where: { $0.description == "Hashable" }) {
try newFunctions.append(
ExtensionDeclSyntax("""
extension \(type.trimmed): Hashable {
}
"""
)
)
}
return newFunctions
}
my question is whether my approach of mapping to IdentifierTypeSyntax and then using description is a good one for identifying whether Hashable is in the protocols list? Or is there a simpler way to do this?
vanvoorden
(Rick van Voorden)
2
Here is my approach from Swift-CowBox. I'm not completely sure how the description property maps to name… you might want to test how description handles any trivia:
struct Person : Hashable /* trivia */ { }
Something else to keep in mind is whether or not this sees adoptions in extensions:
@macro struct Person { }
extension Person : Hashable { }
AFAIK a macro attached to the main declaration will not see (or know about) adoptions that might be lurking in extensions (but there could be a workaround for this I did not know about).
Another edge case is if a type adopts a protocol that also adopts Hashable:
protocol P : Hashable { }
struct Person : P { }
AFAIK the only option at that point is some kind of runtime-check in the macro expansion that tests each adoption does (or does not) adopt Hashable somewhere.
1 Like