Skip to content

Commit 6ebd607

Browse files
EriclmFloEdelmann
andauthored
Update rule define-macros-order for custom macros (#2501)
Co-authored-by: Flo Edelmann <[email protected]>
1 parent 0fbe35e commit 6ebd607

File tree

4 files changed

+335
-10
lines changed

4 files changed

+335
-10
lines changed

Diff for: docs/rules/define-macros-order.md

+37-4
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
pageClass: rule-details
33
sidebarDepth: 0
44
title: vue/define-macros-order
5-
description: enforce order of `defineEmits` and `defineProps` compiler macros
5+
description: enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)
66
since: v8.7.0
77
---
88

99
# vue/define-macros-order
1010

11-
> enforce order of `defineEmits` and `defineProps` compiler macros
11+
> enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)
1212
1313
- :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.
1414
- :bulb: Some problems reported by this rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
1515

1616
## :book: Rule Details
1717

18-
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.
18+
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.
1919

2020
## :wrench: Options
2121

@@ -28,7 +28,7 @@ This rule reports the `defineProps` and `defineEmits` compiler macros when they
2828
}
2929
```
3030

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

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

119119
</eslint-code-block>
120120

121+
### `{ "order": ["definePage", "defineModel", "defineCustom", "defineEmits", "defineSlots"] }`
122+
123+
<eslint-code-block fix :rules="{'vue/define-macros-order': ['error', {order: ['definePage', 'defineModel', 'defineCustom', 'defineEmits', 'defineSlots']}]}">
124+
125+
```vue
126+
<!-- ✓ GOOD -->
127+
<script setup>
128+
definePage()
129+
const model = defineModel()
130+
defineCustom()
131+
defineEmits(/* ... */)
132+
const slots = defineSlots()
133+
</script>
134+
```
135+
136+
</eslint-code-block>
137+
138+
<eslint-code-block fix :rules="{'vue/define-macros-order': ['error', {order: ['definePage', 'defineModel', 'defineCustom', 'defineEmits', 'defineSlots']}]}">
139+
140+
```vue
141+
<!-- ✗ BAD -->
142+
<script setup>
143+
defineEmits(/* ... */)
144+
const slots = defineSlots()
145+
defineProps(/* ... */)
146+
defineCustom({/* ... */})
147+
const model = defineModel()
148+
definePage()
149+
</script>
150+
```
151+
152+
</eslint-code-block>
153+
121154
### `{ "defineExposeLast": true }`
122155

123156
<eslint-code-block fix :rules="{'vue/define-macros-order': ['error', {defineExposeLast: true}]}">

Diff for: docs/rules/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ For example:
213213
| [vue/component-options-name-casing](./component-options-name-casing.md) | enforce the casing of component name in `components` options | :wrench::bulb: | :hammer: |
214214
| [vue/custom-event-name-casing](./custom-event-name-casing.md) | enforce specific casing for custom event name | | :hammer: |
215215
| [vue/define-emits-declaration](./define-emits-declaration.md) | enforce declaration style of `defineEmits` | | :hammer: |
216-
| [vue/define-macros-order](./define-macros-order.md) | enforce order of `defineEmits` and `defineProps` compiler macros | :wrench::bulb: | :lipstick: |
216+
| [vue/define-macros-order](./define-macros-order.md) | enforce order of compiler macros (`defineProps`, `defineEmits`, etc.) | :wrench::bulb: | :lipstick: |
217217
| [vue/define-props-declaration](./define-props-declaration.md) | enforce declaration style of `defineProps` | | :hammer: |
218218
| [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: |
219219
| [vue/html-button-has-type](./html-button-has-type.md) | disallow usage of button without an explicit type attribute | | :hammer: |

Diff for: lib/rules/define-macros-order.js

+28-5
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ const MACROS_PROPS = 'defineProps'
1111
const MACROS_OPTIONS = 'defineOptions'
1212
const MACROS_SLOTS = 'defineSlots'
1313
const MACROS_MODEL = 'defineModel'
14-
const ORDER_SCHEMA = [
14+
const MACROS_EXPOSE = 'defineExpose'
15+
const KNOWN_MACROS = new Set([
1516
MACROS_EMITS,
1617
MACROS_PROPS,
1718
MACROS_OPTIONS,
1819
MACROS_SLOTS,
19-
MACROS_MODEL
20-
]
20+
MACROS_MODEL,
21+
MACROS_EXPOSE
22+
])
2123
const DEFAULT_ORDER = [MACROS_PROPS, MACROS_EMITS]
2224

2325
/**
@@ -109,6 +111,12 @@ function create(context) {
109111
/** @type {ASTNode} */
110112
let defineExposeNode
111113

114+
if (order.includes(MACROS_EXPOSE) && defineExposeLast) {
115+
throw new Error(
116+
"`defineExpose` macro can't be in the `order` array if `defineExposeLast` is true."
117+
)
118+
}
119+
112120
return utils.compositingVisitors(
113121
utils.defineScriptSetupVisitor(context, {
114122
onDefinePropsExit(node) {
@@ -130,6 +138,20 @@ function create(context) {
130138
},
131139
onDefineExposeExit(node) {
132140
defineExposeNode = getDefineMacrosStatement(node)
141+
},
142+
143+
/** @param {CallExpression} node */
144+
'Program > ExpressionStatement > CallExpression, Program > VariableDeclaration > VariableDeclarator > CallExpression'(
145+
node
146+
) {
147+
if (
148+
node.callee &&
149+
node.callee.type === 'Identifier' &&
150+
order.includes(node.callee.name) &&
151+
!KNOWN_MACROS.has(node.callee.name)
152+
) {
153+
macrosNodes.set(node.callee.name, [getDefineMacrosStatement(node)])
154+
}
133155
}
134156
}),
135157
{
@@ -333,7 +355,7 @@ module.exports = {
333355
type: 'layout',
334356
docs: {
335357
description:
336-
'enforce order of `defineEmits` and `defineProps` compiler macros',
358+
'enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)',
337359
categories: undefined,
338360
url: 'https://eslint.vuejs.org/rules/define-macros-order.html'
339361
},
@@ -346,7 +368,8 @@ module.exports = {
346368
order: {
347369
type: 'array',
348370
items: {
349-
enum: ORDER_SCHEMA
371+
type: 'string',
372+
minLength: 1
350373
},
351374
uniqueItems: true,
352375
additionalItems: false

0 commit comments

Comments
 (0)