@@ -8310,8 +8310,21 @@ namespace ts {
8310
8310
return container === declarationContainer;
8311
8311
}
8312
8312
8313
+ function updateReferencesForInterfaceHeritiageClauseTargets(node: InterfaceDeclaration): void {
8314
+ const extendedTypeNode = getClassExtendsHeritageClauseElement(node);
8315
+ if (extendedTypeNode) {
8316
+ const t = getTypeFromTypeNode(extendedTypeNode);
8317
+ if (t !== unknownType && t.symbol && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) {
8318
+ t.symbol.hasReference = true;
8319
+ }
8320
+ }
8321
+ }
8322
+
8313
8323
function checkIdentifier(node: Identifier): Type {
8314
8324
const symbol = getResolvedSymbol(node);
8325
+ if (symbol && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) {
8326
+ symbol.hasReference = true;
8327
+ }
8315
8328
8316
8329
// As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects.
8317
8330
// Although in down-level emit of arrow function, we emit it using function expression which means that
@@ -10226,6 +10239,10 @@ namespace ts {
10226
10239
return unknownType;
10227
10240
}
10228
10241
10242
+ if ((compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) {
10243
+ prop.hasReference = true;
10244
+ }
10245
+
10229
10246
getNodeLinks(node).resolvedSymbol = prop;
10230
10247
10231
10248
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
@@ -12168,6 +12185,8 @@ namespace ts {
12168
12185
}
12169
12186
}
12170
12187
}
12188
+ checkUnusedIdentifiers(node);
12189
+ checkUnusedTypeParameters(node);
12171
12190
}
12172
12191
}
12173
12192
@@ -13238,6 +13257,9 @@ namespace ts {
13238
13257
checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node);
13239
13258
}
13240
13259
}
13260
+ if (!(<FunctionDeclaration>node).body) {
13261
+ checkUnusedTypeParameters(node);
13262
+ }
13241
13263
}
13242
13264
}
13243
13265
@@ -13390,6 +13412,8 @@ namespace ts {
13390
13412
checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node);
13391
13413
13392
13414
checkSourceElement(node.body);
13415
+ checkUnusedIdentifiers(node);
13416
+ checkUnusedTypeParameters(node);
13393
13417
13394
13418
const symbol = getSymbolOfNode(node);
13395
13419
const firstDeclaration = getDeclarationOfKind(symbol, node.kind);
@@ -13582,13 +13606,18 @@ namespace ts {
13582
13606
function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) {
13583
13607
checkGrammarTypeArguments(node, node.typeArguments);
13584
13608
const type = getTypeFromTypeReference(node);
13585
- if (type !== unknownType && node.typeArguments) {
13586
- // Do type argument local checks only if referenced type is successfully resolved
13587
- forEach(node.typeArguments, checkSourceElement);
13588
- if (produceDiagnostics) {
13589
- const symbol = getNodeLinks(node).resolvedSymbol;
13590
- const typeParameters = symbol.flags & SymbolFlags.TypeAlias ? getSymbolLinks(symbol).typeParameters : (<TypeReference>type).target.localTypeParameters;
13591
- checkTypeArgumentConstraints(typeParameters, node.typeArguments);
13609
+ if (type !== unknownType) {
13610
+ if (type.symbol && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) {
13611
+ type.symbol.hasReference = true;
13612
+ }
13613
+ if (node.typeArguments) {
13614
+ // Do type argument local checks only if referenced type is successfully resolved
13615
+ forEach(node.typeArguments, checkSourceElement);
13616
+ if (produceDiagnostics) {
13617
+ const symbol = getNodeLinks(node).resolvedSymbol;
13618
+ const typeParameters = symbol.flags & SymbolFlags.TypeAlias ? getSymbolLinks(symbol).typeParameters : (<TypeReference>type).target.localTypeParameters;
13619
+ checkTypeArgumentConstraints(typeParameters, node.typeArguments);
13620
+ }
13592
13621
}
13593
13622
}
13594
13623
}
@@ -14431,6 +14460,8 @@ namespace ts {
14431
14460
}
14432
14461
14433
14462
checkSourceElement(node.body);
14463
+ checkUnusedIdentifiers(node);
14464
+ checkUnusedTypeParameters(node);
14434
14465
if (!node.asteriskToken) {
14435
14466
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
14436
14467
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
@@ -14452,12 +14483,83 @@ namespace ts {
14452
14483
}
14453
14484
}
14454
14485
14486
+ function checkUnusedIdentifiers(node: FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction | ForInStatement | Block | CatchClause): void {
14487
+ if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) {
14488
+ for (const key in node.locals) {
14489
+ if (hasProperty(node.locals, key)) {
14490
+ const local = node.locals[key];
14491
+ if (!local.hasReference && local.valueDeclaration) {
14492
+ if (local.valueDeclaration.kind !== SyntaxKind.Parameter && compilerOptions.noUnusedLocals) {
14493
+ error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name);
14494
+ }
14495
+ else if (local.valueDeclaration.kind === SyntaxKind.Parameter && compilerOptions.noUnusedParameters) {
14496
+ if (local.valueDeclaration.flags === 0) {
14497
+ error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name);
14498
+ }
14499
+ }
14500
+ }
14501
+ }
14502
+ }
14503
+ }
14504
+ }
14505
+
14506
+ function checkUnusedClassLocals(node: ClassDeclaration): void {
14507
+ if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) {
14508
+ if (node.members) {
14509
+ for (const member of node.members) {
14510
+ if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) {
14511
+ if (isPrivateNode(member) && !member.symbol.hasReference) {
14512
+ error(member.name, Diagnostics._0_is_declared_but_never_used, member.symbol.name);
14513
+ }
14514
+ }
14515
+ else if (member.kind === SyntaxKind.Constructor) {
14516
+ for (const parameter of (<ConstructorDeclaration>member).parameters) {
14517
+ if (isPrivateNode(parameter) && !parameter.symbol.hasReference) {
14518
+ error(parameter.name, Diagnostics._0_is_declared_but_never_used, parameter.symbol.name);
14519
+ }
14520
+ }
14521
+ }
14522
+ }
14523
+ }
14524
+ }
14525
+ }
14526
+
14527
+ function checkUnusedTypeParameters(node: ClassDeclaration | FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction | ConstructorDeclaration | SignatureDeclaration | InterfaceDeclaration) {
14528
+ if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) {
14529
+ if (node.typeParameters) {
14530
+ for (const typeParameter of node.typeParameters) {
14531
+ if (!typeParameter.symbol.hasReference) {
14532
+ error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, typeParameter.symbol.name);
14533
+ }
14534
+ }
14535
+ }
14536
+ }
14537
+ }
14538
+
14539
+ function isPrivateNode(node: Node): boolean {
14540
+ return (node.flags & NodeFlags.Private) !== 0;
14541
+ }
14542
+
14543
+ function checkUnusedModuleLocals(node: ModuleDeclaration | SourceFile): void {
14544
+ if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) {
14545
+ for (const key in node.locals) {
14546
+ if (hasProperty(node.locals, key)) {
14547
+ const local = node.locals[key];
14548
+ if (!local.hasReference && !local.exportSymbol) {
14549
+ forEach(local.declarations, d => error(d.name, Diagnostics._0_is_declared_but_never_used, local.name));
14550
+ }
14551
+ }
14552
+ }
14553
+ }
14554
+ }
14555
+
14455
14556
function checkBlock(node: Block) {
14456
14557
// Grammar checking for SyntaxKind.Block
14457
14558
if (node.kind === SyntaxKind.Block) {
14458
14559
checkGrammarStatementInAmbientContext(node);
14459
14560
}
14460
14561
forEach(node.statements, checkSourceElement);
14562
+ checkUnusedIdentifiers(node);
14461
14563
}
14462
14564
14463
14565
function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
@@ -14962,6 +15064,7 @@ namespace ts {
14962
15064
}
14963
15065
14964
15066
checkSourceElement(node.statement);
15067
+ checkUnusedIdentifiers(node);
14965
15068
}
14966
15069
14967
15070
function checkForInStatement(node: ForInStatement) {
@@ -15009,6 +15112,7 @@ namespace ts {
15009
15112
}
15010
15113
15011
15114
checkSourceElement(node.statement);
15115
+ checkUnusedIdentifiers(node);
15012
15116
}
15013
15117
15014
15118
function checkForInOrForOfVariableDeclaration(iterationStatement: ForInStatement | ForOfStatement): void {
@@ -15448,6 +15552,7 @@ namespace ts {
15448
15552
}
15449
15553
15450
15554
checkBlock(catchClause.block);
15555
+ checkUnusedIdentifiers(catchClause);
15451
15556
}
15452
15557
15453
15558
if (node.finallyBlock) {
@@ -15609,6 +15714,8 @@ namespace ts {
15609
15714
}
15610
15715
checkClassLikeDeclaration(node);
15611
15716
forEach(node.members, checkSourceElement);
15717
+ checkUnusedClassLocals(node);
15718
+ checkUnusedTypeParameters(node);
15612
15719
}
15613
15720
15614
15721
function checkClassLikeDeclaration(node: ClassLikeDeclaration) {
@@ -15918,6 +16025,8 @@ namespace ts {
15918
16025
15919
16026
if (produceDiagnostics) {
15920
16027
checkTypeForDuplicateIndexSignatures(node);
16028
+ updateReferencesForInterfaceHeritiageClauseTargets(node);
16029
+ checkUnusedTypeParameters(node);
15921
16030
}
15922
16031
}
15923
16032
@@ -16314,6 +16423,7 @@ namespace ts {
16314
16423
16315
16424
if (node.body) {
16316
16425
checkSourceElement(node.body);
16426
+ checkUnusedModuleLocals(node);
16317
16427
}
16318
16428
}
16319
16429
@@ -16494,6 +16604,9 @@ namespace ts {
16494
16604
if (target.flags & SymbolFlags.Type) {
16495
16605
checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0);
16496
16606
}
16607
+ if ((compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) {
16608
+ target.hasReference = true;
16609
+ }
16497
16610
}
16498
16611
}
16499
16612
else {
@@ -16836,6 +16949,9 @@ namespace ts {
16836
16949
16837
16950
deferredNodes = [];
16838
16951
forEach(node.statements, checkSourceElement);
16952
+ if (isExternalModule(node)) {
16953
+ checkUnusedModuleLocals(node);
16954
+ }
16839
16955
checkDeferredNodes();
16840
16956
deferredNodes = undefined;
16841
16957
0 commit comments