Skip to content

Commit

Permalink
Update vue/no-template-shadow rule to support setup() and `<scrip…
Browse files Browse the repository at this point in the history
…t setup>` (#1543)
  • Loading branch information
ota-meshi committed Jul 5, 2021
1 parent 747ab5b commit e495132
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 35 deletions.
101 changes: 66 additions & 35 deletions lib/rules/no-template-shadow.js
Expand Up @@ -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: {
Expand Down Expand Up @@ -50,51 +50,82 @@ 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))
)
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
}
})
)
}
Expand Down
114 changes: 114 additions & 0 deletions tests/lib/rules/no-template-shadow.js
Expand Up @@ -115,6 +115,54 @@ ruleTester.run('no-template-shadow', rule, {
}
}
</script>`
},
{
filename: 'test.vue',
code: `
<template>
<div v-for="i in 5">
<div v-for="j in 5">
</div>
</div>
</template>
<script>
export default {
setup() {
return {
k: 42
}
}
}
</script>
`
},
{
filename: 'test.vue',
code: `
<template>
<div v-for="i in 5">
<div v-for="j in 5">
</div>
</div>
</template>
<script setup>
let k = 42
</script>
`
},
{
filename: 'test.vue',
code: `
<template>
<div v-for="i in 5">
<div v-for="j in 5">
</div>
</div>
</template>
<script setup>
defineProps({k:Number})
</script>
`
}
],

Expand Down Expand Up @@ -345,6 +393,72 @@ ruleTester.run('no-template-shadow', rule, {
line: 7
}
]
},
{
filename: 'test.vue',
code: `
<template>
<div v-for="i in 5">
<div v-for="j in 5">
</div>
</div>
</template>
<script>
export default {
setup() {
return {
j: 42
}
}
}
</script>
`,
errors: [
{
message: "Variable 'j' is already declared in the upper scope.",
line: 4
}
]
},
{
filename: 'test.vue',
code: `
<template>
<div v-for="i in 5">
<div v-for="j in 5">
</div>
</div>
</template>
<script setup>
let j = 42
</script>
`,
errors: [
{
message: "Variable 'j' is already declared in the upper scope.",
line: 4
}
]
},
{
filename: 'test.vue',
code: `
<template>
<div v-for="i in 5">
<div v-for="j in 5">
</div>
</div>
</template>
<script setup>
defineProps({j:Number})
</script>
`,
errors: [
{
message: "Variable 'j' is already declared in the upper scope.",
line: 4
}
]
}
]
})

0 comments on commit e495132

Please sign in to comment.