Skip to content

Commit 8ed7491

Browse files
committed
feat(37409): add fix all quick fix to fixInvalidJsxCharacters
1 parent 9120497 commit 8ed7491

13 files changed

+130
-58
lines changed

Diff for: src/compiler/diagnosticMessages.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -5513,10 +5513,18 @@
55135513
"category": "Message",
55145514
"code": 95100
55155515
},
5516-
"Wrap invalid character in an expression container": {
5516+
"Convert all invalid characters to HTML entity code": {
55175517
"category": "Message",
55185518
"code": 95101
55195519
},
5520+
"Wrap invalid character in an expression container": {
5521+
"category": "Message",
5522+
"code": 95102
5523+
},
5524+
"Wrap all invalid characters in an expression container": {
5525+
"category": "Message",
5526+
"code": 95103
5527+
},
55205528

55215529
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
55225530
"category": "Error",

Diff for: src/services/codeFixProvider.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ namespace ts.codefix {
9090
}
9191

9292
function getDiagnostics({ program, sourceFile, cancellationToken }: CodeFixContextBase) {
93-
return program.getSemanticDiagnostics(sourceFile, cancellationToken).concat(computeSuggestionDiagnostics(sourceFile, program, cancellationToken));
93+
return [
94+
...program.getSemanticDiagnostics(sourceFile, cancellationToken),
95+
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
96+
...computeSuggestionDiagnostics(sourceFile, program, cancellationToken)
97+
];
9498
}
9599
}

Diff for: src/services/codefixes/fixInvalidJsxCharacters.ts

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,48 @@
11
/* @internal */
22
namespace ts.codefix {
3-
const fixIdHtmlEntity = "invalidJsxCharactersConvertToHtmlEntity";
4-
const fixIdExpression = "invalidJsxCharactersConvertToExpression";
3+
const fixIdExpression = "fixInvalidJsxCharacters_expression";
4+
const fixIdHtmlEntity = "fixInvalidJsxCharacters_htmlEntity";
55

6-
const errorCodes = [Diagnostics.Unexpected_token_Did_you_mean_or_gt.code, Diagnostics.Unexpected_token_Did_you_mean_or_rbrace.code];
6+
const errorCodes = [
7+
Diagnostics.Unexpected_token_Did_you_mean_or_gt.code,
8+
Diagnostics.Unexpected_token_Did_you_mean_or_rbrace.code
9+
];
710

811
registerCodeFix({
912
errorCodes,
10-
getCodeActions: context => {
11-
const { sourceFile, span } = context;
12-
const changeToExpression = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, span.start, /* useHtmlEntity */ false));
13-
const changeToHtmlEntity = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, span.start, /* useHtmlEntity */ true));
13+
fixIds: [fixIdExpression, fixIdHtmlEntity],
14+
getCodeActions(context) {
15+
const { sourceFile, preferences, span } = context;
16+
const changeToExpression = textChanges.ChangeTracker.with(context, t => doChange(t, preferences, sourceFile, span.start, /* useHtmlEntity */ false));
17+
const changeToHtmlEntity = textChanges.ChangeTracker.with(context, t => doChange(t, preferences, sourceFile, span.start, /* useHtmlEntity */ true));
18+
1419
return [
15-
createCodeFixActionWithoutFixAll(fixIdExpression, changeToExpression, Diagnostics.Wrap_invalid_character_in_an_expression_container),
16-
createCodeFixAction(fixIdHtmlEntity, changeToHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code, fixIdHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code),
20+
createCodeFixAction(fixIdExpression, changeToExpression, Diagnostics.Wrap_invalid_character_in_an_expression_container, fixIdExpression, Diagnostics.Wrap_all_invalid_characters_in_an_expression_container),
21+
createCodeFixAction(fixIdHtmlEntity, changeToHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code, fixIdHtmlEntity, Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code)
1722
];
1823
},
19-
fixIds: [fixIdExpression, fixIdHtmlEntity],
24+
getAllCodeActions(context) {
25+
return codeFixAll(context, errorCodes, (changes, diagnostic) => doChange(changes, context.preferences, diagnostic.file, diagnostic.start, context.fixId === fixIdHtmlEntity));
26+
}
2027
});
2128

