如何创建一个将参数转发到另一个宏的 Swift 宏?

问题描述 投票:0回答:1

我想定义一个新的宏

@publiclyInitiazable
,它是
这个包
中的 @MemberwiseInit(.public, _optionalsDefaultNil: true) 的别名。

我怎样才能轻松做到这一点?我试过了

@attached(member, names: named(init))
public macro publiclyInitializable(
  _ accessLevel: AccessLevelConfig = .public,
  _deunderscoreParameters: Bool? = nil,
  _optionalsDefaultNil: Bool? = true
) =
  #externalMacro(
    module: "MemberwiseInitMacros",
    type: "MemberwiseInitMacro"
  )

但是参数没有被应用:

enter image description here

swift macros swift-macro
1个回答
0
投票

您似乎希望宏具有不同的默认参数。目前,除非您分叉宏的实现,否则这是不可能的。

宏读取其参数的方式与方法读取其参数的方式不同。特别是,宏实现直接从源代码中读取 AST 节点,而不是像调用方法时那样评估参数表达式。您在宏声明中看到的默认参数值根本不会影响宏的扩展方式。它们充其量只是作为文档。

为了使其正常工作,您需要编写自己的宏,该宏可以扩展为

@MemberwiseInit
。然而,从 Swift 6.0 开始,不支持这种宏。您只能使用 MemberAttributeMacro 将属性添加到声明的
members
。充其量,您需要一个封闭类型,例如

@publiclyInitializable
public enum EnclosingType {
    public struct AnyParams { ... }
}

// expands to

public enum EnclosingType {
    @MemberwiseInit(.public, _optionalsDefaultNil: true)
    public struct AnyParams { ... }
}

这种封闭类型可能是不可取的,但您可以使用

typealias
来稍微克服这一点。


或者,您可以分叉存储库并更改宏实现。 是你需要改变的地方。

let configuredAccessLevel: AccessLevelModifier? = extractConfiguredAccessLevel(from: node)
// I have added "?? true" here, so that when this argument cannot be found, it is "true"
// when this argument does exist, and it is "nil", extractLabeledBoolArgument will actually return "false".
// See the implementation of extractLabeledBoolArgument for more details
let optionalsDefaultNil: Bool? =
  extractLabeledBoolArgument("_optionalsDefaultNil", from: node) ?? true

let deunderscoreParameters: Bool =
  extractLabeledBoolArgument("_deunderscoreParameters", from: node) ?? false

// I have changed this from "?? .internal" to "?? .public"
let accessLevel = configuredAccessLevel ?? .public
© www.soinside.com 2019 - 2024. All rights reserved.