• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts.codefix {
3    const fixId = "fixConvertConstToLet";
4    const errorCodes = [Diagnostics.Cannot_assign_to_0_because_it_is_a_constant.code];
5
6    registerCodeFix({
7        errorCodes,
8        getCodeActions: function getCodeActionsToConvertConstToLet(context) {
9            const { sourceFile, span, program } = context;
10            const info = getInfo(sourceFile, span.start, program);
11            if (info === undefined) return;
12
13            const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info.token));
14            return [createCodeFixActionMaybeFixAll(fixId, changes, Diagnostics.Convert_const_to_let, fixId, Diagnostics.Convert_all_const_to_let)];
15        },
16        getAllCodeActions: context => {
17            const { program } = context;
18            const seen = new Map<number, true>();
19
20            return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => {
21                eachDiagnostic(context, errorCodes, diag => {
22                    const info = getInfo(diag.file, diag.start, program);
23                    if (info) {
24                        if (addToSeen(seen, getSymbolId(info.symbol))) {
25                            return doChange(changes, diag.file, info.token);
26                        }
27                    }
28                    return undefined;
29                });
30            }));
31        },
32        fixIds: [fixId]
33    });
34
35    interface Info {
36        symbol: Symbol;
37        token: Token<SyntaxKind.ConstKeyword>;
38    }
39
40    function getInfo(sourceFile: SourceFile, pos: number, program: Program): Info | undefined {
41        const checker = program.getTypeChecker();
42        const symbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, pos));
43        if (symbol === undefined) return;
44
45        const declaration = tryCast(symbol?.valueDeclaration?.parent, isVariableDeclarationList);
46        if (declaration === undefined) return;
47
48        const constToken = findChildOfKind<Token<SyntaxKind.ConstKeyword>>(declaration, SyntaxKind.ConstKeyword, sourceFile);
49        if (constToken === undefined) return;
50
51        return { symbol, token: constToken };
52    }
53
54    function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Token<SyntaxKind.ConstKeyword>) {
55        changes.replaceNode(sourceFile, token, factory.createToken(SyntaxKind.LetKeyword));
56    }
57}
58