eslint-plugin-vue
Advanced tools
Comparing version 9.11.0 to 9.12.0
@@ -9,2 +9,3 @@ /* | ||
module.exports = { | ||
meta: require('./meta'), | ||
rules: { | ||
@@ -127,2 +128,3 @@ 'array-bracket-newline': require('./rules/array-bracket-newline'), | ||
'no-restricted-v-bind': require('./rules/no-restricted-v-bind'), | ||
'no-root-v-if': require('./rules/no-root-v-if'), | ||
'no-setup-props-destructure': require('./rules/no-setup-props-destructure'), | ||
@@ -129,0 +131,0 @@ 'no-shared-component-data': require('./rules/no-shared-component-data'), |
@@ -127,3 +127,5 @@ /** | ||
supportsAutofix: true | ||
supportsAutofix: true, | ||
meta: require('./meta') | ||
} | ||
@@ -130,0 +132,0 @@ |
@@ -7,2 +7,6 @@ /** | ||
/** | ||
* @typedef {{name?: string, set: Set<string>}} PropsInfo | ||
*/ | ||
const utils = require('../utils') | ||
@@ -88,2 +92,15 @@ const { findVariable } = require('@eslint-community/eslint-utils') | ||
/** | ||
* @param { object } options | ||
* @param { boolean } options.shallowOnly Enables mutating the value of a prop but leaving the reference the same | ||
*/ | ||
function parseOptions(options) { | ||
return Object.assign( | ||
{ | ||
shallowOnly: false | ||
}, | ||
options | ||
) | ||
} | ||
module.exports = { | ||
@@ -99,3 +116,11 @@ meta: { | ||
schema: [ | ||
// fill in your schema | ||
{ | ||
type: 'object', | ||
properties: { | ||
shallowOnly: { | ||
type: 'boolean' | ||
} | ||
}, | ||
additionalProperties: false | ||
} | ||
] | ||
@@ -105,3 +130,4 @@ }, | ||
create(context) { | ||
/** @type {Map<ObjectExpression|CallExpression, Set<string>>} */ | ||
const { shallowOnly } = parseOptions(context.options[0]) | ||
/** @type {Map<ObjectExpression|CallExpression, PropsInfo>} */ | ||
const propsMap = new Map() | ||
@@ -145,6 +171,7 @@ /** @type { { type: 'export' | 'mark' | 'definition', object: ObjectExpression } | { type: 'setup', object: CallExpression } | null } */ | ||
* @param {string} name | ||
* @param {boolean} isRootProps | ||
*/ | ||
function verifyMutating(props, name) { | ||
function verifyMutating(props, name, isRootProps = false) { | ||
const invalid = utils.findMutating(props) | ||
if (invalid) { | ||
if (invalid && isShallowOnlyInvalid(invalid, isRootProps)) { | ||
report(invalid.node, name) | ||
@@ -218,2 +245,5 @@ } | ||
let name | ||
if (!isShallowOnlyInvalid(invalid, path.length === 0)) { | ||
continue | ||
} | ||
if (path.length === 0) { | ||
@@ -255,2 +285,16 @@ if (invalid.pathNodes.length === 0) { | ||
/** | ||
* Is shallowOnly false or the prop reassigned | ||
* @param {Exclude<ReturnType<typeof utils.findMutating>, null>} invalid | ||
* @param {boolean} isRootProps | ||
* @return {boolean} | ||
*/ | ||
function isShallowOnlyInvalid(invalid, isRootProps) { | ||
return ( | ||
!shallowOnly || | ||
(invalid.pathNodes.length === (isRootProps ? 1 : 0) && | ||
['assignment', 'update'].includes(invalid.kind)) | ||
) | ||
} | ||
return utils.compositingVisitors( | ||
@@ -262,16 +306,19 @@ {}, | ||
const propsSet = new Set( | ||
props | ||
.map((p) => p.propName) | ||
.filter( | ||
/** | ||
* @returns {propName is string} | ||
*/ | ||
(propName) => | ||
utils.isDef(propName) && | ||
!GLOBALS_WHITE_LISTED.has(propName) && | ||
!defineVariableNames.has(propName) | ||
) | ||
) | ||
propsMap.set(node, propsSet) | ||
const propsInfo = { | ||
name: '', | ||
set: new Set( | ||
props | ||
.map((p) => p.propName) | ||
.filter( | ||
/** | ||
* @returns {propName is string} | ||
*/ | ||
(propName) => | ||
utils.isDef(propName) && | ||
!GLOBALS_WHITE_LISTED.has(propName) && | ||
!defineVariableNames.has(propName) | ||
) | ||
) | ||
} | ||
propsMap.set(node, propsInfo) | ||
vueObjectData = { | ||
@@ -305,4 +352,8 @@ type: 'setup', | ||
)) { | ||
if (path.length === 0) { | ||
propsInfo.name = prop.name | ||
} else { | ||
propsInfo.set.add(prop.name) | ||
} | ||
verifyPropVariable(prop, path) | ||
propsSet.add(prop.name) | ||
} | ||
@@ -313,5 +364,4 @@ } | ||
onVueObjectEnter(node) { | ||
propsMap.set( | ||
node, | ||
new Set( | ||
propsMap.set(node, { | ||
set: new Set( | ||
utils | ||
@@ -322,3 +372,3 @@ .getComponentPropsFromOptions(node) | ||
) | ||
) | ||
}) | ||
}, | ||
@@ -373,3 +423,3 @@ onVueObjectExit(node, { type }) { | ||
name && | ||
/** @type {Set<string>} */ (propsMap.get(vueNode)).has(name) | ||
/** @type {PropsInfo} */ (propsMap.get(vueNode)).set.has(name) | ||
) { | ||
@@ -393,5 +443,5 @@ verifyMutating(mem, name) | ||
name && | ||
/** @type {Set<string>} */ (propsMap.get(vueObjectData.object)).has( | ||
name | ||
) | ||
/** @type {PropsInfo} */ ( | ||
propsMap.get(vueObjectData.object) | ||
).set.has(name) | ||
) { | ||
@@ -409,10 +459,14 @@ verifyMutating(mem, name) | ||
} | ||
const name = node.name | ||
if ( | ||
name && | ||
/** @type {Set<string>} */ (propsMap.get(vueObjectData.object)).has( | ||
name | ||
) | ||
) { | ||
verifyMutating(node, name) | ||
const propsInfo = /** @type {PropsInfo} */ ( | ||
propsMap.get(vueObjectData.object) | ||
) | ||
const isRootProps = !!node.name && propsInfo.name === node.name | ||
const parent = node.parent | ||
const name = | ||
(isRootProps && | ||
parent.type === 'MemberExpression' && | ||
utils.getStaticPropertyName(parent)) || | ||
node.name | ||
if (name && (propsInfo.set.has(name) || isRootProps)) { | ||
verifyMutating(node, name, isRootProps) | ||
} | ||
@@ -440,2 +494,6 @@ }, | ||
const propsInfo = /** @type {PropsInfo} */ ( | ||
propsMap.get(vueObjectData.object) | ||
) | ||
const nodes = utils.getMemberChaining(node) | ||
@@ -445,4 +503,21 @@ const first = nodes[0] | ||
if (isVmReference(first)) { | ||
name = first.name | ||
if (first.name === propsInfo.name) { | ||
// props variable | ||
if (shallowOnly && nodes.length > 2) { | ||
return | ||
} | ||
name = (nodes[1] && getPropertyNameText(nodes[1])) || first.name | ||
} else { | ||
if (shallowOnly && nodes.length > 1) { | ||
return | ||
} | ||
name = first.name | ||
if (!name || !propsInfo.set.has(name)) { | ||
return | ||
} | ||
} | ||
} else if (first.type === 'ThisExpression') { | ||
if (shallowOnly && nodes.length > 2) { | ||
return | ||
} | ||
const mem = nodes[1] | ||
@@ -453,13 +528,9 @@ if (!mem) { | ||
name = utils.getStaticPropertyName(mem) | ||
if (!name || !propsInfo.set.has(name)) { | ||
return | ||
} | ||
} else { | ||
return | ||
} | ||
if ( | ||
name && | ||
/** @type {Set<string>} */ (propsMap.get(vueObjectData.object)).has( | ||
name | ||
) | ||
) { | ||
report(node, name) | ||
} | ||
report(node, name) | ||
} | ||
@@ -466,0 +537,0 @@ }) |
{ | ||
"name": "eslint-plugin-vue", | ||
"version": "9.11.0", | ||
"version": "9.12.0", | ||
"description": "Official ESLint plugin for Vue.js", | ||
@@ -84,3 +84,3 @@ "main": "lib/index.js", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-unicorn": "^42.0.0", | ||
"eslint-plugin-unicorn": "^47.0.0", | ||
"eslint-plugin-vue": "file:.", | ||
@@ -87,0 +87,0 @@ "espree": "^9.3.2", |
Sorry, the diff of this file is too big to display
1176909
280
38028