From c4b20cac194301393f2a53f14639e5624e481681 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 5 Sep 2022 21:08:52 +0200 Subject: [PATCH 01/25] add rule template --- docs/rules/force-types-on-object-props.md | 30 ++++++++++++ lib/rules/force-types-on-object-props.js | 45 ++++++++++++++++++ .../lib/rules/force-types-on-object-props.js | 46 +++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 docs/rules/force-types-on-object-props.md create mode 100644 lib/rules/force-types-on-object-props.js create mode 100644 tests/lib/rules/force-types-on-object-props.js diff --git a/docs/rules/force-types-on-object-props.md b/docs/rules/force-types-on-object-props.md new file mode 100644 index 000000000..70497daa1 --- /dev/null +++ b/docs/rules/force-types-on-object-props.md @@ -0,0 +1,30 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/force-types-on-object-props +description: xxx +--- +# vue/force-types-on-object-props + +> xxx + +- :exclamation: ***This rule has not been released yet.*** + +## :book: Rule Details + +This rule .... + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + diff --git a/lib/rules/force-types-on-object-props.js b/lib/rules/force-types-on-object-props.js new file mode 100644 index 000000000..fb737487e --- /dev/null +++ b/lib/rules/force-types-on-object-props.js @@ -0,0 +1,45 @@ +/** + * @author *****your name***** + * See LICENSE file in root directory for full license. + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Helpers +// ------------------------------------------------------------------------------ + +// ... + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: '', + categories: undefined, + url: '' + }, + fixable: null, + schema: [], + messages: { + // ... + } + }, + /** @param {RuleContext} context */ + create(context) { + // ... + + return utils.defineTemplateBodyVisitor(context, { + // ... + }) + } +} diff --git a/tests/lib/rules/force-types-on-object-props.js b/tests/lib/rules/force-types-on-object-props.js new file mode 100644 index 000000000..b069eab37 --- /dev/null +++ b/tests/lib/rules/force-types-on-object-props.js @@ -0,0 +1,46 @@ +/** + * @author *****your name***** + * See LICENSE file in root directory for full license. + */ +'use strict' + +const RuleTester = require('eslint').RuleTester +const rule = require('../../../lib/rules/force-types-on-object-props') + +const tester = new RuleTester({ + parser: require.resolve('vue-eslint-parser'), + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module' + } +}) + +tester.run('force-types-on-object-props', rule, { + valid: [ + { + filename: 'test.vue', + code: ` + + ` + }, + ], + invalid: [ + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: '...', + line: 'line', + column: 'col' + }, + ] + } + ] +}) From 49d0f30d741c4a8f8591e0c6ad839c57462ebac5 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 5 Sep 2022 21:22:38 +0200 Subject: [PATCH 02/25] prepare documentation --- docs/rules/force-types-on-object-props.md | 73 +++++++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/docs/rules/force-types-on-object-props.md b/docs/rules/force-types-on-object-props.md index 70497daa1..f316b23ae 100644 --- a/docs/rules/force-types-on-object-props.md +++ b/docs/rules/force-types-on-object-props.md @@ -12,19 +12,82 @@ description: xxx ## :book: Rule Details -This rule .... +Prevent missing type declaration of not primitive objects in a TypeScript projects. + +Bad: -```vue - + + +```ts +export default { + props: { + prop: { + type: Array + } + } +} ``` -## :wrench: Options +Good: + + + +```ts +export default { + props: { + prop: { + type: Object as Props, + } + } +} +``` + + + + + +```ts +export default { + props: { + prop: { + type: String, // or any other primitive type + } + } +} +``` + + + + +### Options Nothing. +## When Not To Use It + +When you're not using TypeScript in the project. + +## Further Reading + +Nothing + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/force-types-on-object-props.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/force-types-on-object-props.js) From 9a5320b3d13b2931c6ecfbc2feca15e7df21b534 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 19 Sep 2022 23:51:09 +0200 Subject: [PATCH 03/25] prepare force types on object implementation --- docs/rules/force-types-on-object-props.md | 2 +- lib/rules/force-types-on-object-props.js | 118 ++++++++++++++---- .../lib/rules/force-types-on-object-props.js | 92 ++++++++++---- 3 files changed, 165 insertions(+), 47 deletions(-) diff --git a/docs/rules/force-types-on-object-props.md b/docs/rules/force-types-on-object-props.md index f316b23ae..01b029854 100644 --- a/docs/rules/force-types-on-object-props.md +++ b/docs/rules/force-types-on-object-props.md @@ -81,7 +81,7 @@ Nothing. ## When Not To Use It -When you're not using TypeScript in the project. +When you're not using TypeScript in the project****. ## Further Reading diff --git a/lib/rules/force-types-on-object-props.js b/lib/rules/force-types-on-object-props.js index fb737487e..e6fa875c6 100644 --- a/lib/rules/force-types-on-object-props.js +++ b/lib/rules/force-types-on-object-props.js @@ -1,45 +1,119 @@ /** - * @author *****your name***** + * @author Przemysław Jan Beigert * See LICENSE file in root directory for full license. */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - -const utils = require('../utils') - // ------------------------------------------------------------------------------ // Helpers // ------------------------------------------------------------------------------ -// ... +/** + * Check if all keys and values from second object are resent in first object + * + * @param {{ [key: string]: any }} a object to + * @param {{ [key: string]: any }} b The string to escape. + * @returns {boolean} Returns the escaped string. + */ +const isLooksLike = (a, b) => + a && + b && + Object.keys(b).every((bKey) => { + const bVal = b[bKey] + const aVal = a[bKey] + if (typeof bVal === 'function') { + return bVal(aVal) + } + return bVal == null || /^[bns]/.test(typeof bVal) + ? bVal === aVal + : isLooksLike(aVal, bVal) + }) -// ------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // Rule Definition -// ------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ module.exports = { meta: { - type: 'problem', + type: 'suggestion', docs: { - description: '', - categories: undefined, - url: '' + description: 'enforce user to add type declaration to object props', + categories: ['type safe'], + recommended: false, + url: 'https://eslint.vuejs.org/rules/force-types-on-object-props.html' }, fixable: null, - schema: [], - messages: { - // ... - } + schema: [] }, /** @param {RuleContext} context */ create(context) { - // ... + return { + /** @param {ExportDefaultDeclaration} node */ + ExportDefaultDeclaration(node) { + if (node.declaration.type !== 'ObjectExpression') { + return + } + if (!Array.isArray(node.declaration.properties)) { + return + } + + const property = node.declaration.properties.find( + (property) => + property.type === 'Property' && + isLooksLike(property.key, { type: 'Identifier', name: 'props' }) && + property.value.type === 'ObjectExpression' + ) - return utils.defineTemplateBodyVisitor(context, { - // ... - }) + if ( + !property || + property.type === 'SpreadElement' || + !('properties' in property.value) + ) { + return + } + const properties = property.value.properties + .filter( + (prop) => + prop.type === 'Property' && prop.value.type === 'ObjectExpression' + ) + .map((prop) => + prop.value.properties.find((propValueProperty) => + isLooksLike(propValueProperty.key, { + type: 'Identifier', + name: 'type' + }) + ) + ) + for (const prop of properties) { + if (!prop) { + break + } + if (isLooksLike(prop.value, { type: 'Identifier', name: 'Object' })) { + context.report({ + node: prop, + message: 'Object props has to contains type.' + }) + } + if (prop.value.type === 'TSAsExpression') { + const { typeAnnotation } = prop.value + if ( + [ + 'TSAnyKeyword', + 'TSTypeLiteral', + 'TSUnknownKeyword', + 'TSObjectKeyword' + ].includes(typeAnnotation.type) || + !typeAnnotation.typeName || + typeAnnotation.typeName.name !== 'Prop' + ) { + context.report({ + node: prop, + message: 'Object props has to contains type.' + }) + } + } + } + } + } } } diff --git a/tests/lib/rules/force-types-on-object-props.js b/tests/lib/rules/force-types-on-object-props.js index b069eab37..5b7b8848d 100644 --- a/tests/lib/rules/force-types-on-object-props.js +++ b/tests/lib/rules/force-types-on-object-props.js @@ -7,39 +7,83 @@ const RuleTester = require('eslint').RuleTester const rule = require('../../../lib/rules/force-types-on-object-props') -const tester = new RuleTester({ +const template = (prop) => ` + + +` + +const ruleTester = new RuleTester({ parser: require.resolve('vue-eslint-parser'), - parserOptions: { - ecmaVersion: 2020, - sourceType: 'module' - } + parserOptions: { ecmaVersion: 2015 } }) -tester.run('force-types-on-object-props', rule, { +ruleTester.run('force-types-on-object-props', rule, { valid: [ - { - filename: 'test.vue', - code: ` - - ` - }, + ` + +`, + ` + +`, + template('type: Object as Prop<{}>'), + template('type: String'), + template('type: Number'), + template('type: Boolean'), + template('type: [String, Number, Boolean]') ], invalid: [ { - filename: 'test.vue', - code: ` - - `, + code: template('type: Object'), + errors: [ + { + message: 'Object props has to be typed' + } + ] + }, + { + code: template('type: Object as any'), + errors: [ + { + message: + 'Object props should be typed like this: "type: Object as Prop"' + } + ] + }, + { + code: template('type: Object as {}'), + errors: [ + { + message: + 'Object props should be typed like this: "type: Object as Prop"' + } + ] + }, + { + code: template('type: Object as unknown'), + errors: [ + { + message: + 'Object props should be typed like this: "type: Object as Prop"' + } + ] + }, + { + code: template('type: Object as string'), errors: [ { - message: '...', - line: 'line', - column: 'col' - }, + message: + 'Object props should be typed like this: "type: Object as Prop"' + } ] } ] From bfa7a9fa1a994e38dd2fb39db7851763a6246272 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 3 Oct 2022 20:43:40 +0200 Subject: [PATCH 04/25] fix some unit tests --- lib/rules/force-types-on-object-props.js | 2 +- .../lib/rules/force-types-on-object-props.js | 27 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/rules/force-types-on-object-props.js b/lib/rules/force-types-on-object-props.js index e6fa875c6..ead912e0b 100644 --- a/lib/rules/force-types-on-object-props.js +++ b/lib/rules/force-types-on-object-props.js @@ -86,7 +86,7 @@ module.exports = { ) for (const prop of properties) { if (!prop) { - break + continue } if (isLooksLike(prop.value, { type: 'Identifier', name: 'Object' })) { context.report({ diff --git a/tests/lib/rules/force-types-on-object-props.js b/tests/lib/rules/force-types-on-object-props.js index 53fefd917..608d2eac0 100644 --- a/tests/lib/rules/force-types-on-object-props.js +++ b/tests/lib/rules/force-types-on-object-props.js @@ -8,16 +8,25 @@ const RuleTester = require('eslint').RuleTester const rule = require('../../../lib/rules/force-types-on-object-props') const template = (prop) => ` - - ` const ruleTester = new RuleTester({ parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2015, sourceType: 'module' } + parserOptions: { + ecmaVersion: 2015, + sourceType: 'module', + parser: '@typescript-eslint/parser' + } }) ruleTester.run('force-types-on-object-props', rule, { @@ -54,8 +63,7 @@ ruleTester.run('force-types-on-object-props', rule, { code: template('type: Object as any'), errors: [ { - message: - 'Object props should be typed like this: "type: Object as Prop"' + message: 'Object props has to contains type.' } ] }, @@ -63,8 +71,7 @@ ruleTester.run('force-types-on-object-props', rule, { code: template('type: Object as {}'), errors: [ { - message: - 'Object props should be typed like this: "type: Object as Prop"' + message: 'Object props has to contains type.' } ] }, @@ -72,8 +79,7 @@ ruleTester.run('force-types-on-object-props', rule, { code: template('type: Object as unknown'), errors: [ { - message: - 'Object props should be typed like this: "type: Object as Prop"' + message: 'Object props has to contains type.' } ] }, @@ -81,8 +87,7 @@ ruleTester.run('force-types-on-object-props', rule, { code: template('type: Object as string'), errors: [ { - message: - 'Object props should be typed like this: "type: Object as Prop"' + message: 'Object props has to contains type.' } ] } From 92c09a8885d513d9be3834b978658c9e0731ef80 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 20 Feb 2023 19:59:04 +0100 Subject: [PATCH 05/25] remove double blank lines --- docs/rules/force-types-on-object-props.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/rules/force-types-on-object-props.md b/docs/rules/force-types-on-object-props.md index 01b029854..077b1a84e 100644 --- a/docs/rules/force-types-on-object-props.md +++ b/docs/rules/force-types-on-object-props.md @@ -74,7 +74,6 @@ export default { - ### Options Nothing. From 95aa2a35a40a57d13cdc61e9fb7824a9a1277805 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 20 Feb 2023 20:02:31 +0100 Subject: [PATCH 06/25] set proper category --- lib/rules/force-types-on-object-props.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/force-types-on-object-props.js b/lib/rules/force-types-on-object-props.js index ead912e0b..4c07b9dcd 100644 --- a/lib/rules/force-types-on-object-props.js +++ b/lib/rules/force-types-on-object-props.js @@ -38,7 +38,7 @@ module.exports = { type: 'suggestion', docs: { description: 'enforce user to add type declaration to object props', - categories: ['type safe'], + categories: ['Internal'], recommended: false, url: 'https://eslint.vuejs.org/rules/force-types-on-object-props.html' }, From 96eb868a66440d43d16fade32ca03388718fde31 Mon Sep 17 00:00:00 2001 From: Przemyslaw Jan Beigert Date: Mon, 20 Feb 2023 20:06:08 +0100 Subject: [PATCH 07/25] update docs --- docs/rules/force-types-on-object-props.md | 9 +++++---- docs/rules/index.md | 1 + lib/index.js | 1 + lib/rules/force-types-on-object-props.js | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/rules/force-types-on-object-props.md b/docs/rules/force-types-on-object-props.md index 077b1a84e..c44069b0e 100644 --- a/docs/rules/force-types-on-object-props.md +++ b/docs/rules/force-types-on-object-props.md @@ -2,13 +2,14 @@ pageClass: rule-details sidebarDepth: 0 title: vue/force-types-on-object-props -description: xxx +description: enforce user to add type declaration to object props --- # vue/force-types-on-object-props -> xxx +> enforce user to add type declaration to object props - :exclamation: ***This rule has not been released yet.*** +- :gear: This rule is included in all of `"plugin:vue/base"`, `"plugin:vue/essential"`, `"plugin:vue/vue3-essential"`, `"plugin:vue/strongly-recommended"`, `"plugin:vue/vue3-strongly-recommended"`, `"plugin:vue/recommended"` and `"plugin:vue/vue3-recommended"`. ## :book: Rule Details @@ -78,11 +79,11 @@ export default { Nothing. -## When Not To Use It +## :mute: When Not To Use It When you're not using TypeScript in the project****. -## Further Reading +## :books: Further Reading Nothing diff --git a/docs/rules/index.md b/docs/rules/index.md index b23f68427..a3ce78b34 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -28,6 +28,7 @@ Rules in this category are enabled for all presets provided by eslint-plugin-vue | Rule ID | Description | | | |:--------|:------------|:--:|:--:| | [vue/comment-directive](./comment-directive.md) | support comment-directives in `