Skip to content

Commit 7c4e755

Browse files
author
Andy
authored
When applying // @ts-ignore fix as a group, apply to a line only once. (#21413)
* When applying `// @ts-ignore` fix as a group, apply to a line only once. * Rename line to lineNumber
1 parent f2060c2 commit 7c4e755

File tree

2 files changed

+30
-26
lines changed

2 files changed

+30
-26
lines changed
Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* @internal */
22
namespace ts.codefix {
33
const fixId = "disableJsDiagnostics";
4-
const errorCodes = mapDefined(Object.keys(Diagnostics), key => {
5-
const diag = (Diagnostics as MapLike<DiagnosticMessage>)[key];
4+
const errorCodes = mapDefined(Object.keys(Diagnostics) as ReadonlyArray<keyof typeof Diagnostics>, key => {
5+
const diag = Diagnostics[key];
66
return diag.category === DiagnosticCategory.Error ? diag.code : undefined;
77
});
88

@@ -19,7 +19,7 @@ namespace ts.codefix {
1919

2020
return [{
2121
description: getLocaleSpecificMessage(Diagnostics.Ignore_this_error_message),
22-
changes: [createFileTextChanges(sourceFile.fileName, [getIgnoreCommentLocationForLocation(sourceFile, span.start, newLineCharacter)])],
22+
changes: [createFileTextChanges(sourceFile.fileName, [getIgnoreCommentLocationForLocation(sourceFile, span.start, newLineCharacter).change])],
2323
fixId,
2424
},
2525
{
@@ -35,17 +35,23 @@ namespace ts.codefix {
3535
fixId: undefined,
3636
}];
3737
},
38-
fixIds: [fixId], // No point applying as a group, doing it once will fix all errors
39-
getAllCodeActions: context => codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
40-
if (err.start !== undefined) {
41-
changes.push(getIgnoreCommentLocationForLocation(err.file!, err.start, getNewLineOrDefaultFromHost(context.host, context.formatContext.options)));
42-
}
43-
}),
38+
fixIds: [fixId],
39+
getAllCodeActions: context => {
40+
const seenLines = createMap<true>(); // Only need to add `// @ts-ignore` for a line once.
41+
return codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
42+
if (err.start !== undefined) {
43+
const { lineNumber, change } = getIgnoreCommentLocationForLocation(err.file!, err.start, getNewLineOrDefaultFromHost(context.host, context.formatContext.options));
44+
if (addToSeen(seenLines, lineNumber)) {
45+
changes.push(change);
46+
}
47+
}
48+
});
49+
},
4450
});
4551

46-
function getIgnoreCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string): TextChange {
47-
const { line } = getLineAndCharacterOfPosition(sourceFile, position);
48-
const lineStartPosition = getStartPositionOfLine(line, sourceFile);
52+
function getIgnoreCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string): { lineNumber: number, change: TextChange } {
53+
const { line: lineNumber } = getLineAndCharacterOfPosition(sourceFile, position);
54+
const lineStartPosition = getStartPositionOfLine(lineNumber, sourceFile);
4955
const startPosition = getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition);
5056

5157
// First try to see if we can put the '// @ts-ignore' on the previous line.
@@ -54,19 +60,17 @@ namespace ts.codefix {
5460
// if so, we do not want to separate the node from its comment if we can.
5561
if (!isInComment(sourceFile, startPosition) && !isInString(sourceFile, startPosition) && !isInTemplateString(sourceFile, startPosition)) {
5662
const token = getTouchingToken(sourceFile, startPosition, /*includeJsDocComment*/ false);
57-
const tokenLeadingCommnets = getLeadingCommentRangesOfNode(token, sourceFile);
58-
if (!tokenLeadingCommnets || !tokenLeadingCommnets.length || tokenLeadingCommnets[0].pos >= startPosition) {
59-
return {
60-
span: { start: startPosition, length: 0 },
61-
newText: `// @ts-ignore${newLineCharacter}`
62-
};
63+
const tokenLeadingComments = getLeadingCommentRangesOfNode(token, sourceFile);
64+
if (!tokenLeadingComments || !tokenLeadingComments.length || tokenLeadingComments[0].pos >= startPosition) {
65+
return { lineNumber, change: createTextChange(startPosition, 0, `// @ts-ignore${newLineCharacter}`) };
6366
}
6467
}
6568

6669
// If all fails, add an extra new line immediately before the error span.
67-
return {
68-
span: { start: position, length: 0 },
69-
newText: `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}`
70-
};
70+
return { lineNumber, change: createTextChange(position, 0, `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}`) };
71+
}
72+
73+
function createTextChange(start: number, length: number, newText: string): TextChange {
74+
return { span: { start, length }, newText };
7175
}
7276
}

tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile_all.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
// @Filename: a.js
88
////let x = "";
9-
////x = 1;
10-
////x = true;
9+
////x = 1; x = true;
10+
////x = [];
1111

1212
verify.codeFixAll({
1313
fixId: "disableJsDiagnostics",
1414
newFileContent:
1515
`let x = "";
1616
// @ts-ignore
17-
x = 1;
17+
x = 1; x = true;
1818
// @ts-ignore
19-
x = true;`,
19+
x = [];`,
2020
});

0 commit comments

Comments
 (0)