fixJSDocTypes: Use ChangeTracker (#22391)

This commit is contained in:
Andy
2018-03-08 07:52:03 -08:00
committed by GitHub
parent 2676786e7f
commit 0605424852
2 changed files with 10 additions and 23 deletions

View File

@@ -88,13 +88,6 @@ namespace ts {
return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands);
}
export function codeFixAllWithTextChanges(context: CodeFixAllContext, errorCodes: number[], use: (changes: Push<TextChange>, 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)) {

View File

@@ -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