mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Throw syntax error for } and > in JSX text (#36636)
* Throw syntax error for `}` and `>` in JSX text Fixes #36341 * Add codefix for error
This commit is contained in:
@@ -1135,6 +1135,14 @@
|
||||
"category": "Error",
|
||||
"code": 1380
|
||||
},
|
||||
"Unexpected token. Did you mean `{'}'}` or `}`?": {
|
||||
"category": "Error",
|
||||
"code": 1381
|
||||
},
|
||||
"Unexpected token. Did you mean `{'>'}` or `>`?": {
|
||||
"category": "Error",
|
||||
"code": 1382
|
||||
},
|
||||
|
||||
"The types of '{0}' are incompatible between these types.": {
|
||||
"category": "Error",
|
||||
@@ -5457,6 +5465,14 @@
|
||||
"category": "Message",
|
||||
"code": 95099
|
||||
},
|
||||
"Convert invalid character to its html entity code": {
|
||||
"category": "Message",
|
||||
"code": 95100
|
||||
},
|
||||
"Wrap invalid character in an expression container": {
|
||||
"category": "Message",
|
||||
"code": 95101
|
||||
},
|
||||
|
||||
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -2156,6 +2156,12 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (char === CharacterCodes.greaterThan) {
|
||||
error(Diagnostics.Unexpected_token_Did_you_mean_or_gt, pos, 1);
|
||||
}
|
||||
if (char === CharacterCodes.closeBrace) {
|
||||
error(Diagnostics.Unexpected_token_Did_you_mean_or_rbrace, pos, 1);
|
||||
}
|
||||
|
||||
if (lastNonWhitespace > 0) lastNonWhitespace++;
|
||||
|
||||
|
||||
42
src/services/codefixes/fixInvalidJsxCharacters.ts
Normal file
42
src/services/codefixes/fixInvalidJsxCharacters.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
const fixIdHtmlEntity = "invalidJsxCharactersConvertToHtmlEntity";
|
||||
const fixIdExpression = "invalidJsxCharactersConvertToExpression";
|
||||
|
||||
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));
|
||||
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),
|
||||
];
|
||||
},
|
||||
fixIds: [fixIdExpression, 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) {
|
||||
const character = sourceFile.getText()[start];
|
||||
// sanity check
|
||||
if (!isValidCharacter(character)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const replacement = useHtmlEntity
|
||||
? htmlEntity[character]
|
||||
: `{'${character}'}`;
|
||||
changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 1 }, replacement);
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,7 @@
|
||||
"codefixes/fixModuleAndTargetOptions.ts",
|
||||
"codefixes/fixExtendsInterfaceBecomesImplements.ts",
|
||||
"codefixes/fixForgottenThisPropertyAccess.ts",
|
||||
"codefixes/fixInvalidJsxCharacters.ts",
|
||||
"codefixes/fixUnusedIdentifier.ts",
|
||||
"codefixes/fixUnreachableCode.ts",
|
||||
"codefixes/fixUnusedLabel.ts",
|
||||
|
||||
Reference in New Issue
Block a user