Skip to content

Commit 25d74e2

Browse files
committed
Diagnose if hex literal does not contain any hex digits
Fixes #1214 rdar://104082735
1 parent 19c68cb commit 25d74e2

File tree

4 files changed

+30
-13
lines changed

4 files changed

+30
-13
lines changed

Sources/SwiftParser/Lexer/Cursor.swift

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,17 +1328,18 @@ extension Lexer.Cursor {
13281328
assert(zeroConsumed && xConsumed, "not a hex literal")
13291329

13301330
// 0x[0-9a-fA-F][0-9a-fA-F_]*
1331-
if self.isAtEndOfFile {
1332-
// TODO: Diagnose invalid hex literal '0x'
1333-
return Lexer.Result(.integerLiteral)
1331+
guard let peeked = self.peek() else {
1332+
return Lexer.Result(.integerLiteral, error: (.expectedHexDigitInHexLiteral, self))
13341333
}
1335-
guard let peeked = self.peek(), Unicode.Scalar(peeked).isHexDigit else {
1336-
let errorPos = self
1337-
self.advance(while: { $0.isValidIdentifierContinuationCodePoint })
1338-
return Lexer.Result(
1339-
.integerLiteral,
1340-
error: (.invalidHexDigitInIntegerLiteral, errorPos)
1341-
)
1334+
1335+
guard Unicode.Scalar(peeked).isHexDigit else {
1336+
if Unicode.Scalar(peeked).isValidIdentifierContinuationCodePoint {
1337+
let errorPos = self
1338+
self.advance(while: { $0.isValidIdentifierContinuationCodePoint })
1339+
return Lexer.Result(.integerLiteral, error: (.invalidHexDigitInIntegerLiteral, errorPos))
1340+
} else {
1341+
return Lexer.Result(.integerLiteral, error: (.expectedHexDigitInHexLiteral, self))
1342+
}
13421343
}
13431344

13441345
self.advance(while: { $0.isHexDigit || $0 == Unicode.Scalar("_") })
@@ -2128,9 +2129,6 @@ extension Lexer.Cursor {
21282129
if tmp.advance(if: { Unicode.Scalar($0).isValidIdentifierContinuationCodePoint }) {
21292130
// If this is a valid identifier continuation, but not a valid identifier
21302131
// start, attempt to recover by eating more continuation characters.
2131-
// if (EmitDiagnosticsIfToken) {
2132-
// diagnose(CurPtr - 1, diag::lex_invalid_identifier_start_character)
2133-
// }
21342132
tmp.advance(while: { Unicode.Scalar($0).isValidIdentifierContinuationCodePoint })
21352133
self = tmp
21362134
return .lexemeContents(Lexer.Result(.identifier, error: (.invalidIdentifierStartCharacter, position: start)))

Sources/SwiftParserDiagnostics/LexerDiagnosticMessages.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public enum StaticLexerError: String, DiagnosticMessage {
4242
case expectedClosingBraceInUnicodeEscape = #"expected '}' in \u{...} escape sequence"#
4343
case expectedDigitInFloatLiteral = "expected a digit in floating point exponent"
4444
case expectedHexCodeInUnicodeEscape = #"expected hexadecimal code in \u{...} escape sequence"#
45+
case expectedHexDigitInHexLiteral = "expected hexadecimal digit (0-9, A-F) in integer literal"
4546
case invalidCharacter = "invalid character in source file"
4647
case invalidEscapeSequenceInStringLiteral = "invalid escape sequence in literal"
4748
case invalidIdentifierStartCharacter = "an identifier cannot begin with this character"
@@ -121,6 +122,7 @@ public extension SwiftSyntax.LexerError {
121122
case .expectedClosingBraceInUnicodeEscape: return StaticLexerError.expectedClosingBraceInUnicodeEscape
122123
case .expectedDigitInFloatLiteral: return StaticLexerError.expectedDigitInFloatLiteral
123124
case .expectedHexCodeInUnicodeEscape: return StaticLexerError.expectedHexCodeInUnicodeEscape
125+
case .expectedHexDigitInHexLiteral: return StaticLexerError.expectedHexDigitInHexLiteral
124126
case .insufficientIndentationInMultilineStringLiteral:
125127
// This should be diagnosed when visiting the `StringLiteralExprSyntax`
126128
// inside `ParseDiagnosticsGenerator` but fall back to an error message

Sources/SwiftSyntax/LexerError.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public struct LexerError: Hashable {
2121
case expectedClosingBraceInUnicodeEscape
2222
case expectedDigitInFloatLiteral
2323
case expectedHexCodeInUnicodeEscape
24+
case expectedHexDigitInHexLiteral
2425
case insufficientIndentationInMultilineStringLiteral
2526
case invalidBinaryDigitInIntegerLiteral
2627
case invalidCharacter

Tests/SwiftParserTest/LexerTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,4 +1208,20 @@ public class LexerTests: XCTestCase {
12081208
)
12091209
}
12101210

1211+
func testHexLiteralWithoutNumbers() {
1212+
AssertLexemes(
1213+
"0x1️⃣",
1214+
lexemes: [
1215+
LexemeSpec(.integerLiteral, text: "0x", error: "expected hexadecimal digit (0-9, A-F) in integer literal")
1216+
]
1217+
)
1218+
1219+
AssertLexemes(
1220+
"0x1️⃣ ",
1221+
lexemes: [
1222+
LexemeSpec(.integerLiteral, text: "0x", trailing: " ", error: "expected hexadecimal digit (0-9, A-F) in integer literal")
1223+
]
1224+
)
1225+
}
1226+
12111227
}

0 commit comments

Comments
 (0)