@@ -18,14 +18,14 @@ namespace ts.codefix {
1818
1919 switch ( token . kind ) {
2020 case ts . SyntaxKind . Identifier :
21- return deleteIdentifier ( ) ;
21+ return deleteIdentifierOrPrefixWithUnderscore ( < Identifier > token ) ;
2222
2323 case SyntaxKind . PropertyDeclaration :
2424 case SyntaxKind . NamespaceImport :
25- return deleteNode ( token . parent ) ;
25+ return [ deleteNode ( token . parent ) ] ;
2626
2727 default :
28- return deleteDefault ( ) ;
28+ return [ deleteDefault ( ) ] ;
2929 }
3030
3131 function deleteDefault ( ) {
@@ -40,126 +40,132 @@ namespace ts.codefix {
4040 }
4141 }
4242
43- function deleteIdentifier ( ) : CodeAction [ ] | undefined {
44- switch ( token . parent . kind ) {
43+ function prefixIdentifierWithUnderscore ( identifier : Identifier ) : CodeAction {
44+ const startPosition = identifier . getStart ( sourceFile , /*includeJsDocComment*/ false ) ;
45+ return {
46+ description : formatStringFromArgs ( getLocaleSpecificMessage ( Diagnostics . Prefix_0_with_an_underscore ) , { 0 : token . getText ( ) } ) ,
47+ changes : [ {
48+ fileName : sourceFile . path ,
49+ textChanges : [ {
50+ span : { start : startPosition , length : 0 } ,
51+ newText : "_"
52+ } ]
53+ } ]
54+ } ;
55+ }
56+
57+ function deleteIdentifierOrPrefixWithUnderscore ( identifier : Identifier ) : CodeAction [ ] | undefined {
58+ const parent = identifier . parent ;
59+ switch ( parent . kind ) {
4560 case ts . SyntaxKind . VariableDeclaration :
46- return deleteVariableDeclaration ( < ts . VariableDeclaration > token . parent ) ;
61+ return deleteVariableDeclarationOrPrefixWithUnderscore ( identifier , < ts . VariableDeclaration > parent ) ;
4762
4863 case SyntaxKind . TypeParameter :
49- const typeParameters = ( < DeclarationWithTypeParameters > token . parent . parent ) . typeParameters ;
64+ const typeParameters = ( < DeclarationWithTypeParameters > parent . parent ) . typeParameters ;
5065 if ( typeParameters . length === 1 ) {
5166 const previousToken = getTokenAtPosition ( sourceFile , typeParameters . pos - 1 , /*includeJsDocComment*/ false ) ;
52- if ( ! previousToken || previousToken . kind !== SyntaxKind . LessThanToken ) {
53- return deleteRange ( typeParameters ) ;
54- }
5567 const nextToken = getTokenAtPosition ( sourceFile , typeParameters . end , /*includeJsDocComment*/ false ) ;
56- if ( ! nextToken || nextToken . kind !== SyntaxKind . GreaterThanToken ) {
57- return deleteRange ( typeParameters ) ;
58- }
59- return deleteNodeRange ( previousToken , nextToken ) ;
68+ Debug . assert ( previousToken . kind === SyntaxKind . LessThanToken ) ;
69+ Debug . assert ( nextToken . kind === SyntaxKind . GreaterThanToken ) ;
70+
71+ return [ deleteNodeRange ( previousToken , nextToken ) ] ;
6072 }
6173 else {
62- return deleteNodeInList ( token . parent ) ;
74+ return [ deleteNodeInList ( parent ) ] ;
6375 }
6476
6577 case ts . SyntaxKind . Parameter :
66- const functionDeclaration = < FunctionDeclaration > token . parent . parent ;
67- if ( functionDeclaration . parameters . length === 1 ) {
68- return deleteNode ( token . parent ) ;
69- }
70- else {
71- return deleteNodeInList ( token . parent ) ;
72- }
78+ const functionDeclaration = < FunctionDeclaration > parent . parent ;
79+ return [ functionDeclaration . parameters . length === 1 ? deleteNode ( parent ) : deleteNodeInList ( parent ) ,
80+ prefixIdentifierWithUnderscore ( identifier ) ] ;
7381
7482 // handle case where 'import a = A;'
7583 case SyntaxKind . ImportEqualsDeclaration :
76- const importEquals = getAncestor ( token , SyntaxKind . ImportEqualsDeclaration ) ;
77- return deleteNode ( importEquals ) ;
84+ const importEquals = getAncestor ( identifier , SyntaxKind . ImportEqualsDeclaration ) ;
85+ return [ deleteNode ( importEquals ) ] ;
7886
7987 case SyntaxKind . ImportSpecifier :
80- const namedImports = < NamedImports > token . parent . parent ;
88+ const namedImports = < NamedImports > parent . parent ;
8189 if ( namedImports . elements . length === 1 ) {
8290 // Only 1 import and it is unused. So the entire declaration should be removed.
83- const importSpec = getAncestor ( token , SyntaxKind . ImportDeclaration ) ;
84- return deleteNode ( importSpec ) ;
91+ const importSpec = getAncestor ( identifier , SyntaxKind . ImportDeclaration ) ;
92+ return [ deleteNode ( importSpec ) ] ;
8593 }
8694 else {
8795 // delete import specifier
88- return deleteNodeInList ( token . parent ) ;
96+ return [ deleteNodeInList ( parent ) ] ;
8997 }
9098
9199 // handle case where "import d, * as ns from './file'"
92100 // or "'import {a, b as ns} from './file'"
93101 case SyntaxKind . ImportClause : // this covers both 'import |d|' and 'import |d,| *'
94- const importClause = < ImportClause > token . parent ;
102+ const importClause = < ImportClause > parent ;
95103 if ( ! importClause . namedBindings ) { // |import d from './file'| or |import * as ns from './file'|
96104 const importDecl = getAncestor ( importClause , SyntaxKind . ImportDeclaration ) ;
97- return deleteNode ( importDecl ) ;
105+ return [ deleteNode ( importDecl ) ] ;
98106 }
99107 else {
100108 // import |d,| * as ns from './file'
101109 const start = importClause . name . getStart ( sourceFile ) ;
102110 const nextToken = getTokenAtPosition ( sourceFile , importClause . name . end , /*includeJsDocComment*/ false ) ;
103111 if ( nextToken && nextToken . kind === SyntaxKind . CommaToken ) {
104112 // shift first non-whitespace position after comma to the start position of the node
105- return deleteRange ( { pos : start , end : skipTrivia ( sourceFile . text , nextToken . end , /*stopAfterLineBreaks*/ false , /*stopAtComments*/ true ) } ) ;
113+ return [ deleteRange ( { pos : start , end : skipTrivia ( sourceFile . text , nextToken . end , /*stopAfterLineBreaks*/ false , /*stopAtComments*/ true ) } ) ] ;
106114 }
107115 else {
108- return deleteNode ( importClause . name ) ;
116+ return [ deleteNode ( importClause . name ) ] ;
109117 }
110118 }
111119
112120 case SyntaxKind . NamespaceImport :
113- const namespaceImport = < NamespaceImport > token . parent ;
114- if ( namespaceImport . name === token && ! ( < ImportClause > namespaceImport . parent ) . name ) {
121+ const namespaceImport = < NamespaceImport > parent ;
122+ if ( namespaceImport . name === identifier && ! ( < ImportClause > namespaceImport . parent ) . name ) {
115123 const importDecl = getAncestor ( namespaceImport , SyntaxKind . ImportDeclaration ) ;
116- return deleteNode ( importDecl ) ;
124+ return [ deleteNode ( importDecl ) ] ;
117125 }
118126 else {
119127 const previousToken = getTokenAtPosition ( sourceFile , namespaceImport . pos - 1 , /*includeJsDocComment*/ false ) ;
120128 if ( previousToken && previousToken . kind === SyntaxKind . CommaToken ) {
121129 const startPosition = textChanges . getAdjustedStartPosition ( sourceFile , previousToken , { } , textChanges . Position . FullStart ) ;
122- return deleteRange ( { pos : startPosition , end : namespaceImport . end } ) ;
130+ return [ deleteRange ( { pos : startPosition , end : namespaceImport . end } ) ] ;
123131 }
124- return deleteRange ( namespaceImport ) ;
132+ return [ deleteRange ( namespaceImport ) ] ;
125133 }
126134
127135 default :
128- return deleteDefault ( ) ;
136+ return [ deleteDefault ( ) ] ;
129137 }
130138 }
131139
132140 // token.parent is a variableDeclaration
133- function deleteVariableDeclaration ( varDecl : ts . VariableDeclaration ) : CodeAction [ ] | undefined {
141+ function deleteVariableDeclarationOrPrefixWithUnderscore ( identifier : Identifier , varDecl : ts . VariableDeclaration ) : CodeAction [ ] | undefined {
134142 switch ( varDecl . parent . parent . kind ) {
135143 case SyntaxKind . ForStatement :
136144 const forStatement = < ForStatement > varDecl . parent . parent ;
137145 const forInitializer = < VariableDeclarationList > forStatement . initializer ;
138- if ( forInitializer . declarations . length === 1 ) {
139- return deleteNode ( forInitializer ) ;
140- }
141- else {
142- return deleteNodeInList ( varDecl ) ;
143- }
146+ return [ forInitializer . declarations . length === 1 ? deleteNode ( forInitializer ) : deleteNodeInList ( varDecl ) ] ;
144147
145148 case SyntaxKind . ForOfStatement :
146149 const forOfStatement = < ForOfStatement > varDecl . parent . parent ;
147150 Debug . assert ( forOfStatement . initializer . kind === SyntaxKind . VariableDeclarationList ) ;
148151 const forOfInitializer = < VariableDeclarationList > forOfStatement . initializer ;
149- return replaceNode ( forOfInitializer . declarations [ 0 ] , createObjectLiteral ( ) ) ;
152+ return [
153+ replaceNode ( forOfInitializer . declarations [ 0 ] , createObjectLiteral ( ) ) ,
154+ prefixIdentifierWithUnderscore ( identifier )
155+ ] ;
150156
151157 case SyntaxKind . ForInStatement :
152158 // There is no valid fix in the case of:
153159 // for .. in
154- return undefined ;
160+ return [ prefixIdentifierWithUnderscore ( identifier ) ] ;
155161
156162 default :
157163 const variableStatement = < VariableStatement > varDecl . parent . parent ;
158164 if ( variableStatement . declarationList . declarations . length === 1 ) {
159- return deleteNode ( variableStatement ) ;
165+ return [ deleteNode ( variableStatement ) ] ;
160166 }
161167 else {
162- return deleteNodeInList ( varDecl ) ;
168+ return [ deleteNodeInList ( varDecl ) ] ;
163169 }
164170 }
165171 }
@@ -184,11 +190,11 @@ namespace ts.codefix {
184190 return makeChange ( textChanges . ChangeTracker . fromCodeFixContext ( context ) . replaceNode ( sourceFile , n , newNode ) ) ;
185191 }
186192
187- function makeChange ( changeTracker : textChanges . ChangeTracker ) {
188- return [ {
193+ function makeChange ( changeTracker : textChanges . ChangeTracker ) : CodeAction {
194+ return {
189195 description : formatStringFromArgs ( getLocaleSpecificMessage ( Diagnostics . Remove_declaration_for_Colon_0 ) , { 0 : token . getText ( ) } ) ,
190196 changes : changeTracker . getChanges ( )
191- } ] ;
197+ } ;
192198 }
193199 }
194200 } ) ;
0 commit comments