Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSCode doesn't run ESLint Server with eslint.config.js flat config #1620

Closed
eakl opened this issue Mar 13, 2023 · 84 comments
Closed

VSCode doesn't run ESLint Server with eslint.config.js flat config #1620

eakl opened this issue Mar 13, 2023 · 84 comments
Labels
info-needed Issue requires more information from poster

Comments

@eakl
Copy link

eakl commented Mar 13, 2023

VSCode is not running ESLint server on my codebase when using the new ESLint Flat Config eslint.config.js.

I have the following setup:

  • The app is a Vite + Svelte + TS starter
  • The issue happens in a monorepo (pnpm workspace)
  • ESLint correctly lint my codebase when invoked via the CLI pnpm eslint src
  • Packages has been reinstalled several times with pnpm install and the ESLint server has been restarted
  • VSCode doesn't run ESLint server on my codebase when using the flat config

My codebase structure

/client
   /.vscode
      settings.json
   /src
      main.ts
      App.svelte
   eslint.config.js
   package.json
   vite.config.ts
package.json
pnpm-workspace.yaml

ESLint correctly lint my codebase with pnpm eslint src and find errors in both src/main.ts and src/App.svelte.

But VSCode is unable to run the ESLint server with eslint.config.js located at the workspace root

The Output console says

[Info  - 5:43:59 PM] ESLint server is starting.
[Info  - 5:44:00 PM] ESLint server running in node v16.14.2
[Info  - 5:44:00 PM] ESLint server is running.
[Info  - 5:44:00 PM] 
Failed to load the ESLint library for the document <project_root>/client/src/App.svelte

To use ESLint please install eslint by running pnpm install eslint in the workspace folder test
or globally using 'pnpm install -g eslint'. You need to reopen the workspace after installing eslint.

Alternatively you can disable ESLint for the workspace folder test by executing the 'Disable ESLint' command.

My settings.json located at client/.vscode/settings.json

