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

type-aware lints error with default generate eslint config #11209

Closed
NullVoxPopuli opened this issue Dec 6, 2023 · 4 comments
Closed

type-aware lints error with default generate eslint config #11209

NullVoxPopuli opened this issue Dec 6, 2023 · 4 comments

Comments

@NullVoxPopuli
Copy link

NullVoxPopuli commented Dec 6, 2023

Describe the bug

Hello!!! I'm new to svelte, first issue:

type-aware lints, when enabled, are not supported out of the box.

I also posted about this in the Discord: https://discord.com/channels/457912077277855764/1182013829626986516/1182013829626986516

Reproduction

Project here: https://stackblitz.com/edit/stackblitz-starters-rvyx2s

  • npm create svelte@latest my-app

    ❯ npm create svelte@latest my-app
    Need to install the following packages:
      create-svelte@5.3.3
    Ok to proceed? (y) y
    
    create-svelte version 5.3.3
    
    ┌  Welcome to SvelteKit!
    │
    ◇  Which Svelte app template?
    │  SvelteKit demo app
    │
    ◇  Add type checking with TypeScript?
    │  Yes, using TypeScript syntax
    │
    ◇  Select additional options (use arrow keys/space bar)
    │  Add ESLint for code linting, Add Prettier for code formatting, Add Vitest for unit testing
    │
    └  Your project is ready!
    
    ✔ Typescript
      Inside Svelte components, use <script lang="ts">
    
    ✔ ESLint
      https://github.com/sveltejs/eslint-plugin-svelte
    
    ✔ Prettier
      https://prettier.io/docs/en/options.html
      https://github.com/sveltejs/prettier-plugin-svelte#options
    
    ✔ Vitest
      https://vitest.dev
    
    Install community-maintained integrations:
      https://github.com/svelte-add/svelte-add
    
    Next steps:
      1: cd my-app
      2: npm install
      3: git init && git add -A && git commit -m "Initial commit" (optional)
      4: npm run dev -- --open
    
    To close the dev server, hit Ctrl-C
    
    Stuck? Visit us at https://svelte.dev/chat
    
  • add to the lint config:

    // existing
    		{
      		files: ['*.svelte'],
      		parser: 'svelte-eslint-parser',
      		parserOptions: {
      			parser: '@typescript-eslint/parser'
      		},
    // new
      		rules: {
      			'@typescript-eslint/no-unsafe-argument': 'error',
      			'@typescript-eslint/no-unsafe-assignment': 'error',
      			'@typescript-eslint/no-unsafe-call': 'error',
      			'@typescript-eslint/no-unsafe-member-access': 'error',
      			'@typescript-eslint/no-unsafe-return': 'error'
      		}
      	}
  • pnpm i

  • pnpm eslint .

Logs

❯ pnpm eslint .

