Skip to content

Bug: --fix unexpectedly removes eslint-disable comment #10013

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

Open
4 tasks done
andersk opened this issue Sep 18, 2024 · 2 comments
Open
4 tasks done

Bug: --fix unexpectedly removes eslint-disable comment #10013

andersk opened this issue Sep 18, 2024 · 2 comments
Labels
accepting prs Go ahead, send a pull request that resolves this issue bug Something isn't working

Comments

@andersk
Copy link
Contributor

andersk commented Sep 18, 2024

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have searched for related issues and found none that matched my issue.
  • I have read the FAQ and my problem is not listed.

Issue Description

typescript-eslint correctly flags a @typescript-eslint/no-unsafe-member-access error when accessing an untyped module.

However, if I ignore this error with an eslint-disable-next-line comment, and reportUnusedDisableDirectives is enabled, the comment is unexpectedly removed by eslint --fix.

With the comment removed, the error is not reported when running with --fix, but it is reported when running without --fix.

Reproduction Repository Link

https://gist.github.com/andersk/5bacfa857d080e6ed6627063f0700694

Repro Steps

$ git clone https://gist.github.com/andersk/5bacfa857d080e6ed6627063f0700694 test
$ cd test
$ npm i
$ npx eslint test.ts
$ npx eslint --fix test.ts
$ git diff
diff --git a/test.ts b/test.ts
index 533595b..049fb4d 100644
--- a/test.ts
+++ b/test.ts
@@ -1,5 +1,5 @@
 // @ts-expect-error This module is not typed
 import * as untyped from "./untyped";
 
-// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ 
 console.log(untyped.hello);
$ npx eslint test.ts
/tmp/test/test.ts
  5:21  error  Unsafe member access .hello on an `error` typed value  @typescript-eslint/no-unsafe-member-access

✖ 1 problem (1 error, 0 warnings)

Versions

package version
@typescript-eslint/eslint-plugin 8.6.0
@typescript-eslint/parser 8.6.0
@typescript-eslint/scope-manager 8.6.0
@typescript-eslint/typescript-estree 8.6.0
@typescript-eslint/type-utils 8.6.0
@typescript-eslint/utils 8.6.0
TypeScript 5.5.4
ESLint 9.10.0
node 20.17.0
@andersk andersk added bug Something isn't working triage Waiting for team members to take a look labels Sep 18, 2024
@kirkwaiblinger kirkwaiblinger added accepting prs Go ahead, send a pull request that resolves this issue and removed triage Waiting for team members to take a look labels Sep 18, 2024
@kirkwaiblinger
Copy link
Member

Confirmed locally.... weird!

wondering if it's to do with single run inference related things? Note that the report also shows up as unused in my editor.

@auvred
Copy link
Member

auvred commented Oct 3, 2024

Running eslint test.ts without --fix implies: single run === true -> TS programs are created from tsconfig.json specified in eslint.config.mjs

/**
* If this is a single run in which the user has not provided any existing programs but there
* are programs which need to be created from the provided "project" option,
* create an Iterable which will lazily create the programs as needed by the iteration logic
*/
if (
parseSettings.singleRun &&
!parseSettings.programs &&
parseSettings.projects.size > 0
) {
parseSettings.programs = {
*[Symbol.iterator](): Iterator<ts.Program> {
for (const configFile of parseSettings.projects) {
const existingProgram = existingPrograms.get(configFile[0]);
if (existingProgram) {
yield existingProgram;
} else {
log(
'Detected single-run/CLI usage, creating Program once ahead of time for project: %s',
configFile,
);
const newProgram = createProgramFromConfigFile(configFile[1]);
existingPrograms.set(configFile[0], newProgram);
yield newProgram;
}
}
},
};
}

Running eslint --fix test.ts implies: single run === false -> create watch program -> create watch compiler host -> watch compiler host created with allowJs: true since it is set as the default compiler option
const DEFAULT_COMPILER_OPTIONS: ts.CompilerOptions = {
...CORE_COMPILER_OPTIONS,
allowNonTsExtensions: true,
allowJs: true,
checkJs: true,
};
function createDefaultCompilerOptionsFromExtra(
parseSettings: ParseSettings,
): ts.CompilerOptions {
if (parseSettings.debugLevel.has('typescript')) {
return {
...DEFAULT_COMPILER_OPTIONS,
extendedDiagnostics: true,
};
}
return DEFAULT_COMPILER_OPTIONS;
}

In the second case (with --fix), the TS program allows importing .js files. Therefore, untyped.hello is not reported as an "error typed value".


optionsToExtend (containing allowJs: true) passed to watch compiler host will take precedence over compiler options from the project: 'tsconfig.json' specified. Even if user specified "allowJs": false, importing JS will be allowed during eslint file.ts run. I think we should exclude allowJs from watch compiler host options. WDYT?


A very similar issue was reported in some repositories after single run inference was enabled by default: #9749

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepting prs Go ahead, send a pull request that resolves this issue bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants