diff --git a/Sources/SwiftParser/Lookahead.swift b/Sources/SwiftParser/Lookahead.swift index 85784c0eb6f..b29e4c08688 100644 --- a/Sources/SwiftParser/Lookahead.swift +++ b/Sources/SwiftParser/Lookahead.swift @@ -254,7 +254,7 @@ extension Parser.Lookahead { // If we have a 'didSet' or a 'willSet' label, disambiguate immediately as // an accessor block. let nextToken = self.peek() - if TokenSpec(.didSet) ~= nextToken || TokenSpec(.willSet) ~= nextToken { + if TokenSpec(.didSet) ~= nextToken || TokenSpec(.willSet) ~= nextToken || TokenSpec(.`init`) ~= nextToken { return true } @@ -278,8 +278,8 @@ extension Parser.Lookahead { } } - // Check if we have 'didSet'/'willSet' after attributes. - return lookahead.at(.keyword(.didSet), .keyword(.willSet)) + // Check if we have 'didSet'/'willSet' or 'init' after attributes. + return lookahead.at(.keyword(.didSet), .keyword(.willSet), .keyword(.`init`)) } } diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 2493853e711..f082e73e08e 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -2540,4 +2540,82 @@ final class DeclarationTests: XCTestCase { fixedSource: "let foo: [Int] = []" ) } + + func testInitAccessorsWithDefaultValues() { + assertParse( + """ + struct Test { + var pair: (Int, Int) = (42, 0) { + init(initialValue) {} + + get { (0, 42) } + set { } + } + } + """ + ) + + assertParse( + """ + struct Test { + var pair: (Int, Int) = (42, 0) { + init initializes(a) {} + + get { (0, 42) } + set { } + } + } + """ + ) + + assertParse( + """ + struct Test { + var pair: (Int, Int) = (42, 0) { + get { (0, 42) } + set { } + + init(initialValue1️⃣) {} + } + } + """, + substructure: Syntax( + InitializerDeclSyntax( + initKeyword: .keyword(.`init`), + signature: FunctionSignatureSyntax( + input: ParameterClauseSyntax( + leftParen: .leftParenToken(), + parameterList: FunctionParameterListSyntax([ + FunctionParameterSyntax( + firstName: .identifier("initialValue"), + colon: .colonToken(presence: .missing), + type: TypeSyntax(MissingTypeSyntax(placeholder: .identifier("<#type#>", presence: .missing))) + ) + ]), + rightParen: .rightParenToken(trailingTrivia: .space) + ) + ), + body: CodeBlockSyntax( + leftBrace: .leftBraceToken(), + statements: CodeBlockItemListSyntax([]), + rightBrace: .rightBraceToken() + ) + ) + ), + diagnostics: [ + DiagnosticSpec(message: "expected ':' and type in parameter", fixIts: ["insert ':' and type"]) + ], + fixedSource: + """ + struct Test { + var pair: (Int, Int) = (42, 0) { + get { (0, 42) } + set { } + + init(initialValue: <#type#>) {} + } + } + """ + ) + } }