Skip to content

Commit c3f199a

Browse files
authored
fix(eslint-plugin): [no-unused-vars] highlight last write reference (typescript-eslint#5267)
1 parent 4138b0d commit c3f199a

File tree

3 files changed

+87
-24
lines changed

3 files changed

+87
-24
lines changed

packages/eslint-plugin/src/rules/no-unused-vars.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,15 @@ export default util.createRule<Options, MessageIds>({
422422
for (const unusedVar of unusedVars) {
423423
// Report the first declaration.
424424
if (unusedVar.defs.length > 0) {
425+
const writeReferences = unusedVar.references.filter(
426+
ref =>
427+
ref.isWrite() &&
428+
ref.from.variableScope === unusedVar.scope.variableScope,
429+
);
430+
425431
context.report({
426-
node: unusedVar.references.length
427-
? unusedVar.references[unusedVar.references.length - 1]
428-
.identifier
432+
node: writeReferences.length
433+
? writeReferences[writeReferences.length - 1].identifier
429434
: unusedVar.identifiers[0],
430435
messageId: 'unusedVar',
431436
data: unusedVar.references.some(ref => ref.isWrite())

packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars-eslint.test.ts

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,8 +1753,8 @@ foo.forEach(item => {
17531753
},
17541754
{
17551755
...assignedError('b'),
1756-
line: 4,
1757-
column: 7,
1756+
line: 2,
1757+
column: 9,
17581758
},
17591759
],
17601760
},
@@ -2601,7 +2601,7 @@ myArray = myArray.filter(x => x == 1);
26012601
{
26022602
...assignedError('myArray'),
26032603
line: 3,
2604-
column: 11,
2604+
column: 1,
26052605
},
26062606
],
26072607
},
@@ -2628,8 +2628,8 @@ var a = function () {
26282628
errors: [
26292629
{
26302630
...assignedError('a'),
2631-
line: 3,
2632-
column: 3,
2631+
line: 2,
2632+
column: 5,
26332633
},
26342634
],
26352635
},
@@ -2644,7 +2644,7 @@ var a = function () {
26442644
errors: [
26452645
{
26462646
...assignedError('a'),
2647-
line: 4,
2647+
line: 2,
26482648
column: 5,
26492649
},
26502650
],
@@ -2659,8 +2659,8 @@ const a = () => {
26592659
errors: [
26602660
{
26612661
...assignedError('a'),
2662-
line: 3,
2663-
column: 3,
2662+
line: 2,
2663+
column: 7,
26642664
},
26652665
],
26662666
},
@@ -2674,11 +2674,18 @@ const a = () => () => {
26742674
errors: [
26752675
{
26762676
...assignedError('a'),
2677-
line: 3,
2678-
column: 3,
2677+
line: 2,
2678+
column: 7,
26792679
},
26802680
],
26812681
},
2682+
2683+
// https://github.com/eslint/eslint/issues/14324
2684+
{
2685+
code: 'let x = [];\nx = x.concat(x);',
2686+
parserOptions: { ecmaVersion: 2015 },
2687+
errors: [{ ...assignedError('x'), line: 2, column: 1 }],
2688+
},
26822689
{
26832690
code: `
26842691
let a = 'a';
@@ -2692,20 +2699,42 @@ function foo() {
26922699
`,
26932700
parserOptions: { ecmaVersion: 2020 },
26942701
errors: [
2702+
{
2703+
...assignedError('a'),
2704+
line: 3,
2705+
column: 1,
2706+
},
26952707
{
26962708
...definedError('foo'),
26972709
line: 4,
26982710
column: 10,
26992711
},
2700-
{
2701-
...assignedError('a'),
2702-
line: 7,
2703-
column: 5,
2704-
},
27052712
],
27062713
},
27072714
{
27082715
code: `
2716+
let foo;
2717+
init();
2718+
foo = foo + 2;
2719+
function init() {
2720+
foo = 1;
2721+
}
2722+
`,
2723+
parserOptions: { ecmaVersion: 2020 },
2724+
errors: [{ ...assignedError('foo'), line: 4, column: 1 }],
2725+
},
2726+
{
2727+
code: `
2728+
function foo(n) {
2729+
if (n < 2) return 1;
2730+
return n * foo(n - 1);
2731+
}
2732+
`,
2733+
parserOptions: { ecmaVersion: 2020 },
2734+
errors: [{ ...definedError('foo'), line: 2, column: 10 }],
2735+
},
2736+
{
2737+
code: `
27092738
let c = 'c';
27102739
c = 10;
27112740
function foo1() {

packages/eslint-plugin/tests/rules/no-unused-vars/no-unused-vars.test.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,8 +1458,8 @@ namespace Foo {
14581458
action: 'defined',
14591459
additional: '',
14601460
},
1461-
line: 4,
1462-
column: 15,
1461+
line: 2,
1462+
column: 11,
14631463
},
14641464
],
14651465
},
@@ -1490,8 +1490,8 @@ namespace Foo {
14901490
action: 'defined',
14911491
additional: '',
14921492
},
1493-
line: 5,
1494-
column: 17,
1493+
line: 3,
1494+
column: 13,
14951495
},
14961496
],
14971497
},
@@ -1506,7 +1506,8 @@ interface Foo {
15061506
errors: [
15071507
{
15081508
messageId: 'unusedVar',
1509-
line: 4,
1509+
line: 2,
1510+
column: 11,
15101511
data: {
15111512
varName: 'Foo',
15121513
action: 'defined',
@@ -1523,6 +1524,7 @@ type Foo = Array<Foo>;
15231524
{
15241525
messageId: 'unusedVar',
15251526
line: 2,
1527+
column: 6,
15261528
data: {
15271529
varName: 'Foo',
15281530
action: 'defined',
@@ -1550,6 +1552,7 @@ export const ComponentFoo = () => {
15501552
{
15511553
messageId: 'unusedVar',
15521554
line: 3,
1555+
column: 10,
15531556
data: {
15541557
varName: 'Fragment',
15551558
action: 'defined',
@@ -1577,6 +1580,7 @@ export const ComponentFoo = () => {
15771580
{
15781581
messageId: 'unusedVar',
15791582
line: 2,
1583+
column: 8,
15801584
data: {
15811585
varName: 'React',
15821586
action: 'defined',
@@ -1604,6 +1608,7 @@ export const ComponentFoo = () => {
16041608
{
16051609
messageId: 'unusedVar',
16061610
line: 2,
1611+
column: 8,
16071612
data: {
16081613
varName: 'React',
16091614
action: 'defined',
@@ -1624,6 +1629,7 @@ declare module 'foo' {
16241629
{
16251630
messageId: 'unusedVar',
16261631
line: 3,
1632+
column: 8,
16271633
data: {
16281634
varName: 'Test',
16291635
action: 'defined',
@@ -1649,6 +1655,7 @@ export namespace Foo {
16491655
{
16501656
messageId: 'unusedVar',
16511657
line: 4,
1658+
column: 13,
16521659
data: {
16531660
varName: 'Bar',
16541661
action: 'defined',
@@ -1658,6 +1665,7 @@ export namespace Foo {
16581665
{
16591666
messageId: 'unusedVar',
16601667
line: 5,
1668+
column: 15,
16611669
data: {
16621670
varName: 'Baz',
16631671
action: 'defined',
@@ -1667,6 +1675,7 @@ export namespace Foo {
16671675
{
16681676
messageId: 'unusedVar',
16691677
line: 6,
1678+
column: 17,
16701679
data: {
16711680
varName: 'Bam',
16721681
action: 'defined',
@@ -1676,6 +1685,7 @@ export namespace Foo {
16761685
{
16771686
messageId: 'unusedVar',
16781687
line: 7,
1688+
column: 15,
16791689
data: {
16801690
varName: 'x',
16811691
action: 'assigned a value',
@@ -1696,7 +1706,8 @@ interface Foo {
16961706
errors: [
16971707
{
16981708
messageId: 'unusedVar',
1699-
line: 6,
1709+
line: 2,
1710+
column: 11,
17001711
data: {
17011712
varName: 'Foo',
17021713
action: 'defined',
@@ -1705,5 +1716,23 @@ interface Foo {
17051716
},
17061717
],
17071718
},
1719+
{
1720+
code: `
1721+
let x = null;
1722+
x = foo(x);
1723+
`,
1724+
errors: [
1725+
{
1726+
messageId: 'unusedVar',
1727+
line: 3,
1728+
column: 1,
1729+
data: {
1730+
varName: 'x',
1731+
action: 'assigned a value',
1732+
additional: '',
1733+
},
1734+
},
1735+
],
1736+
},
17081737
],
17091738
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy