From a7c08e4691584e6d2fac55b3dccdd88936ecda6a Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 19 Apr 2018 15:39:44 -0700 Subject: [PATCH] Make code fix to add 'this.' work for statics (#23527) * Make code fix to add 'this.' work for statics * Add 'C.' instead of 'this.' * DanielRosenwasser code review --- src/compiler/diagnosticMessages.json | 4 +-- .../fixForgottenThisPropertyAccess.ts | 31 ++++++++++--------- .../codeFixForgottenThisPropertyAccess_all.ts | 2 +- ...deFixForgottenThisPropertyAccess_static.ts | 25 +++++++++++++++ 4 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 235788258af..a5119f7feb7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3914,7 +3914,7 @@ "category": "Message", "code": 90007 }, - "Add 'this.' to unresolved variable": { + "Add '{0}.' to unresolved variable": { "category": "Message", "code": 90008 }, @@ -4122,7 +4122,7 @@ "category": "Message", "code": 95036 }, - "Add 'this.' to all unresolved variables matching a member name": { + "Add qualifier to all unresolved variables matching a member name": { "category": "Message", "code": 95037 }, diff --git a/src/services/codefixes/fixForgottenThisPropertyAccess.ts b/src/services/codefixes/fixForgottenThisPropertyAccess.ts index b26e4c7cdca..31c6128d003 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -1,35 +1,38 @@ /* @internal */ namespace ts.codefix { const fixId = "forgottenThisPropertyAccess"; - const errorCodes = [Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code]; + const didYouMeanStaticMemberCode = Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code; + const errorCodes = [ + Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code, + didYouMeanStaticMemberCode, + ]; registerCodeFix({ errorCodes, getCodeActions(context) { const { sourceFile } = context; - const token = getNode(sourceFile, context.span.start); - if (!token) { + const info = getInfo(sourceFile, context.span.start, context.errorCode); + if (!info) { return undefined; } - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, token)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_this_to_unresolved_variable, fixId, Diagnostics.Add_this_to_all_unresolved_variables_matching_a_member_name)]; + const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); + 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)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - doChange(changes, context.sourceFile, getNode(diag.file, diag.start!)); + doChange(changes, context.sourceFile, getInfo(diag.file, diag.start!, diag.code)); }), }); - function getNode(sourceFile: SourceFile, pos: number): Identifier | undefined { + interface Info { readonly node: Identifier; readonly className: string | undefined; } + function getInfo(sourceFile: SourceFile, pos: number, diagCode: number): Info | undefined { const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); - return isIdentifier(node) ? node : undefined; + if (!isIdentifier(node)) return undefined; + return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node).name.text : undefined }; } - function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Identifier | undefined): void { - if (!token) { - return; - } + function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void { // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper - suppressLeadingAndTrailingTrivia(token); - changes.replaceNode(sourceFile, token, createPropertyAccess(createThis(), token)); + suppressLeadingAndTrailingTrivia(node); + changes.replaceNode(sourceFile, node, createPropertyAccess(className ? createIdentifier(className) : createThis(), node)); } } diff --git a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts index ab95f6b3355..65d44dd8fdb 100644 --- a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts +++ b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts @@ -10,7 +10,7 @@ verify.codeFixAll({ fixId: "forgottenThisPropertyAccess", - fixAllDescription: "Add 'this.' to all unresolved variables matching a member name", + fixAllDescription: "Add qualifier to all unresolved variables matching a member name", newFileContent: `class C { foo: number; diff --git a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts new file mode 100644 index 00000000000..cc6f8032a51 --- /dev/null +++ b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts @@ -0,0 +1,25 @@ +/// + +////class C { +//// static m() { m(); } +//// n() { m(); } +////} + +verify.codeFix({ + description: "Add 'C.' to unresolved variable", + index: 0, + newFileContent: +`class C { + static m() { C.m(); } + n() { m(); } +}` +}); + +verify.codeFix({ + description: "Add 'C.' to unresolved variable", + newFileContent: +`class C { + static m() { C.m(); } + n() { C.m(); } +}` +});