Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vue/no-loss-of-precision rule #1680

Merged
merged 1 commit into from Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -380,6 +380,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
}
]
}
]
})