Skip to content

Commit 0e616b8

Browse files
committed
Add diagnostic if #endif is followed by any declarations
1 parent 2a9810b commit 0e616b8

File tree

5 files changed

+40
-1
lines changed

5 files changed

+40
-1
lines changed

Sources/SwiftBasicFormat/BasicFormat.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,12 @@ open class BasicFormat: SyntaxRewriter {
186186
}
187187

188188
switch (first?.tokenKind, second?.tokenKind) {
189-
190189
case (.multilineStringQuote, .backslash), // string interpolation segment inside a multi-line string literal
191190
(.multilineStringQuote, .multilineStringQuote), // empty multi-line string literal
192191
(.multilineStringQuote, .stringSegment), // segment starting a multi-line string literal
193192
(.stringSegment, .multilineStringQuote), // ending a multi-line string literal that has a string interpolation segment at its end
194193
(.rightParen, .multilineStringQuote), // ending a multi-line string literal that has a string interpolation segment at its end
194+
(.poundEndifKeyword, _),
195195
(_, .poundElseKeyword),
196196
(_, .poundElseifKeyword),
197197
(_, .poundEndifKeyword),

Sources/SwiftParser/Directives.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,21 @@ extension Parser {
163163
}
164164

165165
let (unexpectedBeforePoundEndIf, poundEndIf) = self.expect(.poundEndifKeyword)
166+
var unexpectedAfterPoundEndif: RawUnexpectedNodesSyntax?
167+
if !self.currentToken.isAtStartOfLine {
168+
var unexpectedTokens = [RawTokenSyntax]()
169+
var loopProgress = LoopProgressCondition()
170+
while !self.at(.eof), !currentToken.isAtStartOfLine, loopProgress.evaluate(self.currentToken) {
171+
unexpectedTokens += [self.consumeAnyToken()]
172+
}
173+
174+
unexpectedAfterPoundEndif = RawUnexpectedNodesSyntax(unexpectedTokens, arena: self.arena)
175+
}
166176
return RawIfConfigDeclSyntax(
167177
clauses: RawIfConfigClauseListSyntax(elements: clauses, arena: self.arena),
168178
unexpectedBeforePoundEndIf,
169179
poundEndif: poundEndIf,
180+
unexpectedAfterPoundEndif,
170181
arena: self.arena
171182
)
172183
}

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,15 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
11361136
}
11371137
}
11381138
}
1139+
1140+
if let unexpectedAfterPoundEndif = node.unexpectedAfterPoundEndif {
1141+
addDiagnostic(
1142+
unexpectedAfterPoundEndif,
1143+
.extraTokensFollowingConditionalCompilationDirective,
1144+
handledNodes: [unexpectedAfterPoundEndif.id]
1145+
)
1146+
}
1147+
11391148
return .visitChildren
11401149
}
11411150

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ extension DiagnosticMessage where Self == StaticParserError {
156156
public static var expectedSequenceExpressionInForEachLoop: Self {
157157
.init("expected Sequence expression for for-each loop")
158158
}
159+
public static var extraTokensFollowingConditionalCompilationDirective: Self {
160+
.init("extra tokens following conditional compilation directive")
161+
}
159162
public static var extraRightBracket: Self {
160163
.init("unexpected ']' in type; did you mean to write an array type?")
161164
}

Tests/SwiftParserTest/DirectiveTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,20 @@ final class DirectiveTests: XCTestCase {
197197
)
198198
}
199199

200+
func testFollowedByDeclarations() {
201+
assertParse(
202+
"""
203+
struct Foo {
204+
#if false
205+
var x: Int
206+
#endif1️⃣; var x = 1
207+
}
208+
""",
209+
diagnostics: [
210+
DiagnosticSpec(
211+
message: "extra tokens following conditional compilation directive"
212+
)
213+
]
214+
)
215+
}
200216
}

0 commit comments

Comments
 (0)