Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix(eslint-plugin): [no-unused-vars] clear error report range#8640

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

developer-bandi
Copy link
Contributor

@developer-bandideveloper-bandi commentedMar 10, 2024
edited by auvred
Loading

PR Checklist

Overview

clear error range inno-unused-vars rule

kirkwaiblinger reacted with thumbs up emoji
@typescript-eslint
Copy link
Contributor

Thanks for the PR,@developer-bandi!

typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community.

The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately.

Thanks again!


🙏Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently onhttps://opencollective.com/typescript-eslint.

@netlifyNetlify
Copy link

netlifybot commentedMar 10, 2024
edited
Loading

Deploy Preview fortypescript-eslint ready!

NameLink
🔨 Latest commit702b828
🔍 Latest deploy loghttps://app.netlify.com/sites/typescript-eslint/deploys/662e656a32de340008a0189f
😎 Deploy Previewhttps://deploy-preview-8640--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 99 (🟢 up 6 from production)
Accessibility: 100 (no change from production)
Best Practices: 92 (no change from production)
SEO: 98 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to yourNetlify site configuration.

@nx-cloudNx Cloud
Copy link

nx-cloudbot commentedMar 10, 2024
edited
Loading

☁️ Nx Cloud Report

CI is running/has finished running commands for commit702b828. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 31 targets

Sent with 💌 fromNxCloud.

@codecovCodecov
Copy link

codecovbot commentedMar 10, 2024
edited
Loading

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 87.21%. Comparing base(216d1b0) to head(d95260e).

❗ Current headd95260e differs from pull request most recent head702b828. Consider uploading reports for the commit702b828 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@##             main    #8640      +/-   ##==========================================- Coverage   87.40%   87.21%   -0.19%==========================================  Files         260      251       -9       Lines       12605    12308     -297       Branches     3937     3880      -57     ==========================================- Hits        11017    10735     -282+ Misses       1313     1303      -10+ Partials      275      270       -5
FlagCoverage Δ
unittest87.21% <100.00%> (-0.19%)⬇️

Flags with carried forward coverage won't be shown.Click here to find out more.

FilesCoverage Δ
packages/eslint-plugin/src/rules/no-unused-vars.ts98.74% <100.00%> (+0.02%)⬆️

... and64 files with indirect coverage changes

@yeonjuan
Copy link
Contributor

yeonjuan commentedMar 10, 2024
edited
Loading

Hi@developer-bandi , I think it would be nice to explicitly specifyendColumn in some invalid test cases to guarantee the behavior and to prevent regressions! 👍

  • no-unused-vars.test.ts
{messageId:'unusedVar',line:3,column:1,endColumn:3,<<<<<<<add `endColumn`onsometestcasesdata:{varName:'foo',action:'assigned a value',additional:'',},},
developer-bandi reacted with thumbs up emoji

@developer-bandi
Copy link
ContributorAuthor

developer-bandi commentedMar 10, 2024
edited
Loading

@yeonjuan thank you, i add test case withendline andendColumn that cover shorten error range

    {      code: `const foo: number = 1;      `,      errors: [        {          messageId: 'unusedVar',          data: {            varName: 'foo',            action: 'assigned a value',            additional: '',          },          line: 2,          column: 7,          endLine: 2,          endColumn:10,        },      ],    },
yeonjuan reacted with thumbs up emoji

@bradzacherbradzacher added the bugSomething isn't working labelApr 4, 2024
Comment on lines 422 to 427
const node = writeReferences.length
? writeReferences[writeReferences.length - 1].identifier
: unusedVar.identifiers[0];

const { start } = node.loc;
const nodeVariableLength = node.name.length;
Copy link
Contributor

@yeonjuanyeonjuanApr 6, 2024
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

👍 What do you think about changing the variable names a bit?

Suggested change
constnode=writeReferences.length
?writeReferences[writeReferences.length-1].identifier
:unusedVar.identifiers[0];
const{ start}=node.loc;
constnodeVariableLength=node.name.length;
constid=writeReferences.length
?writeReferences[writeReferences.length-1].identifier
:unusedVar.identifiers[0];
const{ start}=node.loc;
constidLength=node.name.length;

auvred, armano2, and developer-bandi reacted with thumbs up emoji
Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

it make sense, so i change variable name. thank you!

node: writeReferences.length
? writeReferences[writeReferences.length - 1].identifier
: unusedVar.identifiers[0],
node,

This comment was marked as resolved.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

