Skip to content

Commit 66b5c47

Browse files
authored
Fix crash in codefixes re: braces of class body (microsoft#36087)
* Fix crash in codefixes re: braces of class body Previously, the code that finds braces of a class body assumed they were always there. This is not always the case, so this code checks for that. * fix semicolon lint
1 parent 21316e5 commit 66b5c47

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

src/services/textChanges.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,8 @@ namespace ts.textChanges {
493493
if (getMembersOrProperties(cls).length === 0) {
494494
if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) {
495495
// For `class C {\n}`, don't add the trailing "\n"
496-
const shouldSuffix = (positionsAreOnSameLine as any)(...getClassOrObjectBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any'
496+
const [open, close] = getClassOrObjectBraceEnds(cls, sourceFile);
497+
const shouldSuffix = open && close && positionsAreOnSameLine(open, close, sourceFile);
497498
return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") };
498499
}
499500
else {
@@ -726,7 +727,7 @@ namespace ts.textChanges {
726727
this.classesWithNodesInsertedAtStart.forEach(({ node, sourceFile }) => {
727728
const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile);
728729
// For `class C { }` remove the whitespace inside the braces.
729-
if (positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) {
730+
if (openBraceEnd && closeBraceEnd && positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) {
730731
this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1));
731732
}
732733
});
@@ -783,8 +784,10 @@ namespace ts.textChanges {
783784
return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
784785
}
785786

786-
function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number, number] {
787-
return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end];
787+
function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number | undefined, number | undefined] {
788+
const open = findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile);
789+
const close = findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile);
790+
return [open?.end, close?.end];
788791
}
789792
function getMembersOrProperties(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): NodeArray<Node> {
790793
return isObjectLiteralExpression(cls) ? cls.properties : cls.members;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
//// interface I {
4+
//// m(): void
5+
//// }
6+
//// class C/*c*/ implements I
7+
8+
verify.errorExistsBeforeMarker("c")
9+
goTo.marker("c")
10+
verify.codeFixAvailable([{ "description": "Implement interface 'I'" }])

0 commit comments

Comments
 (0)