From 6dca538ad0d377cb00d1dacddeaf703320518240 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Jan 2020 14:20:39 -0800 Subject: [PATCH 1/2] 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. --- src/services/textChanges.ts | 11 +++++++---- .../fourslash/codeFixClassImplementInterfaceNoBody.ts | 10 ++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/codeFixClassImplementInterfaceNoBody.ts diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 07a75d884d9a2..9b293946cb998 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -493,7 +493,8 @@ namespace ts.textChanges { if (getMembersOrProperties(cls).length === 0) { if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) { // For `class C {\n}`, don't add the trailing "\n" - const shouldSuffix = (positionsAreOnSameLine as any)(...getClassOrObjectBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any' + const [open, close] = getClassOrObjectBraceEnds(cls, sourceFile) + const shouldSuffix = open && close && positionsAreOnSameLine(open, close, sourceFile); return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") }; } else { @@ -726,7 +727,7 @@ namespace ts.textChanges { this.classesWithNodesInsertedAtStart.forEach(({ node, sourceFile }) => { const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile); // For `class C { }` remove the whitespace inside the braces. - if (positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) { + if (openBraceEnd && closeBraceEnd && positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) { this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1)); } }); @@ -783,8 +784,10 @@ namespace ts.textChanges { return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } - function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number, number] { - return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end]; + function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number | undefined, number | undefined] { + const open = findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile); + const close = findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile); + return [open?.end, close?.end]; } function getMembersOrProperties(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): NodeArray { return isObjectLiteralExpression(cls) ? cls.properties : cls.members; diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceNoBody.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceNoBody.ts new file mode 100644 index 0000000000000..78e6ebb83e0d9 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceNoBody.ts @@ -0,0 +1,10 @@ +/// + +//// interface I { +//// m(): void +//// } +//// class C/*c*/ implements I + +verify.errorExistsBeforeMarker("c") +goTo.marker("c") +verify.codeFixAvailable([{ "description": "Implement interface 'I'" }]) From 44de861e4b03cc9dc21a1ab5b903deb69f080aad Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Jan 2020 15:07:50 -0800 Subject: [PATCH 2/2] fix semicolon lint --- src/services/textChanges.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 9b293946cb998..69cffe9b8f5f0 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -493,7 +493,7 @@ namespace ts.textChanges { if (getMembersOrProperties(cls).length === 0) { if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) { // For `class C {\n}`, don't add the trailing "\n" - const [open, close] = getClassOrObjectBraceEnds(cls, sourceFile) + const [open, close] = getClassOrObjectBraceEnds(cls, sourceFile); const shouldSuffix = open && close && positionsAreOnSameLine(open, close, sourceFile); return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") }; }