diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 43dafe03456ab..be18d5b21e409 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31559,6 +31559,18 @@ namespace ts { } } + function isWellKnownSymbol(node: Node) { + const symbol = getSymbolAtLocation(node); + if (!symbol) { + return false; + } + const symbolConstructorSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false); + if (!symbolConstructorSymbol) { + return false; + } + return !!getPropertiesOfObjectType((getTypeOfSymbol(symbolConstructorSymbol) as ObjectType)).includes(symbol); + } + function isSymbolOrSymbolForCall(node: Node) { if (!isCallExpression(node)) return false; let left = node.expression; @@ -31569,13 +31581,17 @@ namespace ts { return false; } + return isReferenceToGlobalESSymbolConstructorSymbol(left); + } + + function isReferenceToGlobalESSymbolConstructorSymbol(node: Identifier) { // make sure `Symbol` is the global symbol const globalESSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false); if (!globalESSymbol) { return false; } - return globalESSymbol === resolveName(left, "Symbol" as __String, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + return globalESSymbol === resolveName(node, "Symbol" as __String, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); } function checkImportCallExpression(node: ImportCall): Type { @@ -36858,7 +36874,8 @@ namespace ts { const symbol = getSymbolOfNode(member); if (!symbol.isReferenced && (hasEffectiveModifier(member, ModifierFlags.Private) || isNamedDeclaration(member) && isPrivateIdentifier(member.name)) - && !(member.flags & NodeFlags.Ambient)) { + && !(member.flags & NodeFlags.Ambient) + && !(isNamedDeclaration(member) && isComputedPropertyName(member.name) && isWellKnownSymbol(member.name.expression))) { addDiagnostic(member, UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); } break; diff --git a/tests/baselines/reference/unusedWellKnownSymbolsInClass.errors.txt b/tests/baselines/reference/unusedWellKnownSymbolsInClass.errors.txt new file mode 100644 index 0000000000000..997eab9bef0a8 --- /dev/null +++ b/tests/baselines/reference/unusedWellKnownSymbolsInClass.errors.txt @@ -0,0 +1,148 @@ +tests/cases/compiler/unusedWellKnownSymbolsInClass.ts(128,14): error TS6133: '[Symbol.iterator]' is declared but its value is never read. +tests/cases/compiler/unusedWellKnownSymbolsInClass.ts(136,12): error TS6133: '[iteratorSymbol]' is declared but its value is never read. + + +==== tests/cases/compiler/unusedWellKnownSymbolsInClass.ts (2 errors) ==== + export class Polling { + private async *[Symbol.asyncIterator]() {} + private *[Symbol.iterator]() {} + + async loop() { + for await (const updates of this) { + void updates + } + } + syncLoop() { + for (const updates of this) { + void updates + } + } + } + + export class WellknownSymbolMethods { + private async *[Symbol.asyncIterator]() { + yield "hello"; + } + + private static [Symbol.hasInstance](instance: unknown) { + return Array.isArray(instance); + } + + private get [Symbol.isConcatSpreadable]() { + return false + } + + private *[Symbol.iterator]() { + yield "hello"; + } + + private get [Symbol.match]() { + return false; + } + + private *[Symbol.matchAll](str: string) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + + private [Symbol.replace](str: string) { + return `s/${str}/foo/g`; + } + + private [Symbol.search](str: string) { + return str.indexOf('foo'); + } + + private [Symbol.split](str: string) { + return 'foo' + } + + private static get [Symbol.species]() { return Array; } + + private [Symbol.toPrimitive](hint: any) { + if (hint === 'number') { + return 42; + } + return null; + } + + private get [Symbol.toStringTag]() { + return 'foo'; + } + + private get [Symbol.unscopables]() { + return {}; + } + } + + export class WellknownSymbolProperties { + private [Symbol.asyncIterator] = function*() { + yield "hello"; + } + + private static [Symbol.hasInstance] = (instance: unknown) => { + return Array.isArray(instance); + } + + private [Symbol.isConcatSpreadable] = false; + + private [Symbol.iterator] = function*() { + yield "hello"; + } + + private [Symbol.match] = false; + + private [Symbol.matchAll] = function*(str: string) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + + private [Symbol.replace] = (str: string) => { + return `s/${str}/foo/g`; + } + + private [Symbol.search] = (str: string) => { + return str.indexOf('foo'); + } + + private [Symbol.split] = (str: string) => { + return 'foo' + } + + private static [Symbol.species] = Array; + + private [Symbol.toPrimitive] = (hint: any) => { + if (hint === 'number') { + return 42; + } + return null; + } + + private [Symbol.toStringTag] = 'foo'; + + private [Symbol.unscopables] = {}; + } + + const MyIterator = Symbol(); + export function testLocalSymbols() { + const Symbol = { + iterator: MyIterator + }; + + return class Foo{ + private *[Symbol.iterator]() { + ~~~~~~~~~~~~~~~~~ +!!! error TS6133: '[Symbol.iterator]' is declared but its value is never read. + yield 1; + } + } + } + + const iteratorSymbol = Symbol.iterator; + export class C { + private *[iteratorSymbol]() { + ~~~~~~~~~~~~~~~~ +!!! error TS6133: '[iteratorSymbol]' is declared but its value is never read. + + } + } \ No newline at end of file diff --git a/tests/baselines/reference/unusedWellKnownSymbolsInClass.js b/tests/baselines/reference/unusedWellKnownSymbolsInClass.js new file mode 100644 index 0000000000000..78b6977cf8d9a --- /dev/null +++ b/tests/baselines/reference/unusedWellKnownSymbolsInClass.js @@ -0,0 +1,250 @@ +//// [unusedWellKnownSymbolsInClass.ts] +export class Polling { + private async *[Symbol.asyncIterator]() {} + private *[Symbol.iterator]() {} + + async loop() { + for await (const updates of this) { + void updates + } + } + syncLoop() { + for (const updates of this) { + void updates + } + } +} + +export class WellknownSymbolMethods { + private async *[Symbol.asyncIterator]() { + yield "hello"; + } + + private static [Symbol.hasInstance](instance: unknown) { + return Array.isArray(instance); + } + + private get [Symbol.isConcatSpreadable]() { + return false + } + + private *[Symbol.iterator]() { + yield "hello"; + } + + private get [Symbol.match]() { + return false; + } + + private *[Symbol.matchAll](str: string) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + + private [Symbol.replace](str: string) { + return `s/${str}/foo/g`; + } + + private [Symbol.search](str: string) { + return str.indexOf('foo'); + } + + private [Symbol.split](str: string) { + return 'foo' + } + + private static get [Symbol.species]() { return Array; } + + private [Symbol.toPrimitive](hint: any) { + if (hint === 'number') { + return 42; + } + return null; + } + + private get [Symbol.toStringTag]() { + return 'foo'; + } + + private get [Symbol.unscopables]() { + return {}; + } +} + +export class WellknownSymbolProperties { + private [Symbol.asyncIterator] = function*() { + yield "hello"; + } + + private static [Symbol.hasInstance] = (instance: unknown) => { + return Array.isArray(instance); + } + + private [Symbol.isConcatSpreadable] = false; + + private [Symbol.iterator] = function*() { + yield "hello"; + } + + private [Symbol.match] = false; + + private [Symbol.matchAll] = function*(str: string) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + + private [Symbol.replace] = (str: string) => { + return `s/${str}/foo/g`; + } + + private [Symbol.search] = (str: string) => { + return str.indexOf('foo'); + } + + private [Symbol.split] = (str: string) => { + return 'foo' + } + + private static [Symbol.species] = Array; + + private [Symbol.toPrimitive] = (hint: any) => { + if (hint === 'number') { + return 42; + } + return null; + } + + private [Symbol.toStringTag] = 'foo'; + + private [Symbol.unscopables] = {}; +} + +const MyIterator = Symbol(); +export function testLocalSymbols() { + const Symbol = { + iterator: MyIterator + }; + + return class Foo{ + private *[Symbol.iterator]() { + yield 1; + } + } +} + +const iteratorSymbol = Symbol.iterator; +export class C { + private *[iteratorSymbol]() { + + } +} + +//// [unusedWellKnownSymbolsInClass.js] +export class Polling { + async *[Symbol.asyncIterator]() { } + *[Symbol.iterator]() { } + async loop() { + for await (const updates of this) { + void updates; + } + } + syncLoop() { + for (const updates of this) { + void updates; + } + } +} +export class WellknownSymbolMethods { + async *[Symbol.asyncIterator]() { + yield "hello"; + } + static [Symbol.hasInstance](instance) { + return Array.isArray(instance); + } + get [Symbol.isConcatSpreadable]() { + return false; + } + *[Symbol.iterator]() { + yield "hello"; + } + get [Symbol.match]() { + return false; + } + *[Symbol.matchAll](str) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + [Symbol.replace](str) { + return `s/${str}/foo/g`; + } + [Symbol.search](str) { + return str.indexOf('foo'); + } + [Symbol.split](str) { + return 'foo'; + } + static get [Symbol.species]() { return Array; } + [Symbol.toPrimitive](hint) { + if (hint === 'number') { + return 42; + } + return null; + } + get [Symbol.toStringTag]() { + return 'foo'; + } + get [Symbol.unscopables]() { + return {}; + } +} +export class WellknownSymbolProperties { + [Symbol.asyncIterator] = function* () { + yield "hello"; + }; + static [Symbol.hasInstance] = (instance) => { + return Array.isArray(instance); + }; + [Symbol.isConcatSpreadable] = false; + [Symbol.iterator] = function* () { + yield "hello"; + }; + [Symbol.match] = false; + [Symbol.matchAll] = function* (str) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + }; + [Symbol.replace] = (str) => { + return `s/${str}/foo/g`; + }; + [Symbol.search] = (str) => { + return str.indexOf('foo'); + }; + [Symbol.split] = (str) => { + return 'foo'; + }; + static [Symbol.species] = Array; + [Symbol.toPrimitive] = (hint) => { + if (hint === 'number') { + return 42; + } + return null; + }; + [Symbol.toStringTag] = 'foo'; + [Symbol.unscopables] = {}; +} +const MyIterator = Symbol(); +export function testLocalSymbols() { + const Symbol = { + iterator: MyIterator + }; + return class Foo { + *[Symbol.iterator]() { + yield 1; + } + }; +} +const iteratorSymbol = Symbol.iterator; +export class C { + *[iteratorSymbol]() { + } +} diff --git a/tests/baselines/reference/unusedWellKnownSymbolsInClass.symbols b/tests/baselines/reference/unusedWellKnownSymbolsInClass.symbols new file mode 100644 index 0000000000000..ece0e23eaa83f --- /dev/null +++ b/tests/baselines/reference/unusedWellKnownSymbolsInClass.symbols @@ -0,0 +1,363 @@ +=== tests/cases/compiler/unusedWellKnownSymbolsInClass.ts === +export class Polling { +>Polling : Symbol(Polling, Decl(unusedWellKnownSymbolsInClass.ts, 0, 0)) + + private async *[Symbol.asyncIterator]() {} +>[Symbol.asyncIterator] : Symbol(Polling[Symbol.asyncIterator], Decl(unusedWellKnownSymbolsInClass.ts, 0, 22)) +>Symbol.asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) + + private *[Symbol.iterator]() {} +>[Symbol.iterator] : Symbol(Polling[Symbol.iterator], Decl(unusedWellKnownSymbolsInClass.ts, 1, 44)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + async loop() { +>loop : Symbol(Polling.loop, Decl(unusedWellKnownSymbolsInClass.ts, 2, 33)) + + for await (const updates of this) { +>updates : Symbol(updates, Decl(unusedWellKnownSymbolsInClass.ts, 5, 20)) +>this : Symbol(Polling, Decl(unusedWellKnownSymbolsInClass.ts, 0, 0)) + + void updates +>updates : Symbol(updates, Decl(unusedWellKnownSymbolsInClass.ts, 5, 20)) + } + } + syncLoop() { +>syncLoop : Symbol(Polling.syncLoop, Decl(unusedWellKnownSymbolsInClass.ts, 8, 3)) + + for (const updates of this) { +>updates : Symbol(updates, Decl(unusedWellKnownSymbolsInClass.ts, 10, 14)) +>this : Symbol(Polling, Decl(unusedWellKnownSymbolsInClass.ts, 0, 0)) + + void updates +>updates : Symbol(updates, Decl(unusedWellKnownSymbolsInClass.ts, 10, 14)) + } + } +} + +export class WellknownSymbolMethods { +>WellknownSymbolMethods : Symbol(WellknownSymbolMethods, Decl(unusedWellKnownSymbolsInClass.ts, 14, 1)) + + private async *[Symbol.asyncIterator]() { +>[Symbol.asyncIterator] : Symbol(WellknownSymbolMethods[Symbol.asyncIterator], Decl(unusedWellKnownSymbolsInClass.ts, 16, 37)) +>Symbol.asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) + + yield "hello"; + } + + private static [Symbol.hasInstance](instance: unknown) { +>[Symbol.hasInstance] : Symbol(WellknownSymbolMethods[Symbol.hasInstance], Decl(unusedWellKnownSymbolsInClass.ts, 19, 3)) +>Symbol.hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>instance : Symbol(instance, Decl(unusedWellKnownSymbolsInClass.ts, 21, 38)) + + return Array.isArray(instance); +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 3 more) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>instance : Symbol(instance, Decl(unusedWellKnownSymbolsInClass.ts, 21, 38)) + } + + private get [Symbol.isConcatSpreadable]() { +>[Symbol.isConcatSpreadable] : Symbol(WellknownSymbolMethods[Symbol.isConcatSpreadable], Decl(unusedWellKnownSymbolsInClass.ts, 23, 3)) +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + return false + } + + private *[Symbol.iterator]() { +>[Symbol.iterator] : Symbol(WellknownSymbolMethods[Symbol.iterator], Decl(unusedWellKnownSymbolsInClass.ts, 27, 3)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + yield "hello"; + } + + private get [Symbol.match]() { +>[Symbol.match] : Symbol(WellknownSymbolMethods[Symbol.match], Decl(unusedWellKnownSymbolsInClass.ts, 31, 3)) +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + return false; + } + + private *[Symbol.matchAll](str: string) { +>[Symbol.matchAll] : Symbol(WellknownSymbolMethods[Symbol.matchAll], Decl(unusedWellKnownSymbolsInClass.ts, 35, 3)) +>Symbol.matchAll : Symbol(SymbolConstructor.matchAll, Decl(lib.es2020.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>matchAll : Symbol(SymbolConstructor.matchAll, Decl(lib.es2020.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 37, 29)) + + for (const n of str.matchAll(/[0-9]+/g)) +>n : Symbol(n, Decl(unusedWellKnownSymbolsInClass.ts, 38, 14)) +>str.matchAll : Symbol(String.matchAll, Decl(lib.es2020.string.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 37, 29)) +>matchAll : Symbol(String.matchAll, Decl(lib.es2020.string.d.ts, --, --)) + + yield n[0]; +>n : Symbol(n, Decl(unusedWellKnownSymbolsInClass.ts, 38, 14)) + } + + private [Symbol.replace](str: string) { +>[Symbol.replace] : Symbol(WellknownSymbolMethods[Symbol.replace], Decl(unusedWellKnownSymbolsInClass.ts, 40, 3)) +>Symbol.replace : Symbol(SymbolConstructor.replace, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>replace : Symbol(SymbolConstructor.replace, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 42, 27)) + + return `s/${str}/foo/g`; +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 42, 27)) + } + + private [Symbol.search](str: string) { +>[Symbol.search] : Symbol(WellknownSymbolMethods[Symbol.search], Decl(unusedWellKnownSymbolsInClass.ts, 44, 3)) +>Symbol.search : Symbol(SymbolConstructor.search, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>search : Symbol(SymbolConstructor.search, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 46, 26)) + + return str.indexOf('foo'); +>str.indexOf : Symbol(String.indexOf, Decl(lib.es5.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 46, 26)) +>indexOf : Symbol(String.indexOf, Decl(lib.es5.d.ts, --, --)) + } + + private [Symbol.split](str: string) { +>[Symbol.split] : Symbol(WellknownSymbolMethods[Symbol.split], Decl(unusedWellKnownSymbolsInClass.ts, 48, 3)) +>Symbol.split : Symbol(SymbolConstructor.split, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>split : Symbol(SymbolConstructor.split, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 50, 25)) + + return 'foo' + } + + private static get [Symbol.species]() { return Array; } +>[Symbol.species] : Symbol(WellknownSymbolMethods[Symbol.species], Decl(unusedWellKnownSymbolsInClass.ts, 52, 3)) +>Symbol.species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 3 more) + + private [Symbol.toPrimitive](hint: any) { +>[Symbol.toPrimitive] : Symbol(WellknownSymbolMethods[Symbol.toPrimitive], Decl(unusedWellKnownSymbolsInClass.ts, 54, 57)) +>Symbol.toPrimitive : Symbol(SymbolConstructor.toPrimitive, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>toPrimitive : Symbol(SymbolConstructor.toPrimitive, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>hint : Symbol(hint, Decl(unusedWellKnownSymbolsInClass.ts, 56, 31)) + + if (hint === 'number') { +>hint : Symbol(hint, Decl(unusedWellKnownSymbolsInClass.ts, 56, 31)) + + return 42; + } + return null; + } + + private get [Symbol.toStringTag]() { +>[Symbol.toStringTag] : Symbol(WellknownSymbolMethods[Symbol.toStringTag], Decl(unusedWellKnownSymbolsInClass.ts, 61, 3)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + return 'foo'; + } + + private get [Symbol.unscopables]() { +>[Symbol.unscopables] : Symbol(WellknownSymbolMethods[Symbol.unscopables], Decl(unusedWellKnownSymbolsInClass.ts, 65, 3)) +>Symbol.unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + return {}; + } +} + +export class WellknownSymbolProperties { +>WellknownSymbolProperties : Symbol(WellknownSymbolProperties, Decl(unusedWellKnownSymbolsInClass.ts, 70, 1)) + + private [Symbol.asyncIterator] = function*() { +>[Symbol.asyncIterator] : Symbol(WellknownSymbolProperties[Symbol.asyncIterator], Decl(unusedWellKnownSymbolsInClass.ts, 72, 40)) +>Symbol.asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) + + yield "hello"; + } + + private static [Symbol.hasInstance] = (instance: unknown) => { +>[Symbol.hasInstance] : Symbol(WellknownSymbolProperties[Symbol.hasInstance], Decl(unusedWellKnownSymbolsInClass.ts, 75, 3)) +>Symbol.hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>instance : Symbol(instance, Decl(unusedWellKnownSymbolsInClass.ts, 77, 41)) + + return Array.isArray(instance); +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 3 more) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>instance : Symbol(instance, Decl(unusedWellKnownSymbolsInClass.ts, 77, 41)) + } + + private [Symbol.isConcatSpreadable] = false; +>[Symbol.isConcatSpreadable] : Symbol(WellknownSymbolProperties[Symbol.isConcatSpreadable], Decl(unusedWellKnownSymbolsInClass.ts, 79, 3)) +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + private [Symbol.iterator] = function*() { +>[Symbol.iterator] : Symbol(WellknownSymbolProperties[Symbol.iterator], Decl(unusedWellKnownSymbolsInClass.ts, 81, 46)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + yield "hello"; + } + + private [Symbol.match] = false; +>[Symbol.match] : Symbol(WellknownSymbolProperties[Symbol.match], Decl(unusedWellKnownSymbolsInClass.ts, 85, 3)) +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + private [Symbol.matchAll] = function*(str: string) { +>[Symbol.matchAll] : Symbol(WellknownSymbolProperties[Symbol.matchAll], Decl(unusedWellKnownSymbolsInClass.ts, 87, 33)) +>Symbol.matchAll : Symbol(SymbolConstructor.matchAll, Decl(lib.es2020.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>matchAll : Symbol(SymbolConstructor.matchAll, Decl(lib.es2020.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 89, 40)) + + for (const n of str.matchAll(/[0-9]+/g)) +>n : Symbol(n, Decl(unusedWellKnownSymbolsInClass.ts, 90, 14)) +>str.matchAll : Symbol(String.matchAll, Decl(lib.es2020.string.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 89, 40)) +>matchAll : Symbol(String.matchAll, Decl(lib.es2020.string.d.ts, --, --)) + + yield n[0]; +>n : Symbol(n, Decl(unusedWellKnownSymbolsInClass.ts, 90, 14)) + } + + private [Symbol.replace] = (str: string) => { +>[Symbol.replace] : Symbol(WellknownSymbolProperties[Symbol.replace], Decl(unusedWellKnownSymbolsInClass.ts, 92, 3)) +>Symbol.replace : Symbol(SymbolConstructor.replace, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>replace : Symbol(SymbolConstructor.replace, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 94, 30)) + + return `s/${str}/foo/g`; +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 94, 30)) + } + + private [Symbol.search] = (str: string) => { +>[Symbol.search] : Symbol(WellknownSymbolProperties[Symbol.search], Decl(unusedWellKnownSymbolsInClass.ts, 96, 3)) +>Symbol.search : Symbol(SymbolConstructor.search, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>search : Symbol(SymbolConstructor.search, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 98, 29)) + + return str.indexOf('foo'); +>str.indexOf : Symbol(String.indexOf, Decl(lib.es5.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 98, 29)) +>indexOf : Symbol(String.indexOf, Decl(lib.es5.d.ts, --, --)) + } + + private [Symbol.split] = (str: string) => { +>[Symbol.split] : Symbol(WellknownSymbolProperties[Symbol.split], Decl(unusedWellKnownSymbolsInClass.ts, 100, 3)) +>Symbol.split : Symbol(SymbolConstructor.split, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>split : Symbol(SymbolConstructor.split, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>str : Symbol(str, Decl(unusedWellKnownSymbolsInClass.ts, 102, 28)) + + return 'foo' + } + + private static [Symbol.species] = Array; +>[Symbol.species] : Symbol(WellknownSymbolProperties[Symbol.species], Decl(unusedWellKnownSymbolsInClass.ts, 104, 3)) +>Symbol.species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 3 more) + + private [Symbol.toPrimitive] = (hint: any) => { +>[Symbol.toPrimitive] : Symbol(WellknownSymbolProperties[Symbol.toPrimitive], Decl(unusedWellKnownSymbolsInClass.ts, 106, 42)) +>Symbol.toPrimitive : Symbol(SymbolConstructor.toPrimitive, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>toPrimitive : Symbol(SymbolConstructor.toPrimitive, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>hint : Symbol(hint, Decl(unusedWellKnownSymbolsInClass.ts, 108, 34)) + + if (hint === 'number') { +>hint : Symbol(hint, Decl(unusedWellKnownSymbolsInClass.ts, 108, 34)) + + return 42; + } + return null; + } + + private [Symbol.toStringTag] = 'foo'; +>[Symbol.toStringTag] : Symbol(WellknownSymbolProperties[Symbol.toStringTag], Decl(unusedWellKnownSymbolsInClass.ts, 113, 3)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + private [Symbol.unscopables] = {}; +>[Symbol.unscopables] : Symbol(WellknownSymbolProperties[Symbol.unscopables], Decl(unusedWellKnownSymbolsInClass.ts, 115, 39)) +>Symbol.unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>unscopables : Symbol(SymbolConstructor.unscopables, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +} + +const MyIterator = Symbol(); +>MyIterator : Symbol(MyIterator, Decl(unusedWellKnownSymbolsInClass.ts, 120, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) + +export function testLocalSymbols() { +>testLocalSymbols : Symbol(testLocalSymbols, Decl(unusedWellKnownSymbolsInClass.ts, 120, 28)) + + const Symbol = { +>Symbol : Symbol(Symbol, Decl(unusedWellKnownSymbolsInClass.ts, 122, 7)) + + iterator: MyIterator +>iterator : Symbol(iterator, Decl(unusedWellKnownSymbolsInClass.ts, 122, 18)) +>MyIterator : Symbol(MyIterator, Decl(unusedWellKnownSymbolsInClass.ts, 120, 5)) + + }; + + return class Foo{ +>Foo : Symbol(Foo, Decl(unusedWellKnownSymbolsInClass.ts, 126, 8)) + + private *[Symbol.iterator]() { +>[Symbol.iterator] : Symbol(Foo[Symbol.iterator], Decl(unusedWellKnownSymbolsInClass.ts, 126, 19)) +>Symbol.iterator : Symbol(iterator, Decl(unusedWellKnownSymbolsInClass.ts, 122, 18)) +>Symbol : Symbol(Symbol, Decl(unusedWellKnownSymbolsInClass.ts, 122, 7)) +>iterator : Symbol(iterator, Decl(unusedWellKnownSymbolsInClass.ts, 122, 18)) + + yield 1; + } + } +} + +const iteratorSymbol = Symbol.iterator; +>iteratorSymbol : Symbol(iteratorSymbol, Decl(unusedWellKnownSymbolsInClass.ts, 133, 5)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + +export class C { +>C : Symbol(C, Decl(unusedWellKnownSymbolsInClass.ts, 133, 39)) + + private *[iteratorSymbol]() { +>[iteratorSymbol] : Symbol(C[iteratorSymbol], Decl(unusedWellKnownSymbolsInClass.ts, 134, 16)) +>iteratorSymbol : Symbol(iteratorSymbol, Decl(unusedWellKnownSymbolsInClass.ts, 133, 5)) + + } +} diff --git a/tests/baselines/reference/unusedWellKnownSymbolsInClass.types b/tests/baselines/reference/unusedWellKnownSymbolsInClass.types new file mode 100644 index 0000000000000..aef98be4068d4 --- /dev/null +++ b/tests/baselines/reference/unusedWellKnownSymbolsInClass.types @@ -0,0 +1,422 @@ +=== tests/cases/compiler/unusedWellKnownSymbolsInClass.ts === +export class Polling { +>Polling : Polling + + private async *[Symbol.asyncIterator]() {} +>[Symbol.asyncIterator] : () => AsyncGenerator +>Symbol.asyncIterator : unique symbol +>Symbol : SymbolConstructor +>asyncIterator : unique symbol + + private *[Symbol.iterator]() {} +>[Symbol.iterator] : () => Generator +>Symbol.iterator : unique symbol +>Symbol : SymbolConstructor +>iterator : unique symbol + + async loop() { +>loop : () => Promise + + for await (const updates of this) { +>updates : never +>this : this + + void updates +>void updates : undefined +>updates : never + } + } + syncLoop() { +>syncLoop : () => void + + for (const updates of this) { +>updates : never +>this : this + + void updates +>void updates : undefined +>updates : never + } + } +} + +export class WellknownSymbolMethods { +>WellknownSymbolMethods : WellknownSymbolMethods + + private async *[Symbol.asyncIterator]() { +>[Symbol.asyncIterator] : () => AsyncGenerator +>Symbol.asyncIterator : unique symbol +>Symbol : SymbolConstructor +>asyncIterator : unique symbol + + yield "hello"; +>yield "hello" : any +>"hello" : "hello" + } + + private static [Symbol.hasInstance](instance: unknown) { +>[Symbol.hasInstance] : (instance: unknown) => boolean +>Symbol.hasInstance : unique symbol +>Symbol : SymbolConstructor +>hasInstance : unique symbol +>instance : unknown + + return Array.isArray(instance); +>Array.isArray(instance) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>instance : unknown + } + + private get [Symbol.isConcatSpreadable]() { +>[Symbol.isConcatSpreadable] : boolean +>Symbol.isConcatSpreadable : unique symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : unique symbol + + return false +>false : false + } + + private *[Symbol.iterator]() { +>[Symbol.iterator] : () => Generator +>Symbol.iterator : unique symbol +>Symbol : SymbolConstructor +>iterator : unique symbol + + yield "hello"; +>yield "hello" : any +>"hello" : "hello" + } + + private get [Symbol.match]() { +>[Symbol.match] : boolean +>Symbol.match : unique symbol +>Symbol : SymbolConstructor +>match : unique symbol + + return false; +>false : false + } + + private *[Symbol.matchAll](str: string) { +>[Symbol.matchAll] : (str: string) => Generator +>Symbol.matchAll : unique symbol +>Symbol : SymbolConstructor +>matchAll : unique symbol +>str : string + + for (const n of str.matchAll(/[0-9]+/g)) +>n : RegExpMatchArray +>str.matchAll(/[0-9]+/g) : IterableIterator +>str.matchAll : (regexp: RegExp) => IterableIterator +>str : string +>matchAll : (regexp: RegExp) => IterableIterator +>/[0-9]+/g : RegExp + + yield n[0]; +>yield n[0] : any +>n[0] : string +>n : RegExpMatchArray +>0 : 0 + } + + private [Symbol.replace](str: string) { +>[Symbol.replace] : (str: string) => string +>Symbol.replace : unique symbol +>Symbol : SymbolConstructor +>replace : unique symbol +>str : string + + return `s/${str}/foo/g`; +>`s/${str}/foo/g` : string +>str : string + } + + private [Symbol.search](str: string) { +>[Symbol.search] : (str: string) => number +>Symbol.search : unique symbol +>Symbol : SymbolConstructor +>search : unique symbol +>str : string + + return str.indexOf('foo'); +>str.indexOf('foo') : number +>str.indexOf : (searchString: string, position?: number) => number +>str : string +>indexOf : (searchString: string, position?: number) => number +>'foo' : "foo" + } + + private [Symbol.split](str: string) { +>[Symbol.split] : (str: string) => string +>Symbol.split : unique symbol +>Symbol : SymbolConstructor +>split : unique symbol +>str : string + + return 'foo' +>'foo' : "foo" + } + + private static get [Symbol.species]() { return Array; } +>[Symbol.species] : ArrayConstructor +>Symbol.species : unique symbol +>Symbol : SymbolConstructor +>species : unique symbol +>Array : ArrayConstructor + + private [Symbol.toPrimitive](hint: any) { +>[Symbol.toPrimitive] : (hint: any) => number +>Symbol.toPrimitive : unique symbol +>Symbol : SymbolConstructor +>toPrimitive : unique symbol +>hint : any + + if (hint === 'number') { +>hint === 'number' : boolean +>hint : any +>'number' : "number" + + return 42; +>42 : 42 + } + return null; +>null : null + } + + private get [Symbol.toStringTag]() { +>[Symbol.toStringTag] : string +>Symbol.toStringTag : unique symbol +>Symbol : SymbolConstructor +>toStringTag : unique symbol + + return 'foo'; +>'foo' : "foo" + } + + private get [Symbol.unscopables]() { +>[Symbol.unscopables] : {} +>Symbol.unscopables : unique symbol +>Symbol : SymbolConstructor +>unscopables : unique symbol + + return {}; +>{} : {} + } +} + +export class WellknownSymbolProperties { +>WellknownSymbolProperties : WellknownSymbolProperties + + private [Symbol.asyncIterator] = function*() { +>[Symbol.asyncIterator] : () => Generator +>Symbol.asyncIterator : unique symbol +>Symbol : SymbolConstructor +>asyncIterator : unique symbol +>function*() { yield "hello"; } : () => Generator + + yield "hello"; +>yield "hello" : any +>"hello" : "hello" + } + + private static [Symbol.hasInstance] = (instance: unknown) => { +>[Symbol.hasInstance] : (instance: unknown) => boolean +>Symbol.hasInstance : unique symbol +>Symbol : SymbolConstructor +>hasInstance : unique symbol +>(instance: unknown) => { return Array.isArray(instance); } : (instance: unknown) => boolean +>instance : unknown + + return Array.isArray(instance); +>Array.isArray(instance) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>instance : unknown + } + + private [Symbol.isConcatSpreadable] = false; +>[Symbol.isConcatSpreadable] : boolean +>Symbol.isConcatSpreadable : unique symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : unique symbol +>false : false + + private [Symbol.iterator] = function*() { +>[Symbol.iterator] : () => Generator +>Symbol.iterator : unique symbol +>Symbol : SymbolConstructor +>iterator : unique symbol +>function*() { yield "hello"; } : () => Generator + + yield "hello"; +>yield "hello" : any +>"hello" : "hello" + } + + private [Symbol.match] = false; +>[Symbol.match] : boolean +>Symbol.match : unique symbol +>Symbol : SymbolConstructor +>match : unique symbol +>false : false + + private [Symbol.matchAll] = function*(str: string) { +>[Symbol.matchAll] : (str: string) => Generator +>Symbol.matchAll : unique symbol +>Symbol : SymbolConstructor +>matchAll : unique symbol +>function*(str: string) { for (const n of str.matchAll(/[0-9]+/g)) yield n[0]; } : (str: string) => Generator +>str : string + + for (const n of str.matchAll(/[0-9]+/g)) +>n : RegExpMatchArray +>str.matchAll(/[0-9]+/g) : IterableIterator +>str.matchAll : (regexp: RegExp) => IterableIterator +>str : string +>matchAll : (regexp: RegExp) => IterableIterator +>/[0-9]+/g : RegExp + + yield n[0]; +>yield n[0] : any +>n[0] : string +>n : RegExpMatchArray +>0 : 0 + } + + private [Symbol.replace] = (str: string) => { +>[Symbol.replace] : (str: string) => string +>Symbol.replace : unique symbol +>Symbol : SymbolConstructor +>replace : unique symbol +>(str: string) => { return `s/${str}/foo/g`; } : (str: string) => string +>str : string + + return `s/${str}/foo/g`; +>`s/${str}/foo/g` : string +>str : string + } + + private [Symbol.search] = (str: string) => { +>[Symbol.search] : (str: string) => number +>Symbol.search : unique symbol +>Symbol : SymbolConstructor +>search : unique symbol +>(str: string) => { return str.indexOf('foo'); } : (str: string) => number +>str : string + + return str.indexOf('foo'); +>str.indexOf('foo') : number +>str.indexOf : (searchString: string, position?: number) => number +>str : string +>indexOf : (searchString: string, position?: number) => number +>'foo' : "foo" + } + + private [Symbol.split] = (str: string) => { +>[Symbol.split] : (str: string) => string +>Symbol.split : unique symbol +>Symbol : SymbolConstructor +>split : unique symbol +>(str: string) => { return 'foo' } : (str: string) => string +>str : string + + return 'foo' +>'foo' : "foo" + } + + private static [Symbol.species] = Array; +>[Symbol.species] : ArrayConstructor +>Symbol.species : unique symbol +>Symbol : SymbolConstructor +>species : unique symbol +>Array : ArrayConstructor + + private [Symbol.toPrimitive] = (hint: any) => { +>[Symbol.toPrimitive] : (hint: any) => number +>Symbol.toPrimitive : unique symbol +>Symbol : SymbolConstructor +>toPrimitive : unique symbol +>(hint: any) => { if (hint === 'number') { return 42; } return null; } : (hint: any) => number +>hint : any + + if (hint === 'number') { +>hint === 'number' : boolean +>hint : any +>'number' : "number" + + return 42; +>42 : 42 + } + return null; +>null : null + } + + private [Symbol.toStringTag] = 'foo'; +>[Symbol.toStringTag] : string +>Symbol.toStringTag : unique symbol +>Symbol : SymbolConstructor +>toStringTag : unique symbol +>'foo' : "foo" + + private [Symbol.unscopables] = {}; +>[Symbol.unscopables] : {} +>Symbol.unscopables : unique symbol +>Symbol : SymbolConstructor +>unscopables : unique symbol +>{} : {} +} + +const MyIterator = Symbol(); +>MyIterator : unique symbol +>Symbol() : unique symbol +>Symbol : SymbolConstructor + +export function testLocalSymbols() { +>testLocalSymbols : () => typeof Foo + + const Symbol = { +>Symbol : { iterator: symbol; } +>{ iterator: MyIterator } : { iterator: symbol; } + + iterator: MyIterator +>iterator : symbol +>MyIterator : unique symbol + + }; + + return class Foo{ +>class Foo{ private *[Symbol.iterator]() { yield 1; } } : typeof Foo +>Foo : typeof Foo + + private *[Symbol.iterator]() { +>[Symbol.iterator] : () => Generator +>Symbol.iterator : symbol +>Symbol : { iterator: symbol; } +>iterator : symbol + + yield 1; +>yield 1 : any +>1 : 1 + } + } +} + +const iteratorSymbol = Symbol.iterator; +>iteratorSymbol : symbol +>Symbol.iterator : unique symbol +>Symbol : SymbolConstructor +>iterator : unique symbol + +export class C { +>C : C + + private *[iteratorSymbol]() { +>[iteratorSymbol] : () => Generator +>iteratorSymbol : symbol + + } +} diff --git a/tests/cases/compiler/unusedWellKnownSymbolsInClass.ts b/tests/cases/compiler/unusedWellKnownSymbolsInClass.ts new file mode 100644 index 0000000000000..5afc7aa9dd927 --- /dev/null +++ b/tests/cases/compiler/unusedWellKnownSymbolsInClass.ts @@ -0,0 +1,143 @@ +// @lib: esnext +// @noUnusedLocals:true +// @target: esnext + +export class Polling { + private async *[Symbol.asyncIterator]() {} + private *[Symbol.iterator]() {} + + async loop() { + for await (const updates of this) { + void updates + } + } + syncLoop() { + for (const updates of this) { + void updates + } + } +} + +export class WellknownSymbolMethods { + private async *[Symbol.asyncIterator]() { + yield "hello"; + } + + private static [Symbol.hasInstance](instance: unknown) { + return Array.isArray(instance); + } + + private get [Symbol.isConcatSpreadable]() { + return false + } + + private *[Symbol.iterator]() { + yield "hello"; + } + + private get [Symbol.match]() { + return false; + } + + private *[Symbol.matchAll](str: string) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + + private [Symbol.replace](str: string) { + return `s/${str}/foo/g`; + } + + private [Symbol.search](str: string) { + return str.indexOf('foo'); + } + + private [Symbol.split](str: string) { + return 'foo' + } + + private static get [Symbol.species]() { return Array; } + + private [Symbol.toPrimitive](hint: any) { + if (hint === 'number') { + return 42; + } + return null; + } + + private get [Symbol.toStringTag]() { + return 'foo'; + } + + private get [Symbol.unscopables]() { + return {}; + } +} + +export class WellknownSymbolProperties { + private [Symbol.asyncIterator] = function*() { + yield "hello"; + } + + private static [Symbol.hasInstance] = (instance: unknown) => { + return Array.isArray(instance); + } + + private [Symbol.isConcatSpreadable] = false; + + private [Symbol.iterator] = function*() { + yield "hello"; + } + + private [Symbol.match] = false; + + private [Symbol.matchAll] = function*(str: string) { + for (const n of str.matchAll(/[0-9]+/g)) + yield n[0]; + } + + private [Symbol.replace] = (str: string) => { + return `s/${str}/foo/g`; + } + + private [Symbol.search] = (str: string) => { + return str.indexOf('foo'); + } + + private [Symbol.split] = (str: string) => { + return 'foo' + } + + private static [Symbol.species] = Array; + + private [Symbol.toPrimitive] = (hint: any) => { + if (hint === 'number') { + return 42; + } + return null; + } + + private [Symbol.toStringTag] = 'foo'; + + private [Symbol.unscopables] = {}; +} + +const MyIterator = Symbol(); +export function testLocalSymbols() { + const Symbol = { + iterator: MyIterator + }; + + return class Foo{ + private *[Symbol.iterator]() { + yield 1; + } + } +} + +const iteratorSymbol = Symbol.iterator; +export class C { + private *[iteratorSymbol]() { + + } +} \ No newline at end of file