Skip to content

Commit c40123f

Browse files
committed
Fix issue that caused AccessorDeclSyntax initializer with header + body to be misparsed
`get {}` was parsed by `Parser.parseDeclaration()` but it doesn't parse accessors. `AccessorDeclSyntax` needs a special implementation of `init(header:bodyBuilder:)`. rdar://131720084
1 parent 248dcef commit c40123f

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

Sources/SwiftSyntaxBuilder/SyntaxNodeWithBody.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212

1313
#if swift(>=6)
1414
public import SwiftSyntax
15+
internal import SwiftParser
1516
#else
1617
import SwiftSyntax
18+
import SwiftParser
1719
#endif
1820

1921
// MARK: - PartialSyntaxNode
@@ -124,7 +126,17 @@ extension WithOptionalCodeBlockSyntax where Self: DeclSyntaxProtocol {
124126
_ header: SyntaxNodeString,
125127
@CodeBlockItemListBuilder bodyBuilder: () throws -> CodeBlockItemListSyntax
126128
) throws {
127-
let decl = DeclSyntax("\(header) {}")
129+
// If the type provides a custom `SyntaxParseable` implementation, use that. Otherwise construct it as a
130+
// `DeclSyntax`.
131+
let decl: DeclSyntax
132+
var stringInterpolation = SyntaxStringInterpolation(literalCapacity: 1, interpolationCount: 1)
133+
stringInterpolation.appendInterpolation(header)
134+
stringInterpolation.appendLiteral(" {}")
135+
if let parsableType = Self.self as? SyntaxParseable.Type {
136+
decl = parsableType.init(stringInterpolation: stringInterpolation).cast(DeclSyntax.self)
137+
} else {
138+
decl = DeclSyntax(stringInterpolation: stringInterpolation)
139+
}
128140
guard let castedDecl = decl.as(Self.self) else {
129141
throw SyntaxStringInterpolationInvalidNodeTypeError(expectedType: Self.self, actualNode: decl)
130142
}
@@ -170,7 +182,17 @@ extension HasTrailingMemberDeclBlock where Self: DeclSyntaxProtocol {
170182
_ header: SyntaxNodeString,
171183
@MemberBlockItemListBuilder membersBuilder: () throws -> MemberBlockItemListSyntax
172184
) throws {
173-
let decl = DeclSyntax("\(header) {}")
185+
// If the type provides a custom `SyntaxParseable` implementation, use that. Otherwise construct it as a
186+
// `DeclSyntax`.
187+
let decl: DeclSyntax
188+
var stringInterpolation = SyntaxStringInterpolation(literalCapacity: 1, interpolationCount: 1)
189+
stringInterpolation.appendInterpolation(header)
190+
stringInterpolation.appendLiteral(" {}")
191+
if let parsableType = Self.self as? SyntaxParseable.Type {
192+
decl = parsableType.init(stringInterpolation: stringInterpolation).cast(DeclSyntax.self)
193+
} else {
194+
decl = DeclSyntax(stringInterpolation: stringInterpolation)
195+
}
174196
guard let castedDecl = decl.as(Self.self) else {
175197
throw SyntaxStringInterpolationInvalidNodeTypeError(expectedType: Self.self, actualNode: decl)
176198
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
import SwiftSyntaxBuilder
15+
import XCTest
16+
17+
final class AccessorDeclTests: XCTestCase {
18+
func testCreateAccessorWithHeaderAndBody() throws {
19+
let accessor = try AccessorDeclSyntax("get") {
20+
ExprSyntax("1")
21+
}
22+
XCTAssertEqual(accessor.body?.statements.count, 1)
23+
}
24+
}

0 commit comments

Comments
 (0)