Skip to content

Commit

Permalink
feat(order-in-components): add side effects suggestions (#2423)
Browse files Browse the repository at this point in the history
  • Loading branch information
waynzh committed Mar 11, 2024
1 parent 3abc04c commit e2dc84b
Show file tree
Hide file tree
Showing 4 changed files with 295 additions and 53 deletions.
2 changes: 1 addition & 1 deletion docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ Rules in this category are enabled for all presets provided by eslint-plugin-vue
| [vue/no-lone-template](./no-lone-template.md) | disallow unnecessary `<template>` | | :three::two::warning: |
| [vue/no-multiple-slot-args](./no-multiple-slot-args.md) | disallow to pass multiple arguments to scoped slots | | :three::two::warning: |
| [vue/no-v-html](./no-v-html.md) | disallow use of v-html to prevent XSS attack | | :three::two::hammer: |
| [vue/order-in-components](./order-in-components.md) | enforce order of properties in components | :wrench: | :three::two::hammer: |
| [vue/order-in-components](./order-in-components.md) | enforce order of properties in components | :wrench::bulb: | :three::two::hammer: |
| [vue/this-in-template](./this-in-template.md) | disallow usage of `this` in template | :wrench: | :three::two::hammer: |

</rules-table>
Expand Down
1 change: 1 addition & 0 deletions docs/rules/order-in-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ since: v3.2.0
- :gear: This rule is included in `"plugin:vue/vue3-recommended"` and `"plugin:vue/recommended"`.
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
- :bulb: Some problems reported by this rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).

## :book: Rule Details

Expand Down
97 changes: 58 additions & 39 deletions lib/rules/order-in-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ module.exports = {
url: 'https://eslint.vuejs.org/rules/order-in-components.html'
},
fixable: 'code', // null or "code" or "whitespace"
hasSuggestions: true,
schema: [
{
type: 'object',
Expand All @@ -231,7 +232,9 @@ module.exports = {
],
messages: {
order:
'The "{{name}}" property should be above the "{{firstUnorderedPropertyName}}" property on line {{line}}.'
'The "{{name}}" property should be above the "{{firstUnorderedPropertyName}}" property on line {{line}}.',
reorderWithSideEffects:
'Manually move "{{name}}" property above "{{firstUnorderedPropertyName}}" property on line {{line}} (might break side effects).'
}
},
/** @param {RuleContext} context */
Expand All @@ -255,6 +258,30 @@ module.exports = {
return num == null ? -1 : num
}

/**
* @param {Property} propertyNode
* @param {Property} unorderedPropertyNode
*/
function* handleFix(fixer, propertyNode, unorderedPropertyNode) {
const afterComma = sourceCode.getTokenAfter(propertyNode)
const hasAfterComma = isComma(afterComma)

const beforeComma = sourceCode.getTokenBefore(propertyNode)
const codeStart = beforeComma.range[1] // to include comments
const codeEnd = hasAfterComma
? afterComma.range[1]
: propertyNode.range[1]

const removeStart = hasAfterComma ? codeStart : beforeComma.range[0]
yield fixer.removeRange([removeStart, codeEnd])

const propertyCode =
sourceCode.text.slice(codeStart, codeEnd) + (hasAfterComma ? '' : ',')
const insertTarget = sourceCode.getTokenBefore(unorderedPropertyNode)

yield fixer.insertTextAfter(insertTarget, propertyCode)
}

/**
* @param {(Property | SpreadElement)[]} propertiesNodes
*/
Expand Down Expand Up @@ -287,6 +314,18 @@ module.exports = {

if (firstUnorderedProperty) {
const line = firstUnorderedProperty.node.loc.start.line
const propertyNode = property.node
const firstUnorderedPropertyNode = firstUnorderedProperty.node
const hasSideEffectsPossibility = propertiesNodes
.slice(
propertiesNodes.indexOf(firstUnorderedPropertyNode),
propertiesNodes.indexOf(propertyNode) + 1
)
.some(
(property) =>
!isNotSideEffectsNode(property, sourceCode.visitorKeys)
)

context.report({
node: property.node,
messageId: 'order',
Expand All @@ -295,44 +334,24 @@ module.exports = {
firstUnorderedPropertyName: firstUnorderedProperty.name,
line
},
*fix(fixer) {
const propertyNode = property.node
const firstUnorderedPropertyNode = firstUnorderedProperty.node
const hasSideEffectsPossibility = propertiesNodes
.slice(
propertiesNodes.indexOf(firstUnorderedPropertyNode),
propertiesNodes.indexOf(propertyNode) + 1
)
.some(
(property) =>
!isNotSideEffectsNode(property, sourceCode.visitorKeys)
)
if (hasSideEffectsPossibility) {
return
}
const afterComma = sourceCode.getTokenAfter(propertyNode)
const hasAfterComma = isComma(afterComma)

const beforeComma = sourceCode.getTokenBefore(propertyNode)
const codeStart = beforeComma.range[1] // to include comments
const codeEnd = hasAfterComma
? afterComma.range[1]
: propertyNode.range[1]

const removeStart = hasAfterComma
? codeStart
: beforeComma.range[0]
yield fixer.removeRange([removeStart, codeEnd])

const propertyCode =
sourceCode.text.slice(codeStart, codeEnd) +
(hasAfterComma ? '' : ',')
const insertTarget = sourceCode.getTokenBefore(
firstUnorderedPropertyNode
)

yield fixer.insertTextAfter(insertTarget, propertyCode)
}
fix: hasSideEffectsPossibility
? undefined
: (fixer) =>
handleFix(fixer, propertyNode, firstUnorderedPropertyNode),
suggest: hasSideEffectsPossibility
? [
{
messageId: 'reorderWithSideEffects',
data: {
name: property.name,
firstUnorderedPropertyName: firstUnorderedProperty.name,
line
},
fix: (fixer) =>
handleFix(fixer, propertyNode, firstUnorderedPropertyNode)
}
]
: undefined
})
}
}
Expand Down
Loading

0 comments on commit e2dc84b

Please sign in to comment.