Merge pull request #20991 from amcasey/GH18794

Refine extends-to-implements code fix
This commit is contained in:
Andrew Casey 2018-01-05 17:52:22 -08:00 committed by GitHub
commit 1957dfef8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 7 deletions

View File

@ -27,11 +27,26 @@ namespace ts.codefix {
}
function doChanges(changes: textChanges.ChangeTracker, sourceFile: SourceFile, extendsToken: Node, heritageClauses: ReadonlyArray<HeritageClause>): void {
changes.replaceNode(sourceFile, extendsToken, createToken(SyntaxKind.ImplementsKeyword));
// We replace existing keywords with commas.
for (let i = 1; i < heritageClauses.length; i++) {
const keywordToken = heritageClauses[i].getFirstToken()!;
changes.replaceNode(sourceFile, keywordToken, createToken(SyntaxKind.CommaToken));
changes.replaceRange(sourceFile, { pos: extendsToken.getStart(), end: extendsToken.end }, createToken(SyntaxKind.ImplementsKeyword));
// If there is already an implements clause, replace the implements keyword with a comma.
if (heritageClauses.length === 2 &&
heritageClauses[0].token === SyntaxKind.ExtendsKeyword &&
heritageClauses[1].token === SyntaxKind.ImplementsKeyword) {
const implementsToken = heritageClauses[1].getFirstToken()!;
const implementsFullStart = implementsToken.getFullStart();
changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, createToken(SyntaxKind.CommaToken));
// Rough heuristic: delete trailing whitespace after keyword so that it's not excessive.
// (Trailing because leading might be indentation, which is more sensitive.)
const text = sourceFile.text;
let end = implementsToken.end;
while (end < text.length && ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) {
end++;
}
changes.deleteRange(sourceFile, { pos: implementsToken.getStart(), end });
}
}
}

View File

@ -8,5 +8,5 @@
verify.codeFix({
description: "Change 'extends' to 'implements'",
// TODO: GH#18794
newRangeContent: "abstract class A implements I1 , I2",
newRangeContent: "abstract class A implements I1, I2",
});

View File

@ -13,5 +13,5 @@
verify.codeFix({
description: "Change 'extends' to 'implements'",
// TODO: GH#18794
newRangeContent: "class A implements I1 , I2 { }",
newRangeContent: "class A implements I1, I2 { }",
});

View File

@ -0,0 +1,19 @@
/// <reference path='fourslash.ts' />
//// interface I1 { }
//// interface I2 { }
//// interface I3 { }
//// [|class MyClass /*A !*/ //B !
//// /*C !*/ extends /*D !*/ I1 /*E !*/ //F !
//// /*G !*/ implements /*H !*/ I2 /*I !*/, /*J !*/ I3 /*K !*/ //L !|]
//// {
//// }
verify.codeFix({
description: "Change 'extends' to 'implements'",
// TODO: GH#18794
newRangeContent: `class MyClass /*A !*/ //B !
/*C !*/ implements /*D !*/ I1, /*E !*/ //F !
/*G !*/ /*H !*/ I2 /*I !*/, /*J !*/ I3 /*K !*/ //L !`,
});