diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index a9f531c901cc9..989df3269c6f8 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -5517,7 +5517,7 @@
"category": "Message",
"code": 95100
},
- "Wrap invalid character in an expression container": {
+ "Convert all invalid characters to HTML entity code": {
"category": "Message",
"code": 95101
},
@@ -5545,6 +5545,14 @@
"category": "Message",
"code": 95107
},
+ "Wrap invalid character in an expression container": {
+ "category": "Message",
+ "code": 95108
+ },
+ "Wrap all invalid characters in an expression container": {
+ "category": "Message",
+ "code": 95109
+ },
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
"category": "Error",
diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts
index e50477358eda3..ab88aa97a3d7e 100644
--- a/src/services/codeFixProvider.ts
+++ b/src/services/codeFixProvider.ts
@@ -90,6 +90,10 @@ namespace ts.codefix {
}
function getDiagnostics({ program, sourceFile, cancellationToken }: CodeFixContextBase) {
- return program.getSemanticDiagnostics(sourceFile, cancellationToken).concat(computeSuggestionDiagnostics(sourceFile, program, cancellationToken));
+ return [
+ ...program.getSemanticDiagnostics(sourceFile, cancellationToken),
+ ...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
+ ...computeSuggestionDiagnostics(sourceFile, program, cancellationToken)
+ ];
}
}
diff --git a/src/services/codefixes/fixInvalidJsxCharacters.ts b/src/services/codefixes/fixInvalidJsxCharacters.ts
index f765c3558dc76..67ce26efd6519 100644
--- a/src/services/codefixes/fixInvalidJsxCharacters.ts
+++ b/src/services/codefixes/fixInvalidJsxCharacters.ts
@@ -1,42 +1,48 @@
/* @internal */
namespace ts.codefix {
- const fixIdHtmlEntity = "invalidJsxCharactersConvertToHtmlEntity";
- const fixIdExpression = "invalidJsxCharactersConvertToExpression";
+ const fixIdExpression = "fixInvalidJsxCharacters_expression";
+ const fixIdHtmlEntity = "fixInvalidJsxCharacters_htmlEntity";
- const errorCodes = [Diagnostics.Unexpected_token_Did_you_mean_or_gt.code, Diagnostics.Unexpected_token_Did_you_mean_or_rbrace.code];
+ const errorCodes = [
+ Diagnostics.Unexpected_token_Did_you_mean_or_gt.code,
+ Diagnostics.Unexpected_token_Did_you_mean_or_rbrace.code
+ ];
registerCodeFix({
errorCodes,
- getCodeActions: context => {
- const { sourceFile, span } = context;
- const changeToExpression = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, span.start, /* useHtmlEntity */ false));
- const changeToHtmlEntity = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, span.start, /* useHtmlEntity */ true));
+ fixIds: [fixIdExpression, fixIdHtmlEntity],
+ getCodeActions(context) {
+ const { sourceFile, preferences, span } = context;
+ const changeToExpression = textChanges.ChangeTracker.with(context, t => doChange(t, preferences, sourceFile, span.start, /* useHtmlEntity */ false));
+ const changeToHtmlEntity = textChanges.ChangeTracker.with(context, t => doChange(t, preferences, sourceFile, span.start, /* useHtmlEntity */ true));
+
return [
- createCodeFixActionWithoutFixAll(fixIdExpression, changeToExpression, Diagnostics.Wrap_invalid_character_in_an_expression_container),
- createCodeFixAction(fixIdHtmlEntity, changeToHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code, fixIdHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code),
+ createCodeFixAction(fixIdExpression, changeToExpression, Diagnostics.Wrap_invalid_character_in_an_expression_container, fixIdExpression, Diagnostics.Wrap_all_invalid_characters_in_an_expression_container),
+ createCodeFixAction(fixIdHtmlEntity, changeToHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code, fixIdHtmlEntity, Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code)
];
},
- fixIds: [fixIdExpression, fixIdHtmlEntity],
+ getAllCodeActions(context) {
+ return codeFixAll(context, errorCodes, (changes, diagnostic) => doChange(changes, context.preferences, diagnostic.file, diagnostic.start, context.fixId === fixIdHtmlEntity));
+ }
});
const htmlEntity = {
">": ">",
"}": "}",
};
+
function isValidCharacter(character: string): character is keyof typeof htmlEntity {
return hasProperty(htmlEntity, character);
}
- function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number, useHtmlEntity: boolean) {
+ function doChange(changes: textChanges.ChangeTracker, preferences: UserPreferences, sourceFile: SourceFile, start: number, useHtmlEntity: boolean) {
const character = sourceFile.getText()[start];
// sanity check
if (!isValidCharacter(character)) {
return;
}
- const replacement = useHtmlEntity
- ? htmlEntity[character]
- : `{'${character}'}`;
+ const replacement = useHtmlEntity ? htmlEntity[character] : `{${quote(character, preferences)}}`;
changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 1 }, replacement);
}
}
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters1.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters1.ts
index 60495c8b8142a..7610e6cc78bdf 100644
--- a/tests/cases/fourslash/codeFixInvalidJsxCharacters1.ts
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters1.ts
@@ -3,17 +3,16 @@
// @jsx: react
// @filename: main.tsx
-//// let x1 =
}
;
+//// let foo = }
;
verify.codeFix({
- description: "Wrap invalid character in an expression container",
- newFileContent:
-`let x1 = {'}'}
;`,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {"}"}
;`,
index: 0,
});
+
verify.codeFix({
- description: "Convert invalid character to its html entity code",
- newFileContent:
-`let x1 = }
;`,
+ description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
+ newFileContent: `let foo = }
;`,
index: 1,
});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters10.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters10.ts
new file mode 100644
index 0000000000000..63ad5a9b15743
--- /dev/null
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters10.ts
@@ -0,0 +1,13 @@
+///
+
+// @jsx: react
+// @filename: main.tsx
+
+//// let foo = >
;
+
+verify.codeFix({
+ index: 0,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {">"}
;`,
+ preferences: { quotePreference: "double" }
+});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters2.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters2.ts
index ef8747d48652d..db8a0b14be270 100644
--- a/tests/cases/fourslash/codeFixInvalidJsxCharacters2.ts
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters2.ts
@@ -3,17 +3,16 @@
// @jsx: react
// @filename: main.tsx
-//// let x2 = >
;
+//// let foo = >
;
verify.codeFix({
- description: "Wrap invalid character in an expression container",
- newFileContent:
-`let x2 = {'>'}
;`,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {">"}
;`,
index: 0,
});
+
verify.codeFix({
- description: "Convert invalid character to its html entity code",
- newFileContent:
-`let x2 = >
;`,
+ description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
+ newFileContent: `let foo = >
;`,
index: 1,
});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters3.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters3.ts
index d9d97c0bec282..9684ddb697b1b 100644
--- a/tests/cases/fourslash/codeFixInvalidJsxCharacters3.ts
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters3.ts
@@ -3,17 +3,16 @@
// @jsx: react
// @filename: main.tsx
-//// let x3 = {"foo"}}
;
+//// let foo = {"foo"}}
;
verify.codeFix({
- description: "Wrap invalid character in an expression container",
- newFileContent:
-`let x3 = {"foo"}{'}'}
;`,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {"foo"}{"}"}
;`,
index: 0,
});
+
verify.codeFix({
- description: "Convert invalid character to its html entity code",
- newFileContent:
-`let x3 = {"foo"}}
;`,
+ description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
+ newFileContent: `let foo = {"foo"}}
;`,
index: 1,
});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters4.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters4.ts
index cbb0e01d29377..517e830f6e822 100644
--- a/tests/cases/fourslash/codeFixInvalidJsxCharacters4.ts
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters4.ts
@@ -3,17 +3,16 @@
// @jsx: react
// @filename: main.tsx
-//// let x4 = {"foo"}>
;
+//// let foo = {"foo"}>
;
verify.codeFix({
- description: "Wrap invalid character in an expression container",
- newFileContent:
-`let x4 = {"foo"}{'>'}
;`,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {"foo"}{">"}
;`,
index: 0,
});
+
verify.codeFix({
- description: "Convert invalid character to its html entity code",
- newFileContent:
-`let x4 = {"foo"}>
;`,
+ description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
+ newFileContent: `let foo = {"foo"}>
;`,
index: 1,
});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters5.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters5.ts
index abc3e7ba16e1c..e660bb0126366 100644
--- a/tests/cases/fourslash/codeFixInvalidJsxCharacters5.ts
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters5.ts
@@ -3,17 +3,16 @@
// @jsx: react
// @filename: main.tsx
-//// let x5 = }{"foo"}
;
+//// let foo = }{"foo"}
;
verify.codeFix({
- description: "Wrap invalid character in an expression container",
- newFileContent:
-`let x5 = {'}'}{"foo"}
;`,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {"}"}{"foo"}
;`,
index: 0,
});
+
verify.codeFix({
- description: "Convert invalid character to its html entity code",
- newFileContent:
-`let x5 = }{"foo"}
;`,
+ description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
+ newFileContent: `let foo = }{"foo"}
;`,
index: 1,
});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters6.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters6.ts
index f29e9ed2b8b2c..c34c9acd33c70 100644
--- a/tests/cases/fourslash/codeFixInvalidJsxCharacters6.ts
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters6.ts
@@ -3,17 +3,16 @@
// @jsx: react
// @filename: main.tsx
-//// let x6 = >{"foo"}
;
+//// let foo = >{"foo"}
;
verify.codeFix({
- description: "Wrap invalid character in an expression container",
- newFileContent:
-`let x6 = {'>'}{"foo"}
;`,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {">"}{"foo"}
;`,
index: 0,
});
+
verify.codeFix({
- description: "Convert invalid character to its html entity code",
- newFileContent:
-`let x6 = >{"foo"}
;`,
+ description: ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code.message,
+ newFileContent: `let foo = >{"foo"}
;`,
index: 1,
});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters7.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters7.ts
new file mode 100644
index 0000000000000..a2d3c0d09d884
--- /dev/null
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters7.ts
@@ -0,0 +1,17 @@
+///
+
+// @jsx: react
+// @filename: main.tsx
+
+////let a = >{"foo"}
;
+////let b = >{"foo"}
;
+////let c = >{"foo"}
;
+
+verify.codeFixAll({
+ fixId: "fixInvalidJsxCharacters_htmlEntity",
+ fixAllDescription: ts.Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code.message,
+ newFileContent:
+`let a = >{"foo"}
;
+let b = >{"foo"}
;
+let c = >{"foo"}
;`
+});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters8.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters8.ts
new file mode 100644
index 0000000000000..511a96e9e3c96
--- /dev/null
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters8.ts
@@ -0,0 +1,17 @@
+///
+
+// @jsx: react
+// @filename: main.tsx
+
+////let a = >{"foo"}
;
+////let b = >{"foo"}
;
+////let c = >{"foo"}
;
+
+verify.codeFixAll({
+ fixId: "fixInvalidJsxCharacters_expression",
+ fixAllDescription: ts.Diagnostics.Wrap_all_invalid_characters_in_an_expression_container.message,
+ newFileContent:
+`let a = {">"}{"foo"}
;
+let b = {">"}{"foo"}
;
+let c = {">"}{"foo"}
;`
+});
diff --git a/tests/cases/fourslash/codeFixInvalidJsxCharacters9.ts b/tests/cases/fourslash/codeFixInvalidJsxCharacters9.ts
new file mode 100644
index 0000000000000..58179e84f43c3
--- /dev/null
+++ b/tests/cases/fourslash/codeFixInvalidJsxCharacters9.ts
@@ -0,0 +1,13 @@
+///
+
+// @jsx: react
+// @filename: main.tsx
+
+//// let foo = >
;
+
+verify.codeFix({
+ index: 0,
+ description: ts.Diagnostics.Wrap_invalid_character_in_an_expression_container.message,
+ newFileContent: `let foo = {'>'}
;`,
+ preferences: { quotePreference: "single" }
+});