@@ -29602,7 +29602,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29602
29602
node.kind === SyntaxKind.PropertyDeclaration)!;
29603
29603
}
29604
29604
29605
- // Check if a parameter or catch variable is assigned anywhere
29605
+ // Check if a parameter, catch variable, or mutable local variable is assigned anywhere definitely
29606
+ function isSymbolAssignedDefinitely(symbol: Symbol) {
29607
+ if (symbol.lastAssignmentPos !== undefined) {
29608
+ return symbol.lastAssignmentPos < 0;
29609
+ }
29610
+ return isSymbolAssigned(symbol) && symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0;
29611
+ }
29612
+
29613
+ // Check if a parameter, catch variable, or mutable local variable is assigned anywhere
29606
29614
function isSymbolAssigned(symbol: Symbol) {
29607
29615
return !isPastLastAssignment(symbol, /*location*/ undefined);
29608
29616
}
@@ -29621,7 +29629,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29621
29629
markNodeAssignments(parent);
29622
29630
}
29623
29631
}
29624
- return !symbol.lastAssignmentPos || location && symbol.lastAssignmentPos < location.pos;
29632
+ return !symbol.lastAssignmentPos || location && Math.abs( symbol.lastAssignmentPos) < location.pos;
29625
29633
}
29626
29634
29627
29635
// Check if a parameter or catch variable (or their bindings elements) is assigned anywhere
@@ -29655,12 +29663,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29655
29663
function markNodeAssignments(node: Node) {
29656
29664
switch (node.kind) {
29657
29665
case SyntaxKind.Identifier:
29658
- if (isAssignmentTarget(node)) {
29666
+ const assigmentTarget = getAssignmentTargetKind(node);
29667
+ if (assigmentTarget !== AssignmentKind.None) {
29659
29668
const symbol = getResolvedSymbol(node as Identifier);
29660
- if (isParameterOrMutableLocalVariable(symbol) && symbol.lastAssignmentPos !== Number.MAX_VALUE) {
29661
- const referencingFunction = findAncestor(node, isFunctionOrSourceFile);
29662
- const declaringFunction = findAncestor(symbol.valueDeclaration, isFunctionOrSourceFile);
29663
- symbol.lastAssignmentPos = referencingFunction === declaringFunction ? extendAssignmentPosition(node, symbol.valueDeclaration!) : Number.MAX_VALUE;
29669
+ const hasDefiniteAssignment = assigmentTarget === AssignmentKind.Definite || (symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0);
29670
+ if (isParameterOrMutableLocalVariable(symbol)) {
29671
+ if (symbol.lastAssignmentPos === undefined || Math.abs(symbol.lastAssignmentPos) !== Number.MAX_VALUE) {
29672
+ const referencingFunction = findAncestor(node, isFunctionOrSourceFile);
29673
+ const declaringFunction = findAncestor(symbol.valueDeclaration, isFunctionOrSourceFile);
29674
+ symbol.lastAssignmentPos = referencingFunction === declaringFunction ? extendAssignmentPosition(node, symbol.valueDeclaration!) : Number.MAX_VALUE;
29675
+ }
29676
+ if (hasDefiniteAssignment && symbol.lastAssignmentPos > 0) {
29677
+ symbol.lastAssignmentPos *= -1;
29678
+ }
29664
29679
}
29665
29680
}
29666
29681
return;
@@ -29670,7 +29685,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29670
29685
if (!(node as ExportSpecifier).isTypeOnly && !exportDeclaration.isTypeOnly && !exportDeclaration.moduleSpecifier && name.kind !== SyntaxKind.StringLiteral) {
29671
29686
const symbol = resolveEntityName(name, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true);
29672
29687
if (symbol && isParameterOrMutableLocalVariable(symbol)) {
29673
- symbol.lastAssignmentPos = Number.MAX_VALUE;
29688
+ const sign = symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0 ? -1 : 1;
29689
+ symbol.lastAssignmentPos = sign * Number.MAX_VALUE;
29674
29690
}
29675
29691
}
29676
29692
return;
@@ -30414,6 +30430,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30414
30430
30415
30431
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
30416
30432
let declaration = localOrExportSymbol.valueDeclaration;
30433
+ const immediateDeclaration = declaration;
30417
30434
30418
30435
// If the identifier is declared in a binding pattern for which we're currently computing the implied type and the
30419
30436
// reference occurs with the same binding pattern, return the non-inferrable any type. This for example occurs in
@@ -30503,7 +30520,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30503
30520
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
30504
30521
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
30505
30522
// declaration container are the same).
30506
- const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) ||
30523
+ const isNeverInitialized = immediateDeclaration && isVariableDeclaration(immediateDeclaration) && !immediateDeclaration.initializer && !immediateDeclaration.exclamationToken && isMutableLocalVariableDeclaration(immediateDeclaration) && !isSymbolAssignedDefinitely(symbol);
30524
+ const assumeInitialized = isParameter || isAlias ||
30525
+ (isOuterVariable && !isNeverInitialized) ||
30526
+ isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) ||
30507
30527
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 ||
30508
30528
isInTypeQuery(node) || isInAmbientOrTypeNode(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
30509
30529
node.parent.kind === SyntaxKind.NonNullExpression ||
@@ -43495,7 +43515,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
43495
43515
case SyntaxKind.MethodDeclaration:
43496
43516
case SyntaxKind.GetAccessor:
43497
43517
case SyntaxKind.SetAccessor:
43498
- if (node.body) { // Don't report unused parameters in overloads
43518
+ // Only report unused parameters on the implementation, not overloads.
43519
+ if (node.body) {
43499
43520
checkUnusedLocalsAndParameters(node, addDiagnostic);
43500
43521
}
43501
43522
checkUnusedTypeParameters(node, addDiagnostic);
0 commit comments