vuejs / eslint-plugin-vue

Official ESLint plugin for Vue.js
https://eslint.vuejs.org/
MIT License
4.47k stars 667 forks source link

Parsing errors only when called from VSCode plugin #2616

Closed Huupke closed 3 days ago

Huupke commented 3 days ago

Full configuration:

import globals from "globals";
import path from "path";
import { fileURLToPath } from "url";
import typescriptPlugin from "typescript-eslint";
import prettierConfigRecommended from "eslint-plugin-prettier/recommended";
import vuePlugin from "eslint-plugin-vue";
import vueParser from "vue-eslint-parser";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default [
    ...vuePlugin.configs["flat/recommended"],
    ...typescriptPlugin.configs.recommended,
    prettierConfigRecommended,
    {
        languageOptions: {
            parser: vueParser,
            parserOptions: {
                parser: typescriptPlugin.parser,
                project: ["./tsconfig.eslint.json", "./ts/tsconfig.json", "./src/tsconfig.json"],
                sourceType: "module",
                tsconfigRootDir: __dirname,
                extraFileExtensions: [".vue"],
            },
            globals: {
                ...globals.browser,
                ...globals.jquery,
            },
        },
        rules: {
            // PascalCase enum members
            // bad default in https://github.com/typescript-eslint/typescript-eslint/issues/6592
            // means have to recreate the entire rule structure here by extracting the defaults from:
            // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/rules/naming-convention.ts
            "@typescript-eslint/naming-convention": [
                "error",
                {
                    selector: "enumMember",
                    format: ["PascalCase"],
                },
            ],
            "@typescript-eslint/no-unused-expressions": "error",
            "@typescript-eslint/no-unused-vars": "error",
            "@typescript-eslint/no-explicit-any": "off",
            curly: "error",
            eqeqeq: ["error", "always"],
            "vue/html-indent": "off",
            "vue/max-attributes-per-line": "off",
            "prettier/prettier": ["error"],
            "eslint-comments/no-unused-disable": "off",
        },
        files: ["ts/**/*.ts", "src/**/*.ts", "src/**/*.vue"],
        ignores: ["node_modules/", "dist/", "release/", "server/"],
    },
];

My relevant VSCode ESLint extension setings.json

{
    "eslint.useFlatConfig": true,
    "eslint.options": { 
        "overrideConfigFile": "/home/<my username>/dev/<my project workspace foldername>/.eslintrc.js" 
    },
    "eslint.workingDirectories": ["./", "./ts", "./src"]
}

What did you do? I recently migrated to flat config and I got this to work from the command line without any parsing errors in vue templates. The problem is that in VSCode the ESLint plugin. eslint -c .eslintrc.js ts/ src/ -> works like a charm for my entire project but when I use VSCode it strugles with the vue files like these:

<template>
    <!-- eslint-disable-next-line vue/no-v-html -->
    <div v-html="htmlAsync" />
</template>

What did you expect to happen? I expect that I don't get ESLint parsing errors on vue templates when run in VSCode.

What actually happened? I get this error in VSCode: "Parsing error: Type expected." or for some other vue files I get "Parsing error: '>' expected."

Repository to reproduce this issue Not available

FloEdelmann commented 3 days ago

You tell the VS Code ESLint extension to use the flat config format, but actually give it a legacy .eslintrc.js config file. I guess that's the issue. Since eslint -c .eslintrc.js doesn't know about the VS Code setting eslint.useFlatConfig, it parses the file based on the file name as a legacy config and thus works as expected. In any case, this is probably not related to eslint-plugin-vue, but to either misconfiguration or a bug in the VS Code extension.

FloEdelmann commented 3 days ago

Or maybe it is because the overrideConfigFile doesn't specify the Vue parser, so the default Espree parser throws an error when asked to parse a Vue file.

Huupke commented 3 days ago

You tell the VS Code ESLint extension to use the flat config format, but actually give it a legacy .eslintrc.js config file. I guess that's the issue. Since eslint -c .eslintrc.js doesn't know about the VS Code setting eslint.useFlatConfig, it parses the file based on the file name as a legacy config and thus works as expected. In any case, this is probably not related to eslint-plugin-vue, but to either misconfiguration or a bug in the VS Code extension.

I didn't know that the filename dictates the format but I saw from the extion debug log eslint:eslint Using config loader LegacyConfigLoader and eslint:config-loader [Legacy]: Calculating config. However after renaming it to eslint.config.js I get the same 'Legacy' mentioned in the file and also still the parsing error. ESLint from the commandline (npm) doesn't seem to assume any format from the filename as it works with any filename as long it's provided with the '-c' option.

Or maybe it is because the overrideConfigFile doesn't specify the Vue parser, so the default Espree parser throws an error when asked to parse a Vue file.

How can this setting result in a different configuration? I intent only to tell ESLint which config to use and it should result in the exact same configuration which specifies the vue parser as you can see in the configuration I posted. After removing this overrideConfigFile setting it seems to work so this setting can't be used just because the filename is different but it also implies the (legacy) format even if the "eslint.useFlatConfig": true is used.

Thanks for the hint!