@@ -32,16 +32,16 @@ namespace ts.codefix {
32
32
33
33
const token = getTokenAtPosition ( sourceFile , start , /*includeJsDocComment*/ false ) ;
34
34
let declaration ! : Declaration ;
35
- const changes = textChanges . ChangeTracker . with ( context , changes => { declaration = doChange ( changes , sourceFile , token , errorCode , program , cancellationToken ) ; } ) ;
35
+ const changes = textChanges . ChangeTracker . with ( context , changes => { declaration = doChange ( changes , sourceFile , token , errorCode , program , cancellationToken , /*markSeenseen*/ returnTrue ) ; } ) ;
36
36
return changes . length === 0 ? undefined
37
37
: [ createCodeFixAction ( fixId , changes , [ getDiagnostic ( errorCode , token ) , getNameOfDeclaration ( declaration ) . getText ( sourceFile ) ] , fixId , Diagnostics . Infer_all_types_from_usage ) ] ;
38
38
} ,
39
39
fixIds : [ fixId ] ,
40
40
getAllCodeActions ( context ) {
41
41
const { sourceFile, program, cancellationToken } = context ;
42
- const seenFunctions = createMap < true > ( ) ;
42
+ const markSeen = nodeSeenTracker ( ) ;
43
43
return codeFixAll ( context , errorCodes , ( changes , err ) => {
44
- doChange ( changes , sourceFile , getTokenAtPosition ( err . file ! , err . start ! , /*includeJsDocComment*/ false ) , err . code , program , cancellationToken , seenFunctions ) ;
44
+ doChange ( changes , sourceFile , getTokenAtPosition ( err . file ! , err . start ! , /*includeJsDocComment*/ false ) , err . code , program , cancellationToken , markSeen ) ;
45
45
} ) ;
46
46
} ,
47
47
} ) ;
@@ -57,7 +57,7 @@ namespace ts.codefix {
57
57
}
58
58
}
59
59
60
- function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , token : Node , errorCode : number , program : Program , cancellationToken : CancellationToken , seenFunctions ?: Map < true > ) : Declaration | undefined {
60
+ function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , token : Node , errorCode : number , program : Program , cancellationToken : CancellationToken , markSeen : NodeSeenTracker ) : Declaration | undefined {
61
61
if ( ! isParameterPropertyModifier ( token . kind ) && token . kind !== SyntaxKind . Identifier && token . kind !== SyntaxKind . DotDotDotToken ) {
62
62
return undefined ;
63
63
}
@@ -67,18 +67,19 @@ namespace ts.codefix {
67
67
// Variable and Property declarations
68
68
case Diagnostics . Member_0_implicitly_has_an_1_type . code :
69
69
case Diagnostics . Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined . code :
70
- if ( isVariableDeclaration ( parent ) || isPropertyDeclaration ( parent ) || isPropertySignature ( parent ) ) { // handle bad location
70
+ if ( ( isVariableDeclaration ( parent ) && markSeen ( parent ) ) || isPropertyDeclaration ( parent ) || isPropertySignature ( parent ) ) { // handle bad location
71
71
annotateVariableDeclaration ( changes , sourceFile , parent , program , cancellationToken ) ;
72
72
return parent ;
73
73
}
74
74
return undefined ;
75
75
76
76
case Diagnostics . Variable_0_implicitly_has_an_1_type . code : {
77
77
const symbol = program . getTypeChecker ( ) . getSymbolAtLocation ( token ) ;
78
- if ( symbol && symbol . valueDeclaration && isVariableDeclaration ( symbol . valueDeclaration ) ) {
78
+ if ( symbol && symbol . valueDeclaration && isVariableDeclaration ( symbol . valueDeclaration ) && markSeen ( symbol . valueDeclaration ) ) {
79
79
annotateVariableDeclaration ( changes , sourceFile , symbol . valueDeclaration , program , cancellationToken ) ;
80
80
return symbol . valueDeclaration ;
81
81
}
82
+ return undefined ;
82
83
}
83
84
}
84
85
@@ -96,7 +97,7 @@ namespace ts.codefix {
96
97
}
97
98
// falls through
98
99
case Diagnostics . Rest_parameter_0_implicitly_has_an_any_type . code :
99
- if ( ! seenFunctions || addToSeen ( seenFunctions , getNodeId ( containingFunction ) ) ) {
100
+ if ( markSeen ( containingFunction ) ) {
100
101
const param = cast ( parent , isParameter ) ;
101
102
annotateParameters ( changes , param , containingFunction , sourceFile , program , cancellationToken ) ;
102
103
return param ;
@@ -318,6 +319,16 @@ namespace ts.codefix {
318
319
case SyntaxKind . ElementAccessExpression :
319
320
inferTypeFromPropertyElementExpressionContext ( < ElementAccessExpression > node . parent , node , checker , usageContext ) ;
320
321
break ;
322
+ case SyntaxKind . VariableDeclaration : {
323
+ const { name, initializer } = node . parent as VariableDeclaration ;
324
+ if ( node === name ) {
325
+ if ( initializer ) { // This can happen for `let x = null;` which still has an implicit-any error.
326
+ addCandidateType ( usageContext , checker . getTypeAtLocation ( initializer ) ) ;
327
+ }
328
+ break ;
329
+ }
330
+ }
331
+ // falls through
321
332
default :
322
333
return inferTypeFromContextualType ( node , checker , usageContext ) ;
323
334
}
@@ -511,7 +522,7 @@ namespace ts.codefix {
511
522
return checker . getStringType ( ) ;
512
523
}
513
524
else if ( usageContext . candidateTypes ) {
514
- return checker . getWidenedType ( checker . getUnionType ( map ( usageContext . candidateTypes , t => checker . getBaseTypeOfLiteralType ( t ) ) , UnionReduction . Subtype ) ) ;
525
+ return checker . getWidenedType ( checker . getUnionType ( usageContext . candidateTypes . map ( t => checker . getBaseTypeOfLiteralType ( t ) ) , UnionReduction . Subtype ) ) ;
515
526
}
516
527
else if ( usageContext . properties && hasCallContext ( usageContext . properties . get ( "then" as __String ) ) ) {
517
528
const paramType = getParameterTypeFromCallContexts ( 0 , usageContext . properties . get ( "then" as __String ) . callContexts , /*isRestParameter*/ false , checker ) ;
0 commit comments