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

Enable Flat Config by default #1644

Open
Tracked by #18093
polyzen opened this issue Apr 27, 2023 · 33 comments
Open
Tracked by #18093

Enable Flat Config by default #1644

polyzen opened this issue Apr 27, 2023 · 33 comments
Labels
feature-request Request for new features or functionality
Milestone

Comments

@polyzen
Copy link

polyzen commented Apr 27, 2023

Flat Config is now considered complete:
eslint/eslint@7162d34

Seems it should no longer be masked behind eslint.experimental.useFlatConfig.

@dbaeumer
Copy link
Member

This might not be easy to enable by default since the ESLint server doesn't start on the workspace folder root.

@ghost
Copy link

ghost commented Oct 16, 2023

Flat config is enabled by default from ESLint v9.0.0 and the ".eslintrc.*" format seems to be removed in v10.0.0
https://eslint.org/blog/2023/10/flat-config-rollout-plans/

@chojnicki
Copy link

Any ETA on that? It's pretty weird that it's considered as experimental feature. It should be default for sure since flat config is becoming standard. Extension should keep up with library :)

@dbaeumer dbaeumer added the feature-request Request for new features or functionality label Dec 4, 2023
@aladdin-add
Copy link

aladdin-add commented Jan 24, 2024

shouldUseFlatConfig can be used for this honor.

const {shouldUseFlatConfig} = require("eslint/use-at-your-own-risk");

shouldUseFlatConfig();

@nzakas
Copy link

nzakas commented Jan 24, 2024

@dbaeumer I think shouldUseFlatConfig() probably helps with this? If not, and you need something else, let us know.

@dbaeumer
Copy link
Member

@nzakas the reason why I haven't switch yet is that I am under the impression that to get to the new FlatESLint class I still need to import 'eslint/use-at-your-own-risk' which I always interpreted as not being final yet.

Has this changed? What I would like to do is to import eslint normally and then have a flag shouldUseFlatConfig. Is this possible?

@nzakas
Copy link

nzakas commented Jan 29, 2024

@dbaeumer the /use-at-your-own-risk entrypoint is intended to let people know that these APIs won't be around forever, more than anything else.

For the latest v8 and all of v9, FlatESLint, LegacyESLint, and shouldUseFlatConfig() are all available through that entrypoint. They'll be removed in v10 (whenever that happens).

Full details here:
https://eslint.org/blog/2023/10/flat-config-rollout-plans/

@dbaeumer
Copy link
Member

dbaeumer commented Jan 30, 2024

Reading the link from above brought me to the following conclusion:

  • 8.x : flat config is not the default an needs to be enabled via an env variable ESLINT_USE_FLAT_CONFIG or when a flat config file exists in the workspace root. Since a lot of VS Code users start VS Code from a dock it is not easy to inject env variables based on workspaces. This is why I introduced the eslint.experimental.useFlatConfig since it gives control over this per workspace. We can debate the name (e.g. the experimental part) but I think it is not worse it to change right now. What I can add is code that checks if ESLINT_USE_FLAT_CONFIG is set and then automatically set eslint.experimental.useFlatConfig.
  • 9.x: flat config is the default unless explicitly disabled. Her the fun begins :-). I can only determine the version of ESLint after I have loaded ESLint. If I get < 9.x I need to reload ESlint from /use-at-your-own-risk in case users opted into flat config.
  • 10.x: more version checks and more if then else code blocks since now the behavior of the classes have changed (ESLint -> FlatConfig).

From my experiences designing API, it would have been easier for API users, if the API would have added new names and removed old names instead if reusing names and changing the meaning. The first would have avoided checking the version since the pure existence of a name would introduce a behavior. In VS Code we usually use a function to load the API to which you can pass a parameter to determine if you want proposed API. If you opt into this they are put into the same namespace.

@nzakas any change to revisit the rollout plan especially around the meaning change of ESLint -> FlatESLint.

@nzakas
Copy link

nzakas commented Jan 31, 2024

I appreciate the feedback, but at this point we are weeks away from a beta (three alpha releases have already been published), so revisiting the rollout plan really isn't in the cards.

To clarify: the change to the behavior of ESLint begins in v9, not v10. This is also why we've added LegacyESLint as a sibling to FlatESLint to give people something solid to hold onto should they decide to support both.