{
  "css.lint.unknownAtRules": "ignore",
  "scss.lint.unknownAtRules": "ignore",
  "eslint.enable": true,
  "eslint.packageManager": "pnpm",
  "eslint.format.enable": true,
  "eslint.validate": [
    "javascript",
    "typescript",
    "svelte"
  ],
  "eslint.experimental.useFlatConfig": true,
  "eslint.workingDirectories": [{ "mode": "auto" }],
  "eslint.options": {
    "overrideConfigFile": "./eslint.config.js"
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}
@MariaSolOs
Copy link
Contributor

For an easier investigation, it would be good to provide a repo with a minimal project that reproduces the issue.

@dbaeumer dbaeumer added the info-needed Issue requires more information from poster label Mar 14, 2023
@eakl
Copy link
Author

eakl commented Mar 16, 2023

Context

  • I share 2 monorepos implementing the new ESLint flat config
  • Both monorepos consist of a root project and multiple subprojects in the playground folder (vanilla JS, React JS/TS, Svelte JS/TS)
  • The first monorepo has one eslint.config.js located at the root of the monorepo
  • The second monorepo has multiple eslint.config.js located in each of the subprojects located in the playground folder
  • To See ESLint in action, open counter.{js,ts,svelte} or App.{jsx,tsx} in each subproject

First Repo

  • The root is a vite/svelte project
  • eslint.config.js is located at the root of the project

VSCode seems to work for all subprojects but not for the root (open Counter.svelte)

Second Repo

  • This repo consists of a library that need to be built. It is an ESLint sharable config project
  • The root project is the sharable config for multiple extensions
  • In the playground folder, each subproject has eslint and the sharable config installed as dependencies. They all have an eslint.config.js at their root.

VSCode doesn't seems to work in this case (open each counter.{js,ts,svelte} or App.{jsx,tsx})

@dbaeumer
Copy link
Member

Flat configs are still experimental and need to be enabled in VSCode ESLint using the eslint.experimental.useFlatConfig setting. I could not find such a setting in the repositories. Do you enable it?

@eakl
Copy link
Author

eakl commented Mar 17, 2023

I has been excluded by my .gitignore but I do have it both of my repos. I have updated the repos with my .vscode/settings.json

EDIT

I have tried to open VSCode at /test which is not a monorepo, just the folder where I have both of my monorepos. ESLint doesn't work at all.

test/
   /eslint-flat-vscode-root
   /eslint-flat-vscode-playground

It seems like the extension has issue traversing the project tree to look for the closest eslint.config.js

@dbaeumer
Copy link
Member

Regarding Svelte files: they are currently not autodetected in the ESLint extension. See #1468. So you need to configure the eslint.validate setting. Please note that if you specify that setting you need to list all language ids you want to see validated including TypeScript and JavaScript.

@dbaeumer
Copy link
Member

For there second repro this is very likely a working directory issue. Have you tried to list the playground directories containing a eslint.config.js file as a working directory (e.g. eslint.workingDirectories setting).

ESLint is very sensitive in regards to the working directory used when searching for configuration files.

@eakl
Copy link
Author

eakl commented Mar 20, 2023

I have tried multiple options

"eslint.workingDirectories": [
    { "pattern": "./playground/*/" }
  ],
"eslint.workingDirectories": ["...", "./playground/20-react-ts", "..."]
"eslint.workingDirectories": [{ "mode": "auto" }]
"eslint.workingDirectories": [{ "mode": "location" }]

When running eslint cli I get this error

~/d/t/eslint-flat-vscode-playground main ❯ pnpm eslint .                       

Oops! Something went wrong! :(

ESLint: 8.36.0

ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:

    npm init @eslint/config

ESLint looked for configuration files in /Users/eliasaboukhalillanvin/dev/test/eslint-flat-vscode-playground/dist and its ancestors. If it found none, it then looked in your home directory.

If you think you already have a configuration file or if you need more help, please stop by the ESLint Discord server: https://eslint.org/chat

@dbaeumer
Copy link
Member

The ESLint extension depends on a proper setup ESLint. If running ESLint in the terminal fails it will very likely fail with the extension as well. What I would recommend is to get it working in the terminal and then take it to the extension. If it works in the terminal but not in the extension I can definitely have a look.

@azat-io
Copy link

azat-io commented Apr 27, 2023

The same problem 😢

@tdfranklin
Copy link

@dbaeumer

I am also running into a the same (or at least very similar) issue. I am able to run ESLint in the terminal, however I am not seeing the errors in the VSCode editor using the new flat config. I created a quick sample repo so you can take a look:

https://github.com/tdfranklin/eslint-test

If you run pnpm lint, you should see 3 errors in App.tsx, however when I open the file in VSCode, I don't see any errors or warnings.

@dbaeumer
Copy link
Member

Works for me

image

Please note that in ESLint extension you still need to enable flat config. The reason is that we need to call different API in ESLint and we need to find a way to abstract that. The setting is:

{
    "eslint.experimental.useFlatConfig": true
}

@azat-io
Copy link

azat-io commented May 18, 2023

@dbaeumer It works! Thanks a lot!

@tdfranklin
Copy link

Very strange - I do have the flag enabled, but I'm getting this error in the output:

image

I thought it might be something to do with it being a monorepo and not ignoring all node_modules folder's, but maybe on of my other VSCode settings is blocking it?

@dbaeumer
Copy link
Member

@tdfranklin does it work in the terminal when executing ./node_modules/.bin/eslint apps/client/src/App.tsx

@tdfranklin
Copy link

tdfranklin commented May 19, 2023

@dbaeumer - Yes, when I run it in the terminal, I don't see any errors.

Today I'm going to move my tsconfig and eslint config to shared workspace packages instead of having them in the root directory and see if that changes anything, so I'll update once I finish if I'm still seeing errors.

@tdfranklin
Copy link

tdfranklin commented May 19, 2023

RESOLVED - I'm leaving the comments below in case they help anyone in the future, but I think I've resolved this issue. After adding the following to my VSCode settings, it seems to be working correctly. Now to see if I can get it to work with the new flat config!

"eslint.workingDirectories": [
    { "pattern": "./apps/*/" },
    { "pattern": "./packages/*/" }
  ]

@dbaeumer - First of all, thank you so much for your help! I've been fighting with trying to get this working all week and it's probably something really obvious that I'm missing, but I just can't put my finger on it....

So first, the new folder structure:

- trinity (root folder)
  - apps
    - dealer
      - src
        - (...all project files)
      - package.json
      - tsconfig.json
      - .eslintrc.json
  - packages
    - tsconfig
      - base.json
      - package.json
    - eslint-config-custom
      - index.js
      - package.json
package.json
pnpm-workspace.yaml

A little bit of additional info - everything was working correctly before moving to a pnpm workspaces monorepo, both in the CLI and UI layers. To try and simplify the issue, I reverted back to the old eslint config and get that working first (as I'm now having issues with getting that to even work in the UI).

Here's all the relevant config files:

-- ROOT CONFIG FILES --

package.json

{
  "name": "trinity-frontend",
  "version": "0.0.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dealer": "pnpm --filter @trinity/dealer",
    "clean": "find ./ -name node_modules -type d -exec rm -rf {} +"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "prettier": "^2.8.4",
    "typescript": "^4.9.5"
  }
}

pnpm-workspace.yaml

packages:
- apps/*
- packages/*

-- TYPESCRIPT CONFIG FILES --

/packages/tsconfig/package.json

{
  "name": "@trinity/tsconfig"
}

/packages/tsconfig/base.json

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true, 
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "ESNext", 
    "moduleResolution": "Node", 
    "resolveJsonModule": true,
    "isolatedModules": true, 
    "noEmit": true, 
    "jsx": "react-jsx", 
    "outDir": "dist", 
    "incremental": true, 
    "noImplicitAny": true,
    "sourceMap": true,
    "importHelpers": true, 
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true
  },
  "exclude": ["node_modules"]
}

-- ESLINT CONFIG FILES --

/packages/eslint-config-custom/package.json

{
  "name": "eslint-config-custom",
  "main": "index.js",
  "version": "1.0.0",
  "dependencies": {
    "@typescript-eslint/eslint-plugin": "^5.53.0",
    "@typescript-eslint/parser": "^5.53.0",
    "eslint": "^8.35.0",
    "eslint-config-prettier": "^8.6.0",
    "eslint-import-resolver-typescript": "^3.5.3",
    "eslint-plugin-import": "^2.27.5",
    "eslint-plugin-jsx-a11y": "^6.7.1",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-simple-import-sort": "^10.0.0"
  }
}
/packages/eslint-config-custom/index.js

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: './tsconfig.json',
  },
  extends: [
    'eslint:recommended',
    'plugin:jsx-a11y/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:react/jsx-runtime',
    'plugin:import/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  plugins: ['react', 'prettier', 'import', 'jsx-a11y', '@typescript-eslint', 'simple-import-sort'],
  settings: {
    react: {
      version: 'detect',
    },
    'import/resolver': {
      typescript: {
        paths: './tsconfig.json',
        alwaysTryTypes: true,
      },
    },
  },
  globals: {
    React: true,
    JSX: true,
    __APP_VERSION__: true,
  },
  rules: {REMOVED FOR BREVITY},
}

-- APP CONFIG FILES --

/apps/dealer/package.json

{
  "name": "@trinity/dealer",
  "version": "3.2.7",
  "main": "index.tsx",
  "private": true,
  "dependencies": { REMOVED FOR BREVITY  },
  "devDependencies": {
    "@trinity/tsconfig": "workspace:^",
    "eslint-config-custom": "workspace:^",
  },
}

/apps/dealer/tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "extends": "@trinity/tsconfig/base.json",
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

/apps/dealer/.eslintrc.json

{
  "root": true,
  "extends": ["custom"]
}

So now what's happening is there seems to be a discrepancy between the CLI and UI on where the tsconfig.json file lives... with the config above, the CLI tool seems to lint the project correctly, however the UI is looking for a tsconfig file in the root directory. So when I update the eslint config file to point to apps/dealer/tsconfig.json then the UI will lint, but the CLI stops working.

Also, I'm not sure if I'm better off trying to keep the config in separate packages the way I have it above or going back and just keeping all of the config in the root directory? While I only have a single app at the moment, I'm trying to prepare the repo to add several more apps and packages and I want to keep it as simple as possible to share both eslint and typescript across the entire project. Any help you could offer would be so appreciated! Thank you!

@tdfranklin
Copy link

@dbaeumer - Ok, sorry for the sidetrack, but we're back to the original issue. So after getting everything working in the monorepo with the old .eslintrc* file, I tried moving back to the new flat config and am running into the same issue as above.

When running the CLI, it successfully lints the project:

image

However, I am getting the same error in the ESLint console for the UI:

image

Do you have any idea what's going on here? Perhaps some other setting I need to tweak in VSCode? (And yes, I made sure to turn back on the flat config option in VSCode):

image

@dbaeumer
Copy link
Member

Can I reproduce that in the repository you provided?

@tdfranklin
Copy link

@dbaeumer - Sorry for the delay, it's been a crazy day, but I just updated that repo to reproduce the same issue.

So currently I have it setup to use the new flat config and it lints from the command line, but on the UI, I am getting the same "unexpected key" error as show above. I also have it setup to swap to the old .eslintrc* style config and that works both on the command line and UI. If you want to switch between the two, in /packages/eslint-config/package.json change the "main" export file to oldConfig.cjs, then in /apps/client/package.json update the lint script to use flat config to be false and then (obviously) disable the setting in VSCode and restart the ESLint server and you will see that both sides work fine. However, with the flat config, the CLI works, but the UI gives that error.

Hopefully that makes sense, but just shout at me if I can provide any additional information. And thank you again for investigating this issue!

@levino
Copy link

levino commented May 23, 2023

I have a very similar issue. In my case I want to use a flat config AND yarn with pnp. Does not work. Only if I switch to nodeLinker: node-modules in my .yarnrc.yml.

@dbaeumer
Copy link
Member

@levino yarn with pnp needs special setup on the yarn side to work with VS Code. Have you followed the steps here: https://yarnpkg.com/getting-started/editor-sdks

@dbaeumer
Copy link
Member

@tdfranklin I pulled from that repository and when trying to run eslint in the terminal it actually fails very early with

/workspaces/eslint-test (main) $ ./node_modules/.bin/eslint apps/client/src/App.tsx

Oops! Something went wrong! :(

ESLint: 8.35.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'globals' imported from /workspaces/eslint-test/eslint.config.js
Did you mean to import globals@13.20.0/node_modules/globals/index.js?
    at new NodeError (node:internal/errors:399:5)
    at packageResolve (node:internal/modules/esm/resolve:794:9)
    at moduleResolve (node:internal/modules/esm/resolve:843:20)
    at ESMLoader.defaultResolve (node:internal/modules/esm/resolve:1058:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:323:32)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:172:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36)

I did run pnpm install before

Anything missing?

@levino
Copy link

levino commented May 23, 2023

Yes. I use a legacy config now with pnp and it works fine.

@tdfranklin
Copy link

tdfranklin commented May 23, 2023

@dbaeumer - That's very odd, globals is included in the eslint-config package.json dependencies so it should have installed...

update For simplicity, I just removed the code that was using globals as it's not part of this issue, so if you pull down the changes, you shouldn't have that issue anymore. Thank you!

@dbaeumer
Copy link
Member

@tdfranklin I pulled and the problem with that setup is now that you need to define a working directory since running eslint in the workspace folder root doesn't work either. It produces

/workspaces/eslint-test (main) $ ./node_modules/.bin/eslint apps/client/src/App.tsx

Oops! Something went wrong! :(

ESLint: 8.35.0

Error: ESLint configuration in apps/client/.eslintrc.json » eslint-config-trinity is invalid:
        - Property "" is the wrong type (expected object but got `"import rules from './flatConfig/index.js'\nexport default rules"`).

Referenced from: /workspaces/eslint-test/apps/client/.eslintrc.json
    at ConfigValidator.validateConfigSchema (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
    at ConfigArrayFactory._normalizeConfigData (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
    at ConfigArrayFactory._loadConfigData (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
    at ConfigArrayFactory._loadExtendedShareableConfig (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
    at ConfigArrayFactory._loadExtends (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
    at _normalizeObjectConfigDataBody.next (<anonymous>)
    at ConfigArrayFactory._normalizeObjectConfigData (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
    at _normalizeObjectConfigData.next (<anonymous>)
    at ConfigArrayFactory.loadInDirectory (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2865:28)

whereas this works: /workspaces/eslint-test/apps/client (main) $ ../../node_modules/.bin/eslint src/App.tsx

So you need to specify apps/client as a working directory using eslint.workingDirectories setting

@dbaeumer
Copy link
Member

image

@tdfranklin
Copy link

@dbaeumer

I did set that up:

image

However, I am still getting the same error:

image

@dbaeumer
Copy link
Member

@tdfranklin hmm, that is very wired since I could get the test repository working with this setup without any problem. What is wired as well is the fact that the error happens in ESLint npm itself when they read the flat config not in the extension code.

When you run it is the terminal are you using something like this: /workspaces/eslint-test/apps/client (main) $ ../../node_modules/.bin/eslint src/App.tsx

Don't go through pnpm run since this might tweak things in a different way not available in the extension.

@tdfranklin
Copy link

@dbaeumer Yea, it's very strange. For me, the CLI tool works fine (both with the method you listed above and just using pnpm lint. Both ways seem to lint the file and return the correct output, it's only when I turn on the VSCode flag and try to use the UI that I get the output listed above in the ESLint console.

I'm not sure if the environment might be a factor, but I am using WSL on Windows 10, so maybe that is causing the issue?

@davidkarlsson
Copy link

@dbaeumer That is strange because I get the same error with 3.0.5 as I did with 3.0.3 with the mjs config. test.ts doesn't show the linting errors and the output log logs this error:

[Info  - 2:27:54 PM] ESLint server is starting.
[Info  - 2:27:54 PM] ESLint server running in node v18.17.1
[Info  - 2:27:54 PM] ESLint server is running.
[Info  - 2:27:55 PM] ESLint library loaded from: D:\vscode-eslint-test\.yarn\sdks\eslint\lib\api.js
[Error - 2:27:55 PM] Calculating config file for file:///d%3A/vscode-eslint-test/test.ts) failed.
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from D:\vscode-eslint-test\eslint.config.mjs
Did you mean to import @eslint-js-npm-8.57.0-00ead3710a-10c0.zip/node_modules/@eslint/js/src/index.js?
    at new NodeError (node:internal/errors:405:5)
    at packageResolve (node:internal/modules/esm/resolve:893:9)
    at moduleResolve (node:internal/modules/esm/resolve:942:20)
    at defaultResolve (node:internal/modules/esm/resolve:1135:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36)

Perhaps there's something with my environment or Yarn installation that's causing this issue then. I just don't understand what it could be. I also noticed @bppdddqqqq had the same problem as me according to a comment here: #1644 (comment) but I think that was with an older version.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 2, 2024

Here is what I did:

  • cloned your repository
  • yarn install
  • opened VS Code with ESLint extension 3.0.5
  • opened test.ts

Any additional info?

@davidkarlsson
Copy link

I thought that would be enough to reproduce the issue so I'm not sure what additional info I can give you unfortunately. I've tried running the repro on multiple computers now (one running win10 and the other win11) but I get the same error on both of them so I'm at a loss of what could be the cause of this.

Do you have any ideas? The only thing I could think of was the node version so I tried setting eslint.runtime to node to change the node version eslint uses from v18.17.1 to my system version which is v20.12.0 but that also didn't make any difference.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 3, 2024

I was able to reproduce this. It seems that you need to have corepack enabled so that yarn does the right thing.

This being said I do think that this comes from some PnP stuff yarn does. I can reproduce the same problem using simple eslint API. The following code:

PowerShell:

> $env:NODE_PATH=".yarn/sdks"

This is what yarn does when running the editor SDK for VS Code (see https://yarnpkg.com/getting-started/editor-sdks)

const library = require(`eslint`);

async function main() {
	const eslint = new (await library.loadESLint({ useFlatConfig: true }))();
	const report = await eslint.lintText(`var test = "hello";`);
	console.log(report);
}

main().catch((error) => {
	console.error(error);
	process.exit(1);
});

produces the exact same error:

bugs\vscode-eslint-test [main ≡ +0 ~1 -0 | +1 ~1 -0 !]> node
Welcome to Node.js v18.18.2.
Type ".help" for more information.
> const library = require(`eslint`);
undefined
> library
{
  Linter: [class Linter],
  loadESLint: [AsyncFunction: loadESLint],
  ESLint: [class ESLint] { configType: 'eslintrc' },
  RuleTester: [class RuleTester] {
    [Symbol(itOnly)]: null,
    [Symbol(it)]: null,
    [Symbol(describe)]: null
  },
  SourceCode: [class SourceCode extends TokenStore]
}
> async function main() { const eslint = new (await library.loadESLint({ useFlatConfig: true }))(); const report = await eslint.lintText(`var test = "hello";`); console.log(repo
rt); }
undefined
> main().catch((error) => { console.error(error); process.exit(1); });
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 117,
  [Symbol(trigger_async_id_symbol)]: 114
}
> Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from C:\xxxxxxxxx\bugs\vscode-eslint-test\eslint.config.mjs
Did you mean to import @eslint-js-npm-8.57.0-00ead3710a-10c0.zip/node_modules/@eslint/js/src/index.js?
    at new NodeError (node:internal/errors:405:5)
    at packageResolve (node:internal/modules/esm/resolve:890:9)
    at moduleResolve (node:internal/modules/esm/resolve:939:20)
    at defaultResolve (node:internal/modules/esm/resolve:1132:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}
bugs\vscode-eslint-test [main ≡ +0 ~1 -0 | +1 ~1 -0 !]>

IMO this is something the yarn people have to look into.

@davidkarlsson
Copy link

I can open a bug report in the Yarn repo for this but are you sure this is an problem with Yarn and not vscode-eslint or eslint? It looks like your repro works in node if you specify .pnp.loader.mjs as a loader which you always have to do with Yarn according to this comment: yarnpkg/berry#5241 (comment):

PS D:\vscode-eslint-test> $env:NODE_PATH
.yarn\sdks
PS D:\vscode-eslint-test> node -r ./.pnp.cjs --loader ./.pnp.loader.mjs
Welcome to Node.js v20.12.0.
Type ".help" for more information.
> .load bug.cjs
const library = require(`eslint`);

async function main() {
  const eslint = new (await library.loadESLint({ useFlatConfig: true }))();
  const report = await eslint.lintText(`var test = "hello";`);
  console.log(report);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 137,
  [Symbol(trigger_async_id_symbol)]: 134
}
> [
  {
    filePath: '<text>',
    messages: [],
    suppressedMessages: [],
    errorCount: 0,
    fatalErrorCount: 0,
    warningCount: 0,
    fixableErrorCount: 0,
    fixableWarningCount: 0,
    usedDeprecatedRules: [Getter]
  }
]

It also seems to work if you start node with yarn node without a loader argument because then the loader is registered automatically I think. I thought that this loader was injected in the node runtime by the vscode eslint sdk package that gets installed when you run the yarn dlx @yarnpkg/sdks vscode command so that it should be able to use ESM? From https://yarnpkg.com/getting-started/editor-sdks:

"The SDKs workaround that by generating indirection packages. When required, these indirection automatically setup the loader before forwarding the require calls to the real packages."

@dbaeumer
Copy link
Member

dbaeumer commented Apr 3, 2024

I thought that this loader was injected in the node runtime by the vscode eslint sdk package that gets installed when you run the yarn dlx @yarnpkg/sdks vscode command so that it should be able to use ESM?

Yes, and this is what is happening. By setting $env:NODE_PATH=".yarn/sdks" node is instructed to load node modules from .yarn/sdks which should inject the loader according to: https://yarnpkg.com/getting-started/editor-sdks

The yarn dlx @yarnpkg/sdks vscode sets the eslint.nodePath setting (see https://github.com/davidkarlsson/vscode-eslint-test/blob/main/.vscode/settings.json#L6) which the extension then passes on to node.

The extension itself doesn't know anything about yarn pnp.

@davidkarlsson
Copy link

Thanks @dbaeumer. I understand the issue better now. I also found another issue about more or less the same problem in #1602 where they fix the loader issue by registering it with the eslint.execArgv option. So I can get linting working with the mjs config file by setting the loader argument like this:

"eslint.execArgv": [
  "--loader=file:///d%3A/vscode-eslint-test/.pnp.loader.mjs"
],

But hardcoding the path there is not really a solution so I'm guessing all we can do is wait for either vscode to implement support for using variables in settings? Or do you think this could be fixed in Yarn somehow without having to use the node loader argument?

@dbaeumer
Copy link
Member

dbaeumer commented Apr 4, 2024

I am still the opinion that this should be addressed in Yarn / yarn dlx. This worked before and has only problems when trying to load mjs config files in ESLint. I don't know a lot about yarn pnp but my guess is that the loading works differently when doing cjs and mjs (they have two different loader files for this) and they don't expect eslint doing mjs load of a config file.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 4, 2024

VS Code itself has an issue to support variables in settings which would be the right approach to avoid the hardcoded absolute path.

@dbaeumer
Copy link
Member

I created yarnpkg/berry#6219 to track the mjs load failure in yarn.

@ctjlewis
Copy link

ctjlewis commented Apr 20, 2024

This is not experimental you morons, it is the default output for the configuration file with eslint --init now. The current behavior of simply not recognizing the new config, without showing any kind of warning, is unjustifiable.

The old config files are now deprecated and are unrecognized on latest:

https://eslint.org/docs/latest/use/configure/configuration-files-deprecated

@skondrashov
Copy link

It does recognize it (you moron) as long as you set your working path correctly.

@ctjlewis
Copy link

I just copied an old .eslintrc and downgraded to 8.0.0 and things are working. This team's only job is to maintain this part of the software. Do better.

@skondrashov
Copy link

You're looking for the people over at eslint who changed how the config is looked up. "This team" is as far as I can tell one person and you certainly aren't paying them.

@konrazem
Copy link

I just copied an old .eslintrc and downgraded to 8.0.0 and things are working. This team's only job is to maintain this part of the software. Do better.

Thank you I didn't noticed I upgraded eslint by mistake. Go back from 9.1 to 8.31 solved this issue (or I think go step by step trough Migrate to v9.x)

@HatemMn
Copy link

HatemMn commented Apr 22, 2024

"eslint.experimental.useFlatConfig": true, This works for me but it seems to disable legacy config files. Would be nice if I could have both options on but I guess that's not possible?

For those who are still having the same problem, this solution has directly fixed it for me

@hanyufoodles
Copy link

I'm using the ESLint extension 3.0.5 and the issue still exists with whatever "eslint.experimental.useFlatConfig": true or "eslint.useFlatConfig": true.

It works fine with eslint.config.cjs in commonjs but it fails to find the module with mjs with yarn pnp. But running eslint on command line works with mjs file. The cause is either in the yarn editor sdk or in the vscode extension.

@dbaeumer
Copy link
Member

dbaeumer commented May 6, 2024

For yarn pnp please see: yarnpkg/berry#6219.

It basically doesn't work with the npm package of eslint in a non VS Code example either.

@fatlard1993
Copy link

My package is "type": "module", and I setup a new eslint.config.js flat config file as a module (with import/export) and the cli lint works as-expected, but no combination of eslint configuration changes in vscode would get it to run inside vscode. I converted my eslint config to cjs with require/module.exports + .cjs extension and the cli still works and vscode now picks it up. I was even able to remove the various config changes suggested in this thread and am now able to run eslint in repos with the old config files AND the new ones side-by-side

@caleb531
Copy link

caleb531 commented Aug 16, 2024

Would it be possible to update this extension to support .mjs or ESM .js syntax for ESLint flag config? I also have a "type":"module" project that I have been recently trying to migrate to ESLint. But this one issue with VS Code is keeping me from switching to ESLint v9 and the flat config format. I would very much prefer not to convert the config to CommonJS.

@dbaeumer
Copy link
Member

This works for me in my examples:

image

@caleb531 could you please provide me with a GitHub repository I can clone with a minimal setup that demos the problem you are seeing?

@caleb531
Copy link

@dbaeumer Well, I have a SvelteKit project, and after further testing I can confirm that VS Code with eslint.config.js is correctly linting JS and TS files, but not Svelte files.

Here is my repository (branch: eslint-v9):
https://github.com/caleb531/personal-website/tree/eslint-v9

Interestingly, when I run pnpm exec eslint, the one error in my Svelte component is properly captured. It's just not showing up in VS Code. This indicates to me that my ESLint config is correct, but the extension is maybe not correctly reading it? I'm not sure.

/Users/caleb/Repositories/personal/personal-website/src/routes/Head.svelte
  24:46  error  Unnecessary escape character: \/  no-useless-escape

✖ 1 problem (1 error, 0 warnings)

I made sure I have the Eslint: Use Flat Config setting enabled in VS Code. I have also made sure that svelte is added to the list of languages to probe in the eslint.probe setting.

The Output pane just shows:

[Info  - 8:43:34 AM] ESLint server is starting.
[Info  - 8:43:34 AM] ESLint server running in node v20.14.0
[Info  - 8:43:34 AM] ESLint server is running.
[Info  - 8:43:35 AM] ESLint library loaded from: /Users/caleb/Repositories/personal/personal-website/node_modules/.pnpm/eslint@9.9.0/node_modules/eslint/lib/api.js

Here is my eslint.config.js for reference:

import js from '@eslint/js';
import ts from 'typescript-eslint';
import svelte from 'eslint-plugin-svelte';
import prettier from 'eslint-config-prettier';
import globals from 'globals';

/** @type {import('eslint').Linter.Config[]} */
export default [
  js.configs.recommended,
  ...ts.configs.recommended,
  ...svelte.configs['flat/recommended'],
  prettier,
  ...svelte.configs['flat/prettier'],
  {
    languageOptions: {
      globals: {
        ...globals.browser,
        ...globals.node
      }
    }
  },
  {
    files: ['**/*.svelte'],
    languageOptions: {
      parserOptions: {
        parser: ts.parser
      }
    }
  },
  {
    ignores: [
      '.DS_Store',
      'node_modules',
      'build',
      '.svelte-kit',
      '.vercel',
      'package',
      '.env',
      '.env.*',
      '!.env.example',
      'pnpm-lock.yaml',
      'package-lock.json',
      'yarn.lock'
    ]
  }
];

Please let me know if I'm missing anything crucial here.

@caleb531
Copy link

I figured it out! I just had to set the eslint.validate array and include 'svelte' in my VS Code workspace settings, like so:

{
  // ...
  "eslint.validate": ["svelte"]
  // ...
}

For anyone who comes across this same issue, also take a look at #1736, which explains the difference between the eslint.probe and eslint.validate settings. I'm not exactly sure why I needed to force validation this way, since I already have the relevant eslint-plugin-svelte settings installed (as well as the Svelte VS Code extension).

Hopefully there are no drawbacks to doing it this way, even though the error shows up correctly in my Problems panel:
Screenshot 2024-08-17 at 10 18 30 AM

@dbaeumer
Copy link
Member

The eslint.validate is necessary for file types for which the server has no auto-probing support. Since ESLint can validate so many different file types the extensions needs to know which types to validate. Since VS Code operates on language ids and not on file extensions you need to specify the language ids you want to see validated. It is comparable to glob patterns on the command line.

@kjmj
Copy link

kjmj commented Sep 4, 2024

@caleb531 This solution also works for me, but doesn't feel ideal. I want my eslint extension to use the exact same rules as defined in eslint.config.js, and I can't seem to get that working. Am I missing something?

I have a pretty standard project created with sveltekit, and eslint.config.js is in the root of my project.

@caleb531
Copy link

caleb531 commented Sep 5, 2024

@kjmj Can you please clarify what you're asking? What's working for you, and what isn't working?

@kjmj
Copy link

kjmj commented Sep 5, 2024

@caleb531 I want VS Code to use my eslint.config.js file for all linting. This approach is preferable to modifying local VS Code settings because it ensures a consistent linting experience for all developers working on the project with a single ESLint configuration file.

@caleb531
Copy link

caleb531 commented Sep 5, 2024

@kjmj @kjmj If you commit a .vscode directory to your project with a settings.json file, those settings will apply to any VS Code window that's open for that project directory, which will apply to any developer on your project as long as they are using VS Code. You can see the settings.json in my personal website repository for an example of this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
info-needed Issue requires more information from poster
Projects
None yet
Development

No branches or pull requests