Skip to content

Commit

Permalink
Update rule define-macros-order for custom macros (#2501)
Browse files Browse the repository at this point in the history
Co-authored-by: Flo Edelmann <[email protected]>
  • Loading branch information
Ericlm and FloEdelmann committed Sep 2, 2024
1 parent 0fbe35e commit 6ebd607
Show file tree
Hide file tree
Showing 4 changed files with 335 additions and 10 deletions.
41 changes: 37 additions & 4 deletions docs/rules/define-macros-order.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
pageClass: rule-details
sidebarDepth: 0
title: vue/define-macros-order
description: enforce order of `defineEmits` and `defineProps` compiler macros
description: enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)
since: v8.7.0
---

# vue/define-macros-order

> enforce order of `defineEmits` and `defineProps` compiler macros
> enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)
- :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

This rule reports the `defineProps` and `defineEmits` compiler macros when they are not the first statements in `<script setup>` (after any potential import statements or type definitions) or when they are not in the correct order.
This rule reports compiler macros (like `defineProps` or `defineEmits` but also custom ones) when they are not the first statements in `<script setup>` (after any potential import statements or type definitions) or when they are not in the correct order.

## :wrench: Options

Expand All @@ -28,7 +28,7 @@ This rule reports the `defineProps` and `defineEmits` compiler macros when they
}
```

- `order` (`string[]`) ... The order of defineEmits and defineProps macros. You can also add `"defineOptions"`, `"defineSlots"`, and `"defineModel"`.
- `order` (`string[]`) ... The order in which the macros should appear. The default is `["defineProps", "defineEmits"]`.
- `defineExposeLast` (`boolean`) ... Force `defineExpose` at the end.

### `{ "order": ["defineProps", "defineEmits"] }` (default)
Expand Down Expand Up @@ -118,6 +118,39 @@ const slots = defineSlots()

</eslint-code-block>

### `{ "order": ["definePage", "defineModel", "defineCustom", "defineEmits", "defineSlots"] }`

<eslint-code-block fix :rules="{'vue/define-macros-order': ['error', {order: ['definePage', 'defineModel', 'defineCustom', 'defineEmits', 'defineSlots']}]}">

```vue
<!-- ✓ GOOD -->
<script setup>
definePage()
const model = defineModel()
defineCustom()
defineEmits(/* ... */)
const slots = defineSlots()
</script>
```

</eslint-code-block>

<eslint-code-block fix :rules="{'vue/define-macros-order': ['error', {order: ['definePage', 'defineModel', 'defineCustom', 'defineEmits', 'defineSlots']}]}">

```vue
<!-- ✗ BAD -->
<script setup>
defineEmits(/* ... */)
const slots = defineSlots()
defineProps(/* ... */)
defineCustom({/* ... */})
const model = defineModel()
definePage()
</script>
```

</eslint-code-block>

### `{ "defineExposeLast": true }`

<eslint-code-block fix :rules="{'vue/define-macros-order': ['error', {defineExposeLast: true}]}">
Expand Down
2 changes: 1 addition & 1 deletion docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ For example:
| [vue/component-options-name-casing](./component-options-name-casing.md) | enforce the casing of component name in `components` options | :wrench::bulb: | :hammer: |
| [vue/custom-event-name-casing](./custom-event-name-casing.md) | enforce specific casing for custom event name | | :hammer: |
| [vue/define-emits-declaration](./define-emits-declaration.md) | enforce declaration style of `defineEmits` | | :hammer: |
| [vue/define-macros-order](./define-macros-order.md) | enforce order of `defineEmits` and `defineProps` compiler macros | :wrench::bulb: | :lipstick: |
| [vue/define-macros-order](./define-macros-order.md) | enforce order of compiler macros (`defineProps`, `defineEmits`, etc.) | :wrench::bulb: | :lipstick: |
| [vue/define-props-declaration](./define-props-declaration.md) | enforce declaration style of `defineProps` | | :hammer: |
| [vue/enforce-style-attribute](./enforce-style-attribute.md) | enforce or forbid the use of the `scoped` and `module` attributes in SFC top level style tags | | :hammer: |
| [vue/html-button-has-type](./html-button-has-type.md) | disallow usage of button without an explicit type attribute | | :hammer: |
Expand Down
33 changes: 28 additions & 5 deletions lib/rules/define-macros-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ const MACROS_PROPS = 'defineProps'
const MACROS_OPTIONS = 'defineOptions'
const MACROS_SLOTS = 'defineSlots'
const MACROS_MODEL = 'defineModel'
const ORDER_SCHEMA = [
const MACROS_EXPOSE = 'defineExpose'
const KNOWN_MACROS = new Set([
MACROS_EMITS,
MACROS_PROPS,
MACROS_OPTIONS,
MACROS_SLOTS,
MACROS_MODEL
]
MACROS_MODEL,
MACROS_EXPOSE
])
const DEFAULT_ORDER = [MACROS_PROPS, MACROS_EMITS]

/**
Expand Down Expand Up @@ -109,6 +111,12 @@ function create(context) {
/** @type {ASTNode} */
let defineExposeNode

if (order.includes(MACROS_EXPOSE) && defineExposeLast) {
throw new Error(
"`defineExpose` macro can't be in the `order` array if `defineExposeLast` is true."
)
}

return utils.compositingVisitors(
utils.defineScriptSetupVisitor(context, {
onDefinePropsExit(node) {
Expand All @@ -130,6 +138,20 @@ function create(context) {
},
onDefineExposeExit(node) {
defineExposeNode = getDefineMacrosStatement(node)
},

/** @param {CallExpression} node */
'Program > ExpressionStatement > CallExpression, Program > VariableDeclaration > VariableDeclarator > CallExpression'(
node
) {
if (
node.callee &&
node.callee.type === 'Identifier' &&
order.includes(node.callee.name) &&
!KNOWN_MACROS.has(node.callee.name)
) {
macrosNodes.set(node.callee.name, [getDefineMacrosStatement(node)])
}
}
}),
{
Expand Down Expand Up @@ -333,7 +355,7 @@ module.exports = {
type: 'layout',
docs: {
description:
'enforce order of `defineEmits` and `defineProps` compiler macros',
'enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)',
categories: undefined,
url: 'https://eslint.vuejs.org/rules/define-macros-order.html'
},
Expand All @@ -346,7 +368,8 @@ module.exports = {
order: {
type: 'array',
items: {
enum: ORDER_SCHEMA
type: 'string',
minLength: 1
},
uniqueItems: true,
additionalItems: false
Expand Down
Loading

0 comments on commit 6ebd607

Please sign in to comment.