In VS Code we usually use a function to load the API to which you can pass a parameter to determine if you want proposed API. If you opt into this they are put into the same namespace.

Can you give an example of this? I'm not opposed to adding something along these lines, but need to see it in action in order to evaluate.

@dbaeumer
Copy link
Member

dbaeumer commented Feb 1, 2024

Actually I don't want to change the timing. I understand that this is not possible. I was more hoping for some sort of additional API to make this easier for API users that need to support 8.x, 9.x and 10.x

Let me first explain what we do in VS Code and LSP to mitigate those changes. In general we do two things:

  • proposed API has NO special name space. This avoid that when we move things to final names stay the same
  • we don't reuse deprecated names

VS Code

ESLint

For ESLint it would be cool to have the following:

  • they top level API (when requiring eslint) exports a function resolveAPI(proposed: boolean).
  • the return literal would have the following entries
{
     shouldUseFlatConfig?, // Function as described
     ESLint?, // The current ESLint class
     ESLint2?, // The flat eslint class
     Linter?, // The current linter class
     Linter2?: // The flat linter class
}

If proposed is false then the 2 classes and the shouldUseFlatConfig would not be there.

Something like this would allow to use the API without checking version to interpret names differently.

Let me know if something like this would be possible?

@nzakas
Copy link

nzakas commented Feb 2, 2024

Because we are getting into API design, let's continue this conversation in the ESLint repo here:
eslint/eslint#18075

@fasttime
Copy link

fasttime commented Feb 3, 2024

  • 9.x: flat config is the default unless explicitly disabled. Her the fun begins :-). I can only determine the version of ESLint after I have loaded ESLint. If I get < 9.x I need to reload ESlint from /use-at-your-own-risk in case users opted into flat config.

No need to load the ESLint class directly: the version of ESLint can be determined from "eslint/package.json". It's exported in all versions of ESLint v8.

I was more hoping for some sort of additional API to make this easier for API users that need to support 8.x, 9.x and 10.x

I'm afraid it won't be easy to add an additional API to already published versions of ESLint 8.x. But it could be added in v9 if it simplifies the upgrade to v10.

@nzakas
Copy link

nzakas commented Feb 26, 2024

The new API has been released in both the v8.x and v9.x branches:
https://eslint.org/docs/latest/integrate/nodejs-api#loadeslint

@lubaker
Copy link

lubaker commented Feb 29, 2024

@dbaeumer with the new API provided by ESLint does that mean that a single VSCode workspace will be able to use both flat and eslintrc configs depending on what ESLint files exist in the current working directory when using ESLint 8?

It appears that the current eslint.experimental.useFlatConfig setting either uses flat config everywhere or eslintrc configs everywhere regardless of what ESLint config files exist in the relevant directories. For example when using ESLint 8, ideally the VSCode plugin matches that version of ESLint's behavior in the sample project below by using the eslintrc config in package1 and the flat config in package2.

project
├── package1
│   └── .eslintrc.json
└── package2
    └── eslint.config.js

@dbaeumer
Copy link
Member

dbaeumer commented Mar 4, 2024

@lubaker I haven't tried the new API so I can't tell yet :-)

@dbaeumer
Copy link
Member

dbaeumer commented Mar 7, 2024

Based on the new API from @nzakas I created a new alpha version of the extension. It can be found here: https://github.com/microsoft/vscode-eslint/releases/tag/3.0.1-alpha.1

If you use 8.57.0 or above it should auto detect flat config. I also has a big change to move to pull diagnostics which gives us better validation scheduling and validating on focus change.

To install it download the VSIX and execute the command Extensions: Install from VSIX

Would be great to get some early feedback since most of my repositories are still using the old config style :-)

@dbaeumer dbaeumer modified the milestones: On Deck, Next Mar 7, 2024
@lubaker
Copy link

lubaker commented Mar 7, 2024

Would be great to get some early feedback since most of my repositories are still using the old config style :-)

This appears to work for me. I'm using ESLint 8.57.0 with your alpha and the "Use Flat Config" setting unchecked. In a directory with a flat config, it is linting using the flat configuration and in directories with the old config style, it lints using that config. 💯

@moeriki
Copy link

moeriki commented Mar 8, 2024

Works OOTB in a "simple" repo. It doesn't in a monorepo (pnpm, eslint config per workspace).