Oops! Something went wrong! :(

ESLint: 8.55.0

Error: Error while loading rule '@typescript-eslint/no-unsafe-argument': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
Occurred while linting /home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/+layout.svelte
    at getParserServices (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@typescript-eslint+utils@6.13.2_eslint@8.55.0_typescript@5.3.2/node_modules/@typescript-eslint/utils/dist/eslint-utils/getParserServices.js:29:15)
    at create (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@typescript-eslint+eslint-plugin@6.13.2_@typescript-eslint+parser@6.13.2_eslint@8.55.0_typescript@5.3.2/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unsafe-argument.js:130:55)
    at create (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@typescript-eslint+utils@6.13.2_eslint@8.55.0_typescript@5.3.2/node_modules/@typescript-eslint/utils/dist/eslint-utils/RuleCreator.js:38:20)
    at createRuleListeners (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:910:21)
    at runRules/< (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1081:110)
    at runRules (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1018:34)
    at _verifyWithoutProcessors (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1370:31)
    at _verifyWithProcessor/messageLists< (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1928:29)
    at _verifyWithProcessor (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1923:37)
    at _verifyWithConfigArray (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1815:25)
    at verify (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:1452:65)
    at verifyAndFix (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/linter/linter.js:2083:29)
    at verifyText (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli-engine/cli-engine.js:254:48)
    at executeOnFiles (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli-engine/cli-engine.js:834:38)
    at lintFiles (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/eslint/eslint.js:551:23)
    at execute (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli.js:402:36)

System Info

~/projects/stackblitz-starters-rvyx2s
❯ cd my-app/

~/projects/stackblitz-starters-rvyx2s/my-app
❯ npx envinfo --system --binaries --browsers --npmPackages "{svelte,@sveltejs/*,vite}"
Need to install the following packages:
  envinfo@7.11.0
Ok to proceed? (y) y

  System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.10.5 - /usr/local/bin/pnpm

Severity

blocking all usage of SvelteKit

Additional Information

Specifying the tsconfig.json,

        project: require.resolve(path.join(__dirname, 'tsconfig.json')),
whole file

const path = require('path');

/** @type { import("eslint").Linter.FlatConfig } /
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended',
'prettier',
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte'],
},
env: {
browser: true,
es2017: true,
node: true,
},
overrides: [
{
files: ['
.svelte'],
parser: 'svelte-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
project: require.resolve(path.join(__dirname, 'tsconfig.json')),
},
rules: {
'@typescript-eslint/no-unsafe-argument': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
},
},
],
};

then,

❯ pnpm eslint .

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/+layout.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/+page.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/Counter.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/Header.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/about/+page.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/sverdle/+page.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/sverdle/how-to-play/+page.svelte
  352:0  error  Parsing error: Cannot read file '/home/projects/stackblitz-starters-rvyx2s/my-app/.svelte-kit/tsconfig.json'

✖ 7 problems (7 errors, 0 warnings)

that .svelte-kit directory is super suspicious, like the CWD that eslint is running is incorrect.

but adding a .. to the tsconfig.json resolve, (as expected) errors earlier:

❯ pnpm eslint .

Oops! Something went wrong! :(

ESLint: 8.55.0

Error: Cannot read config file: /home/projects/stackblitz-starters-rvyx2s/my-app/.eslintrc.cjs
Error: Cannot find module '/home/projects/stackblitz-starters-rvyx2s/tsconfig.json'
Require stack:
- /home/projects/stackblitz-starters-rvyx2s/my-app/.eslintrc.cjs
- /home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
- /home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli-engine/cli-engine.js
- /home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/eslint/eslint.js
- /home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/eslint/index.js
- /home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli.js
- /home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/bin/eslint.js
    at InternalError (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:64:14767)
    at Module._resolveFilename (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:55:12642)
    at resolve (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:98:2256)
    at  (/home/projects/stackblitz-starters-rvyx2s/my-app/.eslintrc.cjs:30:26)
    at function (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:352:208332)
    at Module.prototype._compile (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:55:14871)
    at Module._extensions[".js"] (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:55:15550)
    at Module.prototype.load (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:55:13457)
    at Module._load (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:55:10535)
    at Module.prototype.require (https://stackblitzstartersrvyx2s-lde3.w-corp.staticblitz.com/blitz.6843a59c.js:55:13775)
    at module.exports (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/import-fresh@3.3.0/node_modules/import-fresh/index.js:32:59)
    at loadJSConfigFile (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2583:37)
    at loadConfigFile (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2667:20)
    at loadInDirectory (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2877:34)
    at _loadConfigInAncestors (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)
    at getConfigArrayForFile (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3792:18)
    at _iterateFilesRecursive (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli-engine/file-enumerator.js:450:49)
    at iterateFiles (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli-engine/file-enumerator.js:299:13)
    at executeOnFiles (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli-engine/cli-engine.js:797:9)
    at lintFiles (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/eslint/eslint.js:551:23)
    at execute (/home/projects/stackblitz-starters-rvyx2s/my-app/node_modules/.pnpm/eslint@8.55.0/node_modules/eslint/lib/cli.js:402:36)

So... is something going goofy with the svelte eslint plugin?

@drewkht
Copy link

drewkht commented Dec 10, 2023

Type-aware rules work fine in SvelteKit once you have it configured correctly. Maybe you just didn't show every command you typed throughout the process, but I didn't see that you ran pnpm dev before attempting to run ESLint. SvelteKit auto generates that .svelte-kit folder the first time you start the server, which includes a tsconfig.json file that's supposed to be extended by the tsconfig in the project root.

Normally the tsconfig that's created by the new project CLI tool handles extending the generated tsconfig but I didn't see that happening in your tsconfig you pasted.

https://kit.svelte.dev/docs/project-structure#project-files-tsconfig-json

@NullVoxPopuli
Copy link
Author

NullVoxPopuli commented Dec 11, 2023

Ok, i can give that a go, thanks!

Question tho, Can we change it to use the configs i define? Why use hidden configs? (Or .svelte-kit at all). This feels like a weirdness/departure from broader ecosystem convention

@drewkht
Copy link

drewkht commented Dec 11, 2023

Since v5.x.x (can't remember the exact version) TypeScript supports extending multiple tsconfigs at once. In my SvelteKit projects, from the tsconfig in the root project folder I extend both my own, custom tsconfig that's a package in my monorepo and the auto-generated tsconfig in the .svelte-kit folder and it works fine.

As far as your question about why use the .svelte-kit folder at all - that I can't really say. I'm not involved in the development of SvelteKit in any way, just a fairly experienced Svelte dev that saw your post on Reddit and thought I might know the answer.

I will say, though, that starting issues for problems that are (likely) easily solvable by having thoroughly read the docs (the .svelte-kit folder of auto-generated code is pretty fundamental to SvelteKit and isn't by any means an obscure feature) and then questioning core design decisions of the library as if that's the problem is a bit offputting from the perspective of someone trying to decide whether to devote some time to trying to help. 🤷‍♂️

@NullVoxPopuli
Copy link
Author

NullVoxPopuli commented Dec 11, 2023

that saw your post on Reddit and thought I might know the answer.

I appreciate you taking the time to help!

After running

pnpm dev
# ctrl+c
pnpm eslint .

I was able to successfully lint with type-aware rules, and I see these violations by default:

❯ pnpm eslint .

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/Counter.svelte
   8:21  error  Unsafe argument of type `any` assigned to a parameter of type `number`  @typescript-eslint/no-unsafe-argument
  25:58  error  Unsafe argument of type `any` assigned to a parameter of type `number`  @typescript-eslint/no-unsafe-argument
  26:24  error  Unsafe argument of type `any` assigned to a parameter of type `number`  @typescript-eslint/no-unsafe-argument

/home/projects/stackblitz-starters-rvyx2s/my-app/src/routes/Header.svelte
  19:28  error  Unsafe member access .url on an `any` value  @typescript-eslint/no-unsafe-member-access
  22:28  error  Unsafe member access .url on an `any` value  @typescript-eslint/no-unsafe-member-access
  25:22  error  Unsafe call of an `any` typed value          @typescript-eslint/no-unsafe-call
  25:28  error  Unsafe member access .url on an `any` value  @typescript-eslint/no-unsafe-member-access

✖ 7 problems (7 errors, 0 warnings)

I will say, though, that starting issues for problems that are (likely) easily solvable by having thoroughly read the docs [...] and then questioning core design decisions of the library as if that's the problem is a bit offputting from the perspective of someone trying to decide whether to devote some time to trying to help. 🤷‍♂️

Time for some background -- first, I do appreciate all help, and I didn't mean to "question design decisions", it's just I'm genuinely curious, and type-aware linting is a hard problem to solve with custom file syntax (something I'm helping with in another corner of the broader JavaScript ecosystem) -- especially given responses from the TypeScript team like this:

glancing at your config and the fact that the only files are .vue files - this is is probably due to weirdness between how vue-eslint-parser splits up files and then calls into our tooling.
Overall we just don't have good support for vue - it has a very custom stack which does its own things to call into our parser in not always compatible ways

And here:

Unfortunately we cannot support this usecase.
The TypeScript APIs we use require files to exist on the disk.

which is a fine assumption, but the TS team also doesn't really give you sufficient APIs for pluggability if you dare not use JSX/TSX.

And for Vue (also keep in mind I'm not very involved in that ecosystem), they're still working on figuring out ergonomic type-aware linting as they're regularly running in to problems with typescript-eslint.

Naturally, one might want to look at ['@typescript-eslint/parser's parserOptions.programs](https://github.com/typescript-eslint/typescript-eslint/tree/v5.30.7/packages/parser#parseroptionsprograms), if they already have an extended version of tsc` to handle their custom syntax, but ultimately requires patching tsc.

There is also this project: https://github.com/ota-meshi/typescript-eslint-parser-for-extra-files, but svelte-eslint-parser doesn't depend on it: https://www.npmjs.com/package/svelte-eslint-parser?activeTab=code so I'm not sure if it was a sort of experiment for a time and is no longer needed, or if it has a goal of some other thing that I couldn't figure out quickly enough.

(the .svelte-kit folder of auto-generated code is pretty fundamental to SvelteKit and isn't by any means an obscure feature)

I understand that reading docs is a bare minimum someone can do when starting a project, and I mean this is the most curious way possible, but I want to be clear about something, when I say

This feels like a weirdness/departure from broader ecosystem convention

every ESLint-using project i've seen across many ecosystems runs on source files, and doesn't require first running pnpm dev. So this feels like a bit of an ergonomics/understanding loss! Which I figure there must be a good reason to do (because doing more work than none usually has a very good reason -- maybe getting around some technical constraint or something). And because I'm involved with an ecosystem that is heavily inspired by developments in Svelte / SvelteKit, I was wondering what those challenges were? What do ya'll know that I don't know? ya know?

I have since looked in the .svelte-kit folder, and seems like a svelte-kit project is a project-generator, rather than the actual project itself?
But anywho, the TSConfig, has some aliasing involved, though a lot could probably have been extended from @tsconfig/svelte from https://github.com/tsconfig/bases/blob/main/bases/svelte.json, and all the custom includes are interesting -- is it documented somewhere why this is all "manually" (even though created by a tool), configured? I've seen other projects with custom file syntax not need any of the include/exclude stuff to the level of detail presented here. Is it performance? some neat trick?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants