Skip to content

Commit bedc8d4

Browse files
authored
fix(46195): handle numeric separators and larger integers correctly in codefix for large integers (microsoft#46389)
* fix(46195): handle numeric separators and larger integers correctly * Use `indexOf()` instead of `includes()`
1 parent 5113ba2 commit bedc8d4

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

src/compiler/checker.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -43906,19 +43906,24 @@ namespace ts {
4390643906
}
4390743907

4390843908
function checkNumericLiteralValueSize(node: NumericLiteral) {
43909+
// We should test against `getTextOfNode(node)` rather than `node.text`, because `node.text` for large numeric literals can contain "."
43910+
// e.g. `node.text` for numeric literal `1100000000000000000000` is `1.1e21`.
43911+
const isFractional = getTextOfNode(node).indexOf(".") !== -1;
43912+
const isScientific = node.numericLiteralFlags & TokenFlags.Scientific;
43913+
4390943914
// Scientific notation (e.g. 2e54 and 1e00000000010) can't be converted to bigint
43910-
// Literals with 15 or fewer characters aren't long enough to reach past 2^53 - 1
4391143915
// Fractional numbers (e.g. 9000000000000000.001) are inherently imprecise anyway
43912-
if (node.numericLiteralFlags & TokenFlags.Scientific || node.text.length <= 15 || node.text.indexOf(".") !== -1) {
43916+
if (isFractional || isScientific) {
4391343917
return;
4391443918
}
4391543919

43916-
// We can't rely on the runtime to accurately store and compare extremely large numeric values
43917-
// Even for internal use, we use getTextOfNode: https://github.com/microsoft/TypeScript/issues/33298
43918-
// Thus, if the runtime claims a too-large number is lower than Number.MAX_SAFE_INTEGER,
43919-
// it's likely addition operations on it will fail too
43920-
const apparentValue = +getTextOfNode(node);
43921-
if (apparentValue <= 2 ** 53 - 1 && apparentValue + 1 > apparentValue) {
43920+
// Here `node` is guaranteed to be a numeric literal representing an integer.
43921+
// We need to judge whether the integer `node` represents is <= 2 ** 53 - 1, which can be accomplished by comparing to `value` defined below because:
43922+
// 1) when `node` represents an integer <= 2 ** 53 - 1, `node.text` is its exact string representation and thus `value` precisely represents the integer.
43923+
// 2) otherwise, although `node.text` may be imprecise string representation, its mathematical value and consequently `value` cannot be less than 2 ** 53,
43924+
// thus the result of the predicate won't be affected.
43925+
const value = +node.text;
43926+
if (value <= 2 ** 53 - 1) {
4392243927
return;
4392343928
}
4392443929

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path="fourslash.ts" />
2+
////1000000000000000000000; // 1e21
3+
////1_000_000_000_000_000_000_000; // 1e21
4+
////0x3635C9ADC5DEA00000; // 1e21
5+
////100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; // 1e320
6+
////100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000; // 1e320
7+
8+
verify.codeFixAll({
9+
fixAllDescription: ts.Diagnostics.Convert_all_to_bigint_numeric_literals.message,
10+
fixId: "useBigintLiteral",
11+
newFileContent:
12+
`1000000000000000000000n; // 1e21
13+
1_000_000_000_000_000_000_000n; // 1e21
14+
0x3635C9ADC5DEA00000n; // 1e21
15+
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n; // 1e320
16+
100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000n; // 1e320`,
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference path="fourslash.ts" />
2+
////6_402_373_705_728_000; // 18! < 2 ** 53
3+
////0x16_BE_EC_CA_73_00_00; // 18! < 2 ** 53
4+
5+
verify.not.codeFixAvailable("useBigintLiteral");

0 commit comments

Comments
 (0)