Skip to content

Commit 6e02c94

Browse files
committed
Add diagnostic if #if is followed by any declarations
1 parent 25a1d5d commit 6e02c94

File tree

4 files changed

+68
-18
lines changed

4 files changed

+68
-18
lines changed

Sources/SwiftParser/Directives.swift

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ extension Parser {
106106
// Parse #if
107107
let (unexpectedBeforePoundIfKeyword, poundIfKeyword) = self.expect(.poundIfKeyword)
108108
let condition = RawExprSyntax(self.parseSequenceExpression(.basic, forDirective: true))
109+
let unexpectedBetweenConditionAndElements = self.consumeRemainingTokenOnLine()
109110

110111
clauses.append(
111112
RawIfConfigClauseSyntax(
112113
unexpectedBeforePoundIfKeyword,
113114
poundKeyword: poundIfKeyword,
114115
condition: condition,
116+
unexpectedBetweenConditionAndElements,
115117
elements: syntax(&self, parseIfConfigClauseElements(parseElement, addSemicolonIfNeeded: addSemicolonIfNeeded)),
116118
arena: self.arena
117119
)
@@ -272,20 +274,4 @@ extension Parser {
272274
arena: self.arena
273275
)
274276
}
275-
276-
/// Consumes remaining token on the line and returns a ``RawUnexpectedNodesSyntax``
277-
/// if there is any tokens consumed.
278-
private mutating func consumeRemainingTokenOnLine() -> RawUnexpectedNodesSyntax? {
279-
guard !self.currentToken.isAtStartOfLine else {
280-
return nil
281-
}
282-
283-
var unexpectedTokens = [RawTokenSyntax]()
284-
var loopProgress = LoopProgressCondition()
285-
while !self.at(.eof), !currentToken.isAtStartOfLine, loopProgress.evaluate(self.currentToken) {
286-
unexpectedTokens += [self.consumeAnyToken()]
287-
}
288-
289-
return RawUnexpectedNodesSyntax(unexpectedTokens, arena: self.arena)
290-
}
291277
}

Sources/SwiftParser/Parser.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,22 @@ extension Parser {
257257
return self.consumeAnyToken()
258258
}
259259

260+
/// Consumes remaining token on the line and returns a ``RawUnexpectedNodesSyntax``
261+
/// if there is any tokens consumed.
262+
mutating func consumeRemainingTokenOnLine() -> RawUnexpectedNodesSyntax? {
263+
guard !self.currentToken.isAtStartOfLine else {
264+
return nil
265+
}
266+
267+
var unexpectedTokens = [RawTokenSyntax]()
268+
var loopProgress = LoopProgressCondition()
269+
while !self.at(.eof), !currentToken.isAtStartOfLine, loopProgress.evaluate(self.currentToken) {
270+
unexpectedTokens += [self.consumeAnyToken()]
271+
}
272+
273+
return RawUnexpectedNodesSyntax(unexpectedTokens, arena: self.arena)
274+
}
275+
260276
}
261277

262278
// MARK: Check if we can recover to a token

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,22 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
11001100
return .visitChildren
11011101
}
11021102

1103+
public override func visit(_ node: IfConfigClauseSyntax) -> SyntaxVisitorContinueKind {
1104+
if shouldSkip(node) {
1105+
return .skipChildren
1106+
}
1107+
1108+
if let unexpectedBetweenConditionAndElements = node.unexpectedBetweenConditionAndElements {
1109+
addDiagnostic(
1110+
unexpectedBetweenConditionAndElements,
1111+
.extraTokensFollowingConditionalCompilationDirective,
1112+
handledNodes: [unexpectedBetweenConditionAndElements.id]
1113+
)
1114+
}
1115+
1116+
return .visitChildren
1117+
}
1118+
11031119
public override func visit(_ node: IfConfigDeclSyntax) -> SyntaxVisitorContinueKind {
11041120
for clause in node.clauses where clause.hasError {
11051121
if let unexpectedBeforePoundKeyword = clause.unexpectedBeforePoundKeyword,

Tests/SwiftParserTest/DirectiveTests.swift

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,45 @@ final class DirectiveTests: XCTestCase {
197197
)
198198
}
199199

200-
func testFollowedByDeclarations() {
200+
func testEndIfFollowedByDeclarations() {
201201
assertParse(
202202
"""
203203
struct Foo {
204204
#if false
205205
var x: Int
206-
#endif1️⃣; var x = 1
206+
#endif1️⃣; var x = 1
207+
}
208+
""",
209+
diagnostics: [
210+
DiagnosticSpec(
211+
message: "extra tokens following conditional compilation directive"
212+
)
213+
]
214+
)
215+
}
216+
217+
func testIfFollowByDeclarations() {
218+
assertParse(
219+
"""
220+
struct Foo {
221+
#if DEBUG1️⃣; var x = 1
222+
var x: Int
223+
#endif
224+
}
225+
""",
226+
diagnostics: [
227+
DiagnosticSpec(
228+
message: "extra tokens following conditional compilation directive"
229+
)
230+
]
231+
)
232+
233+
assertParse(
234+
"""
235+
struct Foo {
236+
#if DEBUG || UAT1️⃣; var x = 1
237+
var x: Int
238+
#endif
207239
}
208240
""",
209241
diagnostics: [

0 commit comments

Comments
 (0)