diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 0bfab4eedfcdc..cc503ada0ffb6 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -88,13 +88,6 @@ namespace ts { return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands); } - export function codeFixAllWithTextChanges(context: CodeFixAllContext, errorCodes: number[], use: (changes: Push, error: Diagnostic) => void): CombinedCodeActions { - const changes: TextChange[] = []; - eachDiagnostic(context, errorCodes, diag => use(changes, diag)); - changes.sort((a, b) => b.span.start - a.span.start); - return createCombinedCodeActions([createFileTextChanges(context.sourceFile.fileName, changes)]); - } - function eachDiagnostic({ program, sourceFile }: CodeFixAllContext, errorCodes: number[], cb: (diag: Diagnostic) => void): void { for (const diag of program.getSemanticDiagnostics(sourceFile).concat(computeSuggestionDiagnostics(sourceFile, program))) { if (contains(errorCodes, diag.code)) { diff --git a/src/services/codefixes/fixJSDocTypes.ts b/src/services/codefixes/fixJSDocTypes.ts index 3158e90ce965a..344d840cc2e88 100644 --- a/src/services/codefixes/fixJSDocTypes.ts +++ b/src/services/codefixes/fixJSDocTypes.ts @@ -21,42 +21,36 @@ namespace ts.codefix { return actions; function fix(type: Type, fixId: string): CodeFixAction { - const newText = typeString(type, checker); - return { - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Change_0_to_1), [original, newText]), - changes: [createFileTextChanges(sourceFile.fileName, [createChange(typeNode, sourceFile, newText)])], - fixId, - }; + const newText = checker.typeToString(type); + const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Change_0_to_1), [original, newText]); + const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, typeNode, type, checker)); + return { description, changes, fixId }; } }, fixIds: [fixIdPlain, fixIdNullable], getAllCodeActions(context) { const { fixId, program, sourceFile } = context; const checker = program.getTypeChecker(); - return codeFixAllWithTextChanges(context, errorCodes, (changes, err) => { + return codeFixAll(context, errorCodes, (changes, err) => { const info = getInfo(err.file, err.start!, checker); if (!info) return; const { typeNode, type } = info; const fixedType = typeNode.kind === SyntaxKind.JSDocNullableType && fixId === fixIdNullable ? checker.getNullableType(type, TypeFlags.Undefined) : type; - changes.push(createChange(typeNode, sourceFile, typeString(fixedType, checker))); + doChange(changes, sourceFile, typeNode, fixedType, checker); }); } }); + function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, oldTypeNode: TypeNode, newType: Type, checker: TypeChecker): void { + changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode)); + } + function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode, type: Type } { const decl = findAncestor(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer); const typeNode = decl && decl.type; return typeNode && { typeNode, type: checker.getTypeFromTypeNode(typeNode) }; } - function createChange(declaration: TypeNode, sourceFile: SourceFile, newText: string): TextChange { - return createTextChange(createTextSpanFromNode(declaration, sourceFile), newText); - } - - function typeString(type: Type, checker: TypeChecker): string { - return checker.typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTruncation); - } - // TODO: GH#19856 Node & { type: TypeNode } type TypeContainer = | AsExpression | CallSignatureDeclaration | ConstructSignatureDeclaration | FunctionDeclaration