diff --git a/lib/rules/no-boolean-default.js b/lib/rules/no-boolean-default.js
index e278e3011..6b1f44e74 100644
--- a/lib/rules/no-boolean-default.js
+++ b/lib/rules/no-boolean-default.js
@@ -9,6 +9,7 @@ const utils = require('../utils')
/**
* @typedef {import('../utils').ComponentArrayProp} ComponentArrayProp
* @typedef {import('../utils').ComponentObjectProp} ComponentObjectProp
+ * @typedef {import('../utils').ComponentTypeProp} ComponentTypeProp
*/
// ------------------------------------------------------------------------------
@@ -29,31 +30,10 @@ function isBooleanProp(prop) {
}
/**
- * @typedef {ComponentObjectProp & { value : ObjectExpression }} ObjectExpressionProp
+ * @param {ObjectExpression} propDefValue
*/
-
-/**
- * @param {(ComponentArrayProp | ComponentObjectProp)[]} props
- * @returns {ObjectExpressionProp[]}
- */
-function getBooleanProps(props) {
- return props.filter(
- /**
- * @param {ComponentArrayProp | ComponentObjectProp} prop
- * @returns {prop is ObjectExpressionProp}
- */
- (prop) =>
- prop.value != null &&
- prop.value.type === 'ObjectExpression' &&
- prop.value.properties.some(isBooleanProp)
- )
-}
-
-/**
- * @param {ObjectExpressionProp} propDef
- */
-function getDefaultNode(propDef) {
- return utils.findProperty(propDef.value, 'default')
+function getDefaultNode(propDefValue) {
+ return utils.findProperty(propDefValue, 'default')
}
module.exports = {
@@ -73,42 +53,78 @@ module.exports = {
},
/** @param {RuleContext} context */
create(context) {
- return utils.executeOnVueComponent(context, (obj) => {
- const props = utils.getComponentProps(obj)
- const booleanProps = getBooleanProps(props)
-
- if (!booleanProps.length) return
-
- const booleanType = context.options[0] || 'no-default'
-
- booleanProps.forEach((propDef) => {
- const defaultNode = getDefaultNode(propDef)
+ const booleanType = context.options[0] || 'no-default'
+ /**
+ * @param {ComponentArrayProp | ComponentObjectProp | ComponentTypeProp} prop
+ * @param { { [key: string]: Expression | undefined } } [withDefaultsExpressions]
+ */
+ function processProp(prop, withDefaultsExpressions) {
+ if (prop.type === 'object') {
+ if (prop.value.type !== 'ObjectExpression') {
+ return
+ }
+ if (!prop.value.properties.some(isBooleanProp)) {
+ return
+ }
+ const defaultNode = getDefaultNode(prop.value)
+ if (!defaultNode) {
+ return
+ }
+ verifyDefaultExpression(defaultNode.value)
+ } else if (prop.type === 'type') {
+ if (prop.types.length !== 1 || prop.types[0] !== 'Boolean') {
+ return
+ }
+ const defaultNode =
+ withDefaultsExpressions && withDefaultsExpressions[prop.propName]
if (!defaultNode) {
return
}
+ verifyDefaultExpression(defaultNode)
+ }
+ }
+ /**
+ * @param {(ComponentArrayProp | ComponentObjectProp | ComponentTypeProp)[]} props
+ * @param { { [key: string]: Expression | undefined } } [withDefaultsExpressions]
+ */
+ function processProps(props, withDefaultsExpressions) {
+ for (const prop of props) {
+ processProp(prop, withDefaultsExpressions)
+ }
+ }
+
+ /**
+ * @param {Expression} defaultNode
+ */
+ function verifyDefaultExpression(defaultNode) {
+ switch (booleanType) {
+ case 'no-default':
+ context.report({
+ node: defaultNode,
+ message:
+ 'Boolean prop should not set a default (Vue defaults it to false).'
+ })
+ break
- switch (booleanType) {
- case 'no-default':
+ case 'default-false':
+ if (defaultNode.type !== 'Literal' || defaultNode.value !== false) {
context.report({
node: defaultNode,
- message:
- 'Boolean prop should not set a default (Vue defaults it to false).'
+ message: 'Boolean prop should only be defaulted to false.'
})
- break
-
- case 'default-false':
- if (
- defaultNode.value.type !== 'Literal' ||
- defaultNode.value.value !== false
- ) {
- context.report({
- node: defaultNode,
- message: 'Boolean prop should only be defaulted to false.'
- })
- }
- break
+ }
+ break
+ }
+ }
+ return utils.compositingVisitors(
+ utils.executeOnVueComponent(context, (obj) => {
+ processProps(utils.getComponentProps(obj))
+ }),
+ utils.defineScriptSetupVisitor(context, {
+ onDefinePropsEnter(node, props) {
+ processProps(props, utils.getWithDefaultsPropExpressions(node))
}
})
- })
+ )
}
}
diff --git a/tests/lib/rules/no-boolean-default.js b/tests/lib/rules/no-boolean-default.js
index 7421a049d..ef1af7925 100644
--- a/tests/lib/rules/no-boolean-default.js
+++ b/tests/lib/rules/no-boolean-default.js
@@ -8,6 +8,7 @@
// Requirements
// ------------------------------------------------------------------------------
+const semver = require('semver')
const rule = require('../../../lib/rules/no-boolean-default')
const RuleTester = require('eslint').RuleTester
@@ -229,6 +230,102 @@ ruleTester.run('no-boolean-default', rule, {
}
`,
options: ['default-false']
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser')
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ options: ['default-false']
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ }
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ options: ['default-false']
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ }
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ }
}
],
@@ -314,6 +411,103 @@ ruleTester.run('no-boolean-default', rule, {
line: 6
}
]
- }
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ errors: [
+ {
+ message:
+ 'Boolean prop should not set a default (Vue defaults it to false).',
+ line: 6
+ }
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ options: ['default-false'],
+ errors: [
+ {
+ message: 'Boolean prop should only be defaulted to false.',
+ line: 6
+ }
+ ]
+ },
+ ...(semver.lt(
+ require('@typescript-eslint/parser/package.json').version,
+ '4.0.0'
+ )
+ ? []
+ : [
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ errors: [
+ {
+ message:
+ 'Boolean prop should not set a default (Vue defaults it to false).',
+ line: 7
+ }
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ options: ['default-false'],
+ errors: [
+ {
+ message: 'Boolean prop should only be defaulted to false.',
+ line: 7
+ }
+ ]
+ }
+ ])
]
})