From df0a5ee0629fbb394ff62bcab99a402cf8ef9eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Mon, 8 Jul 2024 20:10:46 +0200 Subject: [PATCH 1/9] Update rule macro order for custom macros See #2499 --- docs/rules/define-macros-order.md | 39 ++++- lib/rules/define-macros-order.js | 22 ++- package.json | 1 + tests/lib/rules/define-macros-order.js | 205 +++++++++++++++++++++++++ 4 files changed, 259 insertions(+), 8 deletions(-) diff --git a/docs/rules/define-macros-order.md b/docs/rules/define-macros-order.md index 5d8dda56c..a688b1633 100644 --- a/docs/rules/define-macros-order.md +++ b/docs/rules/define-macros-order.md @@ -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 ` +``` + + + + + +```vue + + +``` + + + ### `{ "defineExposeLast": true }` diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index f24c58af7..02b467788 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -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] /** @@ -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)]) + } } }), { @@ -345,9 +357,9 @@ module.exports = { properties: { order: { type: 'array', - items: { - enum: ORDER_SCHEMA - }, + // items: { + // enum: ORDER_SCHEMA + // }, uniqueItems: true, additionalItems: false }, diff --git a/package.json b/package.json index 4816e225f..1f9737e4a 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/tests/lib/rules/define-macros-order.js b/tests/lib/rules/define-macros-order.js index 3aa2e434d..af40b130f 100644 --- a/tests/lib/rules/define-macros-order.js +++ b/tests/lib/rules/define-macros-order.js @@ -195,6 +195,25 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + options: [ + { + order: ['definePage', 'defineModel', 'defineEmits'] + } + ] + }, { filename: 'test.vue', code: ` @@ -254,6 +273,22 @@ tester.run('define-macros-order', rule, { order: ['defineModel', 'defineSlots'] } ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [ + { + order: ['definePage', 'defineModel'] + } + ] } ], invalid: [ @@ -382,6 +417,40 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + options: [{ order: ['definePage', 'defineProps'] }], + errors: [ + { + message: message('definePage'), + line: 8 + } + ] + }, { filename: 'test.vue', code: ` @@ -425,6 +494,61 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + options: [ + { order: ['definePage', 'defineCustom', 'defineProps', 'defineEmits'] } + ], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: message('definePage'), + line: 15 + } + ] + }, { filename: 'test.vue', code: ` @@ -537,6 +661,25 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + options: [{ order: ['definePage', 'defineProps'] }], + errors: [ + { + message: message('definePage'), + line: 3 + } + ] + }, { filename: 'test.vue', code: ` @@ -633,6 +776,30 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + options: [{ order: ['defineCustom', 'definePage'] }], + errors: [ + { + message: message('defineCustom'), + line: 5 + } + ] + }, { filename: 'test.vue', code: ` @@ -895,6 +1062,44 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + options: [ + { + order: [ + 'defineSomething', + 'defineCustom', + 'defineModel', + 'defineOptions', + 'definePage' + ] + } + ], + errors: [ + { + message: message('defineSomething'), + line: 5 + } + ] + }, { filename: 'test.vue', code: ` From 7f09e63d292f1c592e1b7e6b79ad5100153776fd Mon Sep 17 00:00:00 2001 From: Flo Edelmann Date: Tue, 9 Jul 2024 14:24:50 +0200 Subject: [PATCH 2/9] Discard changes to package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 1f9737e4a..4816e225f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "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", From e92efa93070e8adfef704befcd93bbf1a042ca1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Tue, 9 Jul 2024 14:29:29 +0200 Subject: [PATCH 3/9] Update lib/rules/define-macros-order.js Changing items accepted by the rule. Co-authored-by: Flo Edelmann --- lib/rules/define-macros-order.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index 02b467788..278009f85 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -357,9 +357,10 @@ module.exports = { properties: { order: { type: 'array', - // items: { - // enum: ORDER_SCHEMA - // }, + items: { + type: string, + minLength: 1 + }, uniqueItems: true, additionalItems: false }, From 03e642588eb9f5460787fe9ba2bb6e5ce85c715d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Tue, 9 Jul 2024 14:32:44 +0200 Subject: [PATCH 4/9] Update tests/lib/rules/define-macros-order.js Tests formatting Co-authored-by: Flo Edelmann --- tests/lib/rules/define-macros-order.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/rules/define-macros-order.js b/tests/lib/rules/define-macros-order.js index af40b130f..31f141658 100644 --- a/tests/lib/rules/define-macros-order.js +++ b/tests/lib/rules/define-macros-order.js @@ -281,7 +281,7 @@ tester.run('define-macros-order', rule, { const page = definePage() const first = defineModel('first') - const second = defineModel('second') + const second = defineModel('second') `, options: [ From cb4169c1bde278325d9607733d708cb1d4ac4ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Tue, 9 Jul 2024 14:42:18 +0200 Subject: [PATCH 5/9] Documentation and add expose macro --- lib/rules/define-macros-order.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index 278009f85..e0f58d564 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -11,12 +11,14 @@ const MACROS_PROPS = 'defineProps' const MACROS_OPTIONS = 'defineOptions' const MACROS_SLOTS = 'defineSlots' const MACROS_MODEL = 'defineModel' -const ORDER_SCHEMA = new Set([ +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] @@ -133,12 +135,11 @@ function create(context) { }, '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) + !KNOWN_MACROS.has(node.callee.name) ) { macrosNodes.set(node.callee.name, [getDefineMacrosStatement(node)]) } @@ -344,8 +345,7 @@ module.exports = { meta: { type: 'layout', docs: { - description: - 'enforce order of `defineEmits` and `defineProps` compiler macros', + description: 'enforce order of specified compiler macros.', categories: undefined, url: 'https://eslint.vuejs.org/rules/define-macros-order.html' }, @@ -358,8 +358,8 @@ module.exports = { order: { type: 'array', items: { - type: string, - minLength: 1 + type: 'string', + minLength: 1 }, uniqueItems: true, additionalItems: false From b5aa691e3f81d6954ee1a30cf828d54d2ee83671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Tue, 9 Jul 2024 14:51:59 +0200 Subject: [PATCH 6/9] Rule documentation --- lib/rules/define-macros-order.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index e0f58d564..23738e66b 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -345,7 +345,8 @@ module.exports = { meta: { type: 'layout', docs: { - description: 'enforce order of specified compiler macros.', + description: + 'enforce order of compiler macros (`defineProps`, `defineEmits`, etc.)', categories: undefined, url: 'https://eslint.vuejs.org/rules/define-macros-order.html' }, From c8a57e84689f5edbc671d0173123cc8e563fc22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Tue, 9 Jul 2024 15:16:41 +0200 Subject: [PATCH 7/9] Fix expose macro in order with defineExposeLast --- lib/rules/define-macros-order.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index 23738e66b..ef398b340 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -111,6 +111,12 @@ function create(context) { /** @type {ASTNode} */ let defineExposeNode + if (order.includes(MACROS_EXPOSE) && defineExposeLast) { + throw new Error( + 'defineExposeLast cannot be used if defineExpose macro is in order array.' + ) + } + return utils.compositingVisitors( utils.defineScriptSetupVisitor(context, { onDefinePropsExit(node) { From c7315748d7c20f955e19b9cc4f4064d3e3f91e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Tue, 9 Jul 2024 15:49:42 +0200 Subject: [PATCH 8/9] Documentation and error message --- docs/rules/define-macros-order.md | 4 ++-- docs/rules/index.md | 2 +- lib/rules/define-macros-order.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/rules/define-macros-order.md b/docs/rules/define-macros-order.md index a688b1633..6dbe5ef07 100644 --- a/docs/rules/define-macros-order.md +++ b/docs/rules/define-macros-order.md @@ -2,13 +2,13 @@ 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 compiler macros (`defineProps`, `defineEmits`, etc.) +> 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). diff --git a/docs/rules/index.md b/docs/rules/index.md index 113ff416b..16a195125 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -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: | diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index ef398b340..8c5cf7070 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -113,7 +113,7 @@ function create(context) { if (order.includes(MACROS_EXPOSE) && defineExposeLast) { throw new Error( - 'defineExposeLast cannot be used if defineExpose macro is in order array.' + "`defineExpose` macro can't be in the `order` array if `defineExposeLast` is true." ) } From 4630eddc4b187b2602b5ce630dbd15e9bfa60920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Le=20Ma=C3=AEtre?= Date: Fri, 19 Jul 2024 08:04:07 +0200 Subject: [PATCH 9/9] Precise macro statement It does not look for any "CallExpression" but for more specific contexts that target macros. --- lib/rules/define-macros-order.js | 5 +- tests/lib/rules/define-macros-order.js | 64 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/lib/rules/define-macros-order.js b/lib/rules/define-macros-order.js index 8c5cf7070..920b5c294 100644 --- a/lib/rules/define-macros-order.js +++ b/lib/rules/define-macros-order.js @@ -140,7 +140,10 @@ function create(context) { defineExposeNode = getDefineMacrosStatement(node) }, - 'CallExpression:exit'(node) { + /** @param {CallExpression} node */ + 'Program > ExpressionStatement > CallExpression, Program > VariableDeclaration > VariableDeclarator > CallExpression'( + node + ) { if ( node.callee && node.callee.type === 'Identifier' && diff --git a/tests/lib/rules/define-macros-order.js b/tests/lib/rules/define-macros-order.js index 31f141658..72b359866 100644 --- a/tests/lib/rules/define-macros-order.js +++ b/tests/lib/rules/define-macros-order.js @@ -214,6 +214,46 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + options: [ + { + order: ['definePage', 'defineModel', 'defineEmits'] + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [ + { + order: ['definePage', 'defineModel', 'defineEmits'] + } + ] + }, { filename: 'test.vue', code: ` @@ -800,6 +840,30 @@ tester.run('define-macros-order', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + options: [{ order: ['defineCustom', 'definePage'] }], + errors: [ + { + message: message('defineCustom'), + line: 5 + } + ] + }, { filename: 'test.vue', code: `