diff --git a/lib/rules/no-template-shadow.js b/lib/rules/no-template-shadow.js
index 44f26cf57..f66f8a701 100644
--- a/lib/rules/no-template-shadow.js
+++ b/lib/rules/no-template-shadow.js
@@ -19,7 +19,7 @@ const utils = require('../utils')
// ------------------------------------------------------------------------------
/** @type {GroupName[]} */
-const GROUP_NAMES = ['props', 'computed', 'data', 'methods']
+const GROUP_NAMES = ['props', 'computed', 'data', 'methods', 'setup']
module.exports = {
meta: {
@@ -50,44 +50,43 @@ module.exports = {
// Public
// ----------------------------------------------------------------------
- return utils.defineTemplateBodyVisitor(
- context,
- {
- /** @param {VElement} node */
- VElement(node) {
- scopeStack = {
- parent: scopeStack,
- nodes: scopeStack
- ? scopeStack.nodes.slice() // make copy
- : []
- }
- if (node.variables) {
- for (const variable of node.variables) {
- const varNode = variable.id
- const name = varNode.name
- if (
- scopeStack.nodes.some((node) => node.name === name) ||
- jsVars.has(name)
- ) {
- context.report({
- node: varNode,
- loc: varNode.loc,
- message:
- "Variable '{{name}}' is already declared in the upper scope.",
- data: {
- name
- }
- })
- } else {
- scopeStack.nodes.push(varNode)
+ return utils.compositingVisitors(
+ utils.isScriptSetup(context)
+ ? {
+ Program() {
+ const globalScope =
+ context.getSourceCode().scopeManager.globalScope
+ if (!globalScope) {
+ return
+ }
+ for (const variable of globalScope.variables) {
+ if (variable.defs.length > 0) {
+ jsVars.add(variable.name)
+ }
+ }
+ const moduleScope = globalScope.childScopes.find(
+ (scope) => scope.type === 'module'
+ )
+ if (!moduleScope) {
+ return
+ }
+ for (const variable of moduleScope.variables) {
+ if (variable.defs.length > 0) {
+ jsVars.add(variable.name)
+ }
}
}
}
- },
- 'VElement:exit'() {
- scopeStack = scopeStack && scopeStack.parent
+ : {},
+ utils.defineScriptSetupVisitor(context, {
+ onDefinePropsEnter(_node, props) {
+ for (const prop of props) {
+ if (prop.propName) {
+ jsVars.add(prop.propName)
+ }
+ }
}
- },
+ }),
utils.executeOnVue(context, (obj) => {
const properties = Array.from(
utils.iterateProperties(obj, new Set(GROUP_NAMES))
@@ -95,6 +94,38 @@ module.exports = {
for (const node of properties) {
jsVars.add(node.name)
}
+ }),
+ utils.defineTemplateBodyVisitor(context, {
+ /** @param {VElement} node */
+ VElement(node) {
+ scopeStack = {
+ parent: scopeStack,
+ nodes: scopeStack ? [...scopeStack.nodes] : []
+ }
+ for (const variable of node.variables) {
+ const varNode = variable.id
+ const name = varNode.name
+ if (
+ scopeStack.nodes.some((node) => node.name === name) ||
+ jsVars.has(name)
+ ) {
+ context.report({
+ node: varNode,
+ loc: varNode.loc,
+ message:
+ "Variable '{{name}}' is already declared in the upper scope.",
+ data: {
+ name
+ }
+ })
+ } else {
+ scopeStack.nodes.push(varNode)
+ }
+ }
+ },
+ 'VElement:exit'() {
+ scopeStack = scopeStack && scopeStack.parent
+ }
})
)
}
diff --git a/tests/lib/rules/no-template-shadow.js b/tests/lib/rules/no-template-shadow.js
index 872dffcf1..1f1daa184 100644
--- a/tests/lib/rules/no-template-shadow.js
+++ b/tests/lib/rules/no-template-shadow.js
@@ -115,6 +115,54 @@ ruleTester.run('no-template-shadow', rule, {
}
}
`
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `
}
],
@@ -345,6 +393,72 @@ ruleTester.run('no-template-shadow', rule, {
line: 7
}
]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `,
+ errors: [
+ {
+ message: "Variable 'j' is already declared in the upper scope.",
+ line: 4
+ }
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `,
+ errors: [
+ {
+ message: "Variable 'j' is already declared in the upper scope.",
+ line: 4
+ }
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `,
+ errors: [
+ {
+ message: "Variable 'j' is already declared in the upper scope.",
+ line: 4
+ }
+ ]
}
]
})