• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts.codefix {
3    const fixId = "fixIncorrectNamedTupleSyntax";
4    const errorCodes = [
5        Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type.code,
6        Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type.code
7    ];
8
9    registerCodeFix({
10        errorCodes,
11        getCodeActions: function getCodeActionsToFixIncorrectNamedTupleSyntax(context) {
12            const { sourceFile, span } = context;
13            const namedTupleMember = getNamedTupleMember(sourceFile, span.start);
14            const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, namedTupleMember));
15            return [createCodeFixAction(fixId, changes, Diagnostics.Move_labeled_tuple_element_modifiers_to_labels, fixId, Diagnostics.Move_labeled_tuple_element_modifiers_to_labels)];
16        },
17        fixIds: [fixId]
18    });
19
20    function getNamedTupleMember(sourceFile: SourceFile, pos: number) {
21        const token = getTokenAtPosition(sourceFile, pos);
22        return findAncestor(token, t => t.kind === SyntaxKind.NamedTupleMember) as NamedTupleMember | undefined;
23    }
24    function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, namedTupleMember?: NamedTupleMember) {
25        if (!namedTupleMember) {
26            return;
27        }
28        let unwrappedType = namedTupleMember.type;
29        let sawOptional = false;
30        let sawRest = false;
31        while (unwrappedType.kind === SyntaxKind.OptionalType || unwrappedType.kind === SyntaxKind.RestType || unwrappedType.kind === SyntaxKind.ParenthesizedType) {
32            if (unwrappedType.kind === SyntaxKind.OptionalType) {
33                sawOptional = true;
34            }
35            else if (unwrappedType.kind === SyntaxKind.RestType) {
36                sawRest = true;
37            }
38            unwrappedType = (unwrappedType as OptionalTypeNode | RestTypeNode | ParenthesizedTypeNode).type;
39        }
40        const updated = factory.updateNamedTupleMember(
41            namedTupleMember,
42            namedTupleMember.dotDotDotToken || (sawRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined),
43            namedTupleMember.name,
44            namedTupleMember.questionToken || (sawOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined),
45            unwrappedType
46        );
47        if (updated === namedTupleMember) {
48            return;
49        }
50        changes.replaceNode(sourceFile, namedTupleMember, updated);
51    }
52}
53