From ff7ef4a25a4f41cb210fd2ed652752e7fad00520 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 12 Apr 2018 09:05:30 -0700 Subject: [PATCH] Add fixName property to CodeFixAction (#23350) --- src/server/client.ts | 3 ++- src/server/protocol.ts | 2 ++ src/server/session.ts | 21 +++++++------------ src/services/codeFixProvider.ts | 12 +++++------ .../addMissingInvocationForDecorator.ts | 2 +- .../codefixes/annotateWithTypeFromJSDoc.ts | 2 +- .../codefixes/convertFunctionToEs6Class.ts | 2 +- src/services/codefixes/convertToEs6Module.ts | 2 +- ...correctQualifiedNameToIndexedAccessType.ts | 2 +- .../codefixes/disableJsDiagnostics.ts | 4 +++- src/services/codefixes/fixAddMissingMember.ts | 9 ++++---- .../codefixes/fixAwaitInSyncFunction.ts | 2 +- src/services/codefixes/fixCannotFindModule.ts | 2 +- ...sDoesntImplementInheritedAbstractMember.ts | 2 +- .../fixClassIncorrectlyImplementsInterface.ts | 2 +- .../fixClassSuperMustPrecedeThisAccess.ts | 2 +- .../fixConstructorForDerivedNeedSuperCall.ts | 2 +- .../fixExtendsInterfaceBecomesImplements.ts | 2 +- .../fixForgottenThisPropertyAccess.ts | 2 +- .../codefixes/fixInvalidImportSyntax.ts | 6 ++++-- src/services/codefixes/fixJSDocTypes.ts | 2 +- src/services/codefixes/fixSpelling.ts | 2 +- .../codefixes/fixStrictClassInitialization.ts | 7 ++++--- src/services/codefixes/fixUnusedIdentifier.ts | 7 ++++--- src/services/codefixes/importFixes.ts | 2 +- src/services/codefixes/inferFromUsage.ts | 2 +- src/services/codefixes/useDefaultImport.ts | 2 +- src/services/types.ts | 2 ++ .../reference/api/tsserverlibrary.d.ts | 5 +++++ tests/baselines/reference/api/typescript.d.ts | 2 ++ 30 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/server/client.ts b/src/server/client.ts index 87bb2e93414..095d58d825d 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -558,7 +558,8 @@ namespace ts.server { const request = this.processRequest(CommandNames.GetCodeFixes, args); const response = this.processResponse(request); - return response.body.map(({ description, changes, fixId, fixAllDescription }) => ({ description, changes: this.convertChanges(changes, file), fixId, fixAllDescription })); + return response.body.map(({ fixName, description, changes, commands, fixId, fixAllDescription }) => + ({ fixName, description, changes: this.convertChanges(changes, file), commands: commands as CodeActionCommand[], fixId, fixAllDescription })); } getCombinedCodeFix = notImplemented; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index e9df92e0f38..7a258a904c2 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1698,6 +1698,8 @@ namespace ts.server.protocol { } export interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ + fixName: string; /** * If present, one may call 'getCombinedCodeFix' with this fixId. * This may be omitted to indicate that the code fix can't be applied in a group. diff --git a/src/server/session.ts b/src/server/session.ts index 5f7cd27cf86..c838d20e15a 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1668,7 +1668,7 @@ namespace ts.server { } } - private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { + private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { if (args.errorCodes.length === 0) { return undefined; } @@ -1678,15 +1678,7 @@ namespace ts.server { const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo); const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, this.getFormatOptions(file), this.getPreferences(file)); - if (!codeActions) { - return undefined; - } - if (simplifiedResult) { - return codeActions.map(codeAction => this.mapCodeAction(project, codeAction)); - } - else { - return codeActions; - } + return simplifiedResult ? codeActions.map(codeAction => this.mapCodeFixAction(project, codeAction)) : codeActions; } private getCombinedCodeFix({ scope, fixId }: protocol.GetCombinedCodeFixRequestArgs, simplifiedResult: boolean): protocol.CombinedCodeActions | CombinedCodeActions { @@ -1734,9 +1726,12 @@ namespace ts.server { return { startPosition, endPosition }; } - private mapCodeAction(project: Project, { description, changes: unmappedChanges, commands, fixId, fixAllDescription }: CodeFixAction): protocol.CodeFixAction { - const changes = unmappedChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName)))); - return { description, changes, commands, fixId, fixAllDescription }; + private mapCodeAction(project: Project, { description, changes, commands }: CodeAction): protocol.CodeAction { + return { description, changes: this.mapTextChangesToCodeEdits(project, changes), commands }; + } + + private mapCodeFixAction(project: Project, { fixName, description, changes, commands, fixId, fixAllDescription }: CodeFixAction): protocol.CodeFixAction { + return { fixName, description, changes: this.mapTextChangesToCodeEdits(project, changes), commands, fixId, fixAllDescription }; } private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray): protocol.FileCodeEdits[] { diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 291f8fd1d66..5fc8df3744c 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -34,16 +34,16 @@ namespace ts { : getLocaleSpecificMessage(diag); } - export function createCodeFixActionNoFixId(changes: FileTextChanges[], description: DiagnosticAndArguments) { - return createCodeFixActionWorker(diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); + export function createCodeFixActionNoFixId(fixName: string, changes: FileTextChanges[], description: DiagnosticAndArguments) { + return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); } - export function createCodeFixAction(changes: FileTextChanges[], description: DiagnosticAndArguments, fixId: {}, fixAllDescription: DiagnosticAndArguments, command?: CodeActionCommand): CodeFixAction { - return createCodeFixActionWorker(diagnosticToString(description), changes, fixId, diagnosticToString(fixAllDescription), command); + export function createCodeFixAction(fixName: string, changes: FileTextChanges[], description: DiagnosticAndArguments, fixId: {}, fixAllDescription: DiagnosticAndArguments, command?: CodeActionCommand): CodeFixAction { + return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, diagnosticToString(fixAllDescription), command); } - function createCodeFixActionWorker(description: string, changes: FileTextChanges[], fixId?: {}, fixAllDescription?: string, command?: CodeActionCommand): CodeFixAction { - return { description, changes, fixId, fixAllDescription, commands: command ? [command] : undefined }; + function createCodeFixActionWorker(fixName: string, description: string, changes: FileTextChanges[], fixId?: {}, fixAllDescription?: string, command?: CodeActionCommand): CodeFixAction { + return { fixName, description, changes, fixId, fixAllDescription, commands: command ? [command] : undefined }; } export function registerCodeFix(reg: CodeFixRegistration) { diff --git a/src/services/codefixes/addMissingInvocationForDecorator.ts b/src/services/codefixes/addMissingInvocationForDecorator.ts index 7b8a7d05fe7..ead64f9a2ca 100644 --- a/src/services/codefixes/addMissingInvocationForDecorator.ts +++ b/src/services/codefixes/addMissingInvocationForDecorator.ts @@ -6,7 +6,7 @@ namespace ts.codefix { errorCodes, getCodeActions: (context) => { const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start)); - return [createCodeFixAction(changes, Diagnostics.Call_decorator_expression, fixId, Diagnostics.Add_to_all_uncalled_decorators)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Call_decorator_expression, fixId, Diagnostics.Add_to_all_uncalled_decorators)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file!, diag.start!)), diff --git a/src/services/codefixes/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts index c8a3977eb3b..5b809452677 100644 --- a/src/services/codefixes/annotateWithTypeFromJSDoc.ts +++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts @@ -8,7 +8,7 @@ namespace ts.codefix { const decl = getDeclaration(context.sourceFile, context.span.start); if (!decl) return; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, decl)); - return [createCodeFixAction(changes, Diagnostics.Annotate_with_type_from_JSDoc, fixId, Diagnostics.Annotate_everything_with_types_from_JSDoc)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Annotate_with_type_from_JSDoc, fixId, Diagnostics.Annotate_everything_with_types_from_JSDoc)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index bb260463831..bf20aeda72b 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -6,7 +6,7 @@ namespace ts.codefix { errorCodes, getCodeActions(context: CodeFixContext) { const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, context.span.start, context.program.getTypeChecker())); - return [createCodeFixAction(changes, Diagnostics.Convert_function_to_an_ES2015_class, fixId, Diagnostics.Convert_all_constructor_functions_to_classes)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Convert_function_to_an_ES2015_class, fixId, Diagnostics.Convert_all_constructor_functions_to_classes)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file!, err.start, context.program.getTypeChecker())), diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index b8c78d57827..67aaa60f186 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -13,7 +13,7 @@ namespace ts.codefix { } }); // No support for fix-all since this applies to the whole file at once anyway. - return [createCodeFixActionNoFixId(changes, Diagnostics.Convert_to_ES6_module)]; + return [createCodeFixActionNoFixId("convertToEs6Module", changes, Diagnostics.Convert_to_ES6_module)]; }, }); diff --git a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts index f47b65aad90..54fe1823863 100644 --- a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts +++ b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts @@ -9,7 +9,7 @@ namespace ts.codefix { if (!qualifiedName) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, qualifiedName)); const newText = `${qualifiedName.left.text}["${qualifiedName.right.text}"]`; - return [createCodeFixAction(changes, [Diagnostics.Rewrite_as_the_indexed_access_type_0, newText], fixId, Diagnostics.Rewrite_all_as_indexed_access_types)]; + return [createCodeFixAction(fixId, changes, [Diagnostics.Rewrite_as_the_indexed_access_type_0, newText], fixId, Diagnostics.Rewrite_all_as_indexed_access_types)]; }, fixIds: [fixId], getAllCodeActions: (context) => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index c53c35c5f81..b5d3059dd42 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -1,5 +1,6 @@ /* @internal */ namespace ts.codefix { + const fixName = "disableJsDiagnostics"; const fixId = "disableJsDiagnostics"; const errorCodes = mapDefined(Object.keys(Diagnostics) as ReadonlyArray, key => { const diag = Diagnostics[key]; @@ -18,6 +19,7 @@ namespace ts.codefix { const fixes: CodeFixAction[] = [ // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file. createCodeFixActionNoFixId( + fixName, [createFileTextChanges(sourceFile.fileName, [ createTextChange(sourceFile.checkJsDirective ? createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end) @@ -27,7 +29,7 @@ namespace ts.codefix { ]; if (textChanges.isValidLocationToAddComment(sourceFile, span.start)) { - fixes.unshift(createCodeFixAction(textChanges.ChangeTracker.with(context, t => makeChange(t, sourceFile, span.start)), Diagnostics.Ignore_this_error_message, fixId, Diagnostics.Add_ts_ignore_to_all_error_messages)); + fixes.unshift(createCodeFixAction(fixName, textChanges.ChangeTracker.with(context, t => makeChange(t, sourceFile, span.start)), Diagnostics.Ignore_this_error_message, fixId, Diagnostics.Add_ts_ignore_to_all_error_messages)); } return fixes; diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 9a3b4854351..940201d7008 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -1,5 +1,6 @@ /* @internal */ namespace ts.codefix { + const fixName = "addMissingMember"; const errorCodes = [ Diagnostics.Property_0_does_not_exist_on_type_1.code, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code, @@ -75,7 +76,7 @@ namespace ts.codefix { function getActionsForAddMissingMemberInJavaScriptFile(context: CodeFixContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, makeStatic: boolean): CodeFixAction | undefined { const changes = textChanges.ChangeTracker.with(context, t => addMissingMemberInJs(t, classDeclarationSourceFile, classDeclaration, tokenName, makeStatic)); return changes.length === 0 ? undefined - : createCodeFixAction(changes, [makeStatic ? Diagnostics.Initialize_static_property_0 : Diagnostics.Initialize_property_0_in_the_constructor, tokenName], fixId, Diagnostics.Add_all_missing_members); + : createCodeFixAction(fixName, changes, [makeStatic ? Diagnostics.Initialize_static_property_0 : Diagnostics.Initialize_property_0_in_the_constructor, tokenName], fixId, Diagnostics.Add_all_missing_members); } function addMissingMemberInJs(changeTracker: textChanges.ChangeTracker, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, makeStatic: boolean): void { @@ -120,7 +121,7 @@ namespace ts.codefix { function createAddPropertyDeclarationAction(context: CodeFixContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, makeStatic: boolean, tokenName: string, typeNode: TypeNode): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => addPropertyDeclaration(t, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic)); - return createCodeFixAction(changes, [makeStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0, tokenName], fixId, Diagnostics.Add_all_missing_members); + return createCodeFixAction(fixName, changes, [makeStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0, tokenName], fixId, Diagnostics.Add_all_missing_members); } function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, typeNode: TypeNode, makeStatic: boolean): void { @@ -153,7 +154,7 @@ namespace ts.codefix { const changes = textChanges.ChangeTracker.with(context, t => t.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, indexSignature)); // No fixId here because code-fix-all currently only works on adding individual named properties. - return createCodeFixActionNoFixId(changes, [Diagnostics.Add_index_signature_for_property_0, tokenName]); + return createCodeFixActionNoFixId(fixName, changes, [Diagnostics.Add_index_signature_for_property_0, tokenName]); } function getActionForMethodDeclaration( @@ -167,7 +168,7 @@ namespace ts.codefix { preferences: UserPreferences, ): CodeFixAction | undefined { const changes = textChanges.ChangeTracker.with(context, t => addMethodDeclaration(t, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs, preferences)); - return createCodeFixAction(changes, [makeStatic ? Diagnostics.Declare_static_method_0 : Diagnostics.Declare_method_0, token.text], fixId, Diagnostics.Add_all_missing_members); + return createCodeFixAction(fixName, changes, [makeStatic ? Diagnostics.Declare_static_method_0 : Diagnostics.Declare_method_0, token.text], fixId, Diagnostics.Add_all_missing_members); } function addMethodDeclaration( diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index 804910e9a22..fd00498573c 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -12,7 +12,7 @@ namespace ts.codefix { const nodes = getNodes(sourceFile, span.start); if (!nodes) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, nodes)); - return [createCodeFixAction(changes, Diagnostics.Add_async_modifier_to_containing_function, fixId, Diagnostics.Add_all_missing_async_modifiers)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Add_async_modifier_to_containing_function, fixId, Diagnostics.Add_all_missing_async_modifiers)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts index 89f7a3f7793..9699cd3ceb4 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -8,7 +8,7 @@ namespace ts.codefix { const { host, sourceFile, span: { start } } = context; const packageName = getTypesPackageNameToInstall(host, sourceFile, start); return packageName === undefined ? [] - : [createCodeFixAction(/*changes*/ [], [Diagnostics.Install_0, packageName], fixId, Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; + : [createCodeFixAction(fixId, /*changes*/ [], [Diagnostics.Install_0, packageName], fixId, Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (_, diag, commands) => { diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index 3a1443c04bb..a931f849cb2 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -11,7 +11,7 @@ namespace ts.codefix { const { program, sourceFile, span } = context; const changes = textChanges.ChangeTracker.with(context, t => addMissingMembers(getClass(sourceFile, span.start), sourceFile, program.getTypeChecker(), t, context.preferences)); - return changes.length === 0 ? undefined : [createCodeFixAction(changes, Diagnostics.Implement_inherited_abstract_class, fixId, Diagnostics.Implement_all_inherited_abstract_classes)]; + return changes.length === 0 ? undefined : [createCodeFixAction(fixId, changes, Diagnostics.Implement_inherited_abstract_class, fixId, Diagnostics.Implement_all_inherited_abstract_classes)]; }, fixIds: [fixId], getAllCodeActions: context => { diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 91815edb775..4e0b5745149 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -11,7 +11,7 @@ namespace ts.codefix { const checker = program.getTypeChecker(); return mapDefined(getClassImplementsHeritageClauseElements(classDeclaration), implementedTypeNode => { const changes = textChanges.ChangeTracker.with(context, t => addMissingDeclarations(checker, implementedTypeNode, sourceFile, classDeclaration, t, context.preferences)); - return changes.length === 0 ? undefined : createCodeFixAction(changes, [Diagnostics.Implement_interface_0, implementedTypeNode.getText(sourceFile)], fixId, Diagnostics.Implement_all_unimplemented_interfaces); + return changes.length === 0 ? undefined : createCodeFixAction(fixId, changes, [Diagnostics.Implement_interface_0, implementedTypeNode.getText(sourceFile)], fixId, Diagnostics.Implement_all_unimplemented_interfaces); }); }, fixIds: [fixId], diff --git a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts index d9c98747286..af38b8e9025 100644 --- a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts +++ b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts @@ -10,7 +10,7 @@ namespace ts.codefix { if (!nodes) return undefined; const { constructor, superCall } = nodes; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, constructor, superCall)); - return [createCodeFixAction(changes, Diagnostics.Make_super_call_the_first_statement_in_the_constructor, fixId, Diagnostics.Make_all_super_calls_the_first_statement_in_their_constructor)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Make_super_call_the_first_statement_in_the_constructor, fixId, Diagnostics.Make_all_super_calls_the_first_statement_in_their_constructor)]; }, fixIds: [fixId], getAllCodeActions(context) { diff --git a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts index 31aa4fcedae..2aed263ee83 100644 --- a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts +++ b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts @@ -8,7 +8,7 @@ namespace ts.codefix { const { sourceFile, span } = context; const ctr = getNode(sourceFile, span.start); const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, ctr)); - return [createCodeFixAction(changes, Diagnostics.Add_missing_super_call, fixId, Diagnostics.Add_all_missing_super_calls)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_super_call, fixId, Diagnostics.Add_all_missing_super_calls)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => diff --git a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts index 381a8228c0d..c3f406b8475 100644 --- a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts +++ b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts @@ -10,7 +10,7 @@ namespace ts.codefix { if (!nodes) return undefined; const { extendsToken, heritageClauses } = nodes; const changes = textChanges.ChangeTracker.with(context, t => doChanges(t, sourceFile, extendsToken, heritageClauses)); - return [createCodeFixAction(changes, Diagnostics.Change_extends_to_implements, fixId, Diagnostics.Change_all_extended_interfaces_to_implements)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Change_extends_to_implements, fixId, Diagnostics.Change_all_extended_interfaces_to_implements)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/codefixes/fixForgottenThisPropertyAccess.ts b/src/services/codefixes/fixForgottenThisPropertyAccess.ts index 2cf7e2143a3..b26e4c7cdca 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -11,7 +11,7 @@ namespace ts.codefix { return undefined; } const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, token)); - return [createCodeFixAction(changes, Diagnostics.Add_this_to_unresolved_variable, fixId, Diagnostics.Add_this_to_all_unresolved_variables_matching_a_member_name)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Add_this_to_unresolved_variable, fixId, Diagnostics.Add_this_to_all_unresolved_variables_matching_a_member_name)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/codefixes/fixInvalidImportSyntax.ts b/src/services/codefixes/fixInvalidImportSyntax.ts index 84bd9867c70..50bf41360bc 100644 --- a/src/services/codefixes/fixInvalidImportSyntax.ts +++ b/src/services/codefixes/fixInvalidImportSyntax.ts @@ -1,5 +1,7 @@ /* @internal */ namespace ts.codefix { + const fixName = "invalidImportSyntax"; + registerCodeFix({ errorCodes: [Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime.code], getCodeActions: getActionsForInvalidImport @@ -43,7 +45,7 @@ namespace ts.codefix { function createAction(context: CodeFixContext, sourceFile: SourceFile, node: Node, replacement: Node): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, node, replacement)); - return createCodeFixActionNoFixId(changes, [Diagnostics.Replace_import_with_0, changes[0].textChanges[0].newText]); + return createCodeFixActionNoFixId("invalidImportSyntax", changes, [Diagnostics.Replace_import_with_0, changes[0].textChanges[0].newText]); } registerCodeFix({ @@ -72,7 +74,7 @@ namespace ts.codefix { addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport)); } const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, createPropertyAccess(expr, "default"), {})); - fixes.push(createCodeFixActionNoFixId(changes, Diagnostics.Use_synthetic_default_member)); + fixes.push(createCodeFixActionNoFixId(fixName, changes, Diagnostics.Use_synthetic_default_member)); return fixes; } } diff --git a/src/services/codefixes/fixJSDocTypes.ts b/src/services/codefixes/fixJSDocTypes.ts index 848666b67f0..1919b0742f0 100644 --- a/src/services/codefixes/fixJSDocTypes.ts +++ b/src/services/codefixes/fixJSDocTypes.ts @@ -22,7 +22,7 @@ namespace ts.codefix { function fix(type: Type, fixId: string, fixAllDescription: DiagnosticMessage): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, typeNode, type, checker)); - return createCodeFixAction(changes, [Diagnostics.Change_0_to_1, original, checker.typeToString(type)], fixId, fixAllDescription); + return createCodeFixAction("jdocTypes", changes, [Diagnostics.Change_0_to_1, original, checker.typeToString(type)], fixId, fixAllDescription); } }, fixIds: [fixIdPlain, fixIdNullable], diff --git a/src/services/codefixes/fixSpelling.ts b/src/services/codefixes/fixSpelling.ts index 59f5e64f212..252b08b356a 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -15,7 +15,7 @@ namespace ts.codefix { const { node, suggestion } = info; const { target } = context.host.getCompilationSettings(); const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestion, target)); - return [createCodeFixAction(changes, [Diagnostics.Change_spelling_to_0, suggestion], fixId, Diagnostics.Fix_all_detected_spelling_errors)]; + return [createCodeFixAction("spelling", changes, [Diagnostics.Change_spelling_to_0, suggestion], fixId, Diagnostics.Fix_all_detected_spelling_errors)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/codefixes/fixStrictClassInitialization.ts b/src/services/codefixes/fixStrictClassInitialization.ts index 69a69a8c3c8..8d4e457662f 100644 --- a/src/services/codefixes/fixStrictClassInitialization.ts +++ b/src/services/codefixes/fixStrictClassInitialization.ts @@ -1,5 +1,6 @@ /* @internal */ namespace ts.codefix { + const fixName = "strictClassInitialization"; const fixIdAddDefiniteAssignmentAssertions = "addMissingPropertyDefiniteAssignmentAssertions"; const fixIdAddUndefinedType = "addMissingPropertyUndefinedType"; const fixIdAddInitializer = "addMissingPropertyInitializer"; @@ -53,7 +54,7 @@ namespace ts.codefix { function getActionForAddMissingDefiniteAssignmentAssertion (context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => addDefiniteAssignmentAssertion(t, context.sourceFile, propertyDeclaration)); - return createCodeFixAction(changes, [Diagnostics.Add_definite_assignment_assertion_to_property_0, propertyDeclaration.getText()], fixIdAddDefiniteAssignmentAssertions, Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties); + return createCodeFixAction(fixName, changes, [Diagnostics.Add_definite_assignment_assertion_to_property_0, propertyDeclaration.getText()], fixIdAddDefiniteAssignmentAssertions, Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties); } function addDefiniteAssignmentAssertion(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void { @@ -71,7 +72,7 @@ namespace ts.codefix { function getActionForAddMissingUndefinedType (context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => addUndefinedType(t, context.sourceFile, propertyDeclaration)); - return createCodeFixAction(changes, [Diagnostics.Add_undefined_type_to_property_0, propertyDeclaration.name.getText()], fixIdAddUndefinedType, Diagnostics.Add_undefined_type_to_all_uninitialized_properties); + return createCodeFixAction(fixName, changes, [Diagnostics.Add_undefined_type_to_property_0, propertyDeclaration.name.getText()], fixIdAddUndefinedType, Diagnostics.Add_undefined_type_to_all_uninitialized_properties); } function addUndefinedType(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void { @@ -86,7 +87,7 @@ namespace ts.codefix { if (!initializer) return undefined; const changes = textChanges.ChangeTracker.with(context, t => addInitializer(t, context.sourceFile, propertyDeclaration, initializer)); - return createCodeFixAction(changes, [Diagnostics.Add_initializer_to_property_0, propertyDeclaration.name.getText()], fixIdAddInitializer, Diagnostics.Add_initializers_to_all_uninitialized_properties); + return createCodeFixAction(fixName, changes, [Diagnostics.Add_initializer_to_property_0, propertyDeclaration.name.getText()], fixIdAddInitializer, Diagnostics.Add_initializers_to_all_uninitialized_properties); } function addInitializer (changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration, initializer: Expression): void { diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index 1fe0107dafb..a37435cd109 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -1,5 +1,6 @@ /* @internal */ namespace ts.codefix { + const fixName = "unusedIdentifier"; const fixIdPrefix = "unusedIdentifier_prefix"; const fixIdDelete = "unusedIdentifier_delete"; const errorCodes = [ @@ -14,7 +15,7 @@ namespace ts.codefix { const importDecl = tryGetFullImport(sourceFile, context.span.start); if (importDecl) { const changes = textChanges.ChangeTracker.with(context, t => t.deleteNode(sourceFile, importDecl)); - return [createCodeFixAction(changes, [Diagnostics.Remove_import_from_0, showModuleSpecifier(importDecl)], fixIdDelete, Diagnostics.Delete_all_unused_declarations)]; + return [createCodeFixAction(fixName, changes, [Diagnostics.Remove_import_from_0, showModuleSpecifier(importDecl)], fixIdDelete, Diagnostics.Delete_all_unused_declarations)]; } const token = getToken(sourceFile, textSpanEnd(context.span)); @@ -22,12 +23,12 @@ namespace ts.codefix { const deletion = textChanges.ChangeTracker.with(context, t => tryDeleteDeclaration(t, sourceFile, token)); if (deletion.length) { - result.push(createCodeFixAction(deletion, [Diagnostics.Remove_declaration_for_Colon_0, token.getText(sourceFile)], fixIdDelete, Diagnostics.Delete_all_unused_declarations)); + result.push(createCodeFixAction(fixName, deletion, [Diagnostics.Remove_declaration_for_Colon_0, token.getText(sourceFile)], fixIdDelete, Diagnostics.Delete_all_unused_declarations)); } const prefix = textChanges.ChangeTracker.with(context, t => tryPrefixDeclaration(t, errorCode, sourceFile, token)); if (prefix.length) { - result.push(createCodeFixAction(prefix, [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, Diagnostics.Prefix_all_unused_declarations_with_where_possible)); + result.push(createCodeFixAction(fixName, prefix, [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, Diagnostics.Prefix_all_unused_declarations_with_where_possible)); } return result; diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index a8993ce0b1d..ddd530e4246 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -35,7 +35,7 @@ namespace ts.codefix { function createCodeAction(descriptionDiagnostic: DiagnosticMessage, diagnosticArgs: [string, string], changes: FileTextChanges[]): CodeFixAction { // TODO: GH#20315 - return createCodeFixActionNoFixId(changes, [descriptionDiagnostic, ...diagnosticArgs] as [DiagnosticMessage, string, string]); + return createCodeFixActionNoFixId("import", changes, [descriptionDiagnostic, ...diagnosticArgs] as [DiagnosticMessage, string, string]); } function convertToImportCodeFixContext(context: CodeFixContext, symbolToken: Node, symbolName: string): ImportCodeFixContext { diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 99556fc84de..8b36d3e5d51 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -34,7 +34,7 @@ namespace ts.codefix { let declaration!: Declaration; const changes = textChanges.ChangeTracker.with(context, changes => { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken); }); return changes.length === 0 ? undefined - : [createCodeFixAction(changes, [getDiagnostic(errorCode, token), getNameOfDeclaration(declaration).getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)]; + : [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), getNameOfDeclaration(declaration).getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)]; }, fixIds: [fixId], getAllCodeActions(context) { diff --git a/src/services/codefixes/useDefaultImport.ts b/src/services/codefixes/useDefaultImport.ts index 7a6a0acfc30..632cfc97e00 100644 --- a/src/services/codefixes/useDefaultImport.ts +++ b/src/services/codefixes/useDefaultImport.ts @@ -9,7 +9,7 @@ namespace ts.codefix { const info = getInfo(sourceFile, start); if (!info) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); - return [createCodeFixAction(changes, Diagnostics.Convert_to_default_import, fixId, Diagnostics.Convert_all_to_default_imports)]; + return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_default_import, fixId, Diagnostics.Convert_all_to_default_imports)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { diff --git a/src/services/types.ts b/src/services/types.ts index c5b58bab04d..01b8b5ad4d4 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -446,6 +446,8 @@ namespace ts { } export interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ + fixName: string; /** * If present, one may call 'getCombinedCodeFix' with this fixId. * This may be omitted to indicate that the code fix can't be applied in a group. diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index daf984fd5aa..2343e68de9c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4273,6 +4273,8 @@ declare namespace ts { commands?: CodeActionCommand[]; } interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ + fixName: string; /** * If present, one may call 'getCombinedCodeFix' with this fixId. * This may be omitted to indicate that the code fix can't be applied in a group. @@ -6347,6 +6349,8 @@ declare namespace ts.server.protocol { commands?: ReadonlyArray<{}>; } interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ + fixName: string; /** * If present, one may call 'getCombinedCodeFix' with this fixId. * This may be omitted to indicate that the code fix can't be applied in a group. @@ -7425,6 +7429,7 @@ declare namespace ts.server { private applyCodeActionCommand; private getStartAndEndPosition; private mapCodeAction; + private mapCodeFixAction; private mapTextChangesToCodeEdits; private mapTextChangesToCodeEditsUsingScriptinfo; private convertTextChangeToCodeEdit; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2fbac7e9f3b..378949d5b5b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4526,6 +4526,8 @@ declare namespace ts { commands?: CodeActionCommand[]; } interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ + fixName: string; /** * If present, one may call 'getCombinedCodeFix' with this fixId. * This may be omitted to indicate that the code fix can't be applied in a group.