i delete node. thank you!

kirkwaiblinger reacted with thumbs up emoji

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Ah, looking closer at this... I may have led you astray, at least partially. Sorry about that! The test failures in CI are due to having removed thenode from the report, since some of the tests specifically check for the type of thenode
(the following function generates error assertions that demand anIdentifier be reported on via thetype field)

/**
* Returns an expected error for assigned-but-not-used variables.
*@param varName The name of the variable
*@param [additional] The additional text for the message data
*@param [type] The node type (defaults to "Identifier")
*@returns An expected error object
*/
functionassignedError(
varName:string,
additional='',
type=AST_NODE_TYPES.Identifier,
):TSESLint.TestCaseError<MessageIds>{
return{
messageId:'unusedVar',
data:{
varName,
action:'assigned a value',
additional,
},
type,
};
}

Now, it's still not clear to me that the value of thenode is actually used in any way other than being tested, though, when theloc is also provided. I ran into the same problem in#8874 and just removed thetype from the test cases, but I'm not totally sure if that is sound.

My thought is
if it has no effect => we should remove thetype from the test, since it's not testing anything at all, but it looks like it is
if it does have an effect => just putnode back.

Maybe@JoshuaKGoldberg or@bradzacher will know for sure? Would either of you know whether there's any reason to provide a reportnode ifloc is being provided?

developer-bandi reacted with thumbs up emoji

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yeah you only need to provide one or the other.

kirkwaiblinger reacted with thumbs up emoji
Copy link
Member

@kirkwaiblingerkirkwaiblinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The code looks good to me! Just requesting a bit more test coverage of the edge cases.
fireworks

