Skip to content

Commit

Permalink
Add vue/no-loss-of-precision rule (#1680)
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi committed Oct 29, 2021
1 parent 0aeaaaf commit 4ade913
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -382,6 +382,7 @@ The following rules extend the rules provided by ESLint itself and apply them to
| [vue/no-empty-pattern](./no-empty-pattern.md) | disallow empty destructuring patterns | |
| [vue/no-extra-parens](./no-extra-parens.md) | disallow unnecessary parentheses | :wrench: |
| [vue/no-irregular-whitespace](./no-irregular-whitespace.md) | disallow irregular whitespace | |
| [vue/no-loss-of-precision](./no-loss-of-precision.md) | disallow literal numbers that lose precision | |
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
| [vue/no-sparse-arrays](./no-sparse-arrays.md) | disallow sparse arrays | |
| [vue/no-useless-concat](./no-useless-concat.md) | disallow unnecessary concatenation of literals or template literals | |
Expand Down
30 changes: 30 additions & 0 deletions docs/rules/no-loss-of-precision.md
@@ -0,0 +1,30 @@
---
pageClass: rule-details
sidebarDepth: 0
title: vue/no-loss-of-precision
description: disallow literal numbers that lose precision
---
# vue/no-loss-of-precision

> disallow literal numbers that lose precision
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>

This rule is the same rule as core [no-loss-of-precision] rule but it applies to the expressions in `<template>`.

:::warning
You must be using ESLint v7.1.0 or later to use this rule.
:::

## :books: Further Reading

- [no-loss-of-precision]

[no-loss-of-precision]: https://eslint.org/docs/rules/no-loss-of-precision

## :mag: Implementation

- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-loss-of-precision.js)
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-loss-of-precision.js)

<sup>Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-loss-of-precision)</sup>
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -93,6 +93,7 @@ module.exports = {
'no-irregular-whitespace': require('./rules/no-irregular-whitespace'),
'no-lifecycle-after-await': require('./rules/no-lifecycle-after-await'),
'no-lone-template': require('./rules/no-lone-template'),
'no-loss-of-precision': require('./rules/no-loss-of-precision'),
'no-multi-spaces': require('./rules/no-multi-spaces'),
'no-multiple-objects-in-class': require('./rules/no-multiple-objects-in-class'),
'no-multiple-slot-args': require('./rules/no-multiple-slot-args'),
Expand Down
16 changes: 16 additions & 0 deletions lib/rules/no-loss-of-precision.js
@@ -0,0 +1,16 @@
/**
* @author Yosuke Ota
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const utils = require('../utils')

// eslint-disable-next-line no-invalid-meta, no-invalid-meta-docs-categories
module.exports = utils.wrapCoreRule('no-loss-of-precision', {
applyDocument: true
})
24 changes: 22 additions & 2 deletions lib/utils/index.js
Expand Up @@ -68,11 +68,11 @@ let ruleMap = null
/**
* Get the core rule implementation from the rule name
* @param {string} name
* @returns {RuleModule}
* @returns {RuleModule | null}
*/
function getCoreRule(name) {
const map = ruleMap || (ruleMap = new (require('eslint').Linter)().getRules())
return map.get(name) || require(`eslint/lib/rules/${name}`)
return map.get(name) || null
}

/**
Expand Down Expand Up @@ -331,6 +331,26 @@ module.exports = {
*/
wrapCoreRule(coreRuleName, options) {
const coreRule = getCoreRule(coreRuleName)
if (!coreRule) {
return {
meta: {
type: 'problem',
docs: {
url: `https://eslint.vuejs.org/rules/${coreRuleName}.html`
}
},
create(context) {
return defineTemplateBodyVisitor(context, {
"VElement[name='template'][parent.type='VDocumentFragment']"(node) {
context.report({
node,
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.`
})
}
})
}
}
}
const {
categories,
skipDynamicArguments,
Expand Down
93 changes: 93 additions & 0 deletions tests/lib/rules/no-loss-of-precision.js
@@ -0,0 +1,93 @@
/**
* @author Yosuke Ota
* See LICENSE file in root directory for full license.
*/
'use strict'

const { RuleTester, ESLint } = require('../../eslint-compat')
const semver = require('semver')
const rule = require('../../../lib/rules/no-loss-of-precision')

const tester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module'
}
})
tester.run('no-loss-of-precision', rule, {
valid: [
...(semver.gte(ESLint.version, '7.1.0')
? [
{
filename: 'test.vue',
code: `
<template>
{{12345}}
{{123.45}}
</template>
`
},
{
filename: 'test.vue',
code: `
<template>
<MyComponent num="12345678901234567890" />
</template>
`
}
]
: [])
],
invalid: [
...(semver.gte(ESLint.version, '7.1.0')
? [
{
filename: 'test.vue',
code: `
<template>
{{12345678901234567890}}
{{0.12345678901234567890}}
</template>
`,
errors: [
{
message: 'This number literal will lose precision at runtime.',
line: 3
},
{
message: 'This number literal will lose precision at runtime.',
line: 4
}
]
},
{
filename: 'test.vue',
code: `
<template>
<MyComponent :num="12345678901234567890" />
</template>
`,
errors: [
{
message: 'This number literal will lose precision at runtime.',
line: 3
}
]
}
]
: [
{
filename: 'test.vue',
code: `
<template>
<MyComponent :num="12345678901234567890" />
</template>
`,
errors: [
'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.'
]
}
])
]
})
41 changes: 41 additions & 0 deletions tests/lib/utils/core-rules/wrap-core-rule.js
@@ -0,0 +1,41 @@
'use strict'

const RuleTester = require('eslint').RuleTester
const utils = require('../../../../lib/utils/index')

const rule = utils.wrapCoreRule('foo')

const tester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module'
}
})

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

tester.run('wrap-core-rule-with-unknown', rule, {
valid: [
{
filename: 'test.js',
code: `var a`
}
],
invalid: [
{
filename: 'test.vue',
code: `<template></template>`,
errors: [
{
message:
'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.',
line: 1,
column: 1
}
]
}
]
})

0 comments on commit 4ade913

Please sign in to comment.