Merge pull request #33300 from JoshuaKGoldberg/too-large-integer-bigint-codefix
Added codefix for numeric literals >= 2 ** 53
This commit is contained in:
commit
e8fc62e1a2
|
@ -33716,9 +33716,33 @@ namespace ts {
|
|||
return grammarErrorOnNode(withMinus ? node.parent : node, diagnosticMessage, literal);
|
||||
}
|
||||
}
|
||||
|
||||
// Realism (size) checking
|
||||
checkNumericLiteralValueSize(node);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkNumericLiteralValueSize(node: NumericLiteral) {
|
||||
// Scientific notation (e.g. 2e54 and 1e00000000010) can't be converted to bigint
|
||||
// Literals with 15 or fewer characters aren't long enough to reach past 2^53 - 1
|
||||
// Fractional numbers (e.g. 9000000000000000.001) are inherently imprecise anyway
|
||||
if (node.numericLiteralFlags & TokenFlags.Scientific || node.text.length <= 15 || node.text.indexOf(".") !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can't rely on the runtime to accurately store and compare extremely large numeric values
|
||||
// Even for internal use, we use getTextOfNode: https://github.com/microsoft/TypeScript/issues/33298
|
||||
// Thus, if the runtime claims a too-large number is lower than Number.MAX_SAFE_INTEGER,
|
||||
// it's likely addition operations on it will fail too
|
||||
const apparentValue = +getTextOfNode(node);
|
||||
if (apparentValue <= 2 ** 53 - 1 && apparentValue + 1 > apparentValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers));
|
||||
}
|
||||
|
||||
function checkGrammarBigIntLiteral(node: BigIntLiteral): boolean {
|
||||
const literalType = isLiteralTypeNode(node.parent) ||
|
||||
isPrefixUnaryExpression(node.parent) && isLiteralTypeNode(node.parent.parent);
|
||||
|
|
|
@ -4643,6 +4643,10 @@
|
|||
"category": "Suggestion",
|
||||
"code": 80007
|
||||
},
|
||||
"Numeric literals with absolute values equal to 2^53 or greater are too large to be represented accurately as integers.": {
|
||||
"category": "Suggestion",
|
||||
"code": 80008
|
||||
},
|
||||
|
||||
"Add missing 'super()' call": {
|
||||
"category": "Message",
|
||||
|
@ -5124,6 +5128,14 @@
|
|||
"category": "Message",
|
||||
"code": 95090
|
||||
},
|
||||
"Convert to a bigint numeric literal": {
|
||||
"category": "Message",
|
||||
"code": 95091
|
||||
},
|
||||
"Convert all to bigint numeric literals": {
|
||||
"category": "Message",
|
||||
"code": 95092
|
||||
},
|
||||
|
||||
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
|
||||
"category": "Error",
|
||||
|
|
33
src/services/codefixes/useBigintLiteral.ts
Normal file
33
src/services/codefixes/useBigintLiteral.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
const fixId = "useBigintLiteral";
|
||||
const errorCodes = [
|
||||
Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers.code,
|
||||
];
|
||||
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
getCodeActions: context => {
|
||||
const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span));
|
||||
if (changes.length > 0) {
|
||||
return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_a_bigint_numeric_literal, fixId, Diagnostics.Convert_all_to_bigint_numeric_literals)];
|
||||
}
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => {
|
||||
return codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag));
|
||||
},
|
||||
});
|
||||
|
||||
function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan) {
|
||||
const numericLiteral = tryCast(getTokenAtPosition(sourceFile, span.start), isNumericLiteral);
|
||||
if (!numericLiteral) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We use .getText to overcome parser inaccuracies: https://github.com/microsoft/TypeScript/issues/33298
|
||||
const newText = numericLiteral.getText(sourceFile) + "n";
|
||||
|
||||
changeTracker.replaceNode(sourceFile, numericLiteral, createBigIntLiteral(newText));
|
||||
}
|
||||
}
|
|
@ -79,6 +79,7 @@
|
|||
"codefixes/fixStrictClassInitialization.ts",
|
||||
"codefixes/requireInTs.ts",
|
||||
"codefixes/useDefaultImport.ts",
|
||||
"codefixes/useBigintLiteral.ts",
|
||||
"codefixes/fixAddModuleReferTypeMissingTypeof.ts",
|
||||
"codefixes/convertToMappedObjectType.ts",
|
||||
"codefixes/removeUnnecessaryAwait.ts",
|
||||
|
|
73
tests/cases/fourslash/codeFixUseBigIntLiteral.ts
Normal file
73
tests/cases/fourslash/codeFixUseBigIntLiteral.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
////9007199254740991;
|
||||
////-9007199254740991;
|
||||
////9007199254740992;
|
||||
////-9007199254740992;
|
||||
////9007199254740993;
|
||||
////-9007199254740993;
|
||||
////9007199254740994;
|
||||
////-9007199254740994;
|
||||
////0x19999999999998;
|
||||
////-0x19999999999998;
|
||||
////0x19999999999999;
|
||||
////-0x19999999999999;
|
||||
////0x20000000000000;
|
||||
////-0x20000000000000;
|
||||
////0x20000000000001;
|
||||
////-0x20000000000001;
|
||||
////2e52;
|
||||
////2e53;
|
||||
////2e54;
|
||||
////1e00000000010;
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Convert_to_a_bigint_numeric_literal.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`9007199254740991;
|
||||
-9007199254740991;
|
||||
9007199254740992n;
|
||||
-9007199254740992;
|
||||
9007199254740993;
|
||||
-9007199254740993;
|
||||
9007199254740994;
|
||||
-9007199254740994;
|
||||
0x19999999999998;
|
||||
-0x19999999999998;
|
||||
0x19999999999999;
|
||||
-0x19999999999999;
|
||||
0x20000000000000;
|
||||
-0x20000000000000;
|
||||
0x20000000000001;
|
||||
-0x20000000000001;
|
||||
2e52;
|
||||
2e53;
|
||||
2e54;
|
||||
1e00000000010;`
|
||||
});
|
||||
|
||||
verify.codeFixAll({
|
||||
fixAllDescription: ts.Diagnostics.Convert_all_to_bigint_numeric_literals.message,
|
||||
fixId: "useBigintLiteral",
|
||||
newFileContent:
|
||||
`9007199254740991;
|
||||
-9007199254740991;
|
||||
9007199254740992n;
|
||||
-9007199254740992n;
|
||||
9007199254740993n;
|
||||
-9007199254740993n;
|
||||
9007199254740994n;
|
||||
-9007199254740994n;
|
||||
0x19999999999998;
|
||||
-0x19999999999998;
|
||||
0x19999999999999;
|
||||
-0x19999999999999;
|
||||
0x20000000000000n;
|
||||
-0x20000000000000n;
|
||||
0x20000000000001n;
|
||||
-0x20000000000001n;
|
||||
2e52;
|
||||
2e53;
|
||||
2e54;
|
||||
1e00000000010;`
|
||||
});
|
Loading…
Reference in a new issue