From 773c50f05ae876dacb65e2a6d2b7e9c662279ec6 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 7 Dec 2018 00:40:13 -0800 Subject: [PATCH] Better error message for invalid bigint literals ending with n Helps with the cases of decimals and exponentials, though not with numbers incorrectly starting with `0`. Fixes #28887. --- src/compiler/diagnosticMessages.json | 8 ++++++++ src/compiler/scanner.ts | 18 +++++++++++++++--- .../baselines/reference/parseBigInt.errors.txt | 12 ++++++------ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cde7516f047..ed7c25d5919 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1015,6 +1015,14 @@ "category": "Error", "code": 1351 }, + "A bigint literal cannot use exponential notation.": { + "category": "Error", + "code": 1352 + }, + "A bigint literal must be an integer.": { + "category": "Error", + "code": 1353 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index a9438110593..1a6da02bbd0 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -976,7 +976,7 @@ namespace ts { } if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) { - checkForIdentifierStartAfterNumericLiteral(); + checkForIdentifierStartAfterNumericLiteral(decimalFragment === undefined && !!(tokenFlags & TokenFlags.Scientific)); return { type: SyntaxKind.NumericLiteral, value: "" + +result // if value is not an integer, it can be safely coerced to a number @@ -990,14 +990,26 @@ namespace ts { } } - function checkForIdentifierStartAfterNumericLiteral() { + function checkForIdentifierStartAfterNumericLiteral(isScientific?: boolean) { if (!isIdentifierStart(text.charCodeAt(pos), languageVersion)) { return; } const identifierStart = pos; const { length } = scanIdentifierParts(); - error(Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length); + + if (length === 1 && text[identifierStart] === "n") { + if (isScientific) { + error(Diagnostics.A_bigint_literal_cannot_use_exponential_notation, identifierStart, length); + } + else { + error(Diagnostics.A_bigint_literal_must_be_an_integer, identifierStart, length); + } + } + else { + error(Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length); + } + pos = identifierStart; } diff --git a/tests/baselines/reference/parseBigInt.errors.txt b/tests/baselines/reference/parseBigInt.errors.txt index 16878e75fe9..72f98ee0f46 100644 --- a/tests/baselines/reference/parseBigInt.errors.txt +++ b/tests/baselines/reference/parseBigInt.errors.txt @@ -1,9 +1,9 @@ tests/cases/compiler/parseBigInt.ts(51,20): error TS2736: Operator '+' cannot be applied to type '123n'. tests/cases/compiler/parseBigInt.ts(52,23): error TS2736: Operator '+' cannot be applied to type '291n'. tests/cases/compiler/parseBigInt.ts(56,25): error TS1005: ',' expected. -tests/cases/compiler/parseBigInt.ts(57,25): error TS1351: An identifier or keyword cannot immediately follow a numeric literal. -tests/cases/compiler/parseBigInt.ts(58,22): error TS1351: An identifier or keyword cannot immediately follow a numeric literal. -tests/cases/compiler/parseBigInt.ts(59,28): error TS1351: An identifier or keyword cannot immediately follow a numeric literal. +tests/cases/compiler/parseBigInt.ts(57,25): error TS1352: A bigint literal cannot use exponential notation. +tests/cases/compiler/parseBigInt.ts(58,22): error TS1353: A bigint literal must be an integer. +tests/cases/compiler/parseBigInt.ts(59,28): error TS1353: A bigint literal must be an integer. tests/cases/compiler/parseBigInt.ts(60,23): error TS1177: Binary digit expected. tests/cases/compiler/parseBigInt.ts(61,20): error TS1178: Octal digit expected. tests/cases/compiler/parseBigInt.ts(62,20): error TS1125: Hexadecimal digit expected. @@ -82,13 +82,13 @@ tests/cases/compiler/parseBigInt.ts(70,72): error TS2345: Argument of type '3' i !!! error TS1005: ',' expected. { const scientific = 1e2n; } ~ -!!! error TS1351: An identifier or keyword cannot immediately follow a numeric literal. +!!! error TS1352: A bigint literal cannot use exponential notation. { const decimal = 4.1n; } ~ -!!! error TS1351: An identifier or keyword cannot immediately follow a numeric literal. +!!! error TS1353: A bigint literal must be an integer. { const leadingDecimal = .1n; } ~ -!!! error TS1351: An identifier or keyword cannot immediately follow a numeric literal. +!!! error TS1353: A bigint literal must be an integer. const emptyBinary = 0bn; // should error but infer 0n !!! error TS1177: Binary digit expected.