我尝试编写一个简单的宏,但调用时出现错误“Expected Macro Expand to Produce an Expression”。
宏观实现
public struct Log14: ExpressionMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) -> ExprSyntax {
return
"""
if #available(iOS 14.0, *) {
os_log(.debug, "\\(0)")
}
"""
}
}
#available
不是宏。它看起来像一个宏,因为它也以#
开头,但它只是一个指定可用性的特殊语法。它不会扩展到任何东西 - 编译器经过硬编码以特殊对待这些。
问题不在于将宏放在宏中。将另一个宏放入宏的扩展中将按照您期望的方式工作。
这里的问题是
if #available(iOS 14.0, *) {
os_log(.debug, "\(0)")
}
不是一个表达式。您的
ExpressionMacro
应该扩展为一个表达式。这里的if
是一个声明。
独立宏现在无法生成语句。现在解决这个问题的一种方法是生成一个立即调用的闭包表达式。也就是说,将其作为扩展返回:
"""
{
if #available(iOS 14.0, *) {
os_log(.debug, "\\(0)")
}
}()
"""
这不适用于任何类型的语句,即对范围敏感的语句,如
return
、defer
、break
等。但对于 if 语句,这种解决方法有效。