Skip to content

Commit 4ade913

Browse files
authored
Add vue/no-loss-of-precision rule (#1680)
1 parent 0aeaaaf commit 4ade913

File tree

7 files changed

+204
-2
lines changed

7 files changed

+204
-2
lines changed

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ The following rules extend the rules provided by ESLint itself and apply them to
382382
| [vue/no-empty-pattern](./no-empty-pattern.md) | disallow empty destructuring patterns | |
383383
| [vue/no-extra-parens](./no-extra-parens.md) | disallow unnecessary parentheses | :wrench: |
384384
| [vue/no-irregular-whitespace](./no-irregular-whitespace.md) | disallow irregular whitespace | |
385+
| [vue/no-loss-of-precision](./no-loss-of-precision.md) | disallow literal numbers that lose precision | |
385386
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
386387
| [vue/no-sparse-arrays](./no-sparse-arrays.md) | disallow sparse arrays | |
387388
| [vue/no-useless-concat](./no-useless-concat.md) | disallow unnecessary concatenation of literals or template literals | |

docs/rules/no-loss-of-precision.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-loss-of-precision
5+
description: disallow literal numbers that lose precision
6+
---
7+
# vue/no-loss-of-precision
8+
9+
> disallow literal numbers that lose precision
10+
11+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
12+
13+
This rule is the same rule as core [no-loss-of-precision] rule but it applies to the expressions in `<template>`.
14+
15+
:::warning
16+
You must be using ESLint v7.1.0 or later to use this rule.
17+
:::
18+
19+
## :books: Further Reading
20+
21+
- [no-loss-of-precision]
22+
23+
[no-loss-of-precision]: https://eslint.org/docs/rules/no-loss-of-precision
24+
25+
## :mag: Implementation
26+
27+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-loss-of-precision.js)
28+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-loss-of-precision.js)
29+
30+
<sup>Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-loss-of-precision)</sup>

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ module.exports = {
9393
'no-irregular-whitespace': require('./rules/no-irregular-whitespace'),
9494
'no-lifecycle-after-await': require('./rules/no-lifecycle-after-await'),
9595
'no-lone-template': require('./rules/no-lone-template'),
96+
'no-loss-of-precision': require('./rules/no-loss-of-precision'),
9697
'no-multi-spaces': require('./rules/no-multi-spaces'),
9798
'no-multiple-objects-in-class': require('./rules/no-multiple-objects-in-class'),
9899
'no-multiple-slot-args': require('./rules/no-multiple-slot-args'),

lib/rules/no-loss-of-precision.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @author Yosuke Ota
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const utils = require('../utils')
12+
13+
// eslint-disable-next-line no-invalid-meta, no-invalid-meta-docs-categories
14+
module.exports = utils.wrapCoreRule('no-loss-of-precision', {
15+
applyDocument: true
16+
})

lib/utils/index.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ let ruleMap = null
6868
/**
6969
* Get the core rule implementation from the rule name
7070
* @param {string} name
71-
* @returns {RuleModule}
71+
* @returns {RuleModule | null}
7272
*/
7373
function getCoreRule(name) {
7474
const map = ruleMap || (ruleMap = new (require('eslint').Linter)().getRules())
75-
return map.get(name) || require(`eslint/lib/rules/${name}`)
75+
return map.get(name) || null
7676
}
7777

7878
/**
@@ -331,6 +331,26 @@ module.exports = {
331331
*/
332332
wrapCoreRule(coreRuleName, options) {
333333
const coreRule = getCoreRule(coreRuleName)
334+
if (!coreRule) {
335+
return {
336+
meta: {
337+
type: 'problem',
338+
docs: {
339+
url: `https://eslint.vuejs.org/rules/${coreRuleName}.html`
340+
}
341+
},
342+
create(context) {
343+
return defineTemplateBodyVisitor(context, {
344+
"VElement[name='template'][parent.type='VDocumentFragment']"(node) {
345+
context.report({
346+
node,
347+
message: `Failed to extend ESLint core rule "${coreRuleName}". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.`
348+
})
349+
}
350+
})
351+
}
352+
}
353+
}
334354
const {
335355
categories,
336356
skipDynamicArguments,
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* @author Yosuke Ota
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const { RuleTester, ESLint } = require('../../eslint-compat')
8+
const semver = require('semver')
9+
const rule = require('../../../lib/rules/no-loss-of-precision')
10+
11+
const tester = new RuleTester({
12+
parser: require.resolve('vue-eslint-parser'),
13+
parserOptions: {
14+
ecmaVersion: 2020,
15+
sourceType: 'module'
16+
}
17+
})
18+
tester.run('no-loss-of-precision', rule, {
19+
valid: [
20+
...(semver.gte(ESLint.version, '7.1.0')
21+
? [
22+
{
23+
filename: 'test.vue',
24+
code: `
25+
<template>
26+
{{12345}}
27+
{{123.45}}
28+
</template>
29+
`
30+
},
31+
{
32+
filename: 'test.vue',
33+
code: `
34+
<template>
35+
<MyComponent num="12345678901234567890" />
36+
</template>
37+
`
38+
}
39+
]
40+
: [])
41+
],
42+
invalid: [
43+
...(semver.gte(ESLint.version, '7.1.0')
44+
? [
45+
{
46+
filename: 'test.vue',
47+
code: `
48+
<template>
49+
{{12345678901234567890}}
50+
{{0.12345678901234567890}}
51+
</template>
52+
`,
53+
errors: [
54+
{
55+
message: 'This number literal will lose precision at runtime.',
56+
line: 3
57+
},
58+
{
59+
message: 'This number literal will lose precision at runtime.',
60+
line: 4
61+
}
62+
]
63+
},
64+
{
65+
filename: 'test.vue',
66+
code: `
67+
<template>
68+
<MyComponent :num="12345678901234567890" />
69+
</template>
70+
`,
71+
errors: [
72+
{
73+
message: 'This number literal will lose precision at runtime.',
74+
line: 3
75+
}
76+
]
77+
}
78+
]
79+
: [
80+
{
81+
filename: 'test.vue',
82+
code: `
83+
<template>
84+
<MyComponent :num="12345678901234567890" />
85+
</template>
86+
`,
87+
errors: [
88+
'Failed to extend ESLint core rule "no-loss-of-precision". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.'
89+
]
90+
}
91+
])
92+
]
93+
})
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict'
2+
3+
const RuleTester = require('eslint').RuleTester
4+
const utils = require('../../../../lib/utils/index')
5+
6+
const rule = utils.wrapCoreRule('foo')
7+
8+
const tester = new RuleTester({
9+
parser: require.resolve('vue-eslint-parser'),
10+
parserOptions: {
11+
ecmaVersion: 2020,
12+
sourceType: 'module'
13+
}
14+
})
15+
16+
// ------------------------------------------------------------------------------
17+
// Tests
18+
// ------------------------------------------------------------------------------
19+
20+
tester.run('wrap-core-rule-with-unknown', rule, {
21+
valid: [
22+
{
23+
filename: 'test.js',
24+
code: `var a`
25+
}
26+
],
27+
invalid: [
28+
{
29+
filename: 'test.vue',
30+
code: `<template></template>`,
31+
errors: [
32+
{
33+
message:
34+
'Failed to extend ESLint core rule "foo". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.',
35+
line: 1,
36+
column: 1
37+
}
38+
]
39+
}
40+
]
41+
})

0 commit comments

Comments
 (0)