Repository: vuejs/eslint-plugin-vue
Pull request #2416 (2024-03-05 05:24:03)

fix(v-for-delimiter-style): ignore Punctuator token
fixes https://github.com/vuejs/vue-eslint-parser/issues/226 (`vue-eslint-parser` issue!)

Maybe we can simply ignore all 'Punctuator' type token, without the need to specifically declare `token.type !== 'Punctuator' || (token.value !== ')' && token.value !== ',')`?


Patch:
diff --git a/lib/rules/enforce-style-attribute.js b/lib/rules/enforce-style-attribute.js
index 9710a131..f089a372 100644
--- a/lib/rules/enforce-style-attribute.js
+++ b/lib/rules/enforce-style-attribute.js
@@ -92,9 +92,9 @@ module.exports = {
       return {}
     }
 
-    const topLevelElements = documentFragment.children.filter(isVElement)
-    const topLevelStyleTags = topLevelElements.filter(
-      (element) => element.rawName === 'style'
+    const topLevelStyleTags = documentFragment.children.filter(
+      /** @returns {element is VElement} */
+      (element) => isVElement(element) && element.rawName === 'style'
     )
 
     if (topLevelStyleTags.length === 0) {
diff --git a/lib/rules/require-explicit-slots.js b/lib/rules/require-explicit-slots.js
index aab09c49..0ae77b59 100644
--- a/lib/rules/require-explicit-slots.js
+++ b/lib/rules/require-explicit-slots.js
@@ -59,9 +59,10 @@ module.exports = {
     if (!documentFragment) {
       return {}
     }
-    const scripts = documentFragment.children
-      .filter(utils.isVElement)
-      .filter((element) => element.name === 'script')
+    const scripts = documentFragment.children.filter(
+      /** @returns {element is VElement} */
+      (element) => utils.isVElement(element) && element.name === 'script'
+    )
     if (scripts.every((script) => !utils.hasAttribute(script, 'lang', 'ts'))) {
       return {}
     }
diff --git a/lib/rules/v-for-delimiter-style.js b/lib/rules/v-for-delimiter-style.js
index 3a494480..f59a4382 100644
--- a/lib/rules/v-for-delimiter-style.js
+++ b/lib/rules/v-for-delimiter-style.js
@@ -42,7 +42,7 @@ module.exports = {
             node.left.length > 0
               ? node.left[node.left.length - 1]
               : tokenStore.getFirstToken(node),
-            (token) => token.type !== 'Punctuator' || token.value !== ')'
+            (token) => token.type !== 'Punctuator'
           )
         )
 
diff --git a/lib/utils/index.js b/lib/utils/index.js
index d4354188..6773611c 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -2643,9 +2643,10 @@ function getScriptSetupElement(context) {
   if (!df) {
     return null
   }
-  const scripts = df.children
-    .filter(isVElement)
-    .filter((e) => e.name === 'script')
+  const scripts = df.children.filter(
+    /** @returns {e is VElement} */
+    (e) => isVElement(e) && e.name === 'script'
+  )
   if (scripts.length === 2) {
     return scripts.find((e) => hasAttribute(e, 'setup')) || null
   } else {
diff --git a/lib/utils/selector.js b/lib/utils/selector.js
index 67960d59..7b1f15c3 100644
--- a/lib/utils/selector.js
+++ b/lib/utils/selector.js
@@ -580,9 +580,10 @@ function buildPseudoNthVElementMatcher(testIndex) {
  */
 function buildPseudoNthOfTypeVElementMatcher(testIndex) {
   return (element) => {
-    const elements = element.parent.children
-      .filter(isVElement)
-      .filter((e) => e.rawName === element.rawName)
+    const elements = element.parent.children.filter(
+      /** @returns {e is VElement} */
+      (e) => isVElement(e) && e.rawName === element.rawName
+    )
     return testIndex(elements.indexOf(element), elements.length)
   }
 }
diff --git a/lib/utils/style-variables/index.js b/lib/utils/style-variables/index.js
index 66f22430..651d06eb 100644
--- a/lib/utils/style-variables/index.js
+++ b/lib/utils/style-variables/index.js
@@ -47,9 +47,10 @@ function getStyleVariablesContext(context) {
   if (!df) {
     return null
   }
-  const styles = df.children
-    .filter(isVElement)
-    .filter((e) => e.name === 'style')
+  const styles = df.children.filter(
+    /** @returns {e is VElement} */
+    (e) => isVElement(e) && e.name === 'style'
+  )
   if (styles.length === 0) {
     return null
   }


Test patch:
diff --git a/tests/lib/rules/v-for-delimiter-style.js b/tests/lib/rules/v-for-delimiter-style.js
index 350fded1..ebec2df5 100644
--- a/tests/lib/rules/v-for-delimiter-style.js
+++ b/tests/lib/rules/v-for-delimiter-style.js
@@ -35,6 +35,19 @@ tester.run('v-for-delimiter-style', rule, {
       filename: 'test.vue',
       code: '<template><div v-for="x    in    xs"></div></template>'
     },
+    {
+      // https://github.com/vuejs/vue-eslint-parser/issues/226
+      filename: 'test.vue',
+      code: '<template><div v-for="(x,) in xs"></div></template>'
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div v-for="(value, key, index) in xs"></div></template>'
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div v-for="{ x, y } in xs"></div></template>'
+    },
     {
       filename: 'test.vue',
       code: '<template><div v-for="x in xs"></div></template>',
@@ -58,6 +71,17 @@ tester.run('v-for-delimiter-style', rule, {
         }
       ]
     },
+    {
+      filename: 'test.vue',
+      code: '<template><div v-for="(x, index) of xs"></div></template>',
+      output: '<template><div v-for="(x, index) in xs"></div></template>',
+      errors: [
+        {
+          message: "Expected 'in' instead of 'of' in 'v-for'.",
+          column: 23
+        }
+      ]
+    },
     {
       filename: 'test.vue',
       code: '<template><div v-for="x    of xs"></div></template>',