Skip to content

Commit 1dc643c

Browse files
committed
Add diagnostic if #sourceLocation is followed by any declarations
1 parent ddbf0d9 commit 1dc643c

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

Sources/SwiftParser/Directives.swift

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,8 @@ 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-
}
166+
let unexpectedAfterPoundEndif = self.consumeRemainingTokenOnLine()
173167

174-
unexpectedAfterPoundEndif = RawUnexpectedNodesSyntax(unexpectedTokens, arena: self.arena)
175-
}
176168
return RawIfConfigDeclSyntax(
177169
clauses: RawIfConfigClauseListSyntax(elements: clauses, arena: self.arena),
178170
unexpectedBeforePoundEndIf,
@@ -267,14 +259,34 @@ extension Parser {
267259
args = nil
268260
}
269261
let (unexpectedBeforeRParen, rparen) = self.expect(.rightParen)
262+
let unexpectedAfterRightParen = self.consumeRemainingTokenOnLine()
263+
270264
return RawPoundSourceLocationSyntax(
271265
poundSourceLocation: line,
272266
unexpectedBeforeLParen,
273267
leftParen: lparen,
274268
args: args,
275269
unexpectedBeforeRParen,
276270
rightParen: rparen,
271+
unexpectedAfterRightParen,
277272
arena: self.arena
278273
)
279274
}
275+
276+
/// Consumes remaining token on the line and returns a ``RawUnexpectedNodesSyntax``
277+
/// if there is any tokens conrumed.
278+
private mutating func consumeRemainingTokenOnLine() -> RawUnexpectedNodesSyntax? {
279+
var rawUnexpectedNodesSyntax: RawUnexpectedNodesSyntax?
280+
if !self.currentToken.isAtStartOfLine {
281+
var unexpectedTokens = [RawTokenSyntax]()
282+
var loopProgress = LoopProgressCondition()
283+
while !self.at(.eof), !currentToken.isAtStartOfLine, loopProgress.evaluate(self.currentToken) {
284+
unexpectedTokens += [self.consumeAnyToken()]
285+
}
286+
287+
rawUnexpectedNodesSyntax = RawUnexpectedNodesSyntax(unexpectedTokens, arena: self.arena)
288+
}
289+
290+
return rawUnexpectedNodesSyntax
291+
}
280292
}

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,22 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
14201420
return .visitChildren
14211421
}
14221422

1423+
public override func visit(_ node: PoundSourceLocationSyntax) -> SyntaxVisitorContinueKind {
1424+
if shouldSkip(node) {
1425+
return .skipChildren
1426+
}
1427+
1428+
if let unexpectedAfterRightParen = node.unexpectedAfterRightParen {
1429+
addDiagnostic(
1430+
unexpectedAfterRightParen,
1431+
.extraTokensAtTheEndOfSourceLocationDirective,
1432+
handledNodes: [unexpectedAfterRightParen.id]
1433+
)
1434+
}
1435+
1436+
return .visitChildren
1437+
}
1438+
14231439
public override func visit(_ node: PrecedenceGroupAssignmentSyntax) -> SyntaxVisitorContinueKind {
14241440
if shouldSkip(node) {
14251441
return .skipChildren

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 extraTokensAtTheEndOfSourceLocationDirective: Self {
160+
.init("extra tokens at the end of #sourceLocation directive")
161+
}
159162
public static var extraTokensFollowingConditionalCompilationDirective: Self {
160163
.init("extra tokens following conditional compilation directive")
161164
}

Tests/SwiftParserTest/DirectiveTests.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,17 @@ final class DirectiveTests: XCTestCase {
213213
]
214214
)
215215
}
216+
217+
func testSourcelocationDirectiveFollowedByDeclarations() {
218+
assertParse(
219+
"""
220+
#sourceLocation(file: "other.swift", line: 1)1️⃣; let x = 1
221+
""",
222+
diagnostics: [
223+
DiagnosticSpec(
224+
message: "extra tokens at the end of #sourceLocation directive"
225+
)
226+
]
227+
)
228+
}
216229
}

0 commit comments

Comments
 (0)