[Error - 11:24:40] Request textDocument/codeAction failed.
  Message: Request textDocument/codeAction failed with message: No ESLint configuration found in […]/project/workspace/scripts.
  Code: -32603 

@karlhorky
Copy link
Contributor

karlhorky commented Mar 8, 2024

@moeriki are you running into this design feature of the ESLint Flat Config, where it is recommended to use a single flat config in the root also in monorepos? Maybe also comment on the ESLint discussion over here?

@moeriki
Copy link

moeriki commented Mar 8, 2024

I see. It's an interesting discussion worth following, and I might try it out. But I don't feel like they mention a technical limitation. It looks more like a general new recommendation, that wasn't possible before with the RC config architecture. But it think it should still be up to the developer to decide what's best for them.

@dbaeumer
Copy link
Member

dbaeumer commented Mar 11, 2024

@moeriki do you let eslint know about the working directories of your mono repository using the eslint.workingdirectories setting? you could use the auto mode [{ "mode": "auto" }]

@bppdddqqqq
Copy link

bppdddqqqq commented Mar 16, 2024

Flat Config loader seems to not work in Yarn+PnP environments. It will fail to import any requirement. Using version 3.0.1, but I've also tested it on latest version. Nodepath is set to .yarn/sdks

[Error - 12:48:03 PM] Calculating config file for file:///c%3A/...EmailCard.tsx) failed.
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-config-prettier' imported from C:\...\eslint.config.js
Did you mean to import eslint-config-prettier-virtual-e87a680651/4/AppData/Local/Yarn/Berry/cache/eslint-config-prettier-npm-9.1.0-0e1fd42d7d-10c0.zip/node_modules/eslint-config-prettier/index.js?
    at packageResolve (node:internal/modules/esm/resolve:853:9)
    at moduleResolve (node:internal/modules/esm/resolve:910:20)
    at defaultResolve (node:internal/modules/esm/resolve:1130:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:396:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:365:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:240:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
    at link (node:internal/modules/esm/module_job:84:36)

from eslint.config.js:

import eslintPrettier from 'eslint-config-prettier'
import tseslint from 'typescript-eslint';
import reactPlugin from 'eslint-plugin-react';
import hooksPlugin from 'eslint-plugin-react-hooks';

export default tsconfig({
   ...
})

Edit:

Found the mitigation. Rewriting the config into CommonJS seems to remedy the issue, there is something cursed happening with ESM Module Imports in the VSCode-land.

@dbaeumer
Copy link
Member

I just created a mjs example here:

using npm which works in the extension (please ensure to use the alpha I posted here: #1644 (comment))

Does validation happen correctly for you in the terminal using eslint from the node_modules folder.

@dbaeumer
Copy link
Member

Created a new alpha release here: https://github.com/microsoft/vscode-eslint/releases/tag/3.0.3-alpha.1

Has support for auto detecting flat config roots if no working directories are specified. This should make the conversion from rc -> flat easier.

@rdecoito
Copy link

Trying out 3.0.3-alpha.1 in a rush monorepo. All projects have an eslint.config.js (I also tried esling.config.mjs) and have eslint v8.57 installed in their package.json. Forgive the lack of a full repro right now - I have some speculation that, if correct, probably doesn't require one. But if it doesn't pan out I'll try to whip one up.

I'm getting the following error (abridged log becuase I'm manually scrubbing company and project names):

[Error - 12:47:51 PM] Calculating config file for file:///home/lrdecoito/development/<projname>/website/apps/%40<companyname>/<package1>/eslint.config.mjs) failed.
Error: No ESLint configuration found in /home/lrdecoito/development/<projname>/website/apps/@<companyname>/<package1>.

I noticed there's a %40 replacing the @ sign in the path to my eslint.config.mjs file. But the %40 is only in that first log line, not the second line (the beginning of the stack trace).

Is it possible that this version of vscode-eslint is URL-encoding the path and attempting to resolve that in the file system, which causes the resolution to fail if it includes non-ascii characters?

@rdecoito
Copy link

Disregard the last comment. I don't think it has anything to with encoded path resolution, and that's what I get for taking guesses at things I don't know anything about.

I found some time today to create a reproduction repo that replicates the Rush monorepo setup I'm currently using in my project. You can find it at https://github.com/rdecoito/eslint-monorepo-repro, along with a README that explains reproduction steps. Let me know if you run into any problems but it should all be kosher.

Here's the first handful of lines I see in the VSCode Output tab for ESLint (using 3.0.0-alpha.1):

[Info  - 4:14:22 PM] ESLint server is starting.
[Info  - 4:14:22 PM] ESLint server running in node v18.17.1
[Info  - 4:14:22 PM] ESLint server is running.
[Info  - 4:14:23 PM] ESLint library loaded from: /home/lrdecoito/development/eslint-monorepo-repro/common/temp/node_modules/.pnpm/eslint@8.57.0/node_modules/eslint/lib/api.js
[Error - 4:14:23 PM] Calculating config file for file:///home/lrdecoito/development/eslint-monorepo-repro/projects/application-1/src/App.tsx) failed.
Error: No ESLint configuration found in /home/lrdecoito/development/eslint-monorepo-repro/projects/application-1/src.
    at CascadingConfigArrayFactory._finalizeConfigArray (/home/lrdecoito/development/eslint-monorepo-repro/common/temp/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:4000:19)
    at CascadingConfigArrayFactory.getConfigArrayForFile (/home/lrdecoito/development/eslint-monorepo-repro/common/temp/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3791:21)
    at CLIEngine.isPathIgnored (/home/lrdecoito/development/eslint-monorepo-repro/common/temp/node_modules/.pnpm/eslint@8.57.0/node_modules/eslint/lib/cli-engine/cli-engine.js:1000:18)
    at ESLint.isPathIgnored (/home/lrdecoito/development/eslint-monorepo-repro/common/temp/node_modules/.pnpm/eslint@8.57.0/node_modules/eslint/lib/eslint/eslint.js:681:26)
    at /home/lrdecoito/.vscode/extensions/dbaeumer.vscode-eslint-3.0.3/server/out/eslintServer.js:1:24136
    at Object.M [as withClass] (/home/lrdecoito/.vscode/extensions/dbaeumer.vscode-eslint-3.0.3/server/out/eslintServer.js:1:19646)
    at async O.then.m.validate (/home/lrdecoito/.vscode/extensions/dbaeumer.vscode-eslint-3.0.3/server/out/eslintServer.js:1:24088)
    at async /home/lrdecoito/.vscode/extensions/dbaeumer.vscode-eslint-3.0.3/server/out/eslintServer.js:1:233174
    at async /home/lrdecoito/.vscode/extensions/dbaeumer.vscode-eslint-3.0.3/server/out/eslintServer.js:1:63719

The setup here is having the monorepo open as a single folder in VSCode and having each project in that repo declare its own eslint.config.js configuration. I know there's been some discussion in other issues about whether you should have a single config at the root of a monorepo or individual configs in each project, but I think the only correct answer is "either way should work." The paradigm my reproduction repo is following is that of independent projects, where you could pluck one of your monorepo projects out into its own repo with no file copy-pasting and very little editing. Thus, I think it's necessary to support this use case for flat configs.

Thanks for all your hard work, Dirk! I really do love this extension and you're a real champion for everything you've done.

@dbaeumer
Copy link
Member

@rdecoito thanks for the great repro. Highly appreciated.

Found the problem and is addressed by: #1817

@dbaeumer
Copy link
Member

New release here: https://github.com/microsoft/vscode-eslint/releases/tag/3.0.5-alpha.1

@dbaeumer
Copy link
Member

dbaeumer commented Apr 2, 2024

3.0.5 got released a a pre-release version in the marketplace.

@newoga
Copy link

newoga commented Apr 7, 2024

@dbaeumer Just installed the 3.0.5 prerelease and it worked out of the box for me. The environment is a pnpm monorepo that contains packages with both flat and legacy config formats.

Thanks for the hard work on this. 👍

@aladdin-add
Copy link

eslint v9 has been released: https://eslint.org/blog/2024/04/eslint-v9.0.0-released/

@nzakas
Copy link

nzakas commented May 9, 2024

@dbaeumer is there a timeline for a beta or final release?

@dbaeumer
Copy link
Member

I want to release a new version (not pre-release) beginning of next week. However there will still be a loose end with yarn pnp and mjs files. The details are here: yarnpkg/berry#6219

To make that work we need a new yarn version and VS Code being move to Electron 29 which will be the case with the next stable release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests