Skip to content

Commit 83a617e

Browse files
committed
Fix parsing bug when a postfix expression is followed by an empty #if clause
1 parent 701a58b commit 83a617e

File tree

7 files changed

+28
-9
lines changed

7 files changed

+28
-9
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extension Parser {
3232
mutating func parseAttribute() -> RawAttributeListSyntax.Element {
3333
if self.at(.poundIfKeyword) {
3434
return .ifConfigDecl(
35-
self.parsePoundIfDirective { parser -> RawAttributeListSyntax.Element in
35+
self.parsePoundIfDirective { (parser, _) -> RawAttributeListSyntax.Element in
3636
return parser.parseAttribute()
3737
} syntax: { parser, attributes in
3838
return .attributes(RawAttributeListSyntax(elements: attributes, arena: parser.arena))

Sources/SwiftParser/Declarations.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ extension Parser {
165165
public mutating func parseDeclaration(inMemberDeclList: Bool = false) -> RawDeclSyntax {
166166
switch self.at(anyIn: PoundDeclarationStart.self) {
167167
case (.poundIfKeyword, _)?:
168-
let directive = self.parsePoundIfDirective { parser in
168+
let directive = self.parsePoundIfDirective { (parser, _) in
169169
let parsedDecl = parser.parseDeclaration()
170170
let semicolon = parser.consume(if: .semicolon)
171171
return RawMemberDeclListItemSyntax(

Sources/SwiftParser/Directives.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ extension Parser {
6666
/// into a syntax collection.
6767
@_spi(RawSyntax)
6868
public mutating func parsePoundIfDirective<Element: RawSyntaxNodeProtocol>(
69-
_ parseElement: (inout Parser) -> Element?,
69+
_ parseElement: (_ parser: inout Parser, _ isFirstElement: Bool) -> Element?,
7070
addSemicolonIfNeeded: (_ lastElement: Element, _ newItemAtStartOfLine: Bool, _ parser: inout Parser) -> Element? = { _, _, _ in nil },
7171
syntax: (inout Parser, [Element]) -> RawIfConfigClauseSyntax.Elements?
7272
) -> RawIfConfigDeclSyntax {
@@ -83,7 +83,7 @@ extension Parser {
8383
do {
8484
var firstIteration = true
8585
var loopProgress = LoopProgressCondition()
86-
while let poundIfHandle = self.canRecoverTo(any: firstIteration ? [.poundIfKeyword] : [.poundIfKeyword, .poundElseifKeyword, .poundElseKeyword]),
86+
while let poundIfHandle = self.canRecoverTo(any: firstIteration ? [.poundIfKeyword] : [.poundElseifKeyword, .poundElseKeyword]),
8787
loopProgress.evaluate(self.currentToken)
8888
{
8989
let (unexpectedBeforePoundIf, poundIf) = self.eat(poundIfHandle)
@@ -104,7 +104,7 @@ extension Parser {
104104
var elementsProgress = LoopProgressCondition()
105105
while !self.at(any: [.eof, .poundElseKeyword, .poundElseifKeyword, .poundEndifKeyword]) && elementsProgress.evaluate(currentToken) {
106106
let newItemAtStartOfLine = self.currentToken.isAtStartOfLine
107-
guard let element = parseElement(&self), !element.isEmpty else {
107+
guard let element = parseElement(&self, elements.isEmpty), !element.isEmpty else {
108108
break
109109
}
110110
if let lastElement = elements.last, let fixedUpLastItem = addSemicolonIfNeeded(lastElement, newItemAtStartOfLine, &self) {

Sources/SwiftParser/Expressions.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,10 @@ extension Parser {
624624
) -> RawExprSyntax {
625625
assert(self.at(.poundIfKeyword))
626626

627-
let config = self.parsePoundIfDirective { parser -> RawExprSyntax? in
627+
let config = self.parsePoundIfDirective { (parser, isFirstElement) -> RawExprSyntax? in
628+
if !isFirstElement {
629+
return nil
630+
}
628631
let head: RawExprSyntax
629632
if parser.at(any: [.period, .prefixPeriod]) {
630633
head = parser.parseDottedExpressionSuffix(nil)

Sources/SwiftParser/Statements.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ extension Parser {
752752
elements.append(
753753
.ifConfigDecl(
754754
self.parsePoundIfDirective(
755-
{ $0.parseSwitchCases(allowStandaloneStmtRecovery: allowStandaloneStmtRecovery) },
755+
{ (parser, _) in parser.parseSwitchCases(allowStandaloneStmtRecovery: allowStandaloneStmtRecovery) },
756756
syntax: { parser, cases in
757757
guard cases.count == 1, let firstCase = cases.first else {
758758
assert(cases.isEmpty)

Sources/SwiftParser/TopLevel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ extension Parser {
201201
/// wrapping declaration instead of being consumed by lookeahead.
202202
private mutating func parseItem(isAtTopLevel: Bool = false, allowInitDecl: Bool = true) -> RawCodeBlockItemSyntax.Item {
203203
if self.at(.poundIfKeyword) {
204-
let directive = self.parsePoundIfDirective {
205-
$0.parseCodeBlockItem()
204+
let directive = self.parsePoundIfDirective { (parser, _) in
205+
parser.parseCodeBlockItem()
206206
} addSemicolonIfNeeded: { lastElement, newItemAtStartOfLine, parser in
207207
if lastElement.semicolon == nil && !newItemAtStartOfLine {
208208
return RawCodeBlockItemSyntax(

Tests/SwiftParserTest/DirectiveTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ final class DirectiveTests: XCTestCase {
6969
)
7070
}
7171

72+
func testPostfixIfConfigExpressionContainsPoundIf() {
73+
AssertParse(
74+
"""
75+
b
76+
#if true
77+
.a
78+
1️⃣#if true
79+
#endif
80+
#endif
81+
""",
82+
diagnostics: [
83+
DiagnosticSpec(message: "unexpected code in conditional compilation block")
84+
]
85+
)
86+
}
87+
7288
func testSourceLocation() {
7389
AssertParse(
7490
"""

0 commit comments

Comments
 (0)