eslint-plugin-vue
Advanced tools
Comparing version 9.2.0 to 9.3.0
@@ -71,5 +71,18 @@ /** | ||
/** @type { string[] } */ | ||
const registeredComponents = [] | ||
/** @type { Set<string> } */ | ||
const registeredComponents = new Set() | ||
if (utils.isScriptSetup(context)) { | ||
// For <script setup> | ||
const globalScope = context.getSourceCode().scopeManager.globalScope | ||
if (globalScope) { | ||
// Only check find the import module | ||
const moduleScope = globalScope.childScopes.find( | ||
(scope) => scope.type === 'module' | ||
) | ||
for (const variable of (moduleScope && moduleScope.variables) || []) { | ||
registeredComponents.add(variable.name) | ||
} | ||
} | ||
} | ||
/** | ||
@@ -99,3 +112,3 @@ * Checks whether the given node is the verification target node. | ||
if ( | ||
registeredComponents | ||
[...registeredComponents] | ||
.filter((name) => casing.isPascalCase(name)) // When defining a component with PascalCase, you can use either case | ||
@@ -158,5 +171,5 @@ .some( | ||
? utils.executeOnVue(context, (obj) => { | ||
registeredComponents.push( | ||
...utils.getRegisteredComponents(obj).map((n) => n.name) | ||
) | ||
for (const n of utils.getRegisteredComponents(obj)) { | ||
registeredComponents.add(n.name) | ||
} | ||
}) | ||
@@ -163,0 +176,0 @@ : {}) |
@@ -28,18 +28,22 @@ /** | ||
/** | ||
* @typedef {object} NameWithLoc | ||
* @property {string} name | ||
* @property {SourceLocation} loc | ||
*/ | ||
/** | ||
* Get the name param node from the given CallExpression | ||
* @param {CallExpression} node CallExpression | ||
* @returns { Literal & { value: string } | null } | ||
* @returns { NameWithLoc | null } | ||
*/ | ||
function getNameParamNode(node) { | ||
const nameLiteralNode = node.arguments[0] | ||
if ( | ||
!nameLiteralNode || | ||
nameLiteralNode.type !== 'Literal' || | ||
typeof nameLiteralNode.value !== 'string' | ||
) { | ||
// cannot check | ||
return null | ||
if (nameLiteralNode && utils.isStringLiteral(nameLiteralNode)) { | ||
const name = utils.getStringLiteralValue(nameLiteralNode) | ||
if (name != null) { | ||
return { name, loc: nameLiteralNode.loc } | ||
} | ||
} | ||
return /** @type {Literal & { value: string }} */ (nameLiteralNode) | ||
// cannot check | ||
return null | ||
} | ||
@@ -134,6 +138,6 @@ /** | ||
/** | ||
* @param { Literal & { value: string } } nameLiteralNode | ||
* @param { NameWithLoc } nameWithLoc | ||
*/ | ||
function verify(nameLiteralNode) { | ||
const name = nameLiteralNode.value | ||
function verify(nameWithLoc) { | ||
const name = nameWithLoc.name | ||
if (isValidEventName(name) || ignores.some((re) => re.test(name))) { | ||
@@ -143,3 +147,3 @@ return | ||
context.report({ | ||
node: nameLiteralNode, | ||
loc: nameWithLoc.loc, | ||
messageId: 'unexpected', | ||
@@ -161,4 +165,4 @@ data: { | ||
CallExpression(node, info) { | ||
const nameLiteralNode = getNameParamNode(node) | ||
if (!nameLiteralNode) { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -177,3 +181,3 @@ return | ||
// verify setup(props,{emit}) {emit()} | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} else { | ||
@@ -188,3 +192,3 @@ const emit = getCalleeMemberNode(node) | ||
// verify setup(props,context) {context.emit()} | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} | ||
@@ -201,4 +205,4 @@ } | ||
const callee = node.callee | ||
const nameLiteralNode = getNameParamNode(node) | ||
if (!nameLiteralNode) { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -208,3 +212,3 @@ return | ||
if (callee.type === 'Identifier' && callee.name === '$emit') { | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} | ||
@@ -211,0 +215,0 @@ } |
@@ -60,18 +60,23 @@ /** | ||
/** | ||
* @typedef {object} NameWithLoc | ||
* @property {string} name | ||
* @property {SourceLocation} loc | ||
* @property {Range} range | ||
*/ | ||
/** | ||
* Get the name param node from the given CallExpression | ||
* @param {CallExpression} node CallExpression | ||
* @returns { Literal & { value: string } | null } | ||
* @returns { NameWithLoc | null } | ||
*/ | ||
function getNameParamNode(node) { | ||
const nameLiteralNode = node.arguments[0] | ||
if ( | ||
!nameLiteralNode || | ||
nameLiteralNode.type !== 'Literal' || | ||
typeof nameLiteralNode.value !== 'string' | ||
) { | ||
// cannot check | ||
return null | ||
if (nameLiteralNode && utils.isStringLiteral(nameLiteralNode)) { | ||
const name = utils.getStringLiteralValue(nameLiteralNode) | ||
if (name != null) { | ||
return { name, loc: nameLiteralNode.loc, range: nameLiteralNode.range } | ||
} | ||
} | ||
return /** @type {Literal & { value: string }} */ (nameLiteralNode) | ||
// cannot check | ||
return null | ||
} | ||
@@ -138,6 +143,6 @@ /** | ||
/** | ||
* @param { Literal & { value: string } } nameLiteralNode | ||
* @param { NameWithLoc } nameWithLoc | ||
*/ | ||
function verify(nameLiteralNode) { | ||
const name = nameLiteralNode.value | ||
function verify(nameWithLoc) { | ||
const name = nameWithLoc.name | ||
@@ -149,3 +154,3 @@ for (const option of options) { | ||
context.report({ | ||
node: nameLiteralNode, | ||
loc: nameWithLoc.loc, | ||
messageId: 'restrictedEvent', | ||
@@ -158,10 +163,10 @@ data: { message }, | ||
const sourceCode = context.getSourceCode() | ||
return fixer.replaceText( | ||
nameLiteralNode, | ||
return fixer.replaceTextRange( | ||
nameWithLoc.range, | ||
`${ | ||
sourceCode.text[nameLiteralNode.range[0]] | ||
sourceCode.text[nameWithLoc.range[0]] | ||
}${JSON.stringify(option.suggest) | ||
.slice(1, -1) | ||
.replace(/'/gu, "\\'")}${ | ||
sourceCode.text[nameLiteralNode.range[1] - 1] | ||
sourceCode.text[nameWithLoc.range[1] - 1] | ||
}` | ||
@@ -186,4 +191,4 @@ ) | ||
const callee = node.callee | ||
const nameLiteralNode = getNameParamNode(node) | ||
if (!nameLiteralNode) { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -193,3 +198,3 @@ return | ||
if (callee.type === 'Identifier' && callee.name === '$emit') { | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} | ||
@@ -248,4 +253,4 @@ } | ||
CallExpression(node, { node: vueNode }) { | ||
const nameLiteralNode = getNameParamNode(node) | ||
if (!nameLiteralNode) { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -264,3 +269,3 @@ return | ||
// verify setup(props,{emit}) {emit()} | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} else { | ||
@@ -275,3 +280,3 @@ const emit = getCalleeMemberNode(node) | ||
// verify setup(props,context) {context.emit()} | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} | ||
@@ -287,4 +292,4 @@ } | ||
CallExpression(node) { | ||
const nameLiteralNode = getNameParamNode(node) | ||
if (!nameLiteralNode) { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -297,3 +302,3 @@ return | ||
// verify this.$emit() | ||
verify(nameLiteralNode) | ||
verify(nameWithLoc) | ||
} | ||
@@ -300,0 +305,0 @@ } |
@@ -57,2 +57,26 @@ /** | ||
]) | ||
/** | ||
* @typedef {object} NameWithLoc | ||
* @property {string} name | ||
* @property {SourceLocation} loc | ||
* @property {Range} range | ||
*/ | ||
/** | ||
* Get the name param node from the given CallExpression | ||
* @param {CallExpression} node CallExpression | ||
* @returns { NameWithLoc | null } | ||
*/ | ||
function getNameParamNode(node) { | ||
const nameLiteralNode = node.arguments[0] | ||
if (nameLiteralNode && utils.isStringLiteral(nameLiteralNode)) { | ||
const name = utils.getStringLiteralValue(nameLiteralNode) | ||
if (name != null) { | ||
return { name, loc: nameLiteralNode.loc, range: nameLiteralNode.range } | ||
} | ||
} | ||
// cannot check | ||
return null | ||
} | ||
// ------------------------------------------------------------------------------ | ||
@@ -118,7 +142,7 @@ // Rule Definition | ||
* @param {ComponentProp[]} props | ||
* @param {Literal} nameLiteralNode | ||
* @param {NameWithLoc} nameWithLoc | ||
* @param {ObjectExpression | Program} vueDefineNode | ||
*/ | ||
function verifyEmit(emits, props, nameLiteralNode, vueDefineNode) { | ||
const name = `${nameLiteralNode.value}` | ||
function verifyEmit(emits, props, nameWithLoc, vueDefineNode) { | ||
const name = nameWithLoc.name | ||
if (emits.some((e) => e.emitName === name || e.emitName == null)) { | ||
@@ -134,3 +158,3 @@ return | ||
context.report({ | ||
node: nameLiteralNode, | ||
loc: nameWithLoc.loc, | ||
messageId: 'missing', | ||
@@ -144,3 +168,3 @@ data: { | ||
}, | ||
suggest: buildSuggest(vueDefineNode, emits, nameLiteralNode, context) | ||
suggest: buildSuggest(vueDefineNode, emits, nameWithLoc, context) | ||
}) | ||
@@ -162,9 +186,9 @@ } | ||
/** | ||
* @param {CallExpression & { arguments: [Literal, ...Expression] }} node | ||
* @param {CallExpression} node | ||
* @param {VueObjectData} [info] | ||
*/ | ||
'CallExpression[arguments.0.type=Literal]'(node, info) { | ||
CallExpression(node, info) { | ||
const callee = utils.skipChainExpression(node.callee) | ||
const nameLiteralNode = node.arguments[0] | ||
if (!nameLiteralNode || typeof nameLiteralNode.value !== 'string') { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -196,3 +220,3 @@ return | ||
vuePropsDeclarations.get(vueDefineNode) || [], | ||
nameLiteralNode, | ||
nameWithLoc, | ||
vueDefineNode | ||
@@ -210,3 +234,3 @@ ) | ||
vuePropsDeclarations.get(vueDefineNode) || [], | ||
nameLiteralNode, | ||
nameWithLoc, | ||
vueDefineNode | ||
@@ -226,3 +250,3 @@ ) | ||
vuePropsDeclarations.get(vueDefineNode) || [], | ||
nameLiteralNode, | ||
nameWithLoc, | ||
vueDefineNode | ||
@@ -238,7 +262,7 @@ ) | ||
{ | ||
/** @param { CallExpression & { argument: [Literal, ...Expression] } } node */ | ||
'CallExpression[arguments.0.type=Literal]'(node) { | ||
/** @param { CallExpression } node */ | ||
CallExpression(node) { | ||
const callee = utils.skipChainExpression(node.callee) | ||
const nameLiteralNode = /** @type {Literal} */ (node.arguments[0]) | ||
if (!nameLiteralNode || typeof nameLiteralNode.value !== 'string') { | ||
const nameWithLoc = getNameParamNode(node) | ||
if (!nameWithLoc) { | ||
// cannot check | ||
@@ -254,3 +278,3 @@ return | ||
vueTemplateDefineData.props, | ||
nameLiteralNode, | ||
nameWithLoc, | ||
vueTemplateDefineData.define | ||
@@ -422,7 +446,7 @@ ) | ||
* @param {ComponentEmit[]} emits | ||
* @param {Literal} nameNode | ||
* @param {NameWithLoc} nameWithLoc | ||
* @param {RuleContext} context | ||
* @returns {Rule.SuggestionReportDescriptor[]} | ||
*/ | ||
function buildSuggest(define, emits, nameNode, context) { | ||
function buildSuggest(define, emits, nameWithLoc, context) { | ||
const emitsKind = | ||
@@ -437,3 +461,3 @@ define.type === 'ObjectExpression' ? '`emits` option' : '`defineEmits`' | ||
data: { | ||
name: `${nameNode.value}`, | ||
name: nameWithLoc.name, | ||
emitsKind | ||
@@ -444,3 +468,3 @@ }, | ||
// Array | ||
return fixer.insertTextAfter(last.node, `, '${nameNode.value}'`) | ||
return fixer.insertTextAfter(last.node, `, '${nameWithLoc.name}'`) | ||
} else if (last.type === 'object') { | ||
@@ -450,3 +474,3 @@ // Object | ||
last.node, | ||
`, '${nameNode.value}': null` | ||
`, '${nameWithLoc.name}': null` | ||
) | ||
@@ -485,7 +509,7 @@ } else { | ||
messageId: 'addOneOption', | ||
data: { name: `${nameNode.value}`, emitsKind }, | ||
data: { name: `${nameWithLoc.name}`, emitsKind }, | ||
fix(fixer) { | ||
return fixer.insertTextAfter( | ||
leftBracket, | ||
`'${nameNode.value}'${ | ||
`'${nameWithLoc.name}'${ | ||
emitsOptionValue.elements.length > 0 ? ',' : '' | ||
@@ -504,7 +528,7 @@ }` | ||
messageId: 'addOneOption', | ||
data: { name: `${nameNode.value}`, emitsKind }, | ||
data: { name: `${nameWithLoc.name}`, emitsKind }, | ||
fix(fixer) { | ||
return fixer.insertTextAfter( | ||
leftBrace, | ||
`'${nameNode.value}': null${ | ||
`'${nameWithLoc.name}': null${ | ||
emitsOptionValue.properties.length > 0 ? ',' : '' | ||
@@ -527,3 +551,3 @@ }` | ||
messageId: 'addArrayEmitsOption', | ||
data: { name: `${nameNode.value}`, emitsKind }, | ||
data: { name: `${nameWithLoc.name}`, emitsKind }, | ||
fix(fixer) { | ||
@@ -533,3 +557,3 @@ if (afterOptionNode) { | ||
sourceCode.getTokenBefore(afterOptionNode), | ||
`\nemits: ['${nameNode.value}'],` | ||
`\nemits: ['${nameWithLoc.name}'],` | ||
) | ||
@@ -542,3 +566,3 @@ } else if (object.properties.length > 0) { | ||
before, | ||
`,\nemits: ['${nameNode.value}']` | ||
`,\nemits: ['${nameWithLoc.name}']` | ||
) | ||
@@ -554,3 +578,3 @@ } else { | ||
objectLeftBrace, | ||
`\nemits: ['${nameNode.value}']${ | ||
`\nemits: ['${nameWithLoc.name}']${ | ||
objectLeftBrace.loc.end.line < objectRightBrace.loc.start.line | ||
@@ -566,3 +590,3 @@ ? '' | ||
messageId: 'addObjectEmitsOption', | ||
data: { name: `${nameNode.value}`, emitsKind }, | ||
data: { name: `${nameWithLoc.name}`, emitsKind }, | ||
fix(fixer) { | ||
@@ -572,3 +596,3 @@ if (afterOptionNode) { | ||
sourceCode.getTokenBefore(afterOptionNode), | ||
`\nemits: {'${nameNode.value}': null},` | ||
`\nemits: {'${nameWithLoc.name}': null},` | ||
) | ||
@@ -581,3 +605,3 @@ } else if (object.properties.length > 0) { | ||
before, | ||
`,\nemits: {'${nameNode.value}': null}` | ||
`,\nemits: {'${nameWithLoc.name}': null}` | ||
) | ||
@@ -593,3 +617,3 @@ } else { | ||
objectLeftBrace, | ||
`\nemits: {'${nameNode.value}': null}${ | ||
`\nemits: {'${nameWithLoc.name}': null}${ | ||
objectLeftBrace.loc.end.line < objectRightBrace.loc.start.line | ||
@@ -596,0 +620,0 @@ ? '' |
{ | ||
"name": "eslint-plugin-vue", | ||
"version": "9.2.0", | ||
"version": "9.3.0", | ||
"description": "Official ESLint plugin for Vue.js", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1150683
36280