2229
const htmlEntity = {
2330
">": ">",
2431
"}": "}",
2532
};
33+
2634
function isValidCharacter(character: string): character is keyof typeof htmlEntity {
2735
return hasProperty(htmlEntity, character);
2836
}
2937

30-
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number, useHtmlEntity: boolean) {
38+
function doChange(changes: textChanges.ChangeTracker, preferences: UserPreferences, sourceFile: SourceFile, start: number, useHtmlEntity: boolean) {
3139
const character = sourceFile.getText()[start];
3240
// sanity check
3341
if (!isValidCharacter(character)) {
3442
return;
3543
}
3644

37-
const replacement = useHtmlEntity
38-
? htmlEntity[character]
39-
: `{'${character}'}`;
45+
const replacement = useHtmlEntity ? htmlEntity[character] : `{${quote(character, preferences)}}`;
4046
changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 1 }, replacement);
4147
}
4248
}

Diff for: tests/cases/fourslash/codeFixInvalidJsxCharacters1.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// @jsx: react
44
// @filename: main.tsx
55

6-
//// let x1 = <div>}</div>;
6+
//// let foo = <div>}</div>;
77

88
verify.codeFix({
9-
description: "Wrap invalid character in an expression container",
10-
newFileContent:
11-
`let x1 = <div>{'}'}</div>;`,
9+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
10+
newFileContent: `let foo = <div>{"}"}</div>;`,
1211
index: 0,
1312
});
13+
1414
verify.codeFix({
15-
description: "Convert invalid character to its html entity code",
16-
newFileContent:
17-
`let x1 = <div>&rbrace;</div>;`,
15+
description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
16+
newFileContent: `let foo = <div>&rbrace;</div>;`,
1817
index: 1,
1918
});
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @jsx: react
4+
// @filename: main.tsx
5+
6+
//// let foo = <div>></div>;
7+
8+
verify.codeFix({
9+
index: 0,
10+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
11+
newFileContent: `let foo = <div>{">"}</div>;`,
12+
preferences: { quotePreference: "double" }
13+
});

Diff for: tests/cases/fourslash/codeFixInvalidJsxCharacters2.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// @jsx: react
44
// @filename: main.tsx
55

6-
//// let x2 = <div>></div>;
6+
//// let foo = <div>></div>;
77

88
verify.codeFix({
9-
description: "Wrap invalid character in an expression container",
10-
newFileContent:
11-
`let x2 = <div>{'>'}</div>;`,
9+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
10+
newFileContent: `let foo = <div>{">"}</div>;`,
1211
index: 0,
1312
});
13+
1414
verify.codeFix({
15-
description: "Convert invalid character to its html entity code",
16-
newFileContent:
17-
`let x2 = <div>&gt;</div>;`,
15+
description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
16+
newFileContent: `let foo = <div>&gt;</div>;`,
1817
index: 1,
1918
});

Diff for: tests/cases/fourslash/codeFixInvalidJsxCharacters3.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// @jsx: react
44
// @filename: main.tsx
55

6-
//// let x3 = <div>{"foo"}}</div>;
6+
//// let foo = <div>{"foo"}}</div>;
77

88
verify.codeFix({
9-
description: "Wrap invalid character in an expression container",
10-
newFileContent:
11-
`let x3 = <div>{"foo"}{'}'}</div>;`,
9+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
10+
newFileContent: `let foo = <div>{"foo"}{"}"}</div>;`,
1211
index: 0,
1312
});
13+
1414
verify.codeFix({
15-
description: "Convert invalid character to its html entity code",
16-
newFileContent:
17-
`let x3 = <div>{"foo"}&rbrace;</div>;`,
15+
description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
16+
newFileContent: `let foo = <div>{"foo"}&rbrace;</div>;`,
1817
index: 1,
1918
});

Diff for: tests/cases/fourslash/codeFixInvalidJsxCharacters4.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// @jsx: react
44
// @filename: main.tsx
55

6-
//// let x4 = <div>{"foo"}></div>;
6+
//// let foo = <div>{"foo"}></div>;
77

