Skip to content

Add result builder support to SubscriptDeclSyntax #2949

Open
@thafner0

Description

@thafner0

Description

Currently a SubscriptDeclSyntax can only be initialized using a string or the different parts that make it up. Adding the capability for result builders to create accessors would greatly increase the ease of use in generating subscripts. It would be ideal for the result builders to support both the shortened syntax that only provides a getter and the longer syntax providing the ability to declare multiple accessors. Similar to the issue I just opened with the VariableDeclSyntax type not having the ability to declare multiple accessors using result builders (issue #2948), this extension could also use a private shared initializer incorporating the work done by both types and then each specific implementation incorporating the differences specific to that kind of result builder.

Comparison Between Current and Proposed methods

Note that after this change, the existing methods to create subscripts will still be supported. Also, all modifications of this code is to go into the SwiftSyntaxBuilder target since it deals with the result builders. The following usage of the currently available API assumes that SwiftSyntax and SwiftSyntaxBuilder are both imported.

Protocol Requirements

Protocol requirements aren't affected by this change since they have no body. In these cases, continuing to use the SwiftSyntaxBuilder SubscriptDeclSyntax(_:) is sufficient. See the example below:

try! SubscriptDeclSyntax("subscript(_ index: Index) -> Element")

Single Accessor

This code:

SubscriptDeclSyntax(parameterClause: FunctionParameterClauseSyntax(parametersBuilder: {
"_ index: Index"
}),
returnClause: ReturnClauseSyntax(arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), type: TypeSyntax("Element")),
accessorBlock: .getter(CodeBlockItemSyntax {
// code in getter, represented as SwiftSyntax types
})
)

is currently required to generate (the lack of tabs is currently due to it appearing that there isn't a way to tabulate code in GitHub markdown):

subscript(_ index: Index) -> Element {
// code in getter
}

Using result builders, the above code can be simplified to:

try! SubscriptDeclSyntax("subscript(_ index: Index) -> Element") {
// code in getter represented as SwiftSyntax types
}

Multiple Accessors

Similarly we can apply the above code with an additional set accessor generated using the currently available API:

SubscriptDeclSyntax(parameterClause: FunctionParameterClauseSyntax(parametersBuilder: {
"_ index: Index"
}),
returnClause: ReturnClauseSyntax(arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), type: TypeSyntax("Element")),
accessorBlock: .accessors(AccessorDeclListSyntax {
try! AccessorDeclSyntax("get") {
// code in getter represented as SwiftSyntax types
}
try! AccessorDeclSyntax("set") {
// code in setter represented as SwiftSyntax types
}
})
)

which generates:

subscript(_ index: Index) -> Element {
get {
// code in getter
}
set {
// code in setter
}
}

and would be expressible as the following if this feature is adopted:

SubscriptDeclSyntax("subscript(_ index: Index) -> Element") {
try! AccessorDeclSyntax("get") {
// code in getter represented as SwiftSyntax types
}
try! AccessorDeclSyntax("set") {
// code in setter represented as SwiftSyntax types
}
}

Declarations

The method headers that would be added would likely be similar to:

// single getter
public init(_ header: SyntaxNodeString, @CodeBlockItemListBuilder accessor: () throws -> CodeBlockItemListSyntax) throws {
try self.init(header, accessorBlock: .getter(accessor()))
}

// multiple accessors
public init(_ header: SyntaxNodeString, @AccessorDeclListBuilder accessors: () throws -> AccessorDeclListSyntax) throws {
try self.init(header, accessorBlock: .accessors(accessors()))
}

// shared initializer doing any required work that would be common to both of the above public methods, receiving the formatted accessor from the appropriate public method declared above.
private init(_ header: SyntaxNodeString, accessorBlock: AccessorBlockSyntax) throws

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions