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.
This commit is contained in:
Josh Goldberg
2018-12-07 00:40:13 -08:00
parent 71286e3d49
commit 773c50f05a
3 changed files with 29 additions and 9 deletions

View File

@@ -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",

View File

@@ -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;
}

View File

@@ -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.