Swift 宏 - 未生成变量

Swift Macros - Variable is not getting generated

提问人:AndreiVataselu 提问时间:10/27/2023 更新时间:10/27/2023 访问量:32

问:

我正在尝试构建一个用于模拟属性的宏,我偶然发现了以下问题:

我有这个协议,我把我的宏附加到它上面

@MyMock
protocol SomeProtocolHere {
    var thisIsMyProperty: Bool { get } 
}

在幕后,我希望宏为我创建一个用于该协议的模拟类

class SomeProtocolHereMock: SomeProtocolHere {
    var thisIsMyPropertyMocked: Bool!
    var thisIsMyProperty: Bool { thisIsMyPropertyMocked }
}

我遇到的问题是我只生成了属性的声明,而没有访问器块。为什么它不生成访问器块?

final class SomeProtocolHereMock: SomeProtocolHere {
    var somethingToReturnReturnValue: Bool!
    var somethingToReturn: Bool
}

这是我用来生成属性的代码

    static func makeVariableMock(from variableDecl: VariableDeclSyntax) -> MemberBlockItemListSyntax {
        let returnValueVariableName = "\(variableDecl.name)ReturnValue"
        
        let mockedUnwrappedProperty = VariableDeclSyntax(
            modifiers:
                DeclModifierListSyntax {
                    if variableDecl.isPublic {
                        DeclModifierSyntax(name: .keyword(.public))
                    }
                },
            bindingSpecifier: .keyword(.var),
            bindings:
                PatternBindingListSyntax {
                    PatternBindingSyntax(
                        pattern:
                            IdentifierPatternSyntax(identifier: .identifier(returnValueVariableName)),
                        typeAnnotation:
                            TypeAnnotationSyntax(type:
                                                    ImplicitlyUnwrappedOptionalTypeSyntax(
                                                        wrappedType: IdentifierTypeSyntax(
                                                            name: TokenSyntax.identifier(variableDecl.type)))
                                                    )
                    )
                    
                }
        )
        
        let originalVariable = VariableDeclSyntax(
            modifiers:
                DeclModifierListSyntax {
                    if variableDecl.isPublic {
                        DeclModifierSyntax(name: .keyword(.public))
                    }
                },
            bindingSpecifier: .keyword(.var),
            bindings:
                PatternBindingListSyntax {
                    PatternBindingSyntax(
                        pattern:
                            IdentifierPatternSyntax(identifier: .identifier(variableDecl.name)),
                        typeAnnotation:
                            TypeAnnotationSyntax(type: IdentifierTypeSyntax(name: TokenSyntax.identifier(variableDecl.type))),
                        accessorBlock: AccessorBlockSyntax(
                            CodeBlockItemListSyntax {
                                CodeBlockItemSyntax(
                                    item: .expr(ExprSyntax(fromProtocol: DeclReferenceExprSyntax(baseName: TokenSyntax.identifier(returnValueVariableName))))
                                )
                            }
                        ))
            }
        )
        
        return MemberBlockItemListSyntax {
            MemberBlockItemSyntax(decl: mockedUnwrappedProperty)
            MemberBlockItemSyntax(decl: originalVariable)
        }
    }
swift-宏 swift5.9

评论


答:

0赞 AndreiVataselu 10/27/2023 #1

经过进一步的挖掘,我发现了问题所在。参数为 nil。为了修复它,我不得不使用初始值设定项而不是accessorBlockinit(accessors:)init?(_ node:)

AccessorBlockSyntax(accessors: .getter(
    CodeBlockItemListSyntax {
        CodeBlockItemSyntax(
            item: .expr(ExprSyntax(fromProtocol: DeclReferenceExprSyntax(baseName: TokenSyntax.identifier(returnValueVariableName))))
        )
    })