From 63395f47f907ab8e517f5cfc7896cf38550ee008 Mon Sep 17 00:00:00 2001 From: ota Date: Tue, 9 Jun 2020 12:11:00 +0900 Subject: [PATCH] Format some files Format the files for which the PR has been finished. --- .eslintrc.js | 11 - lib/rules/order-in-components.js | 74 ++-- lib/rules/require-direct-export.js | 99 +++-- lib/utils/index.js | 523 ++++++++++++++--------- tests/lib/rules/order-in-components.js | 317 +++++++++----- tests/lib/rules/require-direct-export.js | 97 +++-- tests/lib/utils/vue-component.js | 21 +- 7 files changed, 701 insertions(+), 441 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 97e2e03f9..7bc7d0960 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -40,17 +40,6 @@ module.exports = { // Introduce prettier. but ignore files to avoid conflicts with PR. { files: [ - // https://github.com/vuejs/eslint-plugin-vue/pull/1107 - 'lib/rules/order-in-components.js', - 'tests/lib/rules/order-in-components.js', - // https://github.com/vuejs/eslint-plugin-vue/pull/1090 - 'lib/rules/require-direct-export.js', - 'tests/lib/rules/require-direct-export.js', - 'lib/utils/index.js', - 'tests/lib/utils/vue-component.js', - // https://github.com/vuejs/eslint-plugin-vue/pull/982 - 'lib/rules/attributes-order.js', - 'tests/lib/rules/attributes-order.js', // https://github.com/vuejs/eslint-plugin-vue/pull/819 'lib/rules/attributes-order.js', 'tests/lib/rules/attributes-order.js' diff --git a/lib/rules/order-in-components.js b/lib/rules/order-in-components.js index 29c34f26d..afdb17828 100644 --- a/lib/rules/order-in-components.js +++ b/lib/rules/order-in-components.js @@ -89,19 +89,15 @@ const groups = { 'renderTriggered', // for Vue.js 3.x 'errorCaptured' // for Vue.js 2.5.0+ ], - ROUTER_GUARDS: [ - 'beforeRouteEnter', - 'beforeRouteUpdate', - 'beforeRouteLeave' - ] + ROUTER_GUARDS: ['beforeRouteEnter', 'beforeRouteUpdate', 'beforeRouteLeave'] } -function getOrderMap (order) { +function getOrderMap(order) { const orderMap = new Map() order.forEach((property, i) => { if (Array.isArray(property)) { - property.forEach(p => orderMap.set(p, i)) + property.forEach((p) => orderMap.set(p, i)) } else { orderMap.set(property, i) } @@ -110,11 +106,11 @@ function getOrderMap (order) { return orderMap } -function isComma (node) { +function isComma(node) { return node.type === 'Punctuator' && node.value === ',' } -const ARITHMETIC_OPERATORS = ['+', '-', '*', '/', '%', '**'/* es2016 */] +const ARITHMETIC_OPERATORS = ['+', '-', '*', '/', '%', '**' /* es2016 */] const BITWISE_OPERATORS = ['&', '|', '^', '~', '<<', '>>', '>>>'] const COMPARISON_OPERATORS = ['==', '!=', '===', '!==', '>', '>=', '<', '<='] const RELATIONAL_OPERATORS = ['in', 'instanceof'] @@ -124,7 +120,7 @@ const ALL_BINARY_OPERATORS = [].concat( COMPARISON_OPERATORS, RELATIONAL_OPERATORS ) -const LOGICAL_OPERATORS = ['&&', '||', '??'/* es2020 */] +const LOGICAL_OPERATORS = ['&&', '||', '??' /* es2020 */] /* * Result `true` if the node is sure that there are no side effects @@ -142,12 +138,12 @@ const LOGICAL_OPERATORS = ['&&', '||', '??'/* es2020 */] * @param {Object} visitorKeys sourceCode.visitorKey * @returns {Boolean} no side effects */ -function isNotSideEffectsNode (node, visitorKeys) { +function isNotSideEffectsNode(node, visitorKeys) { let result = true let skipNode = false traverseNodes(node, { visitorKeys, - enterNode (node) { + enterNode(node) { if (!result || skipNode) { return } @@ -166,9 +162,12 @@ function isNotSideEffectsNode (node, visitorKeys) { node.type !== 'Property' && node.type !== 'ObjectExpression' && node.type !== 'ArrayExpression' && - (node.type !== 'UnaryExpression' || !['!', '~', '+', '-', 'typeof'].includes(node.operator)) && - (node.type !== 'BinaryExpression' || !ALL_BINARY_OPERATORS.includes(node.operator)) && - (node.type !== 'LogicalExpression' || !LOGICAL_OPERATORS.includes(node.operator)) && + (node.type !== 'UnaryExpression' || + !['!', '~', '+', '-', 'typeof'].includes(node.operator)) && + (node.type !== 'BinaryExpression' || + !ALL_BINARY_OPERATORS.includes(node.operator)) && + (node.type !== 'LogicalExpression' || + !LOGICAL_OPERATORS.includes(node.operator)) && node.type !== 'MemberExpression' && node.type !== 'ConditionalExpression' && // es2015 @@ -179,7 +178,7 @@ function isNotSideEffectsNode (node, visitorKeys) { result = false } }, - leaveNode (node) { + leaveNode(node) { if (skipNode === node) { skipNode = null } @@ -215,23 +214,25 @@ module.exports = { ] }, - create (context) { + create(context) { const options = context.options[0] || {} const order = options.order || defaultOrder - const extendedOrder = order.map(property => groups[property] || property) + const extendedOrder = order.map((property) => groups[property] || property) const orderMap = getOrderMap(extendedOrder) const sourceCode = context.getSourceCode() - function checkOrder (propertiesNodes, orderMap) { + function checkOrder(propertiesNodes, orderMap) { const properties = propertiesNodes - .filter(property => property.type === 'Property') - .map(property => property.key) + .filter((property) => property.type === 'Property') + .map((property) => property.key) properties.forEach((property, i) => { const propertiesAbove = properties.slice(0, i) const unorderedProperties = propertiesAbove - .filter(p => orderMap.get(p.name) > orderMap.get(property.name)) - .sort((p1, p2) => orderMap.get(p1.name) > orderMap.get(p2.name) ? 1 : -1) + .filter((p) => orderMap.get(p.name) > orderMap.get(property.name)) + .sort((p1, p2) => + orderMap.get(p1.name) > orderMap.get(p2.name) ? 1 : -1 + ) const firstUnorderedProperty = unorderedProperties[0] @@ -245,7 +246,7 @@ module.exports = { firstUnorderedPropertyName: firstUnorderedProperty.name, line }, - fix (fixer) { + fix(fixer) { const propertyNode = property.parent const firstUnorderedPropertyNode = firstUnorderedProperty.parent const hasSideEffectsPossibility = propertiesNodes @@ -253,7 +254,10 @@ module.exports = { propertiesNodes.indexOf(firstUnorderedPropertyNode), propertiesNodes.indexOf(propertyNode) + 1 ) - .some((property) => !isNotSideEffectsNode(property, sourceCode.visitorKeys)) + .some( + (property) => + !isNotSideEffectsNode(property, sourceCode.visitorKeys) + ) if (hasSideEffectsPossibility) { return undefined } @@ -262,12 +266,20 @@ module.exports = { const beforeComma = sourceCode.getTokenBefore(propertyNode) const codeStart = beforeComma.range[1] // to include comments - const codeEnd = hasAfterComma ? afterComma.range[1] : propertyNode.range[1] - - const propertyCode = sourceCode.text.slice(codeStart, codeEnd) + (hasAfterComma ? '' : ',') - const insertTarget = sourceCode.getTokenBefore(firstUnorderedPropertyNode) - - const removeStart = hasAfterComma ? codeStart : beforeComma.range[0] + const codeEnd = hasAfterComma + ? afterComma.range[1] + : propertyNode.range[1] + + const propertyCode = + sourceCode.text.slice(codeStart, codeEnd) + + (hasAfterComma ? '' : ',') + const insertTarget = sourceCode.getTokenBefore( + firstUnorderedPropertyNode + ) + + const removeStart = hasAfterComma + ? codeStart + : beforeComma.range[0] return [ fixer.removeRange([removeStart, codeEnd]), diff --git a/lib/rules/require-direct-export.js b/lib/rules/require-direct-export.js index 2bc0abd12..472a01846 100644 --- a/lib/rules/require-direct-export.js +++ b/lib/rules/require-direct-export.js @@ -25,28 +25,31 @@ module.exports = { categories: undefined, url: 'https://eslint.vuejs.org/rules/require-direct-export.html' }, - fixable: null, // or "code" or "whitespace" - schema: [{ - type: 'object', - properties: { - disallowFunctionalComponentFunction: { type: 'boolean' } - }, - additionalProperties: false - }] + fixable: null, // or "code" or "whitespace" + schema: [ + { + type: 'object', + properties: { + disallowFunctionalComponentFunction: { type: 'boolean' } + }, + additionalProperties: false + } + ] }, - create (context) { + create(context) { const filePath = context.getFilename() if (!utils.isVueFile(filePath)) return {} - const disallowFunctional = (context.options[0] || {}).disallowFunctionalComponentFunction + const disallowFunctional = (context.options[0] || {}) + .disallowFunctionalComponentFunction let maybeVue3Functional let scopeStack = null return { /** @param {Declaration | Expression} node */ - 'ExportDefaultDeclaration > *' (node) { + 'ExportDefaultDeclaration > *'(node) { if (node.type === 'ObjectExpression') { // OK return @@ -54,7 +57,7 @@ module.exports = { if (!disallowFunctional) { if (node.type === 'ArrowFunctionExpression') { if (node.body.type !== 'BlockStatement') { - // OK + // OK return } maybeVue3Functional = { @@ -62,7 +65,10 @@ module.exports = { } return } - if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration') { + if ( + node.type === 'FunctionExpression' || + node.type === 'FunctionDeclaration' + ) { maybeVue3Functional = { body: node.body } @@ -75,35 +81,44 @@ module.exports = { message: `Expected the component literal to be directly exported.` }) }, - ...(disallowFunctional ? {} : { - ':function > BlockStatement' (node) { - if (!maybeVue3Functional) { - return - } - scopeStack = { upper: scopeStack, withinVue3FunctionalBody: maybeVue3Functional.body === node } - }, - /** @param {ReturnStatement} node */ - ReturnStatement (node) { - if (scopeStack && scopeStack.withinVue3FunctionalBody && node.argument) { - maybeVue3Functional.hasReturnArgument = true - } - }, - ':function > BlockStatement:exit' (node) { - scopeStack = scopeStack && scopeStack.upper - }, - /** @param {ExportDefaultDeclaration} node */ - 'ExportDefaultDeclaration:exit' (node) { - if (!maybeVue3Functional) { - return - } - if (!maybeVue3Functional.hasReturnArgument) { - context.report({ - node, - message: `Expected the component literal to be directly exported.` - }) - } - } - }) + ...(disallowFunctional + ? {} + : { + ':function > BlockStatement'(node) { + if (!maybeVue3Functional) { + return + } + scopeStack = { + upper: scopeStack, + withinVue3FunctionalBody: maybeVue3Functional.body === node + } + }, + /** @param {ReturnStatement} node */ + ReturnStatement(node) { + if ( + scopeStack && + scopeStack.withinVue3FunctionalBody && + node.argument + ) { + maybeVue3Functional.hasReturnArgument = true + } + }, + ':function > BlockStatement:exit'(node) { + scopeStack = scopeStack && scopeStack.upper + }, + /** @param {ExportDefaultDeclaration} node */ + 'ExportDefaultDeclaration:exit'(node) { + if (!maybeVue3Functional) { + return + } + if (!maybeVue3Functional.hasReturnArgument) { + context.report({ + node, + message: `Expected the component literal to be directly exported.` + }) + } + } + }) } } } diff --git a/lib/utils/index.js b/lib/utils/index.js index e9f8efe50..6ff8d6f7e 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -67,21 +67,23 @@ const componentComments = new WeakMap() * @param {RuleContext} context The rule context object. * @param {TokenStore} tokenStore The token store object for template. */ -function wrapContextToOverrideTokenMethods (context, tokenStore) { +function wrapContextToOverrideTokenMethods(context, tokenStore) { const eslintSourceCode = context.getSourceCode() let tokensAndComments - function getTokensAndComments () { + function getTokensAndComments() { if (tokensAndComments) { return tokensAndComments } const templateBody = eslintSourceCode.ast.templateBody - tokensAndComments = templateBody ? tokenStore.getTokens(templateBody, { - includeComments: true - }) : [] + tokensAndComments = templateBody + ? tokenStore.getTokens(templateBody, { + includeComments: true + }) + : [] return tokensAndComments } const sourceCode = new Proxy(Object.assign({}, eslintSourceCode), { - get (object, key) { + get(object, key) { if (key === 'tokensAndComments') { return getTokensAndComments() } @@ -91,7 +93,7 @@ function wrapContextToOverrideTokenMethods (context, tokenStore) { return { __proto__: context, - getSourceCode () { + getSourceCode() { return sourceCode } } @@ -101,7 +103,7 @@ function wrapContextToOverrideTokenMethods (context, tokenStore) { * Wrap the rule context object to override report method to skip the dynamic argument. * @param {RuleContext} context The rule context object. */ -function wrapContextToOverrideReportMethodToSkipDynamicArgument (context) { +function wrapContextToOverrideReportMethodToSkipDynamicArgument(context) { const sourceCode = context.getSourceCode() const templateBody = sourceCode.ast.templateBody if (!templateBody) { @@ -110,30 +112,40 @@ function wrapContextToOverrideReportMethodToSkipDynamicArgument (context) { const directiveKeyRanges = [] const traverseNodes = vueEslintParser.AST.traverseNodes traverseNodes(templateBody, { - enterNode (node, parent) { + enterNode(node, parent) { if ( - parent && parent.type === 'VDirectiveKey' && node.type === 'VExpressionContainer' + parent && + parent.type === 'VDirectiveKey' && + node.type === 'VExpressionContainer' ) { directiveKeyRanges.push(node.range) } }, - leaveNode () {} + leaveNode() {} }) return { __proto__: context, - report (descriptor, ...args) { + report(descriptor, ...args) { let range = null if (descriptor.loc) { - const startLoc = isLoc(descriptor.loc.start) ? descriptor.loc.start : descriptor.loc + const startLoc = isLoc(descriptor.loc.start) + ? descriptor.loc.start + : descriptor.loc const endLoc = descriptor.loc.end || startLoc - range = [sourceCode.getIndexFromLoc(startLoc), sourceCode.getIndexFromLoc(endLoc)] + range = [ + sourceCode.getIndexFromLoc(startLoc), + sourceCode.getIndexFromLoc(endLoc) + ] } else if (descriptor.node) { range = descriptor.node.range } if (range) { for (const directiveKeyRange of directiveKeyRanges) { - if (range[0] < directiveKeyRange[1] && directiveKeyRange[0] < range[1]) { + if ( + range[0] < directiveKeyRange[1] && + directiveKeyRange[0] < range[1] + ) { return } } @@ -142,8 +154,13 @@ function wrapContextToOverrideReportMethodToSkipDynamicArgument (context) { } } - function isLoc (loc) { - return loc && typeof loc === 'object' && typeof loc.line === 'number' && typeof loc.column === 'number' + function isLoc(loc) { + return ( + loc && + typeof loc === 'object' && + typeof loc.line === 'number' && + typeof loc.column === 'number' + ) } } @@ -174,10 +191,15 @@ module.exports = { * @param {RuleModule["create"]} [options.create] If define, extend core rule. * @returns {RuleModule} The wrapped rule implementation. */ - wrapCoreRule (coreRule, options) { - const { categories, skipDynamicArguments, skipDynamicArgumentsReport, create } = options || {} + wrapCoreRule(coreRule, options) { + const { + categories, + skipDynamicArguments, + skipDynamicArgumentsReport, + create + } = options || {} return { - create (context) { + create(context) { const tokenStore = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore() @@ -189,7 +211,9 @@ module.exports = { } if (skipDynamicArgumentsReport) { - context = wrapContextToOverrideReportMethodToSkipDynamicArgument(context) + context = wrapContextToOverrideReportMethodToSkipDynamicArgument( + context + ) } // Move `Program` handlers to `VElement[parent.type!='VElement']` @@ -200,7 +224,8 @@ module.exports = { delete handlers.Program } if (handlers['Program:exit']) { - handlers["VElement[parent.type!='VElement']:exit"] = handlers['Program:exit'] + handlers["VElement[parent.type!='VElement']:exit"] = + handlers['Program:exit'] delete handlers['Program:exit'] } @@ -213,8 +238,12 @@ module.exports = { original(...args) } } - handlers['VDirectiveKey > VExpressionContainer'] = () => { withinDynamicArguments = true } - handlers['VDirectiveKey > VExpressionContainer:exit'] = () => { withinDynamicArguments = false } + handlers['VDirectiveKey > VExpressionContainer'] = () => { + withinDynamicArguments = true + } + handlers['VDirectiveKey > VExpressionContainer:exit'] = () => { + withinDynamicArguments = false + } } if (create) { @@ -229,7 +258,9 @@ module.exports = { docs: Object.assign({}, coreRule.meta.docs, { category: null, categories, - url: `https://eslint.vuejs.org/rules/${path.basename(coreRule.meta.docs.url || '')}.html`, + url: `https://eslint.vuejs.org/rules/${path.basename( + coreRule.meta.docs.url || '' + )}.html`, extensionRule: true, coreRuleUrl: coreRule.meta.docs.url }) @@ -242,7 +273,7 @@ module.exports = { * @param {ASTNode} node The element node to check. * @returns {boolean} `true` if the node is the root element. */ - isRootElement (node) { + isRootElement(node) { assert(node && node.type === 'VElement') return ( @@ -256,7 +287,7 @@ module.exports = { * @param {ASTNode} node The element node to get the previous sibling element. * @returns {ASTNode|null} The previous sibling element. */ - prevSibling (node) { + prevSibling(node) { assert(node && node.type === 'VElement') let prevElement = null @@ -279,7 +310,7 @@ module.exports = { * @param {string} [value] The attribute value to check. * @returns {boolean} `true` if the start tag has the attribute. */ - hasAttribute (node, name, value) { + hasAttribute(node, name, value) { assert(node && node.type === 'VElement') return Boolean(this.getAttribute(node, name, value)) }, @@ -291,7 +322,7 @@ module.exports = { * @param {string} [argument] The directive argument to check. * @returns {boolean} `true` if the start tag has the directive. */ - hasDirective (node, name, argument) { + hasDirective(node, name, argument) { assert(node && node.type === 'VElement') return Boolean(this.getDirective(node, name, argument)) }, @@ -302,7 +333,7 @@ module.exports = { * @param {RuleContext} context The rule context to use parser services. * @returns {boolean} `true` if the directive attribute has their empty value (`=""`). */ - isEmptyValueDirective (node, context) { + isEmptyValueDirective(node, context) { assert(node && node.type === 'VAttribute') if (node.value == null) { return false @@ -312,7 +343,10 @@ module.exports = { } let valueText = context.getSourceCode().getText(node.value) - if ((valueText[0] === '"' || valueText[0] === "'") && valueText[0] === valueText[valueText.length - 1]) { + if ( + (valueText[0] === '"' || valueText[0] === "'") && + valueText[0] === valueText[valueText.length - 1] + ) { // quoted valueText = valueText.slice(1, -1) } @@ -329,7 +363,7 @@ module.exports = { * @param {RuleContext} context The rule context to use parser services. * @returns {boolean} `true` if the directive attribute has their empty expression value. */ - isEmptyExpressionValueDirective (node, context) { + isEmptyExpressionValueDirective(node, context) { assert(node && node.type === 'VAttribute') if (node.value == null) { return false @@ -351,11 +385,20 @@ module.exports = { // empty return true } - if (!quote1 && token.type === 'Punctuator' && (token.value === '"' || token.value === "'")) { + if ( + !quote1 && + token.type === 'Punctuator' && + (token.value === '"' || token.value === "'") + ) { quote1 = token continue } - if (!quote2 && quote1 && token.type === 'Punctuator' && (token.value === quote1.value)) { + if ( + !quote2 && + quote1 && + token.type === 'Punctuator' && + token.value === quote1.value + ) { quote2 = token continue } @@ -373,15 +416,13 @@ module.exports = { * @param {string} [value] The attribute value to check. * @returns {ASTNode} The found attribute. */ - getAttribute (node, name, value) { + getAttribute(node, name, value) { assert(node && node.type === 'VElement') - return node.startTag.attributes.find(a => - !a.directive && - a.key.name === name && - ( - value === undefined || - (a.value != null && a.value.value === value) - ) + return node.startTag.attributes.find( + (a) => + !a.directive && + a.key.name === name && + (value === undefined || (a.value != null && a.value.value === value)) ) }, @@ -392,12 +433,14 @@ module.exports = { * @param {string} [argument] The directive argument to check. * @returns {ASTNode} The found directive. */ - getDirective (node, name, argument) { + getDirective(node, name, argument) { assert(node && node.type === 'VElement') - return node.startTag.attributes.find(a => - a.directive && - a.key.name.name === name && - (argument === undefined || (a.key.argument && a.key.argument.name) === argument) + return node.startTag.attributes.find( + (a) => + a.directive && + a.key.name.name === name && + (argument === undefined || + (a.key.argument && a.key.argument.name) === argument) ) }, @@ -406,24 +449,26 @@ module.exports = { * @param {ASTNode} componentObject * @returns {Array} Array of ASTNodes */ - getRegisteredComponents (componentObject) { - const componentsNode = componentObject.properties - .find(p => + getRegisteredComponents(componentObject) { + const componentsNode = componentObject.properties.find( + (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'components' && p.value.type === 'ObjectExpression' - ) + ) - if (!componentsNode) { return [] } + if (!componentsNode) { + return [] + } return componentsNode.value.properties - .filter(p => p.type === 'Property') - .map(node => { + .filter((p) => p.type === 'Property') + .map((node) => { const name = getStaticPropertyName(node) return name ? { node, name } : null }) - .filter(comp => comp != null) + .filter((comp) => comp != null) }, /** @@ -431,15 +476,16 @@ module.exports = { * @param {ASTNode} node The element node to check. * @returns {boolean} `true` if the previous sibling element has `if` or `else-if` directive. */ - prevElementHasIf (node) { + prevElementHasIf(node) { assert(node && node.type === 'VElement') const prev = this.prevSibling(node) return ( prev != null && - prev.startTag.attributes.some(a => - a.directive && - (a.key.name.name === 'if' || a.key.name.name === 'else-if') + prev.startTag.attributes.some( + (a) => + a.directive && + (a.key.name.name === 'if' || a.key.name.name === 'else-if') ) ) }, @@ -449,11 +495,12 @@ module.exports = { * @param {ASTNode} node The start tag node to check. * @returns {boolean} `true` if the node is a custom component. */ - isCustomComponent (node) { + isCustomComponent(node) { assert(node && node.type === 'VElement') return ( - (this.isHtmlElementNode(node) && !this.isHtmlWellKnownElementName(node.rawName)) || + (this.isHtmlElementNode(node) && + !this.isHtmlWellKnownElementName(node.rawName)) || this.hasAttribute(node, 'is') || this.hasDirective(node, 'bind', 'is') ) @@ -464,7 +511,7 @@ module.exports = { * @param {ASTNode} node The node to check. * @returns {boolean} `true` if the node is a HTML element. */ - isHtmlElementNode (node) { + isHtmlElementNode(node) { assert(node && node.type === 'VElement') return node.namespace === vueEslintParser.AST.NS.HTML @@ -475,7 +522,7 @@ module.exports = { * @param {ASTNode} node The node to check. * @returns {boolean} `true` if the name is a SVG element. */ - isSvgElementNode (node) { + isSvgElementNode(node) { assert(node && node.type === 'VElement') return node.namespace === vueEslintParser.AST.NS.SVG @@ -486,7 +533,7 @@ module.exports = { * @param {ASTNode} node The node to check. * @returns {boolean} `true` if the node is a MathML element. */ - isMathMLElementNode (node) { + isMathMLElementNode(node) { assert(node && node.type === 'VElement') return node.namespace === vueEslintParser.AST.NS.MathML @@ -497,7 +544,7 @@ module.exports = { * @param {string} name The name to check. * @returns {boolean} `true` if the name is an well-known element name. */ - isHtmlWellKnownElementName (name) { + isHtmlWellKnownElementName(name) { assert(typeof name === 'string') return HTML_ELEMENT_NAMES.has(name) @@ -508,7 +555,7 @@ module.exports = { * @param {string} name The name to check. * @returns {boolean} `true` if the name is an well-known SVG element name. */ - isSvgWellKnownElementName (name) { + isSvgWellKnownElementName(name) { assert(typeof name === 'string') return SVG_ELEMENT_NAMES.has(name) }, @@ -518,7 +565,7 @@ module.exports = { * @param {string} name The name to check. * @returns {boolean} `true` if the name is a void element name. */ - isHtmlVoidElementName (name) { + isHtmlVoidElementName(name) { assert(typeof name === 'string') return VOID_ELEMENT_NAMES.has(name) @@ -529,7 +576,7 @@ module.exports = { * @param {ASTNode} node MemberExpression * @returns {Array} */ - parseMemberExpression (node) { + parseMemberExpression(node) { const members = [] let memberExpression @@ -565,14 +612,15 @@ module.exports = { * @param {ObjectExpression} componentObject Object with component definition * @return {(ComponentArrayProp | ComponentObjectProp)[]} Array of component props in format: [{key?: String, value?: ASTNode, node: ASTNod}] */ - getComponentProps (componentObject) { - const propsNode = componentObject.properties - .find(p => + getComponentProps(componentObject) { + const propsNode = componentObject.properties.find( + (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'props' && - (p.value.type === 'ObjectExpression' || p.value.type === 'ArrayExpression') - ) + (p.value.type === 'ObjectExpression' || + p.value.type === 'ArrayExpression') + ) if (!propsNode) { return [] @@ -580,19 +628,29 @@ module.exports = { if (propsNode.value.type === 'ObjectExpression') { return propsNode.value.properties - .filter(prop => prop.type === 'Property') - .map(prop => { + .filter((prop) => prop.type === 'Property') + .map((prop) => { return { - key: prop.key, value: unwrapTypes(prop.value), node: prop, + key: prop.key, + value: unwrapTypes(prop.value), + node: prop, propName: getStaticPropertyName(prop) } }) } else { return propsNode.value.elements - .filter(prop => prop) - .map(prop => { - const key = prop.type === 'Literal' && typeof prop.value === 'string' ? prop : null - return { key, value: null, node: prop, propName: key != null ? prop.value : null } + .filter((prop) => prop) + .map((prop) => { + const key = + prop.type === 'Literal' && typeof prop.value === 'string' + ? prop + : null + return { + key, + value: null, + node: prop, + propName: key != null ? prop.value : null + } }) } }, @@ -602,14 +660,15 @@ module.exports = { * @param {ObjectExpression} componentObject Object with component definition * @return {(ComponentArrayEmit | ComponentObjectEmit)[]} Array of component emits in format: [{key?: String, value?: ASTNode, node: ASTNod}] */ - getComponentEmits (componentObject) { - const emitsNode = componentObject.properties - .find(p => + getComponentEmits(componentObject) { + const emitsNode = componentObject.properties.find( + (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'emits' && - (p.value.type === 'ObjectExpression' || p.value.type === 'ArrayExpression') - ) + (p.value.type === 'ObjectExpression' || + p.value.type === 'ArrayExpression') + ) if (!emitsNode) { return [] @@ -617,19 +676,29 @@ module.exports = { if (emitsNode.value.type === 'ObjectExpression') { return emitsNode.value.properties - .filter(prop => prop.type === 'Property') - .map(prop => { + .filter((prop) => prop.type === 'Property') + .map((prop) => { return { - key: prop.key, value: unwrapTypes(prop.value), node: prop, + key: prop.key, + value: unwrapTypes(prop.value), + node: prop, emitName: getStaticPropertyName(prop) } }) } else { return emitsNode.value.elements - .filter(prop => prop) - .map(prop => { - const key = prop.type === 'Literal' && typeof prop.value === 'string' ? prop : null - return { key, value: null, node: prop, emitName: key != null ? prop.value : null } + .filter((prop) => prop) + .map((prop) => { + const key = + prop.type === 'Literal' && typeof prop.value === 'string' + ? prop + : null + return { + key, + value: null, + node: prop, + emitName: key != null ? prop.value : null + } }) } }, @@ -639,20 +708,22 @@ module.exports = { * @param {ObjectExpression} componentObject Object with component definition * @return {ComponentComputedProperty[]} Array of computed properties in format: [{key: String, value: ASTNode}] */ - getComputedProperties (componentObject) { - const computedPropertiesNode = componentObject.properties - .find(p => + getComputedProperties(componentObject) { + const computedPropertiesNode = componentObject.properties.find( + (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'computed' && p.value.type === 'ObjectExpression' - ) + ) - if (!computedPropertiesNode) { return [] } + if (!computedPropertiesNode) { + return [] + } return computedPropertiesNode.value.properties - .filter(cp => cp.type === 'Property') - .map(cp => { + .filter((cp) => cp.type === 'Property') + .map((cp) => { const key = getStaticPropertyName(cp) /** @type {Expression} */ const propValue = cp.value @@ -663,13 +734,13 @@ module.exports = { value = propValue.body } else if (propValue.type === 'ObjectExpression') { /** @type { (Property & { value: FunctionExpression }) | undefined} */ - const get = propValue.properties - .find(p => + const get = propValue.properties.find( + (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'get' && p.value.type === 'FunctionExpression' - ) + ) value = get ? get.value.body : null } @@ -684,7 +755,7 @@ module.exports = { * @param {RuleContext} context The ESLint rule context object. * @param {Function} cb Callback function */ - executeOnVue (context, cb) { + executeOnVue(context, cb) { return compositingVisitors( this.executeOnVueComponent(context, cb), this.executeOnVueInstance(context, cb) @@ -703,10 +774,10 @@ module.exports = { * @param {RuleContext} context The ESLint rule context object. * @param {Object} visitor The visitor to traverse the Vue Objects. */ - defineVueVisitor (context, visitor) { + defineVueVisitor(context, visitor) { let vueStack = null - function callVisitor (key, node) { + function callVisitor(key, node) { if (visitor[key] && vueStack) { visitor[key](node, vueStack) } @@ -727,7 +798,7 @@ module.exports = { node, type, parent: vueStack, - get functional () { + get functional() { /** @type {Property} */ const functional = node.properties.find( (p) => @@ -789,9 +860,9 @@ module.exports = { * @param {RuleContext} context The ESLint rule context object. * @param {Function} cb Callback function */ - executeOnVueInstance (context, cb) { + executeOnVueInstance(context, cb) { return { - 'ObjectExpression:exit' (node) { + 'ObjectExpression:exit'(node) { const type = getVueObjectType(context, node) if (!type || type !== 'instance') return cb(node, type) @@ -804,11 +875,15 @@ module.exports = { * @param {RuleContext} context The ESLint rule context object. * @param {Function} cb Callback function */ - executeOnVueComponent (context, cb) { + executeOnVueComponent(context, cb) { return { - 'ObjectExpression:exit' (node) { + 'ObjectExpression:exit'(node) { const type = getVueObjectType(context, node) - if (!type || (type !== 'mark' && type !== 'export' && type !== 'definition')) return + if ( + !type || + (type !== 'mark' && type !== 'export' && type !== 'definition') + ) + return cb(node, type) } } @@ -819,19 +894,23 @@ module.exports = { * @param {RuleContext} _context The ESLint rule context object. * @param {Function} cb Callback function */ - executeOnCallVueComponent (_context, cb) { + executeOnCallVueComponent(_context, cb) { return { - "CallExpression > MemberExpression > Identifier[name='component']": (node) => { + "CallExpression > MemberExpression > Identifier[name='component']": ( + node + ) => { const callExpr = node.parent.parent const callee = callExpr.callee if (callee.type === 'MemberExpression') { const calleeObject = unwrapTypes(callee.object) - if (calleeObject.type === 'Identifier' && + if ( + calleeObject.type === 'Identifier' && // calleeObject.name === 'Vue' && // Any names can be used in Vue.js 3.x. e.g. app.component() callee.property === node && - callExpr.arguments.length >= 1) { + callExpr.arguments.length >= 1 + ) { cb(callExpr) } } @@ -844,7 +923,7 @@ module.exports = { * @param {Set} groups Name of parent group * @returns {IterableIterator} */ - * iterateProperties (node, groups) { + *iterateProperties(node, groups) { for (const item of node.properties) { if (item.type !== 'Property') { continue @@ -853,13 +932,13 @@ module.exports = { if (!name || !groups.has(name)) continue if (item.value.type === 'ArrayExpression') { - yield * this.iterateArrayExpression(item.value, name) + yield* this.iterateArrayExpression(item.value, name) } else if (item.value.type === 'ObjectExpression') { - yield * this.iterateObjectExpression(item.value, name) + yield* this.iterateObjectExpression(item.value, name) } else if (item.value.type === 'FunctionExpression') { - yield * this.iterateFunctionExpression(item.value, name) + yield* this.iterateFunctionExpression(item.value, name) } else if (item.value.type === 'ArrowFunctionExpression') { - yield * this.iterateArrowFunctionExpression(item.value, name) + yield* this.iterateArrowFunctionExpression(item.value, name) } } }, @@ -870,7 +949,7 @@ module.exports = { * @param {string} groupName Name of parent group * @returns {IterableIterator} */ - * iterateArrayExpression (node, groupName) { + *iterateArrayExpression(node, groupName) { assert(node.type === 'ArrayExpression') for (const item of node.elements) { if (item.type === 'Literal' || item.type === 'TemplateLiteral') { @@ -888,28 +967,40 @@ module.exports = { * @param {string} groupName Name of parent group * @returns {IterableIterator} */ - * iterateObjectExpression (node, groupName) { + *iterateObjectExpression(node, groupName) { assert(node.type === 'ObjectExpression') let usedGetter for (const item of node.properties) { if (item.type === 'Property') { const key = item.key - if (key.type === 'Identifier' || key.type === 'Literal' || key.type === 'TemplateLiteral') { + if ( + key.type === 'Identifier' || + key.type === 'Literal' || + key.type === 'TemplateLiteral' + ) { const name = getStaticPropertyName(item) if (name) { if (item.kind === 'set') { // find getter pair - if (!usedGetter) { usedGetter = new Set() } - if (node.properties.some(item2 => { - if (item2.type === 'Property' && item2.kind === 'get' && !usedGetter.has(item2)) { - const getterName = getStaticPropertyName(item2) - if (getterName === name) { - usedGetter.add(item2) - return true + if (!usedGetter) { + usedGetter = new Set() + } + if ( + node.properties.some((item2) => { + if ( + item2.type === 'Property' && + item2.kind === 'get' && + !usedGetter.has(item2) + ) { + const getterName = getStaticPropertyName(item2) + if (getterName === name) { + usedGetter.add(item2) + return true + } } - } - return false - })) { + return false + }) + ) { // has getter pair continue } @@ -927,12 +1018,16 @@ module.exports = { * @param {string} groupName Name of parent group * @returns {IterableIterator} */ - * iterateFunctionExpression (node, groupName) { + *iterateFunctionExpression(node, groupName) { assert(node.type === 'FunctionExpression') if (node.body.type === 'BlockStatement') { for (const item of node.body.body) { - if (item.type === 'ReturnStatement' && item.argument && item.argument.type === 'ObjectExpression') { - yield * this.iterateObjectExpression(item.argument, groupName) + if ( + item.type === 'ReturnStatement' && + item.argument && + item.argument.type === 'ObjectExpression' + ) { + yield* this.iterateObjectExpression(item.argument, groupName) } } } @@ -944,17 +1039,21 @@ module.exports = { * @param {string} groupName Name of parent group * @returns {IterableIterator} */ - * iterateArrowFunctionExpression (node, groupName) { + *iterateArrowFunctionExpression(node, groupName) { assert(node.type === 'ArrowFunctionExpression') const body = node.body if (body.type === 'BlockStatement') { for (const item of body.body) { - if (item.type === 'ReturnStatement' && item.argument && item.argument.type === 'ObjectExpression') { - yield * this.iterateObjectExpression(item.argument, groupName) + if ( + item.type === 'ReturnStatement' && + item.argument && + item.argument.type === 'ObjectExpression' + ) { + yield* this.iterateObjectExpression(item.argument, groupName) } } } else if (body.type === 'ObjectExpression') { - yield * this.iterateObjectExpression(body, groupName) + yield* this.iterateObjectExpression(body, groupName) } }, @@ -963,7 +1062,7 @@ module.exports = { * @param {boolean} treatUndefinedAsUnspecified * @param {Function} cb Callback function */ - executeOnFunctionsWithoutReturn (treatUndefinedAsUnspecified, cb) { + executeOnFunctionsWithoutReturn(treatUndefinedAsUnspecified, cb) { let funcInfo = { funcInfo: null, codePath: null, @@ -972,11 +1071,11 @@ module.exports = { node: null } - function isReachable (segment) { + function isReachable(segment) { return segment.reachable } - function isValidReturn () { + function isValidReturn() { if (funcInfo.codePath.currentSegments.some(isReachable)) { return false } @@ -984,7 +1083,7 @@ module.exports = { } return { - onCodePathStart (codePath, node) { + onCodePathStart(codePath, node) { funcInfo = { codePath, funcInfo, @@ -993,19 +1092,19 @@ module.exports = { node } }, - onCodePathEnd () { + onCodePathEnd() { funcInfo = funcInfo.funcInfo }, - ReturnStatement (node) { + ReturnStatement(node) { funcInfo.hasReturn = true funcInfo.hasReturnValue = Boolean(node.argument) }, - 'ArrowFunctionExpression:exit' (node) { + 'ArrowFunctionExpression:exit'(node) { if (!isValidReturn() && !node.expression) { cb(funcInfo.node) } }, - 'FunctionExpression:exit' (node) { + 'FunctionExpression:exit'(node) { if (!isValidReturn()) { cb(funcInfo.node) } @@ -1018,7 +1117,7 @@ module.exports = { * @param {ASTNode} node * @returns {boolean} */ - isSingleLine (node) { + isSingleLine(node) { return node.loc.start.line === node.loc.end.line }, @@ -1027,12 +1126,14 @@ module.exports = { * @param {Program} node The program node to check. * @returns {boolean} `true` if it has invalid EOF. */ - hasInvalidEOF (node) { + hasInvalidEOF(node) { const body = node.templateBody if (body == null || body.errors == null) { return } - return body.errors.some(error => typeof error.code === 'string' && error.code.startsWith('eof-')) + return body.errors.some( + (error) => typeof error.code === 'string' && error.code.startsWith('eof-') + ) }, /** @@ -1041,7 +1142,7 @@ module.exports = { * @param {ESLintNode} node The node to parse * @return {[ESLintNode, ...MemberExpression[]]} The chaining nodes */ - getMemberChaining (node) { + getMemberChaining(node) { const nodes = [] let n = node @@ -1059,7 +1160,7 @@ module.exports = { * @param {ASTNode} node The node to parse (MemberExpression | CallExpression) * @return {String} eg. 'this.asd.qwe().map().filter().test.reduce()' */ - parseMemberOrCallExpression (node) { + parseMemberOrCallExpression(node) { const parsedCallee = [] let n = node let isFunc @@ -1096,13 +1197,13 @@ module.exports = { * @param {string} b string b to compare * @returns {number} */ - editDistance (a, b) { + editDistance(a, b) { if (a === b) { return 0 } const alen = a.length const blen = b.length - const dp = Array.from({ length: alen + 1 }).map(_ => + const dp = Array.from({ length: alen + 1 }).map((_) => Array.from({ length: blen + 1 }).fill(0) ) for (let i = 0; i <= alen; i++) { @@ -1135,7 +1236,7 @@ module.exports = { * @param {ASTNode} node The node to check * @returns {boolean} `true` if the given node is `this`. */ - isThis (node, context) { + isThis(node, context) { if (node.type === 'ThisExpression') { return true } @@ -1162,7 +1263,9 @@ module.exports = { def.parent.kind === 'const' && def.node.id.type === 'Identifier' ) { - return def.node && def.node.init && def.node.init.type === 'ThisExpression' + return ( + def.node && def.node.init && def.node.init.type === 'ThisExpression' + ) } } return false @@ -1172,7 +1275,7 @@ module.exports = { * @param {MemberExpression|Identifier} props * @returns { { kind: 'assignment' | 'update' | 'call' , node: Node, pathNodes: MemberExpression[] } } */ - findMutating (props) { + findMutating(props) { /** @type {MemberExpression[]} */ const pathNodes = [] let node = props @@ -1197,7 +1300,12 @@ module.exports = { } else if (target.type === 'CallExpression') { if (node !== props && target.callee === node) { const callName = getStaticPropertyName(node) - if (callName && /^push|pop|shift|unshift|reverse|splice|sort|copyWithin|fill$/u.exec(callName)) { + if ( + callName && + /^push|pop|shift|unshift|reverse|splice|sort|copyWithin|fill$/u.exec( + callName + ) + ) { // this.xxx.push() pathNodes.pop() return { @@ -1231,15 +1339,23 @@ module.exports = { * @param {Object} [scriptVisitor] The visitor to traverse the script. * @returns {Object} The merged visitor. */ -function defineTemplateBodyVisitor (context, templateBodyVisitor, scriptVisitor) { +function defineTemplateBodyVisitor( + context, + templateBodyVisitor, + scriptVisitor +) { if (context.parserServices.defineTemplateBodyVisitor == null) { context.report({ loc: { line: 1, column: 0 }, - message: 'Use the latest vue-eslint-parser. See also https://eslint.vuejs.org/user-guide/#what-is-the-use-the-latest-vue-eslint-parser-error' + message: + 'Use the latest vue-eslint-parser. See also https://eslint.vuejs.org/user-guide/#what-is-the-use-the-latest-vue-eslint-parser-error' }) return {} } - return context.parserServices.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor) + return context.parserServices.defineTemplateBodyVisitor( + templateBodyVisitor, + scriptVisitor + ) } /** @@ -1248,8 +1364,12 @@ function defineTemplateBodyVisitor (context, templateBodyVisitor, scriptVisitor) * @param {T} node * @return {T} */ -function unwrapTypes (node) { - return !node ? node : node.type === 'TSAsExpression' ? unwrapTypes(node.expression) : node +function unwrapTypes(node) { + return !node + ? node + : node.type === 'TSAsExpression' + ? unwrapTypes(node.expression) + : node } /** @@ -1257,7 +1377,7 @@ function unwrapTypes (node) { * @param {Property|MethodDefinition|MemberExpression|Literal|TemplateLiteral|Identifier} node - The node to get. * @return {string|null} The property name if static. Otherwise, null. */ -function getStaticPropertyName (node) { +function getStaticPropertyName(node) { let prop switch (node && node.type) { case 'Property': @@ -1272,7 +1392,7 @@ function getStaticPropertyName (node) { case 'Identifier': prop = node break - // no default + // no default } switch (prop && prop.type) { @@ -1288,13 +1408,13 @@ function getStaticPropertyName (node) { return prop.name } break - // no default + // no default } return null } -function isVueFile (path) { +function isVueFile(path) { return path.endsWith('.vue') || path.endsWith('.jsx') } @@ -1306,10 +1426,12 @@ function isVueFile (path) { * @param {string} path File name with extension * @returns {boolean} */ -function isVueComponentFile (node, path) { - return isVueFile(path) && - node.type === 'ExportDefaultDeclaration' && - node.declaration.type === 'ObjectExpression' +function isVueComponentFile(node, path) { + return ( + isVueFile(path) && + node.type === 'ExportDefaultDeclaration' && + node.declaration.type === 'ObjectExpression' + ) } /** @@ -1318,7 +1440,7 @@ function isVueComponentFile (node, path) { * @param {ASTNode} node Node to check * @returns {boolean} */ -function isVueComponent (node) { +function isVueComponent(node) { if (node.type === 'CallExpression') { const callee = node.callee @@ -1331,8 +1453,8 @@ function isVueComponent (node) { // for Vue.js 2.x // Vue.component('xxx', {}) || Vue.mixin({}) || Vue.extend('xxx', {}) const isFullVueComponentForVue2 = - ['component', 'mixin', 'extend'].includes(propName) && - isObjectArgument(node) + ['component', 'mixin', 'extend'].includes(propName) && + isObjectArgument(node) return isFullVueComponentForVue2 } @@ -1340,8 +1462,7 @@ function isVueComponent (node) { // for Vue.js 3.x // app.component('xxx', {}) || app.mixin({}) const isFullVueComponent = - ['component', 'mixin'].includes(propName) && - isObjectArgument(node) + ['component', 'mixin'].includes(propName) && isObjectArgument(node) return isFullVueComponent } @@ -1371,9 +1492,11 @@ function isVueComponent (node) { return false - function isObjectArgument (node) { - return node.arguments.length > 0 && - unwrapTypes(node.arguments.slice(-1)[0]).type === 'ObjectExpression' + function isObjectArgument(node) { + return ( + node.arguments.length > 0 && + unwrapTypes(node.arguments.slice(-1)[0]).type === 'ObjectExpression' + ) } } @@ -1383,13 +1506,15 @@ function isVueComponent (node) { * @param {ASTNode} node Node to check * @returns {boolean} */ -function isVueInstance (node) { +function isVueInstance(node) { const callee = node.callee - return node.type === 'NewExpression' && - callee.type === 'Identifier' && - callee.name === 'Vue' && - node.arguments.length && - unwrapTypes(node.arguments[0]).type === 'ObjectExpression' + return ( + node.type === 'NewExpression' && + callee.type === 'Identifier' && + callee.name === 'Vue' && + node.arguments.length && + unwrapTypes(node.arguments[0]).type === 'ObjectExpression' + ) } /** @@ -1398,7 +1523,7 @@ function isVueInstance (node) { * @param {ObjectExpression} node Node to check * @returns { 'mark' | 'export' | 'definition' | 'instance' | null } The Vue definition type. */ -function getVueObjectType (context, node) { +function getVueObjectType(context, node) { if (node.type !== 'ObjectExpression') { return null } @@ -1410,12 +1535,18 @@ function getVueObjectType (context, node) { if (parent.type === 'ExportDefaultDeclaration') { // export default {} in .vue || .jsx const filePath = context.getFilename() - if (isVueComponentFile(parent, filePath) && unwrapTypes(parent.declaration) === node) { + if ( + isVueComponentFile(parent, filePath) && + unwrapTypes(parent.declaration) === node + ) { return 'export' } } else if (parent.type === 'CallExpression') { // Vue.component('xxx', {}) || component('xxx', {}) - if (isVueComponent(parent) && unwrapTypes(parent.arguments.slice(-1)[0]) === node) { + if ( + isVueComponent(parent) && + unwrapTypes(parent.arguments.slice(-1)[0]) === node + ) { return 'definition' } } else if (parent.type === 'NewExpression') { @@ -1425,7 +1556,11 @@ function getVueObjectType (context, node) { } } } - if (getComponentComments(context).some(el => el.loc.end.line === node.loc.start.line - 1)) { + if ( + getComponentComments(context).some( + (el) => el.loc.end.line === node.loc.start.line - 1 + ) + ) { return 'mark' } return null @@ -1436,18 +1571,20 @@ function getVueObjectType (context, node) { * @param {RuleContext} context The ESLint rule context object. * @return {Token[]} The the component comments. */ -function getComponentComments (context) { +function getComponentComments(context) { let tokens = componentComments.get(context) if (tokens) { return tokens } const sourceCode = context.getSourceCode() - tokens = sourceCode.getAllComments().filter(comment => /@vue\/component/g.test(comment.value)) + tokens = sourceCode + .getAllComments() + .filter((comment) => /@vue\/component/g.test(comment.value)) componentComments.set(context, tokens) return tokens } -function compositingVisitors (visitor, ...visitors) { +function compositingVisitors(visitor, ...visitors) { for (const v of visitors) { for (const key in v) { if (visitor[key]) { diff --git a/tests/lib/rules/order-in-components.js b/tests/lib/rules/order-in-components.js index 9e6dbb2d8..5c99608fc 100644 --- a/tests/lib/rules/order-in-components.js +++ b/tests/lib/rules/order-in-components.js @@ -15,7 +15,6 @@ const parserOptions = { } ruleTester.run('order-in-components', rule, { - valid: [ { filename: 'test.vue', @@ -199,10 +198,13 @@ ruleTester.run('order-in-components', rule, { }, } `, - errors: [{ - message: 'The "props" property should be above the "data" property on line 4.', - line: 9 - }] + errors: [ + { + message: + 'The "props" property should be above the "data" property on line 4.', + line: 9 + } + ] }, { filename: 'test.jsx', @@ -224,7 +226,11 @@ ruleTester.run('order-in-components', rule, { }, } `, - parserOptions: { ecmaVersion: 6, sourceType: 'module', ecmaFeatures: { jsx: true }}, + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + ecmaFeatures: { jsx: true } + }, output: ` export default { name: 'app', @@ -243,16 +249,23 @@ ruleTester.run('order-in-components', rule, { }, } `, - errors: [{ - message: 'The "name" property should be above the "render" property on line 3.', - line: 8 - }, { - message: 'The "data" property should be above the "render" property on line 3.', - line: 9 - }, { - message: 'The "props" property should be above the "data" property on line 9.', - line: 14 - }] + errors: [ + { + message: + 'The "name" property should be above the "render" property on line 3.', + line: 8 + }, + { + message: + 'The "data" property should be above the "render" property on line 3.', + line: 9 + }, + { + message: + 'The "props" property should be above the "data" property on line 9.', + line: 14 + } + ] }, { filename: 'test.js', @@ -281,10 +294,13 @@ ruleTester.run('order-in-components', rule, { template: '
' }) `, - errors: [{ - message: 'The "components" property should be above the "data" property on line 4.', - line: 9 - }] + errors: [ + { + message: + 'The "components" property should be above the "data" property on line 4.', + line: 9 + } + ] }, { filename: 'test.js', @@ -313,10 +329,13 @@ ruleTester.run('order-in-components', rule, { template: '
' }) `, - errors: [{ - message: 'The "components" property should be above the "data" property on line 4.', - line: 9 - }] + errors: [ + { + message: + 'The "components" property should be above the "data" property on line 4.', + line: 9 + } + ] }, { filename: 'test.js', @@ -347,10 +366,13 @@ ruleTester.run('order-in-components', rule, { template: '
' }) `, - errors: [{ - message: 'The "components" property should be above the "data" property on line 5.', - line: 10 - }] + errors: [ + { + message: + 'The "components" property should be above the "data" property on line 5.', + line: 10 + } + ] }, { filename: 'test.js', @@ -381,13 +403,18 @@ ruleTester.run('order-in-components', rule, { template: '
' }) `, - errors: [{ - message: 'The "el" property should be above the "name" property on line 3.', - line: 4 - }, { - message: 'The "components" property should be above the "data" property on line 5.', - line: 10 - }] + errors: [ + { + message: + 'The "el" property should be above the "name" property on line 3.', + line: 4 + }, + { + message: + 'The "components" property should be above the "data" property on line 5.', + line: 10 + } + ] }, { filename: 'example.vue', @@ -428,10 +455,13 @@ ruleTester.run('order-in-components', rule, { }, }; `, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 16 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 16 + } + ] }, { filename: 'example.vue', @@ -453,10 +483,13 @@ ruleTester.run('order-in-components', rule, { }; `, options: [{ order: ['data', 'test', 'name'] }], - errors: [{ - message: 'The "test" property should be above the "name" property on line 5.', - line: 6 - }] + errors: [ + { + message: + 'The "test" property should be above the "name" property on line 5.', + line: 6 + } + ] }, { filename: 'example.vue', @@ -479,10 +512,13 @@ ruleTester.run('order-in-components', rule, { } }; `, - errors: [{ - message: 'The "name" property should be above the "data" property on line 4.', - line: 7 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 4.', + line: 7 + } + ] }, { filename: 'example.vue', @@ -505,20 +541,26 @@ ruleTester.run('order-in-components', rule, { }/*test*/ }; `, - errors: [{ - message: 'The "name" property should be above the "data" property on line 4.', - line: 7 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 4.', + line: 7 + } + ] }, { filename: 'example.vue', code: `export default {data(){},name:'burger'};`, parserOptions, output: `export default {name:'burger',data(){}};`, - errors: [{ - message: 'The "name" property should be above the "data" property on line 1.', - line: 1 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 1.', + line: 1 + } + ] }, { // side-effects CallExpression @@ -533,10 +575,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects NewExpression @@ -551,10 +596,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects UpdateExpression @@ -569,10 +617,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects AssignmentExpression @@ -587,10 +638,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects TaggedTemplateExpression @@ -605,10 +659,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects key @@ -623,10 +680,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects object deep props @@ -641,10 +701,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects array elements @@ -659,10 +722,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects call at middle @@ -677,10 +743,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects delete @@ -695,10 +764,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects within BinaryExpression @@ -713,10 +785,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects within ConditionalExpression @@ -731,10 +806,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // side-effects within TemplateLiteral @@ -749,10 +827,13 @@ ruleTester.run('order-in-components', rule, { `, parserOptions, output: null, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 6 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 6 + } + ] }, { // without side-effects @@ -774,10 +855,13 @@ ruleTester.run('order-in-components', rule, { test: fn(), }; `, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 5 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 5 + } + ] }, { // don't side-effects @@ -815,10 +899,13 @@ ruleTester.run('order-in-components', rule, { testNullish: a ?? b, }; `, - errors: [{ - message: 'The "name" property should be above the "data" property on line 3.', - line: 14 - }] + errors: [ + { + message: + 'The "name" property should be above the "data" property on line 3.', + line: 14 + } + ] } ] }) diff --git a/tests/lib/rules/require-direct-export.js b/tests/lib/rules/require-direct-export.js index 16b6aa96a..d8dc568b1 100644 --- a/tests/lib/rules/require-direct-export.js +++ b/tests/lib/rules/require-direct-export.js @@ -23,7 +23,6 @@ const ruleTester = new RuleTester({ } }) ruleTester.run('require-direct-export', rule, { - valid: [ { filename: 'test.vue', @@ -84,11 +83,13 @@ ruleTester.run('require-direct-export', rule, { code: ` const A = {}; export default A`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 3 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 3 + } + ] }, { filename: 'test.vue', @@ -97,38 +98,46 @@ ruleTester.run('require-direct-export', rule, { return h('div', props.msg) }; export default A`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 5 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 5 + } + ] }, { filename: 'test.vue', code: `export default function NoReturn() {}`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 1 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 1 + } + ] }, { filename: 'test.vue', code: `export default function () {}`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 1 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 1 + } + ] }, { filename: 'test.vue', code: `export default () => {}`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 1 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 1 + } + ] }, { filename: 'test.vue', @@ -137,22 +146,26 @@ ruleTester.run('require-direct-export', rule, { return b } }`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 1 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 1 + } + ] }, { filename: 'test.vue', code: `export default () => { return }`, - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 1 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 1 + } + ] }, { filename: 'test.vue', @@ -162,11 +175,13 @@ ruleTester.run('require-direct-export', rule, { }; export default A`, options: [{ disallowFunctionalComponentFunction: true }], - errors: [{ - message: 'Expected the component literal to be directly exported.', - type: 'ExportDefaultDeclaration', - line: 5 - }] + errors: [ + { + message: 'Expected the component literal to be directly exported.', + type: 'ExportDefaultDeclaration', + line: 5 + } + ] }, { filename: 'test.vue', diff --git a/tests/lib/utils/vue-component.js b/tests/lib/utils/vue-component.js index 794075d47..91da3d28c 100644 --- a/tests/lib/utils/vue-component.js +++ b/tests/lib/utils/vue-component.js @@ -10,8 +10,8 @@ const utils = require('../../../lib/utils/index') // ------------------------------------------------------------------------------ const rule = { - create (context) { - return utils.executeOnVueComponent(context, obj => { + create(context) { + return utils.executeOnVueComponent(context, (obj) => { context.report({ node: obj, message: 'Component detected.' @@ -30,7 +30,7 @@ const parserOptions = { sourceType: 'module' } -function makeError (line) { +function makeError(line) { return { message: 'Component detected.', line, @@ -38,7 +38,7 @@ function makeError (line) { } } -function validTests (ext) { +function validTests(ext) { return [ { filename: `test.${ext}`, @@ -118,7 +118,7 @@ function validTests (ext) { ] } -function invalidTests (ext) { +function invalidTests(ext) { return [ { filename: `test.${ext}`, @@ -327,14 +327,16 @@ function invalidTests (ext) { const ruleTester = new RuleTester() ruleTester.run('vue-component', rule, { - valid: [ { filename: 'test.js', code: `export default { }`, parserOptions } - ].concat(validTests('js')).concat(validTests('jsx')).concat(validTests('vue')), + ] + .concat(validTests('js')) + .concat(validTests('jsx')) + .concat(validTests('vue')), invalid: [ { filename: 'test.vue', @@ -348,5 +350,8 @@ ruleTester.run('vue-component', rule, { parserOptions, errors: [makeError(1)] } - ].concat(invalidTests('js')).concat(invalidTests('jsx')).concat(invalidTests('vue')) + ] + .concat(invalidTests('js')) + .concat(invalidTests('jsx')) + .concat(invalidTests('vue')) })