• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts.codefix {
3    const fixId = "forgottenThisPropertyAccess";
4    const didYouMeanStaticMemberCode = Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code;
5    const errorCodes = [
6        Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code,
7        Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.code,
8        didYouMeanStaticMemberCode,
9    ];
10    registerCodeFix({
11        errorCodes,
12        getCodeActions(context) {
13            const { sourceFile } = context;
14            const info = getInfo(sourceFile, context.span.start, context.errorCode);
15            if (!info) {
16                return undefined;
17            }
18            const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info));
19            return [createCodeFixAction(fixId, changes, [Diagnostics.Add_0_to_unresolved_variable, info.className || "this"], fixId, Diagnostics.Add_qualifier_to_all_unresolved_variables_matching_a_member_name)];
20        },
21        fixIds: [fixId],
22        getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
23            const info = getInfo(diag.file, diag.start, diag.code);
24            if (info) doChange(changes, context.sourceFile, info);
25        }),
26    });
27
28    interface Info {
29        readonly node: Identifier | PrivateIdentifier;
30        readonly className: string | undefined;
31    }
32
33    function getInfo(sourceFile: SourceFile, pos: number, diagCode: number): Info | undefined {
34        const node = getTokenAtPosition(sourceFile, pos);
35        if (isIdentifier(node) || isPrivateIdentifier(node)) {
36            return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node)!.name!.text : undefined };
37        }
38    }
39
40    function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void {
41        // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper
42        suppressLeadingAndTrailingTrivia(node);
43        changes.replaceNode(sourceFile, node, factory.createPropertyAccessExpression(className ? factory.createIdentifier(className) : factory.createThis(), node));
44    }
45}
46