From 37d4f6a69d25743b85541b8eb1221da4c670f2a2 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 8 Jan 2018 16:44:58 -0800 Subject: [PATCH] Mark references to dynamically-named properties as used (#21010) * Mark references to dynamically-named properties as used * Avoid showing the symbol ID * Use symbolToString instead of showSymbol --- src/compiler/checker.ts | 6 ++- ..._writeOnlyProperty_dynamicNames.errors.txt | 17 ++++++++ ...edLocals_writeOnlyProperty_dynamicNames.js | 25 ++++++++++++ ...als_writeOnlyProperty_dynamicNames.symbols | 31 +++++++++++++++ ...ocals_writeOnlyProperty_dynamicNames.types | 39 +++++++++++++++++++ ...edLocals_writeOnlyProperty_dynamicNames.ts | 13 +++++++ 6 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.errors.txt create mode 100644 tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.js create mode 100644 tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.symbols create mode 100644 tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.types create mode 100644 tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c66afe73d91..2b8244ca06c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8252,6 +8252,7 @@ namespace ts { const prop = getPropertyOfType(objectType, propName); if (prop) { if (accessExpression) { + markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword); if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) { error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, symbolToString(prop)); return unknownType; @@ -21356,8 +21357,9 @@ namespace ts { // Already would have reported an error on the getter. break; } - if (!member.symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) { - error(member.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(member.symbol)); + const symbol = getSymbolOfNode(member); + if (!symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) { + error(member.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol)); } break; case SyntaxKind.Constructor: diff --git a/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.errors.txt b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.errors.txt new file mode 100644 index 00000000000..9f95f4cfd2f --- /dev/null +++ b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.errors.txt @@ -0,0 +1,17 @@ +tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts(4,13): error TS6133: '[x]' is declared but its value is never read. + + +==== tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts (1 errors) ==== + const x = Symbol("x"); + const y = Symbol("y"); + class C { + private [x]: number; + ~~~ +!!! error TS6133: '[x]' is declared but its value is never read. + private [y]: number; + m() { + this[x] = 0; // write-only + this[y]; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.js b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.js new file mode 100644 index 00000000000..6c5bf109b57 --- /dev/null +++ b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.js @@ -0,0 +1,25 @@ +//// [noUnusedLocals_writeOnlyProperty_dynamicNames.ts] +const x = Symbol("x"); +const y = Symbol("y"); +class C { + private [x]: number; + private [y]: number; + m() { + this[x] = 0; // write-only + this[y]; + } +} + + +//// [noUnusedLocals_writeOnlyProperty_dynamicNames.js] +var x = Symbol("x"); +var y = Symbol("y"); +var C = /** @class */ (function () { + function C() { + } + C.prototype.m = function () { + this[x] = 0; // write-only + this[y]; + }; + return C; +}()); diff --git a/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.symbols b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.symbols new file mode 100644 index 00000000000..6a30e2a9fa9 --- /dev/null +++ b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts === +const x = Symbol("x"); +>x : Symbol(x, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 0, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) + +const y = Symbol("y"); +>y : Symbol(y, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 1, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) + +class C { +>C : Symbol(C, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 1, 22)) + + private [x]: number; +>x : Symbol(x, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 0, 5)) + + private [y]: number; +>y : Symbol(y, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 1, 5)) + + m() { +>m : Symbol(C.m, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 4, 24)) + + this[x] = 0; // write-only +>this : Symbol(C, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 1, 22)) +>x : Symbol(x, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 0, 5)) + + this[y]; +>this : Symbol(C, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 1, 22)) +>y : Symbol(y, Decl(noUnusedLocals_writeOnlyProperty_dynamicNames.ts, 1, 5)) + } +} + diff --git a/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.types b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.types new file mode 100644 index 00000000000..7b173395a99 --- /dev/null +++ b/tests/baselines/reference/noUnusedLocals_writeOnlyProperty_dynamicNames.types @@ -0,0 +1,39 @@ +=== tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts === +const x = Symbol("x"); +>x : unique symbol +>Symbol("x") : unique symbol +>Symbol : SymbolConstructor +>"x" : "x" + +const y = Symbol("y"); +>y : unique symbol +>Symbol("y") : unique symbol +>Symbol : SymbolConstructor +>"y" : "y" + +class C { +>C : C + + private [x]: number; +>x : unique symbol + + private [y]: number; +>y : unique symbol + + m() { +>m : () => void + + this[x] = 0; // write-only +>this[x] = 0 : 0 +>this[x] : number +>this : this +>x : unique symbol +>0 : 0 + + this[y]; +>this[y] : number +>this : this +>y : unique symbol + } +} + diff --git a/tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts b/tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts new file mode 100644 index 00000000000..065c6f89e7a --- /dev/null +++ b/tests/cases/compiler/noUnusedLocals_writeOnlyProperty_dynamicNames.ts @@ -0,0 +1,13 @@ +// @noUnusedLocals: true +// @lib: es6 + +const x = Symbol("x"); +const y = Symbol("y"); +class C { + private [x]: number; + private [y]: number; + m() { + this[x] = 0; // write-only + this[y]; + } +}