Skip to content

Commit 5ab2abc

Browse files
authored
Merge branch 'master' into update-resources
2 parents 43f9f1d + 15f7032 commit 5ab2abc

9 files changed

+279
-23
lines changed

Diff for: docs/rules/multi-word-component-names.md

+4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ export default {
169169

170170
</eslint-code-block>
171171

172+
## :couple: Related Rules
173+
174+
- [vue/no-reserved-component-names](./no-reserved-component-names.md)
175+
172176
## :books: Further Reading
173177

174178
- [Style guide - Multi-word component names](https://vuejs.org/style-guide/rules-essential.html#use-multi-word-component-names)

Diff for: docs/rules/no-reserved-component-names.md

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export default {
7272

7373
</eslint-code-block>
7474

75+
## :couple: Related Rules
76+
77+
- [vue/multi-word-component-names](./multi-word-component-names.md)
78+
7579
## :books: Further Reading
7680

7781
- [List of html elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element)

Diff for: lib/rules/no-dupe-keys.js

+39-17
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
*/
55
'use strict'
66

7+
const { findVariable } = require('@eslint-community/eslint-utils')
78
const utils = require('../utils')
89

910
/**
1011
* @typedef {import('../utils').GroupName} GroupName
12+
* @typedef {import('eslint').Scope.Variable} Variable
13+
* @typedef {import('../utils').ComponentProp} ComponentProp
1114
*/
1215

1316
/** @type {GroupName[]} */
@@ -39,24 +42,43 @@ module.exports = {
3942
const options = context.options[0] || {}
4043
const groups = new Set([...GROUP_NAMES, ...(options.groups || [])])
4144

42-
return utils.executeOnVue(context, (obj) => {
43-
/** @type {Set<string>} */
44-
const usedNames = new Set()
45-
const properties = utils.iterateProperties(obj, groups)
46-
47-
for (const o of properties) {
48-
if (usedNames.has(o.name)) {
49-
context.report({
50-
node: o.node,
51-
message: "Duplicated key '{{name}}'.",
52-
data: {
53-
name: o.name
54-
}
55-
})
45+
return utils.compositingVisitors(
46+
utils.executeOnVue(context, (obj) => {
47+
const properties = utils.iterateProperties(obj, groups)
48+
/** @type {Set<string>} */
49+
const usedNames = new Set()
50+
for (const o of properties) {
51+
if (usedNames.has(o.name)) {
52+
context.report({
53+
node: o.node,
54+
message: "Duplicated key '{{name}}'.",
55+
data: {
56+
name: o.name
57+
}
58+
})
59+
}
60+
61+
usedNames.add(o.name)
5662
}
63+
}),
64+
utils.defineScriptSetupVisitor(context, {
65+
onDefinePropsEnter(node, props) {
66+
for (const prop of props) {
67+
if (!prop.propName) continue
5768

58-
usedNames.add(o.name)
59-
}
60-
})
69+
const variable = findVariable(context.getScope(), prop.propName)
70+
if (!variable || variable.defs.length === 0) continue
71+
72+
context.report({
73+
node: variable.defs[0].node,
74+
message: "Duplicated key '{{name}}'.",
75+
data: {
76+
name: prop.propName
77+
}
78+
})
79+
}
80+
}
81+
})
82+
)
6183
}
6284
}

Diff for: lib/rules/no-duplicate-attr-inheritance.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,23 @@ module.exports = {
2626
/** @type {string | number | boolean | RegExp | BigInt | null} */
2727
let inheritsAttrs = true
2828

29-
return Object.assign(
30-
utils.executeOnVue(context, (node) => {
31-
const inheritAttrsProp = utils.findProperty(node, 'inheritAttrs')
29+
/** @param {ObjectExpression} node */
30+
function processOptions(node) {
31+
const inheritAttrsProp = utils.findProperty(node, 'inheritAttrs')
3232

33-
if (inheritAttrsProp && inheritAttrsProp.value.type === 'Literal') {
34-
inheritsAttrs = inheritAttrsProp.value.value
33+
if (inheritAttrsProp && inheritAttrsProp.value.type === 'Literal') {
34+
inheritsAttrs = inheritAttrsProp.value.value
35+
}
36+
}
37+
38+
return utils.compositingVisitors(
39+
utils.executeOnVue(context, processOptions),
40+
utils.defineScriptSetupVisitor(context, {
41+
onDefineOptionsEnter(node) {
42+
if (node.arguments.length === 0) return
43+
const define = node.arguments[0]
44+
if (define.type !== 'ObjectExpression') return
45+
processOptions(define)
3546
}
3647
}),
3748
utils.defineTemplateBodyVisitor(context, {

Diff for: lib/rules/no-undef-properties.js

+11
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ module.exports = {
127127

128128
/** @type { Set<string | ASTNode> } */
129129
this.reported = new Set()
130+
131+
this.hasUnknownProperty = false
130132
}
131133
/**
132134
* Report
@@ -135,6 +137,7 @@ module.exports = {
135137
* @param {boolean} [options.props]
136138
*/
137139
verifyReferences(references, options) {
140+
if (this.hasUnknownProperty) return
138141
const report = this.report.bind(this)
139142
verifyUndefProperties(this.defineProperties, references, null)
140143

@@ -206,6 +209,10 @@ module.exports = {
206209
}
207210
})
208211
}
212+
213+
markAsHasUnknownProperty() {
214+
this.hasUnknownProperty = true
215+
}
209216
}
210217

211218
/** @type {Map<ASTNode, VueComponentContext>} */
@@ -280,6 +287,10 @@ module.exports = {
280287
const ctx = getVueComponentContext(programNode)
281288

282289
for (const prop of props) {
290+
if (prop.type === 'unknown') {
291+
ctx.markAsHasUnknownProperty()
292+
return
293+
}
283294
if (!prop.propName) {
284295
continue
285296
}

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eslint-plugin-vue",
3-
"version": "9.13.0",
3+
"version": "9.14.0",
44
"description": "Official ESLint plugin for Vue.js",
55
"main": "lib/index.js",
66
"scripts": {

Diff for: tests/lib/rules/no-dupe-keys.js

+105
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,32 @@ ruleTester.run('no-dupe-keys', rule, {
390390
},
391391
}
392392
`
393+
},
394+
{
395+
filename: 'test.vue',
396+
code: `
397+
<script setup>
398+
defineProps({
399+
foo: String,
400+
})
401+
const bar = 0
402+
</script>
403+
`,
404+
parser: require.resolve('vue-eslint-parser')
405+
},
406+
{
407+
filename: 'test.vue',
408+
code: `
409+
<script setup lang="ts">
410+
defineProps<{
411+
foo: string;
412+
}>();
413+
414+
const bar = 0
415+
</script>
416+
`,
417+
parser: require.resolve('vue-eslint-parser'),
418+
parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
393419
}
394420
],
395421

@@ -861,6 +887,85 @@ ruleTester.run('no-dupe-keys', rule, {
861887
line: 7
862888
}
863889
]
890+
},
891+
{
892+
filename: 'test.vue',
893+
code: `
894+
<script setup>
895+
defineProps({
896+
foo: String,
897+
})
898+
const foo = 0
899+
</script>
900+
`,
901+
parser: require.resolve('vue-eslint-parser'),
902+
errors: [
903+
{
904+
message: "Duplicated key 'foo'.",
905+
line: 6
906+
}
907+
]
908+
},
909+
{
910+
filename: 'test.vue',
911+
code: `
912+
<script setup>
913+
import { Foo } from './Foo.vue';
914+
import baz from './baz';
915+
916+
defineProps({
917+
foo: String,
918+
bar: String,
919+
baz: String,
920+
});
921+
922+
function foo() {
923+
const baz = 'baz';
924+
}
925+
const bar = () => 'bar';
926+
</script>
927+
`,
928+
parser: require.resolve('vue-eslint-parser'),
929+
errors: [
930+
{
931+
message: "Duplicated key 'baz'.",
932+
line: 4
933+
},
934+
{
935+
message: "Duplicated key 'foo'.",
936+
line: 12
937+
},
938+
{
939+
message: "Duplicated key 'bar'.",
940+
line: 15
941+
}
942+
]
943+
},
944+
{
945+
filename: 'test.vue',
946+
code: `
947+
<script setup lang="ts">
948+
defineProps<{
949+
foo: string;
950+
bar: string;
951+
}>();
952+
953+
const foo = 'foo';
954+
const bar = 'bar';
955+
</script>
956+
`,
957+
parser: require.resolve('vue-eslint-parser'),
958+
parserOptions: { parser: require.resolve('@typescript-eslint/parser') },
959+
errors: [
960+
{
961+
message: "Duplicated key 'foo'.",
962+
line: 8
963+
},
964+
{
965+
message: "Duplicated key 'bar'.",
966+
line: 9
967+
}
968+
]
864969
}
865970
]
866971
})

Diff for: tests/lib/rules/no-duplicate-attr-inheritance.js

+52
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,26 @@ ruleTester.run('no-duplicate-attr-inheritance', rule, {
7979
export default { }
8080
</script>
8181
`
82+
},
83+
{
84+
filename: 'test.vue',
85+
code: `
86+
<script>
87+
export default { inheritAttrs: false }
88+
</script>
89+
<script setup>
90+
</script>
91+
<template><div v-bind="$attrs" /></template>
92+
`
93+
},
94+
{
95+
filename: 'test.vue',
96+
code: `
97+
<script setup>
98+
defineOptions({ inheritAttrs: false })
99+
</script>
100+
<template><div v-bind="$attrs" /></template>
101+
`
82102
}
83103
],
84104

@@ -99,6 +119,38 @@ ruleTester.run('no-duplicate-attr-inheritance', rule, {
99119
</script>
100120
`,
101121
errors: ['Set "inheritAttrs" to false.']
122+
},
123+
{
124+
filename: 'test.vue',
125+
code: `
126+
<script>
127+
export default { inheritAttrs: true }
128+
</script>
129+
<script setup>
130+
</script>
131+
<template><div v-bind="$attrs" /></template>
132+
`,
133+
errors: [
134+
{
135+
message: 'Set "inheritAttrs" to false.',
136+
line: 7
137+
}
138+
]
139+
},
140+
{
141+
filename: 'test.vue',
142+
code: `
143+
<script setup>
144+
defineOptions({ inheritAttrs: true })
145+
</script>
146+
<template><div v-bind="$attrs" /></template>
147+
`,
148+
errors: [
149+
{
150+
message: 'Set "inheritAttrs" to false.',
151+
line: 5
152+
}
153+
]
102154
}
103155
]
104156
})

0 commit comments

Comments
 (0)