@@ -9,15 +9,20 @@ import { getNonOverlappingReplacements, filterProblemsForFile } from './runner/f
9
9
10
10
const isTsLintLanguageServiceMarker = Symbol ( '__isTsLintLanguageServiceMarker__' ) ;
11
11
12
- class FailureMap {
13
- private readonly _map = new Map < string , tslint . RuleFailure > ( ) ;
12
+ interface Problem {
13
+ failure : tslint . RuleFailure ;
14
+ fixable : boolean ;
15
+ }
16
+
17
+ class ProblemMap {
18
+ private readonly _map = new Map < string , Problem > ( ) ;
14
19
15
20
public get ( start : number , end : number ) {
16
21
return this . _map . get ( this . key ( start , end ) ) ;
17
22
}
18
23
19
- public set ( start : number , end : number , failure : tslint . RuleFailure ) : void {
20
- this . _map . set ( this . key ( start , end ) , failure ) ;
24
+ public set ( start : number , end : number , problem : Problem ) : void {
25
+ this . _map . set ( this . key ( start , end ) , problem ) ;
21
26
}
22
27
23
28
public values ( ) {
@@ -31,7 +36,7 @@ class FailureMap {
31
36
}
32
37
33
38
export class TSLintPlugin {
34
- private readonly codeFixActions = new Map < string , FailureMap > ( ) ;
39
+ private readonly codeFixActions = new Map < string , ProblemMap > ( ) ;
35
40
private readonly configFileWatcher : ConfigFileWatcher ;
36
41
private readonly runner : TsLintRunner ;
37
42
@@ -182,12 +187,12 @@ export class TSLintPlugin {
182
187
const documentFixes = this . codeFixActions . get ( fileName ) ;
183
188
if ( documentFixes ) {
184
189
const problem = documentFixes . get ( start , end ) ;
185
- if ( problem ) {
186
- const fix = problem . getFix ( ) ;
190
+ if ( problem && problem . fixable ) {
191
+ const fix = problem . failure . getFix ( ) ;
187
192
if ( fix ) {
188
- fixes . push ( this . getRuleFailureQuickFix ( problem , fileName ) ) ;
193
+ fixes . push ( this . getRuleFailureQuickFix ( problem . failure , fileName ) ) ;
189
194
190
- const fixAll = this . getRuleFailureFixAllQuickFix ( problem . getRuleName ( ) , documentFixes , fileName ) ;
195
+ const fixAll = this . getRuleFailureFixAllQuickFix ( problem . failure . getRuleName ( ) , documentFixes , fileName ) ;
191
196
if ( fixAll ) {
192
197
fixes . push ( fixAll ) ;
193
198
}
@@ -197,50 +202,44 @@ export class TSLintPlugin {
197
202
fixes . push ( this . getFixAllAutoFixableQuickFix ( documentFixes , fileName ) ) ;
198
203
199
204
if ( problem ) {
200
- fixes . push ( this . getDisableRuleQuickFix ( problem , fileName , this . getProgram ( ) . getSourceFile ( fileName ) ! ) ) ;
205
+ fixes . push ( this . getDisableRuleQuickFix ( problem . failure , fileName , this . getProgram ( ) . getSourceFile ( fileName ) ! ) ) ;
201
206
}
202
207
}
203
208
204
209
return fixes ;
205
210
}
206
211
207
- private recordCodeAction ( problem : tslint . RuleFailure , file : ts . SourceFile ) {
208
- let fix : tslint . Fix | undefined ;
209
-
212
+ private recordCodeAction ( failure : tslint . RuleFailure , file : ts . SourceFile ) {
210
213
// tslint can return a fix with an empty replacements array, these fixes are ignored
211
- if ( problem . getFix && problem . getFix ( ) && ! replacementsAreEmpty ( problem . getFix ( ) ) ) { // tslint fixes are not available in tslint < 3.17
212
- fix = problem . getFix ( ) ; // createAutoFix(problem, document, problem.getFix());
213
- }
214
-
215
- if ( ! fix ) {
216
- return ;
217
- }
214
+ const fixable = ! ! ( failure . getFix && failure . getFix ( ) && ! replacementsAreEmpty ( failure . getFix ( ) ) ) ;
218
215
219
216
let documentAutoFixes = this . codeFixActions . get ( file . fileName ) ;
220
217
if ( ! documentAutoFixes ) {
221
- documentAutoFixes = new FailureMap ( ) ;
218
+ documentAutoFixes = new ProblemMap ( ) ;
222
219
this . codeFixActions . set ( file . fileName , documentAutoFixes ) ;
223
220
}
224
- documentAutoFixes . set ( problem . getStartPosition ( ) . getPosition ( ) , problem . getEndPosition ( ) . getPosition ( ) , problem ) ;
221
+ documentAutoFixes . set ( failure . getStartPosition ( ) . getPosition ( ) , failure . getEndPosition ( ) . getPosition ( ) , { failure , fixable } ) ;
225
222
}
226
223
227
- private getRuleFailureQuickFix ( problem : tslint . RuleFailure , fileName : string ) : ts_module . CodeFixAction {
224
+ private getRuleFailureQuickFix ( failure : tslint . RuleFailure , fileName : string ) : ts_module . CodeFixAction {
228
225
return {
229
- description : `Fix: ${ problem . getFailure ( ) } ` ,
226
+ description : `Fix: ${ failure . getFailure ( ) } ` ,
230
227
fixName : '' ,
231
- changes : [ problemToFileTextChange ( problem , fileName ) ] ,
228
+ changes : [ failureToFileTextChange ( failure , fileName ) ] ,
232
229
} ;
233
230
}
234
231
235
232
/**
236
233
* Generate a code action that fixes all instances of ruleName.
237
234
*/
238
- private getRuleFailureFixAllQuickFix ( ruleName : string , problems : FailureMap , fileName : string ) : ts_module . CodeFixAction | undefined {
235
+ private getRuleFailureFixAllQuickFix ( ruleName : string , problems : ProblemMap , fileName : string ) : ts_module . CodeFixAction | undefined {
239
236
const changes : ts_module . FileTextChanges [ ] = [ ] ;
240
237
241
238
for ( const problem of problems . values ( ) ) {
242
- if ( problem . getRuleName ( ) === ruleName ) {
243
- changes . push ( problemToFileTextChange ( problem , fileName ) ) ;
239
+ if ( problem . fixable ) {
240
+ if ( problem . failure . getRuleName ( ) === ruleName ) {
241
+ changes . push ( failureToFileTextChange ( problem . failure , fileName ) ) ;
242
+ }
244
243
}
245
244
}
246
245
@@ -256,22 +255,22 @@ export class TSLintPlugin {
256
255
} ;
257
256
}
258
257
259
- private getDisableRuleQuickFix ( problem : tslint . RuleFailure , fileName : string , file : ts_module . SourceFile ) : ts_module . CodeFixAction {
258
+ private getDisableRuleQuickFix ( failure : tslint . RuleFailure , fileName : string , file : ts_module . SourceFile ) : ts_module . CodeFixAction {
260
259
return {
261
- description : `Disable rule '${ problem . getRuleName ( ) } '` ,
260
+ description : `Disable rule '${ failure . getRuleName ( ) } '` ,
262
261
fixName : '' ,
263
262
changes : [ {
264
263
fileName,
265
264
textChanges : [ {
266
- newText : `// tslint:disable-next-line: ${ problem . getRuleName ( ) } \n` ,
267
- span : { start : file . getLineStarts ( ) [ problem . getStartPosition ( ) . getLineAndCharacter ( ) . line ] , length : 0 } ,
265
+ newText : `// tslint:disable-next-line: ${ failure . getRuleName ( ) } \n` ,
266
+ span : { start : file . getLineStarts ( ) [ failure . getStartPosition ( ) . getLineAndCharacter ( ) . line ] , length : 0 } ,
268
267
} ] ,
269
268
} ] ,
270
269
} ;
271
270
}
272
271
273
- private getFixAllAutoFixableQuickFix ( documentFixes : FailureMap , fileName : string ) : ts_module . CodeFixAction {
274
- const allReplacements = getNonOverlappingReplacements ( Array . from ( documentFixes . values ( ) ) ) ;
272
+ private getFixAllAutoFixableQuickFix ( documentFixes : ProblemMap , fileName : string ) : ts_module . CodeFixAction {
273
+ const allReplacements = getNonOverlappingReplacements ( Array . from ( documentFixes . values ( ) ) . filter ( x => x . fixable ) . map ( x => x . failure ) ) ;
275
274
return {
276
275
description : `Fix all auto-fixable tslint failures` ,
277
276
fixName : '' ,
@@ -286,28 +285,28 @@ export class TSLintPlugin {
286
285
return this . project . getLanguageService ( ) . getProgram ( ) ! ;
287
286
}
288
287
289
- private makeDiagnostic ( problem : tslint . RuleFailure , file : ts . SourceFile ) : ts . Diagnostic {
290
- const message = ( problem . getRuleName ( ) !== null )
291
- ? `${ problem . getFailure ( ) } (${ problem . getRuleName ( ) } )`
292
- : `${ problem . getFailure ( ) } ` ;
288
+ private makeDiagnostic ( failure : tslint . RuleFailure , file : ts . SourceFile ) : ts . Diagnostic {
289
+ const message = ( failure . getRuleName ( ) !== null )
290
+ ? `${ failure . getFailure ( ) } (${ failure . getRuleName ( ) } )`
291
+ : `${ failure . getFailure ( ) } ` ;
293
292
294
- const category = this . getDiagnosticCategory ( problem ) ;
293
+ const category = this . getDiagnosticCategory ( failure ) ;
295
294
296
295
return {
297
296
file,
298
- start : problem . getStartPosition ( ) . getPosition ( ) ,
299
- length : problem . getEndPosition ( ) . getPosition ( ) - problem . getStartPosition ( ) . getPosition ( ) ,
297
+ start : failure . getStartPosition ( ) . getPosition ( ) ,
298
+ length : failure . getEndPosition ( ) . getPosition ( ) - failure . getStartPosition ( ) . getPosition ( ) ,
300
299
messageText : message ,
301
300
category,
302
301
source : TSLINT_ERROR_SOURCE ,
303
302
code : TSLINT_ERROR_CODE ,
304
303
} ;
305
304
}
306
305
307
- private getDiagnosticCategory ( problem : tslint . RuleFailure ) : ts . DiagnosticCategory {
306
+ private getDiagnosticCategory ( failure : tslint . RuleFailure ) : ts . DiagnosticCategory {
308
307
if ( this . configurationManager . config . alwaysShowRuleFailuresAsWarnings === true ) {
309
308
return this . ts . DiagnosticCategory . Warning ;
310
- } else if ( problem . getRuleSeverity && problem . getRuleSeverity ( ) === 'error' ) {
309
+ } else if ( failure . getRuleSeverity && failure . getRuleSeverity ( ) === 'error' ) {
311
310
// tslint5 supports to assign severities to rules
312
311
return this . ts . DiagnosticCategory . Error ;
313
312
}
@@ -339,8 +338,8 @@ function convertReplacementToTextChange(repl: tslint.Replacement): ts_module.Tex
339
338
} ;
340
339
}
341
340
342
- function problemToFileTextChange ( problem : tslint . RuleFailure , fileName : string ) : ts_module . FileTextChanges {
343
- const fix = problem . getFix ( ) ;
341
+ function failureToFileTextChange ( failure : tslint . RuleFailure , fileName : string ) : ts_module . FileTextChanges {
342
+ const fix = failure . getFix ( ) ;
344
343
const replacements : tslint . Replacement [ ] = getReplacements ( fix ) ;
345
344
346
345
return {
0 commit comments