@@ -419,10 +419,23 @@ export default createRule<Options, MessageIds>({
ref.from.variableScope === unusedVar.scope.variableScope,
);

const id = writeReferences.length

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Even though these branches collapse to do the same thing, I think it could be good to test both branches, in case one day they get separated (for example, to report different error messages)

What do you think about adding test cases with all 4 report loc fields for some cases like the following?

letfoo:number;
letfoo:number=1;foo=2;foo=3;

developer-bandi reacted with thumbs up emoji

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

(testing)
Could you also add a test case that uses thedeclare modifier with the fullloc data?

FYI - here and in other comments, there's probably no need to addnew test cases; modifying existing ones to have the fullloc data would work too 🙂

developer-bandi reacted with thumbs up emoji
@kirkwaiblingerkirkwaiblinger added the awaiting responseIssues waiting for a reply from the OP or another party labelApr 19, 2024
@github-actionsgithub-actionsbot removed the awaiting responseIssues waiting for a reply from the OP or another party labelApr 19, 2024
@kirkwaiblingerkirkwaiblinger added the 1 approval>=1 team member has approved this PR; we're now leaving it open for more reviews before we merge labelApr 19, 2024
armano2
armano2 previously approved these changesApr 22, 2024
bradzacher
bradzacher previously approved these changesApr 22, 2024
@kirkwaiblingerkirkwaiblinger added the awaiting responseIssues waiting for a reply from the OP or another party labelApr 23, 2024
@yeonjuan

This comment was marked as duplicate.

Copy link
Member

@kirkwaiblingerkirkwaiblinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

In great shape - only thing remaining blocking merge is resolution of#8640 (comment) (by removing type from test cases). Thanks!

@github-actionsgithub-actionsbot removed the awaiting responseIssues waiting for a reply from the OP or another party labelApr 28, 2024
Copy link
Member

@kirkwaiblingerkirkwaiblinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

rocket

@kirkwaiblingerkirkwaiblinger merged commit8127873 intotypescript-eslint:mainApr 28, 2024
57 of 58 checks passed
@cpojer
Copy link

I believe this change brokeeslint-plugin-unused-imports, which relies onno-unused-vars from this plugin to pull the node and amend the error. Seehttps://github.com/sweepline/eslint-plugin-unused-imports/blob/master/lib/rules/load-rule.js for the code that loads this rule.

It now crashes here becausenode is undefined:https://github.com/sweepline/eslint-plugin-unused-imports/blob/master/lib/rules/predicates.js#L28

I don't see a good reason whynode has to be removed. Would you mind puttingnode back into thecontext.report call?

@bradzacher
Copy link
Member

It does seem a very brittle that that plugin is depending on our private, internal implementation details like that.

For example if we were to change the rule to report on a different node then the rule would similarly break.

From the looks of it that's a horridly inefficient plugin too.
It utiliseseslint-rule-composer.
That util works by:

  1. duplicating the rule by wrapping its create function in a new rule
  2. monkey-patches thecontext object that ESLint passes so that it can intercept the reports generated by the wrapped rule.

(1) is especially bad because it means you have multiple copies of the rule. i.e. if you use bothunused-imports/no-unused-imports andunused-imports/no-unused-vars then you're running theno-unused-vars rule TWICE.

This is a really unstable setup and I'm really not sure if we should be supporting usage of our private internals like that.


I'm not sure I understand the point of the plugin - what is the usecase for separating out the imports from the regular variables? What's the benefit from working this way?

@cpojer
Copy link

Yup, I get your argument. In this case you could argue it keeps API shape compatibility with the corresponding rule in eslint, if you need a reason.

The plugin comes with a fixer, which I run when hittingcmd+s in VS Code, and it removes all unused imports automatically. If you hoisted this feature into your version ofno-unused-vars, I can imagine droppingeslint-plugin-unused-imports.

Note that the ESLint plugin has almost 2m downloads per week, and I'm sure many are using it while also using typescript-eslint, so you'll likely hear from more people soon. I'm just the one who lives on the bleeding edge :D

cc@sweepline – would you be open to porting this rule intoeslint-plugin-unused-imports? If yes,@bradzacher would you be open to making a patch release that adds backnode until that happens?

JacobZyy, LeonsCd, and mcost45 reacted with thumbs up emoji

@timtucker-dte
Copy link

@bradzacher we're using the plugin for auto-removing unused imports on save / build as well

@JacobZyy

This comment has been minimized.

@LeonsCd
Copy link

LeonsCd commentedApr 30, 2024
edited
Loading

I ran into the same issue, and now it's just messed up the whole plugin. I don't think we should be doing these breaking updates.

@bradzacher
Copy link
Member

Let me be very clear:
We changed a private, explicitly not exposed to the public, internal implementation detail.

The other pluginmonkey patches eslint's API so it can hook into ourinternals.

There is no breaking change here.

If something builds on top of private implementation details and breaks when we change those details - that is not a breaking change.

That fact is not up for debate.


How to best remedy this is an open question that we shall discuss amongst the maintenance team and make a decision.

mcost45, JacobZyy, kirkwaiblinger, and JoshuaKGoldberg reacted with thumbs up emoji

@HitkoDev
Copy link

HitkoDev commentedApr 30, 2024
edited
Loading

To be clear: the plugin in question is used by almost 10% oftypescript-eslint userbase. The plugin itself adds ~100 lines of code to automatically remove unused variables and imports, which is something those users need.

Is there any good reason such functionality shouldn't be a part oftypescript-eslint?

@JacobZyy
Copy link

mabe typescript-eslint can set a new rule namedno-unused-imports and make it fixable. the fact is, I have three plugin have a rule named'no-unused-vars', and I also really need the auto-fixable ruleunused-imports
Besides, sometimesno-unused-imports is to noisy in editor, and that can refer to the solution of@antfu 's config, turn off the rule in editor and turn it on in the cli.
image

@auvredauvred mentioned this pull requestApr 30, 2024
26 tasks
@JoshuaKGoldberg
Copy link
Member

plugin in question is used by almost 10% oftypescript-eslint userbase

No, it's very unlikely that 1 in 10 of our users are usingeslint-plugin-unused-imports. npm download numbers are an inaccurate metric (reference: 2.3m for the plugin, 27m for us today). Another inaccurate measurement would be GitHub stars, 420 vs 14.6k today.

A more reliable metric would be something like Sourcegraph searches of open source repositories'package.json files today:

At least in open source land, it seems more likely that theno-unused-imports plugin is floating around 3% of our users.

bradzacher reacted with thumbs up emoji

@JoshuaKGoldberg
Copy link
Member

Is there any good reason such functionality shouldn't be a part oftypescript-eslint?

Two reasons. The first is that@typescript-eslint/no-unused-vars acts as an "extension rule" on top of the baseeslint/no-unused-vars rule. We don't add any major new functionality on top of base rules here. If you want that added, it'd be an issue for ESLint core.

The reason why ESLint core isn't enthusiastically adding in the automatic removal of values is that it's actually a tricky thing to get right. Seemingly unused imports and variables can actually have side effects that change your code's behavior - which is very dangerous to have in an automatic rule fixer!

Example of an import with a side effect:

// a.jsletcount=0;console.log("Gotcha!");exportconstgetCount=()=>count;
// b.js// Unused. Should we auto fix to...//  import {} from "./a.js" ?//  import "./a.js" ?//  nothing at all?import{getCount}from"./a.js";console.log("Hi!");

Example of a variable with a side effect:

letcount=0;exportfunctiongetNextCount(){return(count+=1);}// Unused. Should we auto-fix to...//  getNextCount()//  nothing at all?letunusedIsh=getNextCount();

Example of a variable without:

functionhasNoSideEffect(){for(leti=0;i<9001**7;i+=1){}}// Unused. Should we auto-fix to...//  hasNoSideEffect()//  nothing at all?letalsoUnusedIsh=hasNoSideEffect()

By using a plugin likeeslint-plugin-unused-imports, you explicitly are taking on the risk of changing code behavior due to side effects like that. Which, hey, might be a great sign about how you've structured your code 😄 nice job avoiding side effects! But lint rules can't make that assumption for the general case.

One thing lint rulescan do is addsuggestions: which are likefixes but won't be applied automatically.Rule Change: Add support for suggestions for unused var tracks adding that on the ESLint side. That issue was accepted, assigned, and has an open pull request now! 🙌

For more info on the difference between afix and asuggestion, see:

bradzacher reacted with thumbs up emoji

@JoshuaKGoldberg
Copy link
Member

JoshuaKGoldberg commentedApr 30, 2024
edited
Loading

Given that:

...the "right" solution would be foreslint-plugin-unused-imports to work with what it's given: either theloc ornode depending on the version of@typescript-eslint/eslint-plugin. That's being tracked bysweepline/eslint-plugin-unused-imports#77, and has a PR open already insweepline/eslint-plugin-unused-imports#78.

Edit: that PR was merged the same minute as I posted this comment. Nice!
Edit 2:eslint-plugin-unused-imports@3.2.0 includes the fix. 👏

@JoshuaKGoldberg
Copy link
Member

Anyway, perour PR contributing guide, a previously-merged PR isn't the right place to discuss changes. We'd generally ask that bug reports and feature requests be reported as a standalone new issue so they're more discoverable. We get that this was a blocker for everyone usingeslint-plugin-unused-imports so it's reasonable that the discussion ended up happening here. Thanks for the reports, all! ❤️

Locking this issue as this specific typescript-eslint PR doesn't need any more discussion. If more issues on the topic get filed I'll make sure they show up here. Cheers!

@typescript-eslinttypescript-eslint locked asresolvedand limited conversation to collaboratorsApr 30, 2024
@bradzacher
Copy link
Member

The issue with an autofixer is that a lot of people run them on save.

So imagine this:

  1. you addimport foo from "foo" to your file
  2. you save the file
  3. you attempt to use the variablefoo
  4. you get an error because the import was deleted in (2)

There's many variations of this situation - the development loop is an inherently messy thing and there's no way for a static analysis tool to delineate between "unused and it should be deleted" and "unused but it should not be deleted".

There's also the issue of side-effects that Josh mentioned. If you autofix delete an import or a variable - you can change runtime behaviour because side-effects are lost.

There actually used to be a fixer forno-unused-vars a long, long time ago but it was removed because people found it both annoying and dangerous.

There's always scope to introduce an optional fixer for people to opt-in to the danger / annoyance. But as Josh mentioned the rule is intended to be a TS-compatible replacement for the base rule. Whilst itis a complete rewrite - the options, features and reports of the rule are the same.
We don't like to break too far from the base rules for our extension rules because it places a heavy maintenance burden on us. The more forking we do; the harder it is to merge upstream changes.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@JoshuaKGoldbergJoshuaKGoldbergJoshuaKGoldberg left review comments

@yeonjuanyeonjuanyeonjuan left review comments

@kirkwaiblingerkirkwaiblingerkirkwaiblinger approved these changes

@armano2armano2armano2 left review comments

@bradzacherbradzacherbradzacher left review comments

Assignees
No one assigned
Labels
1 approval>=1 team member has approved this PR; we're now leaving it open for more reviews before we mergebugSomething isn't working
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

11 participants
@developer-bandi@yeonjuan@cpojer@bradzacher@timtucker-dte@JacobZyy@LeonsCd@HitkoDev@JoshuaKGoldberg@armano2@kirkwaiblinger

[8]ページ先頭

©2009-2025 Movatter.jp