Skip to content

Commit

Permalink
Update rule macro order for custom macros
Browse files Browse the repository at this point in the history
See #2499
  • Loading branch information
Ericlm committed Jul 8, 2024
1 parent f5cb93d commit 1038e01
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 8 deletions.
39 changes: 36 additions & 3 deletions docs/rules/define-macros-order.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ 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
22 changes: 17 additions & 5 deletions lib/rules/define-macros-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ const MACROS_PROPS = 'defineProps'
const MACROS_OPTIONS = 'defineOptions'
const MACROS_SLOTS = 'defineSlots'
const MACROS_MODEL = 'defineModel'
const ORDER_SCHEMA = [
const ORDER_SCHEMA = new Set([
MACROS_EMITS,
MACROS_PROPS,
MACROS_OPTIONS,
MACROS_SLOTS,
MACROS_MODEL
]
])
const DEFAULT_ORDER = [MACROS_PROPS, MACROS_EMITS]

/**
Expand Down Expand Up @@ -130,6 +130,18 @@ function create(context) {
},
onDefineExposeExit(node) {
defineExposeNode = getDefineMacrosStatement(node)
},

'CallExpression:exit'(node) {
// check if the node is a macro in the order
if (
node.callee &&
node.callee.type === 'Identifier' &&
order.includes(node.callee.name) &&
!ORDER_SCHEMA.has(node.callee.name)
) {
macrosNodes.set(node.callee.name, [getDefineMacrosStatement(node)])
}
}
}),
{
Expand Down Expand Up @@ -345,9 +357,9 @@ module.exports = {
properties: {
order: {
type: 'array',
items: {
enum: ORDER_SCHEMA
},
// items: {
// enum: ORDER_SCHEMA
// },
uniqueItems: true,
additionalItems: false
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"start": "npm run test:base -- --watch --growl",
"test:base": "mocha \"tests/lib/**/*.js\" --reporter dot",
"test": "nyc npm run test:base -- \"tests/integrations/*.js\" --timeout 60000",
"test:define-macros-order": "mocha \"tests/lib/rules/define-macros-order.js\" --timeout 60000",
"test:integrations": "mocha \"tests/integrations/*.js\" --timeout 60000",
"debug": "mocha --inspect \"tests/lib/**/*.js\" --reporter dot --timeout 60000",
"cover": "npm run cover:test && npm run cover:report",
Expand Down
205 changes: 205 additions & 0 deletions tests/lib/rules/define-macros-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,25 @@ tester.run('define-macros-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script setup>
import Foo from 'foo'
/** Page */
definePage()
/** model */
const model = defineModel()
/** emits */
defineEmits(['update:foo'])
</script>
`,
options: [
{
order: ['definePage', 'defineModel', 'defineEmits']
}
]
},
{
filename: 'test.vue',
code: `
Expand Down Expand Up @@ -254,6 +273,22 @@ tester.run('define-macros-order', rule, {
order: ['defineModel', 'defineSlots']
}
]
},
{
filename: 'test.vue',
code: `
<script setup>
const page = definePage()
const first = defineModel('first')
const second = defineModel('second')
</script>
`,
options: [
{
order: ['definePage', 'defineModel']
}
]
}
],
invalid: [
Expand Down Expand Up @@ -382,6 +417,40 @@ tester.run('define-macros-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script setup>
console.log('test1')
const props = defineProps({
test: Boolean
})
console.log('test2')
const page = definePage({
name: 'hello'
})
</script>
`,
output: `
<script setup>
const page = definePage({
name: 'hello'
})
const props = defineProps({
test: Boolean
})
console.log('test1')
console.log('test2')
</script>
`,
options: [{ order: ['definePage', 'defineProps'] }],
errors: [
{
message: message('definePage'),
line: 8
}
]
},
{
filename: 'test.vue',
code: `
Expand Down Expand Up @@ -425,6 +494,61 @@ tester.run('define-macros-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script lang="ts" setup>
interface Props {
msg?: string
labels?: string[]
}
const props = defineProps<{
msg?: string
labels?: string[]
}>()
defineCustom()
const emit = defineEmits<{(e: 'update:test'): void}>()
const page = definePage({
name: 'hello'
})
</script>
`,
output: `
<script lang="ts" setup>
interface Props {
msg?: string
labels?: string[]
}
const page = definePage({
name: 'hello'
})
defineCustom()
const props = defineProps<{
msg?: string
labels?: string[]
}>()
const emit = defineEmits<{(e: 'update:test'): void}>()
</script>
`,
options: [
{ order: ['definePage', 'defineCustom', 'defineProps', 'defineEmits'] }
],
languageOptions: {
parserOptions: {
parser: require.resolve('@typescript-eslint/parser')
}
},
errors: [
{
message: message('definePage'),
line: 15
}
]
},
{
filename: 'test.vue',
code: `
Expand Down Expand Up @@ -537,6 +661,25 @@ tester.run('define-macros-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script setup>
const props = defineProps({ test: Boolean });definePage({name: 'hello'})
</script>
`,
output: `
<script setup>
definePage({name: 'hello'});const props = defineProps({ test: Boolean }); </script>
`,
options: [{ order: ['definePage', 'defineProps'] }],
errors: [
{
message: message('definePage'),
line: 3
}
]
},
{
filename: 'test.vue',
code: `
Expand Down Expand Up @@ -633,6 +776,30 @@ tester.run('define-macros-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script setup>
definePage({name: 'hello'})
console.log('test1')
defineCustom({ test: Boolean })
</script>
`,
output: `
<script setup>
defineCustom({ test: Boolean })
definePage({name: 'hello'})
console.log('test1')
</script>
`,
options: [{ order: ['defineCustom', 'definePage'] }],
errors: [
{
message: message('defineCustom'),
line: 5
}
]
},
{
filename: 'test.vue',
code: `
Expand Down Expand Up @@ -895,6 +1062,44 @@ tester.run('define-macros-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script setup>
defineOptions({})
defineCustom('second')
const something = defineSomething('first')
definePage()
const model = defineModel('second')
</script>
`,
output: `
<script setup>
const something = defineSomething('first')
defineCustom('second')
const model = defineModel('second')
defineOptions({})
definePage()
</script>
`,
options: [
{
order: [
'defineSomething',
'defineCustom',
'defineModel',
'defineOptions',
'definePage'
]
}
],
errors: [
{
message: message('defineSomething'),
line: 5
}
]
},
{
filename: 'test.vue',
code: `
Expand Down

0 comments on commit 1038e01

Please sign in to comment.