From 2796ebfe35ca08518ed196b522181bc0deff2373 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 9 Oct 2017 11:04:28 -0700 Subject: [PATCH] In resolveNameHelper, use a lastNonBlockLocation (#18918) --- src/compiler/checker.ts | 6 ++- .../noUnusedLocals_selfReference.errors.txt | 16 ++++-- .../reference/noUnusedLocals_selfReference.js | 14 ++++- .../noUnusedLocals_selfReference.symbols | 53 +++++++++++-------- .../noUnusedLocals_selfReference.types | 13 ++++- .../compiler/noUnusedLocals_selfReference.ts | 7 ++- 6 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8e18c432a6..58ac3bc52c0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -908,6 +908,7 @@ namespace ts { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location let result: Symbol; let lastLocation: Node; + let lastNonBlockLocation: Node; let propertyWithInvalidInitializer: Node; const errorLocation = location; let grandparent: Node; @@ -1126,6 +1127,9 @@ namespace ts { } break; } + if (location.kind !== SyntaxKind.Block) { + lastNonBlockLocation = location; + } lastLocation = location; location = location.parent; } @@ -1133,7 +1137,7 @@ namespace ts { // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`. // If `result === lastLocation.symbol`, that means that we are somewhere inside `lastLocation` looking up a name, and resolving to `lastLocation` itself. // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used. - if (isUse && result && nameNotFoundMessage && noUnusedIdentifiers && result !== lastLocation.symbol) { + if (isUse && result && nameNotFoundMessage && noUnusedIdentifiers && result !== lastNonBlockLocation.symbol) { result.isReferenced = true; } diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt index e4a0d478cb4..603bc54d448 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt +++ b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt @@ -1,14 +1,22 @@ tests/cases/compiler/noUnusedLocals_selfReference.ts(3,10): error TS6133: 'f' is declared but its value is never read. -tests/cases/compiler/noUnusedLocals_selfReference.ts(4,7): error TS6133: 'C' is declared but its value is never read. -tests/cases/compiler/noUnusedLocals_selfReference.ts(7,6): error TS6133: 'E' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(5,14): error TS6133: 'g' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(9,7): error TS6133: 'C' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(12,6): error TS6133: 'E' is declared but its value is never read. -==== tests/cases/compiler/noUnusedLocals_selfReference.ts (3 errors) ==== +==== tests/cases/compiler/noUnusedLocals_selfReference.ts (4 errors) ==== export {}; // Make this a module scope, so these are local variables. - function f() { f; } + function f() { ~ !!! error TS6133: 'f' is declared but its value is never read. + f; + function g() { + ~ +!!! error TS6133: 'g' is declared but its value is never read. + g; + } + } class C { ~ !!! error TS6133: 'C' is declared but its value is never read. diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.js b/tests/baselines/reference/noUnusedLocals_selfReference.js index 5f206fbc3dc..a8f3d6a8aed 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.js +++ b/tests/baselines/reference/noUnusedLocals_selfReference.js @@ -1,7 +1,12 @@ //// [noUnusedLocals_selfReference.ts] export {}; // Make this a module scope, so these are local variables. -function f() { f; } +function f() { + f; + function g() { + g; + } +} class C { m() { C; } } @@ -19,7 +24,12 @@ P; //// [noUnusedLocals_selfReference.js] "use strict"; exports.__esModule = true; -function f() { f; } +function f() { + f; + function g() { + g; + } +} var C = /** @class */ (function () { function C() { } diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.symbols b/tests/baselines/reference/noUnusedLocals_selfReference.symbols index dcd815b2619..015a78d87d3 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.symbols +++ b/tests/baselines/reference/noUnusedLocals_selfReference.symbols @@ -1,43 +1,52 @@ === tests/cases/compiler/noUnusedLocals_selfReference.ts === export {}; // Make this a module scope, so these are local variables. -function f() { f; } ->f : Symbol(f, Decl(noUnusedLocals_selfReference.ts, 0, 10)) +function f() { >f : Symbol(f, Decl(noUnusedLocals_selfReference.ts, 0, 10)) + f; +>f : Symbol(f, Decl(noUnusedLocals_selfReference.ts, 0, 10)) + + function g() { +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 3, 6)) + + g; +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 3, 6)) + } +} class C { ->C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 2, 19)) +>C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 7, 1)) m() { C; } ->m : Symbol(C.m, Decl(noUnusedLocals_selfReference.ts, 3, 9)) ->C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 2, 19)) +>m : Symbol(C.m, Decl(noUnusedLocals_selfReference.ts, 8, 9)) +>C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 7, 1)) } enum E { A = 0, B = E.A } ->E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 5, 1)) ->A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 6, 8)) ->B : Symbol(E.B, Decl(noUnusedLocals_selfReference.ts, 6, 15)) ->E.A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 6, 8)) ->E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 5, 1)) ->A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 6, 8)) +>E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 10, 1)) +>A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) +>B : Symbol(E.B, Decl(noUnusedLocals_selfReference.ts, 11, 15)) +>E.A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) +>E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 10, 1)) +>A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) // Does not detect mutual recursion. function g() { D; } ->g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 6, 25)) ->D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 9, 19)) +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 11, 25)) +>D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 14, 19)) class D { m() { g; } } ->D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 9, 19)) ->m : Symbol(D.m, Decl(noUnusedLocals_selfReference.ts, 10, 9)) ->g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 6, 25)) +>D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 14, 19)) +>m : Symbol(D.m, Decl(noUnusedLocals_selfReference.ts, 15, 9)) +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 11, 25)) // Does not work on private methods. class P { private m() { this.m; } } ->P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 10, 22)) ->m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) ->this.m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) ->this : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 10, 22)) ->m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) +>P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) +>m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) +>this.m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) +>this : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) +>m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) P; ->P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 10, 22)) +>P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.types b/tests/baselines/reference/noUnusedLocals_selfReference.types index 7d2741c5681..7e75062db34 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.types +++ b/tests/baselines/reference/noUnusedLocals_selfReference.types @@ -1,10 +1,19 @@ === tests/cases/compiler/noUnusedLocals_selfReference.ts === export {}; // Make this a module scope, so these are local variables. -function f() { f; } ->f : () => void +function f() { >f : () => void + f; +>f : () => void + + function g() { +>g : () => void + + g; +>g : () => void + } +} class C { >C : C diff --git a/tests/cases/compiler/noUnusedLocals_selfReference.ts b/tests/cases/compiler/noUnusedLocals_selfReference.ts index 8eb528743c0..fc6b02b6006 100644 --- a/tests/cases/compiler/noUnusedLocals_selfReference.ts +++ b/tests/cases/compiler/noUnusedLocals_selfReference.ts @@ -2,7 +2,12 @@ export {}; // Make this a module scope, so these are local variables. -function f() { f; } +function f() { + f; + function g() { + g; + } +} class C { m() { C; } }