From 87d265e67af28b7514080472453bb650f3b6393b Mon Sep 17 00:00:00 2001 From: chouchouji <1305974212@qq.com> Date: Sun, 16 Feb 2025 22:41:33 +0800 Subject: [PATCH] feat(require-name-property): support check defineOptions --- lib/rules/require-name-property.js | 132 ++++++++++++++++++----------- 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/lib/rules/require-name-property.js b/lib/rules/require-name-property.js index cc2d3db8d..9ee3453f8 100644 --- a/lib/rules/require-name-property.js +++ b/lib/rules/require-name-property.js @@ -41,6 +41,54 @@ function isNameProperty(node) { ) } +/** + * Report error if there has no name property + * @param {RuleContext} context + * @param {CallExpression | ObjectExpression} node + * @param {ObjectExpression} expression + */ +function report(context, node, expression) { + context.report({ + node, + messageId: 'missingName', + suggest: [ + { + messageId: 'addName', + fix(fixer) { + const extension = path.extname(context.getFilename()) + const filename = path.basename(context.getFilename(), extension) + const sourceCode = context.getSourceCode() + + if (expression.properties.length > 0) { + const firstToken = sourceCode.getFirstToken( + expression.properties[0] + ) + const indentText = getLineEmptyIndent(sourceCode, firstToken) + // insert name property before the first property + return fixer.insertTextBefore( + expression.properties[0], + `name: '${filename}',\n${indentText}` + ) + } + + const firstToken = sourceCode.getFirstToken(expression) + const lastToken = sourceCode.getLastToken(expression) + // if the component is empty, insert name property and indent + if (firstToken.value === '{' && lastToken.value === '}') { + const indentText = getLineEmptyIndent(sourceCode, firstToken) + return fixer.replaceTextRange( + [firstToken.range[1], lastToken.range[0]], + `\n${indentText} name: '${filename}'\n${indentText}` + ) + } + + return null + } + } + ] + }) +} + module.exports = { meta: { type: 'suggestion', @@ -51,7 +99,17 @@ module.exports = { }, fixable: null, hasSuggestions: true, - schema: [], + schema: [ + { + type: 'object', + properties: { + checkScriptSetup: { + type: 'boolean' + } + }, + additionalProperties: false + } + ], messages: { missingName: 'Required name property is not set.', addName: 'Add name property to component.' @@ -59,57 +117,35 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { - if (utils.isScriptSetup(context)) { - return {} - } - return utils.executeOnVue(context, (component, type) => { - if (type === 'definition') { - const defType = getVueComponentDefinitionType(component) - if (defType === 'mixin') { - return - } - } - - if (component.properties.some(isNameProperty)) return + const option = context.options[1] || {} + const checkScriptSetup = !!option.checkScriptSetup - context.report({ - node: component, - messageId: 'missingName', - suggest: [ - { - messageId: 'addName', - fix(fixer) { - const extension = path.extname(context.getFilename()) - const filename = path.basename(context.getFilename(), extension) - const sourceCode = context.getSourceCode() - // fix only when property is not empty - if (component.properties.length > 0) { - const firstToken = sourceCode.getFirstToken( - component.properties[0] - ) - const indentText = getLineEmptyIndent(sourceCode, firstToken) - // insert name property before the first property - return fixer.insertTextBefore( - component.properties[0], - `name: '${filename}',\n${indentText}` - ) - } + return utils.compositingVisitors( + checkScriptSetup + ? utils.defineScriptSetupVisitor(context, { + onDefineOptionsEnter(node) { + if (node.arguments.length === 0) return + const define = node.arguments[0] + if (define.type !== 'ObjectExpression') return + const nameNode = utils.findProperty(define, 'name') + if (nameNode) return - const firstToken = sourceCode.getFirstToken(component) - const lastToken = sourceCode.getLastToken(component) - // if the component is empty, insert name property and indent - if (firstToken.value === '{' && lastToken.value === '}') { - const indentText = getLineEmptyIndent(sourceCode, firstToken) - return fixer.replaceTextRange( - [firstToken.range[1], lastToken.range[0]], - `\n${indentText} name: '${filename}'\n${indentText}` - ) - } - return null + report(context, node, define) } + }) + : {}, + utils.executeOnVue(context, (component, type) => { + if (type === 'definition') { + const defType = getVueComponentDefinitionType(component) + if (defType === 'mixin') { + return } - ] + } + + if (component.properties.some(isNameProperty)) return + + report(context, component, component) }) - }) + ) } }