Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 535b0f2

Browse files
yeonjuanbradzacher
andauthored
feat(eslint-plugin): add extension rule no-loss-of-precision (typescript-eslint#2196)
Co-authored-by: Brad Zacher <[email protected]>
1 parent 5e4dda2 commit 535b0f2

File tree

9 files changed

+154
-15
lines changed

9 files changed

+154
-15
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"cspell": "^4.0.61",
7777
"cz-conventional-changelog": "^3.2.0",
7878
"downlevel-dts": "^0.4.0",
79-
"eslint": "^7.0.0",
79+
"eslint": "^7.2.0",
8080
"eslint-plugin-eslint-comments": "^3.1.2",
8181
"eslint-plugin-eslint-plugin": "^2.2.1",
8282
"eslint-plugin-import": "^2.20.2",

packages/eslint-plugin/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ In these cases, we create what we call an extension rule; a rule within our plug
191191
| [`@typescript-eslint/no-extra-parens`](./docs/rules/no-extra-parens.md) | Disallow unnecessary parentheses | | :wrench: | |
192192
| [`@typescript-eslint/no-extra-semi`](./docs/rules/no-extra-semi.md) | Disallow unnecessary semicolons | :heavy_check_mark: | :wrench: | |
193193
| [`@typescript-eslint/no-invalid-this`](./docs/rules/no-invalid-this.md) | disallow `this` keywords outside of classes or class-like objects | | | |
194+
| [`@typescript-eslint/no-loss-of-precision`](./docs/rules/no-loss-of-precision.md) | Disallow literal numbers that lose precision | | | |
194195
| [`@typescript-eslint/no-magic-numbers`](./docs/rules/no-magic-numbers.md) | Disallow magic numbers | | | |
195196
| [`@typescript-eslint/no-unused-expressions`](./docs/rules/no-unused-expressions.md) | Disallow unused expressions | | | |
196197
| [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables | :heavy_check_mark: | | |
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Disallow literal numbers that lose precision (`no-loss-of-precision`)
2+
3+
## Rule Details
4+
5+
This rule extends the base [`eslint/no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision) rule.
6+
It adds support for [numeric separators](https://github.com/tc39/proposal-numeric-separator).
7+
Note that this rule requires ESLint v7.
8+
9+
## How to use
10+
11+
```jsonc
12+
{
13+
// note you must disable the base rule as it can report incorrect errors
14+
"no-loss-of-precision": "off",
15+
"@typescript-eslint/no-loss-of-precision": ["error"]
16+
}
17+
```
18+
19+
<sup>Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/no-loss-of-precision.md)</sup>

packages/eslint-plugin/src/configs/all.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export = {
5959
'no-invalid-this': 'off',
6060
'@typescript-eslint/no-invalid-this': 'error',
6161
'@typescript-eslint/no-invalid-void-type': 'error',
62+
'no-loss-of-precision': 'off',
63+
'@typescript-eslint/no-loss-of-precision': 'error',
6264
'no-magic-numbers': 'off',
6365
'@typescript-eslint/no-magic-numbers': 'error',
6466
'@typescript-eslint/no-misused-new': 'error',

packages/eslint-plugin/src/rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import typedef from './typedef';
9696
import unboundMethod from './unbound-method';
9797
import unifiedSignatures from './unified-signatures';
9898
import linesBetweenClassMembers from './lines-between-class-members';
99+
import noLossOfPrecision from './no-loss-of-precision';
99100

100101
export default {
101102
'adjacent-overload-signatures': adjacentOverloadSignatures,
@@ -196,4 +197,5 @@ export default {
196197
'unbound-method': unboundMethod,
197198
'unified-signatures': unifiedSignatures,
198199
'lines-between-class-members': linesBetweenClassMembers,
200+
'no-loss-of-precision': noLossOfPrecision,
199201
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { TSESTree } from '@typescript-eslint/experimental-utils';
2+
import BaseRule from 'eslint/lib/rules/no-loss-of-precision';
3+
import * as util from '../util';
4+
5+
const baseRule = ((): typeof BaseRule | null => {
6+
try {
7+
return require('eslint/lib/rules/no-loss-of-precision');
8+
} catch {
9+
/* istanbul ignore next */
10+
return null;
11+
}
12+
})();
13+
14+
type Options = util.InferOptionsTypeFromRule<typeof BaseRule>;
15+
type MessageIds = util.InferMessageIdsTypeFromRule<typeof BaseRule>;
16+
17+
export default util.createRule<Options, MessageIds>({
18+
name: 'no-loss-of-precision',
19+
meta: {
20+
type: 'problem',
21+
docs: {
22+
description: 'Disallow literal numbers that lose precision',
23+
category: 'Possible Errors',
24+
recommended: false,
25+
extendsBaseRule: true,
26+
},
27+
schema: [],
28+
messages: baseRule?.meta.messages ?? { noLossOfPrecision: '' },
29+
},
30+
defaultOptions: [],
31+
create(context) {
32+
/* istanbul ignore if */ if (baseRule === null) {
33+
throw new Error(
34+
'@typescript-eslint/no-loss-of-precision requires at least ESLint v7.1.0',
35+
);
36+
}
37+
38+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
39+
const rules = baseRule!.create(context);
40+
41+
function isSeperatedNumeric(node: TSESTree.Literal): boolean {
42+
return typeof node.value === 'number' && node.raw.includes('_');
43+
}
44+
return {
45+
Literal(node: TSESTree.Literal): void {
46+
rules.Literal({
47+
...node,
48+
raw: isSeperatedNumeric(node) ? node.raw.replace(/_/g, '') : node.raw,
49+
});
50+
},
51+
};
52+
},
53+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import rule from '../../src/rules/no-loss-of-precision';
2+
import { RuleTester } from '../RuleTester';
3+
4+
const ruleTester = new RuleTester({
5+
parser: '@typescript-eslint/parser',
6+
});
7+
8+
ruleTester.run('no-loss-of-precision', rule, {
9+
valid: [
10+
'const x = 12345;',
11+
'const x = 123.456;',
12+
'const x = -123.456;',
13+
'const x = 123_456;',
14+
'const x = 123_00_000_000_000_000_000_000_000;',
15+
'const x = 123.000_000_000_000_000_000_000_0;',
16+
],
17+
invalid: [
18+
{
19+
code: 'const x = 9007199254740993;',
20+
errors: [{ messageId: 'noLossOfPrecision' }],
21+
},
22+
{
23+
code: 'const x = 9_007_199_254_740_993;',
24+
errors: [{ messageId: 'noLossOfPrecision' }],
25+
},
26+
{
27+
code: 'const x = 9_007_199_254_740.993e3;',
28+
errors: [{ messageId: 'noLossOfPrecision' }],
29+
},
30+
{
31+
code:
32+
'const x = 0b100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_001;',
33+
errors: [{ messageId: 'noLossOfPrecision' }],
34+
},
35+
],
36+
});

packages/eslint-plugin/typings/eslint-rules.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,3 +702,16 @@ declare module 'eslint/lib/rules/dot-notation' {
702702
>;
703703
export = rule;
704704
}
705+
706+
declare module 'eslint/lib/rules/no-loss-of-precision' {
707+
import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
708+
709+
const rule: TSESLint.RuleModule<
710+
'noLossOfPrecision',
711+
[],
712+
{
713+
Literal(node: TSESTree.Literal): void;
714+
}
715+
>;
716+
export = rule;
717+
}

yarn.lock

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,7 @@ acorn@^6.0.1:
17501750
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
17511751
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
17521752

1753-
acorn@^7.1.0, acorn@^7.1.1:
1753+
acorn@^7.1.0, acorn@^7.2.0:
17541754
version "7.2.0"
17551755
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe"
17561756
integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==
@@ -3614,6 +3614,14 @@ eslint-scope@^5.0.0:
36143614
esrecurse "^4.1.0"
36153615
estraverse "^4.1.1"
36163616

3617+
eslint-scope@^5.1.0:
3618+
version "5.1.0"
3619+
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5"
3620+
integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==
3621+
dependencies:
3622+
esrecurse "^4.1.0"
3623+
estraverse "^4.1.1"
3624+
36173625
eslint-utils@^2.0.0:
36183626
version "2.0.0"
36193627
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd"
@@ -3626,21 +3634,26 @@ eslint-visitor-keys@^1.1.0:
36263634
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
36273635
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
36283636

3629-
eslint@^7.0.0:
3630-
version "7.0.0"
3631-
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.0.0.tgz#c35dfd04a4372110bd78c69a8d79864273919a08"
3632-
integrity sha512-qY1cwdOxMONHJfGqw52UOpZDeqXy8xmD0u8CT6jIstil72jkhURC704W8CFyTPDPllz4z4lu0Ql1+07PG/XdIg==
3637+
eslint-visitor-keys@^1.2.0:
3638+
version "1.2.0"
3639+
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa"
3640+
integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==
3641+
3642+
eslint@^7.2.0:
3643+
version "7.2.0"
3644+
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.2.0.tgz#d41b2e47804b30dbabb093a967fb283d560082e6"
3645+
integrity sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ==
36333646
dependencies:
36343647
"@babel/code-frame" "^7.0.0"
36353648
ajv "^6.10.0"
36363649
chalk "^4.0.0"
36373650
cross-spawn "^7.0.2"
36383651
debug "^4.0.1"
36393652
doctrine "^3.0.0"
3640-
eslint-scope "^5.0.0"
3653+
eslint-scope "^5.1.0"
36413654
eslint-utils "^2.0.0"
3642-
eslint-visitor-keys "^1.1.0"
3643-
espree "^7.0.0"
3655+
eslint-visitor-keys "^1.2.0"
3656+
espree "^7.1.0"
36443657
esquery "^1.2.0"
36453658
esutils "^2.0.2"
36463659
file-entry-cache "^5.0.1"
@@ -3668,14 +3681,14 @@ eslint@^7.0.0:
36683681
text-table "^0.2.0"
36693682
v8-compile-cache "^2.0.3"
36703683

3671-
espree@^7.0.0:
3672-
version "7.0.0"
3673-
resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e"
3674-
integrity sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==
3684+
espree@^7.1.0:
3685+
version "7.1.0"
3686+
resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c"
3687+
integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==
36753688
dependencies:
3676-
acorn "^7.1.1"
3689+
acorn "^7.2.0"
36773690
acorn-jsx "^5.2.0"
3678-
eslint-visitor-keys "^1.1.0"
3691+
eslint-visitor-keys "^1.2.0"
36793692

36803693
esprima@^2.7.0:
36813694
version "2.7.3"

0 commit comments

Comments
 (0)