@@ -16,14 +16,16 @@ namespace ts.codefix {
16
16
getCodeActions ( context ) {
17
17
const { errorCode, sourceFile, program } = context ;
18
18
const checker = program . getTypeChecker ( ) ;
19
+ const sourceFiles = program . getSourceFiles ( ) ;
19
20
const startToken = getTokenAtPosition ( sourceFile , context . span . start , /*includeJsDocComment*/ false ) ;
20
21
21
22
const importDecl = tryGetFullImport ( startToken ) ;
22
23
if ( importDecl ) {
23
24
const changes = textChanges . ChangeTracker . with ( context , t => t . deleteNode ( sourceFile , importDecl ) ) ;
24
25
return [ createCodeFixAction ( fixName , changes , [ Diagnostics . Remove_import_from_0 , showModuleSpecifier ( importDecl ) ] , fixIdDelete , Diagnostics . Delete_all_unused_declarations ) ] ;
25
26
}
26
- const delDestructure = textChanges . ChangeTracker . with ( context , t => tryDeleteFullDestructure ( t , sourceFile , startToken , /*deleted*/ undefined , checker , /*isFixAll*/ false ) ) ;
27
+ const delDestructure = textChanges . ChangeTracker . with ( context , t =>
28
+ tryDeleteFullDestructure ( t , sourceFile , startToken , /*deleted*/ undefined , checker , sourceFiles , /*isFixAll*/ false ) ) ;
27
29
if ( delDestructure . length ) {
28
30
return [ createCodeFixAction ( fixName , delDestructure , Diagnostics . Remove_destructuring , fixIdDelete , Diagnostics . Delete_all_unused_declarations ) ] ;
29
31
}
@@ -35,7 +37,8 @@ namespace ts.codefix {
35
37
const token = getToken ( sourceFile , textSpanEnd ( context . span ) ) ;
36
38
const result : CodeFixAction [ ] = [ ] ;
37
39
38
- const deletion = textChanges . ChangeTracker . with ( context , t => tryDeleteDeclaration ( t , sourceFile , token , /*deleted*/ undefined , checker , /*isFixAll*/ false ) ) ;
40
+ const deletion = textChanges . ChangeTracker . with ( context , t =>
41
+ tryDeleteDeclaration ( t , sourceFile , token , /*deleted*/ undefined , checker , sourceFiles , /*isFixAll*/ false ) ) ;
39
42
if ( deletion . length ) {
40
43
result . push ( createCodeFixAction ( fixName , deletion , [ Diagnostics . Remove_declaration_for_Colon_0 , token . getText ( sourceFile ) ] , fixIdDelete , Diagnostics . Delete_all_unused_declarations ) ) ;
41
44
}
@@ -50,9 +53,10 @@ namespace ts.codefix {
50
53
fixIds : [ fixIdPrefix , fixIdDelete ] ,
51
54
getAllCodeActions : context => {
52
55
// Track a set of deleted nodes that may be ancestors of other marked for deletion -- only delete the ancestors.
53
- const deleted = new NodeSet ( ) ;
56
+ const deletedAncestors = new NodeSet ( ) ;
54
57
const { sourceFile, program } = context ;
55
58
const checker = program . getTypeChecker ( ) ;
59
+ const sourceFiles = program . getSourceFiles ( ) ;
56
60
return codeFixAll ( context , errorCodes , ( changes , diag ) => {
57
61
const startToken = getTokenAtPosition ( sourceFile , diag . start , /*includeJsDocComment*/ false ) ;
58
62
const token = findPrecedingToken ( textSpanEnd ( diag ) , diag . file ) ! ;
@@ -64,15 +68,15 @@ namespace ts.codefix {
64
68
break ;
65
69
case fixIdDelete :
66
70
// Ignore if this range was already deleted.
67
- if ( deleted . some ( d => rangeContainsPosition ( d , diag . start ) ) ) break ;
71
+ if ( hasDeletedAncestor ( deletedAncestors , token ) ) break ;
68
72
69
73
const importDecl = tryGetFullImport ( startToken ) ;
70
74
if ( importDecl ) {
71
75
changes . deleteNode ( sourceFile , importDecl ) ;
72
76
}
73
- else if ( ! tryDeleteFullDestructure ( changes , sourceFile , startToken , deleted , checker , /*isFixAll*/ true ) &&
74
- ! tryDeleteFullVariableStatement ( changes , sourceFile , startToken , deleted ) ) {
75
- tryDeleteDeclaration ( changes , sourceFile , token , deleted , checker , /*isFixAll*/ true ) ;
77
+ else if ( ! tryDeleteFullDestructure ( changes , sourceFile , startToken , deletedAncestors , checker , sourceFiles , /*isFixAll*/ true ) &&
78
+ ! tryDeleteFullVariableStatement ( changes , sourceFile , startToken , deletedAncestors ) ) {
79
+ tryDeleteDeclaration ( changes , sourceFile , token , deletedAncestors , checker , sourceFiles , /*isFixAll*/ true ) ;
76
80
}
77
81
break ;
78
82
default :
@@ -82,12 +86,16 @@ namespace ts.codefix {
82
86
} ,
83
87
} ) ;
84
88
89
+ function hasDeletedAncestor ( deletedAncestors : ReadonlyNodeSet , node : Node ) : boolean {
90
+ return deletedAncestors . some ( d => rangeContainsPosition ( d , node . pos ) ) ;
91
+ }
92
+
85
93
// Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing.
86
94
function tryGetFullImport ( startToken : Node ) : ImportDeclaration | undefined {
87
95
return startToken . kind === SyntaxKind . ImportKeyword ? tryCast ( startToken . parent , isImportDeclaration ) : undefined ;
88
96
}
89
97
90
- function tryDeleteFullDestructure ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , startToken : Node , deletedAncestors : NodeSet | undefined , checker : TypeChecker , isFixAll : boolean ) : boolean {
98
+ function tryDeleteFullDestructure ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , startToken : Node , deletedAncestors : NodeSet | undefined , checker : TypeChecker , sourceFiles : ReadonlyArray < SourceFile > , isFixAll : boolean ) : boolean {
91
99
if ( startToken . kind !== SyntaxKind . OpenBraceToken || ! isObjectBindingPattern ( startToken . parent ) ) return false ;
92
100
const decl = cast ( startToken . parent , isObjectBindingPattern ) . parent ;
93
101
switch ( decl . kind ) {
@@ -98,9 +106,10 @@ namespace ts.codefix {
98
106
if ( ! mayDeleteParameter ( decl , checker , isFixAll ) ) break ;
99
107
if ( deletedAncestors ) deletedAncestors . add ( decl ) ;
100
108
changes . deleteNodeInList ( sourceFile , decl ) ;
109
+ deleteUnusedArguments ( changes , deletedAncestors , decl , sourceFiles , checker ) ;
101
110
break ;
102
111
case SyntaxKind . BindingElement :
103
- if ( deletedAncestors ) deletedAncestors . add ( decl ) ;
112
+ if ( deletedAncestors ) deletedAncestors . add ( decl ) ;
104
113
changes . deleteNode ( sourceFile , decl ) ;
105
114
break ;
106
115
default :
@@ -148,8 +157,8 @@ namespace ts.codefix {
148
157
return false ;
149
158
}
150
159
151
- function tryDeleteDeclaration ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , token : Node , deletedAncestors : NodeSet | undefined , checker : TypeChecker , isFixAll : boolean ) {
152
- tryDeleteDeclarationWorker ( changes , sourceFile , token , deletedAncestors , checker , isFixAll ) ;
160
+ function tryDeleteDeclaration ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , token : Node , deletedAncestors : NodeSet | undefined , checker : TypeChecker , sourceFiles : ReadonlyArray < SourceFile > , isFixAll : boolean ) {
161
+ tryDeleteDeclarationWorker ( changes , sourceFile , token , deletedAncestors , checker , sourceFiles , isFixAll ) ;
153
162
if ( isIdentifier ( token ) ) deleteAssignments ( changes , sourceFile , token , checker ) ;
154
163
}
155
164
@@ -162,7 +171,7 @@ namespace ts.codefix {
162
171
} ) ;
163
172
}
164
173
165
- function tryDeleteDeclarationWorker ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , token : Node , deletedAncestors : NodeSet | undefined , checker : TypeChecker , isFixAll : boolean ) : void {
174
+ function tryDeleteDeclarationWorker ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , token : Node , deletedAncestors : NodeSet | undefined , checker : TypeChecker , sourceFiles : ReadonlyArray < SourceFile > , isFixAll : boolean ) : void {
166
175
const parent = token . parent ;
167
176
switch ( parent . kind ) {
168
177
case SyntaxKind . VariableDeclaration :
@@ -212,6 +221,7 @@ namespace ts.codefix {
212
221
else {
213
222
changes . deleteNodeInList ( sourceFile , parent ) ;
214
223
}
224
+ deleteUnusedArguments ( changes , deletedAncestors , parent as ParameterDeclaration , sourceFiles , checker ) ;
215
225
break ;
216
226
217
227
case SyntaxKind . BindingElement : {
@@ -341,20 +351,22 @@ namespace ts.codefix {
341
351
}
342
352
}
343
353
344
- function mayDeleteParameter ( p : ParameterDeclaration , checker : TypeChecker , isFixAll : boolean ) {
354
+ function mayDeleteParameter ( p : ParameterDeclaration , checker : TypeChecker , isFixAll : boolean ) : boolean {
345
355
const parent = p . parent ;
346
356
switch ( parent . kind ) {
347
357
case SyntaxKind . MethodDeclaration :
348
- // Don't remove a parameter if this overrides something
358
+ // Don't remove a parameter if this overrides something.
349
359
const symbol = checker . getSymbolAtLocation ( parent . name ) ! ;
350
360
if ( isMemberSymbolInBaseType ( symbol , checker ) ) return false ;
351
361
// falls through
352
362
353
363
case SyntaxKind . Constructor :
354
364
case SyntaxKind . FunctionDeclaration :
365
+ return true ;
366
+
355
367
case SyntaxKind . FunctionExpression :
356
368
case SyntaxKind . ArrowFunction : {
357
- // Can't remove a non-last parameter. Can remove a parameter in code-fix-all if future parameters are also unused.
369
+ // Can't remove a non-last parameter in a callback . Can remove a parameter in code-fix-all if future parameters are also unused.
358
370
const { parameters } = parent ;
359
371
const index = parameters . indexOf ( p ) ;
360
372
Debug . assert ( index !== - 1 ) ;
@@ -371,4 +383,16 @@ namespace ts.codefix {
371
383
return Debug . failBadSyntaxKind ( parent ) ;
372
384
}
373
385
}
386
+
387
+ function deleteUnusedArguments ( changes : textChanges . ChangeTracker , deletedAncestors : NodeSet | undefined , deletedParameter : ParameterDeclaration , sourceFiles : ReadonlyArray < SourceFile > , checker : TypeChecker ) : void {
388
+ FindAllReferences . Core . eachSignatureCall ( deletedParameter . parent , sourceFiles , checker , ( sourceFile , call ) => {
389
+ if ( deletedAncestors && hasDeletedAncestor ( deletedAncestors , call ) ) return ;
390
+ const index = deletedParameter . parent . parameters . indexOf ( deletedParameter ) ;
391
+ if ( call . arguments . length > index ) { // Just in case the call didn't provide enough arguments.
392
+ const argument = call . arguments [ index ] ;
393
+ changes . deleteNodeInList ( sourceFile , argument ) ;
394
+ if ( deletedAncestors ) deletedAncestors . add ( argument ) ;
395
+ }
396
+ } ) ;
397
+ }
374
398
}
0 commit comments