Skip to content

Commit e8fc5cb

Browse files
committed
Update
1 parent e3a231d commit e8fc5cb

File tree

4 files changed

+170
-89
lines changed

4 files changed

+170
-89
lines changed

Diff for: docs/rules/script-setup-uses-vars.md

+4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ If you are not using `<script setup>` or if you do not use the `no-unused-vars`
5454
- [vue/jsx-uses-vars](./jsx-uses-vars.md)
5555
- [no-unused-vars](https://eslint.org/docs/rules/no-unused-vars)
5656

57+
## :books: Further Reading
58+
59+
- [Vue RFCs - 0040-script-setup](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md)
60+
5761
## :mag: Implementation
5862

5963
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/script-setup-uses-vars.js)

Diff for: lib/rules/script-setup-uses-vars.js

+1-10
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,7 @@ module.exports = {
3131
* @returns {RuleListener} AST event handlers.
3232
*/
3333
create(context) {
34-
const df =
35-
context.parserServices.getDocumentFragment &&
36-
context.parserServices.getDocumentFragment()
37-
if (!df) {
38-
return {}
39-
}
40-
const scriptSetupNode = df.children
41-
.filter(utils.isVElement)
42-
.find((e) => e.name === 'script' && utils.hasAttribute(e, 'setup'))
43-
if (!scriptSetupNode) {
34+
if (!utils.isScriptSetup(context)) {
4435
return {}
4536
}
4637
/** @type {Set<string>} */

Diff for: lib/utils/index.js

+144-79
Original file line numberDiff line numberDiff line change
@@ -406,28 +406,6 @@ module.exports = {
406406
return null
407407
},
408408

409-
/**
410-
* Check whether the given start tag has specific directive.
411-
* @param {VElement} node The start tag node to check.
412-
* @param {string} name The attribute name to check.
413-
* @param {string} [value] The attribute value to check.
414-
* @returns {boolean} `true` if the start tag has the attribute.
415-
*/
416-
hasAttribute(node, name, value) {
417-
return Boolean(this.getAttribute(node, name, value))
418-
},
419-
420-
/**
421-
* Check whether the given start tag has specific directive.
422-
* @param {VElement} node The start tag node to check.
423-
* @param {string} name The directive name to check.
424-
* @param {string} [argument] The directive argument to check.
425-
* @returns {boolean} `true` if the start tag has the directive.
426-
*/
427-
hasDirective(node, name, argument) {
428-
return Boolean(this.getDirective(node, name, argument))
429-
},
430-
431409
/**
432410
* Check whether the given directive attribute has their empty value (`=""`).
433411
* @param {VDirective} node The directive attribute node to check.
@@ -515,71 +493,41 @@ module.exports = {
515493
* @param {string} [value] The attribute value to check.
516494
* @returns {VAttribute | null} The found attribute.
517495
*/
518-
getAttribute(node, name, value) {
519-
return (
520-
node.startTag.attributes.find(
521-
/**
522-
* @param {VAttribute | VDirective} node
523-
* @returns {node is VAttribute}
524-
*/
525-
(node) => {
526-
return (
527-
!node.directive &&
528-
node.key.name === name &&
529-
(value === undefined ||
530-
(node.value != null && node.value.value === value))
531-
)
532-
}
533-
) || null
534-
)
535-
},
496+
getAttribute,
497+
498+
/**
499+
* Check whether the given start tag has specific directive.
500+
* @param {VElement} node The start tag node to check.
501+
* @param {string} name The attribute name to check.
502+
* @param {string} [value] The attribute value to check.
503+
* @returns {boolean} `true` if the start tag has the attribute.
504+
*/
505+
hasAttribute,
536506

537507
/**
538508
* Get the directive list which has the given name.
539509
* @param {VElement | VStartTag} node The start tag node to check.
540510
* @param {string} name The directive name to check.
541511
* @returns {VDirective[]} The array of `v-slot` directives.
542512
*/
543-
getDirectives(node, name) {
544-
const attributes =
545-
node.type === 'VElement' ? node.startTag.attributes : node.attributes
546-
return attributes.filter(
547-
/**
548-
* @param {VAttribute | VDirective} node
549-
* @returns {node is VDirective}
550-
*/
551-
(node) => {
552-
return node.directive && node.key.name.name === name
553-
}
554-
)
555-
},
513+
getDirectives,
556514
/**
557515
* Get the directive which has the given name.
558516
* @param {VElement} node The start tag node to check.
559517
* @param {string} name The directive name to check.
560518
* @param {string} [argument] The directive argument to check.
561519
* @returns {VDirective | null} The found directive.
562520
*/
563-
getDirective(node, name, argument) {
564-
return (
565-
node.startTag.attributes.find(
566-
/**
567-
* @param {VAttribute | VDirective} node
568-
* @returns {node is VDirective}
569-
*/
570-
(node) => {
571-
return (
572-
node.directive &&
573-
node.key.name.name === name &&
574-
(argument === undefined ||
575-
(node.key.argument &&
576-
node.key.argument.type === 'VIdentifier' &&
577-
node.key.argument.name) === argument)
578-
)
579-
}
580-
) || null
581-
)
582-
},
521+
getDirective,
522+
523+
/**
524+
* Check whether the given start tag has specific directive.
525+
* @param {VElement} node The start tag node to check.
526+
* @param {string} name The directive name to check.
527+
* @param {string} [argument] The directive argument to check.
528+
* @returns {boolean} `true` if the start tag has the directive.
529+
*/
530+
hasDirective,
583531

584532
/**
585533
* Returns the list of all registered components
@@ -643,13 +591,13 @@ module.exports = {
643591
for (const childNode of node.children) {
644592
if (childNode.type === 'VElement') {
645593
let connected
646-
if (this.hasDirective(childNode, 'if')) {
594+
if (hasDirective(childNode, 'if')) {
647595
connected = false
648596
vIf = true
649-
} else if (this.hasDirective(childNode, 'else-if')) {
597+
} else if (hasDirective(childNode, 'else-if')) {
650598
connected = vIf
651599
vIf = true
652-
} else if (this.hasDirective(childNode, 'else')) {
600+
} else if (hasDirective(childNode, 'else')) {
653601
connected = vIf
654602
vIf = false
655603
} else {
@@ -685,9 +633,9 @@ module.exports = {
685633
!this.isHtmlWellKnownElementName(node.rawName)) ||
686634
(this.isSvgElementNode(node) &&
687635
!this.isSvgWellKnownElementName(node.rawName)) ||
688-
this.hasAttribute(node, 'is') ||
689-
this.hasDirective(node, 'bind', 'is') ||
690-
this.hasDirective(node, 'is')
636+
hasAttribute(node, 'is') ||
637+
hasDirective(node, 'bind', 'is') ||
638+
hasDirective(node, 'is')
691639
)
692640
},
693641

@@ -1023,6 +971,28 @@ module.exports = {
1023971

1024972
isVueFile,
1025973

974+
/**
975+
* Checks whether the current file is uses `<script setup>`
976+
* @param {RuleContext} context The ESLint rule context object.
977+
*/
978+
isScriptSetup(context) {
979+
const df =
980+
context.parserServices.getDocumentFragment &&
981+
context.parserServices.getDocumentFragment()
982+
if (!df) {
983+
return false
984+
}
985+
const scripts = df.children
986+
.filter(isVElement)
987+
.filter((e) => e.name === 'script')
988+
if (scripts.length === 2) {
989+
return scripts.some((e) => hasAttribute(e, 'setup'))
990+
} else {
991+
const script = scripts[0]
992+
return script && hasAttribute(script, 'setup')
993+
}
994+
},
995+
1026996
/**
1027997
* Check if current file is a Vue instance or component and call callback
1028998
* @param {RuleContext} context The ESLint rule context object.
@@ -2199,3 +2169,98 @@ function* iterateWatchHandlerValues(property) {
21992169
yield value
22002170
}
22012171
}
2172+
2173+
/**
2174+
* Get the attribute which has the given name.
2175+
* @param {VElement} node The start tag node to check.
2176+
* @param {string} name The attribute name to check.
2177+
* @param {string} [value] The attribute value to check.
2178+
* @returns {VAttribute | null} The found attribute.
2179+
*/
2180+
function getAttribute(node, name, value) {
2181+
return (
2182+
node.startTag.attributes.find(
2183+
/**
2184+
* @param {VAttribute | VDirective} node
2185+
* @returns {node is VAttribute}
2186+
*/
2187+
(node) => {
2188+
return (
2189+
!node.directive &&
2190+
node.key.name === name &&
2191+
(value === undefined ||
2192+
(node.value != null && node.value.value === value))
2193+
)
2194+
}
2195+
) || null
2196+
)
2197+
}
2198+
2199+
/**
2200+
* Get the directive list which has the given name.
2201+
* @param {VElement | VStartTag} node The start tag node to check.
2202+
* @param {string} name The directive name to check.
2203+
* @returns {VDirective[]} The array of `v-slot` directives.
2204+
*/
2205+
function getDirectives(node, name) {
2206+
const attributes =
2207+
node.type === 'VElement' ? node.startTag.attributes : node.attributes
2208+
return attributes.filter(
2209+
/**
2210+
* @param {VAttribute | VDirective} node
2211+
* @returns {node is VDirective}
2212+
*/
2213+
(node) => {
2214+
return node.directive && node.key.name.name === name
2215+
}
2216+
)
2217+
}
2218+
/**
2219+
* Get the directive which has the given name.
2220+
* @param {VElement} node The start tag node to check.
2221+
* @param {string} name The directive name to check.
2222+
* @param {string} [argument] The directive argument to check.
2223+
* @returns {VDirective | null} The found directive.
2224+
*/
2225+
function getDirective(node, name, argument) {
2226+
return (
2227+
node.startTag.attributes.find(
2228+
/**
2229+
* @param {VAttribute | VDirective} node
2230+
* @returns {node is VDirective}
2231+
*/
2232+
(node) => {
2233+
return (
2234+
node.directive &&
2235+
node.key.name.name === name &&
2236+
(argument === undefined ||
2237+
(node.key.argument &&
2238+
node.key.argument.type === 'VIdentifier' &&
2239+
node.key.argument.name) === argument)
2240+
)
2241+
}
2242+
) || null
2243+
)
2244+
}
2245+
2246+
/**
2247+
* Check whether the given start tag has specific directive.
2248+
* @param {VElement} node The start tag node to check.
2249+
* @param {string} name The attribute name to check.
2250+
* @param {string} [value] The attribute value to check.
2251+
* @returns {boolean} `true` if the start tag has the attribute.
2252+
*/
2253+
function hasAttribute(node, name, value) {
2254+
return Boolean(getAttribute(node, name, value))
2255+
}
2256+
2257+
/**
2258+
* Check whether the given start tag has specific directive.
2259+
* @param {VElement} node The start tag node to check.
2260+
* @param {string} name The directive name to check.
2261+
* @param {string} [argument] The directive argument to check.
2262+
* @returns {boolean} `true` if the start tag has the directive.
2263+
*/
2264+
function hasDirective(node, name, argument) {
2265+
return Boolean(getDirective(node, name, argument))
2266+
}

Diff for: tests/lib/rules/script-setup-uses-vars.js

+21
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,27 @@ describe('script-setup-uses-vars', () => {
252252
line: 4
253253
}
254254
]
255+
},
256+
257+
// Not `<script setup>`
258+
{
259+
filename: 'test.vue',
260+
code: `
261+
<script>
262+
/* eslint script-setup-uses-vars: 1 */
263+
const msg = 'Hello!'
264+
</script>
265+
266+
<template>
267+
<div>{{ msg }}</div>
268+
</template>
269+
`,
270+
errors: [
271+
{
272+
message: "'msg' is assigned a value but never used.",
273+
line: 4
274+
}
275+
]
255276
}
256277
]
257278
})

0 commit comments

Comments
 (0)