• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts.codefix {
3    const fixIdExpression = "fixInvalidJsxCharacters_expression";
4    const fixIdHtmlEntity = "fixInvalidJsxCharacters_htmlEntity";
5
6    const errorCodes = [
7        Diagnostics.Unexpected_token_Did_you_mean_or_gt.code,
8        Diagnostics.Unexpected_token_Did_you_mean_or_rbrace.code
9    ];
10
11    registerCodeFix({
12        errorCodes,
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
19            return [
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)
22            ];
23        },
24        getAllCodeActions(context) {
25            return codeFixAll(context, errorCodes, (changes, diagnostic) => doChange(changes, context.preferences, diagnostic.file, diagnostic.start, context.fixId === fixIdHtmlEntity));
26        }
27    });
28
29    const htmlEntity = {
30        ">": ">",
31        "}": "}",
32    };
33
34    function isValidCharacter(character: string): character is keyof typeof htmlEntity {
35        return hasProperty(htmlEntity, character);
36    }
37
38    function doChange(changes: textChanges.ChangeTracker, preferences: UserPreferences, sourceFile: SourceFile, start: number, useHtmlEntity: boolean) {
39        const character = sourceFile.getText()[start];
40        // sanity check
41        if (!isValidCharacter(character)) {
42            return;
43        }
44
45        const replacement = useHtmlEntity ? htmlEntity[character] : `{${quote(sourceFile, preferences, character)}}`;
46        changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 1 }, replacement);
47    }
48}
49