88
verify.codeFix({
9-
description: "Wrap invalid character in an expression container",
10-
newFileContent:
11-
`let x4 = <div>{"foo"}{'>'}</div>;`,
9+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
10+
newFileContent: `let foo = <div>{"foo"}{">"}</div>;`,
1211
index: 0,
1312
});
13+
1414
verify.codeFix({
15-
description: "Convert invalid character to its html entity code",
16-
newFileContent:
17-
`let x4 = <div>{"foo"}&gt;</div>;`,
15+
description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
16+
newFileContent: `let foo = <div>{"foo"}&gt;</div>;`,
1817
index: 1,
1918
});

Diff for: tests/cases/fourslash/codeFixInvalidJsxCharacters5.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// @jsx: react
44
// @filename: main.tsx
55

6-
//// let x5 = <div>}{"foo"}</div>;
6+
//// let foo = <div>}{"foo"}</div>;
77

88
verify.codeFix({
9-
description: "Wrap invalid character in an expression container",
10-
newFileContent:
11-
`let x5 = <div>{'}'}{"foo"}</div>;`,
9+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
10+
newFileContent: `let foo = <div>{"}"}{"foo"}</div>;`,
1211
index: 0,
1312
});
13+
1414
verify.codeFix({
15-
description: "Convert invalid character to its html entity code",
16-
newFileContent:
17-
`let x5 = <div>&rbrace;{"foo"}</div>;`,
15+
description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
16+
newFileContent: `let foo = <div>&rbrace;{"foo"}</div>;`,
1817
index: 1,
1918
});

Diff for: tests/cases/fourslash/codeFixInvalidJsxCharacters6.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// @jsx: react
44
// @filename: main.tsx
55

6-
//// let x6 = <div>>{"foo"}</div>;
6+
//// let foo = <div>>{"foo"}</div>;
77

88
verify.codeFix({
9-
description: "Wrap invalid character in an expression container",
10-
newFileContent:
11-
`let x6 = <div>{'>'}{"foo"}</div>;`,
9+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
10+
newFileContent: `let foo = <div>{">"}{"foo"}</div>;`,
1211
index: 0,
1312
});
13+
1414
verify.codeFix({
15-
description: "Convert invalid character to its html entity code",
16-
newFileContent:
17-
`let x6 = <div>&gt;{"foo"}</div>;`,
15+
description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
16+
newFileContent: `let foo = <div>&gt;{"foo"}</div>;`,
1817
index: 1,
1918
});
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @jsx: react
4+
// @filename: main.tsx
5+
6+
////let a = <div>>{"foo"}</div>;
7+
////let b = <div>>{"foo"}</div>;
8+
////let c = <div>>{"foo"}</div>;
9+
10+
verify.codeFixAll({
11+
fixId: "fixInvalidJsxCharacters_htmlEntity",
12+
fixAllDescription: ts.Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code.message,
13+
newFileContent:
14+
`let a = <div>&gt;{"foo"}</div>;
15+
let b = <div>&gt;{"foo"}</div>;
16+
let c = <div>&gt;{"foo"}</div>;`
17+
});
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @jsx: react
4+
// @filename: main.tsx
5+
6+
////let a = <div>>{"foo"}</div>;
7+
////let b = <div>>{"foo"}</div>;
8+
////let c = <div>>{"foo"}</div>;
9+
10+
verify.codeFixAll({
11+
fixId: "fixInvalidJsxCharacters_expression",
12+
fixAllDescription: ts.Diagnostics.Wrap_all_invalid_characters_in_an_expression_container.message,
13+
newFileContent:
14+
`let a = <div>{">"}{"foo"}</div>;
15+
let b = <div>{">"}{"foo"}</div>;
16+
let c = <div>{">"}{"foo"}</div>;`
17+
});
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @jsx: react
4+
// @filename: main.tsx
5+
6+
//// let foo = <div>></div>;
7+
8+
verify.codeFix({
9+
index: 0,
10+
description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
11+
newFileContent: `let foo = <div>{'>'}</div>;`,
12+
preferences: { quotePreference: "single" }
13+
});

0 commit comments

Comments
 (0)