diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 0ddc304e2f9..d6db8cfd377 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -778,20 +778,29 @@ namespace ts.formatting { } function isSemicolonDeletionContext(context: FormattingContext): boolean { - const nextToken = isTrivia(context.nextTokenSpan.kind) - ? context.nextTokenParent.getChildAt(0) - : context.nextTokenSpan; - - const startLine = context.sourceFile.getLineAndCharacterOfPosition(context.currentTokenSpan.pos).line; - const endLine = context.sourceFile.getLineAndCharacterOfPosition(nextToken.pos).line; - if (startLine === endLine) { - return nextToken.kind === SyntaxKind.CloseBraceToken - || nextToken.kind === SyntaxKind.EndOfFileToken; + let nextTokenKind = context.nextTokenSpan.kind; + let nextTokenStart = context.nextTokenSpan.pos; + if (isTrivia(nextTokenKind)) { + const sourceFile = context.currentTokenParent.getSourceFile(); + const nextRealToken = context.nextTokenParent === context.currentTokenParent + ? findNextToken(context.currentTokenParent, sourceFile, sourceFile) + : context.nextTokenParent.getFirstToken(); + if (!nextRealToken) { + return true; + } + nextTokenKind = nextRealToken.kind; + nextTokenStart = nextRealToken.getStart(); } + const startLine = context.sourceFile.getLineAndCharacterOfPosition(context.currentTokenSpan.pos).line; + const endLine = context.sourceFile.getLineAndCharacterOfPosition(nextTokenStart).line; + if (startLine === endLine) { + return nextTokenKind === SyntaxKind.CloseBraceToken + || nextTokenKind === SyntaxKind.EndOfFileToken; + } - if (nextToken.kind === SyntaxKind.SemicolonClassElement || - nextToken.kind === SyntaxKind.SemicolonToken + if (nextTokenKind === SyntaxKind.SemicolonClassElement || + nextTokenKind === SyntaxKind.SemicolonToken ) { return false; } @@ -807,7 +816,7 @@ namespace ts.formatting { // } return !(isPropertySignature(context.currentTokenParent) && !context.currentTokenParent.type - && nextToken.kind === SyntaxKind.OpenParenToken); + && nextTokenKind === SyntaxKind.OpenParenToken); } if (isPropertyDeclaration(context.currentTokenParent)) { @@ -817,17 +826,17 @@ namespace ts.formatting { return context.currentTokenParent.kind !== SyntaxKind.ForStatement && context.currentTokenParent.kind !== SyntaxKind.EmptyStatement && context.currentTokenParent.kind !== SyntaxKind.SemicolonClassElement - && nextToken.kind !== SyntaxKind.OpenBracketToken - && nextToken.kind !== SyntaxKind.OpenParenToken - && nextToken.kind !== SyntaxKind.PlusToken - && nextToken.kind !== SyntaxKind.MinusToken - && nextToken.kind !== SyntaxKind.SlashToken - && nextToken.kind !== SyntaxKind.RegularExpressionLiteral - && nextToken.kind !== SyntaxKind.CommaToken - && nextToken.kind !== SyntaxKind.TemplateExpression - && nextToken.kind !== SyntaxKind.TemplateHead - && nextToken.kind !== SyntaxKind.NoSubstitutionTemplateLiteral - && nextToken.kind !== SyntaxKind.DotToken; + && nextTokenKind !== SyntaxKind.OpenBracketToken + && nextTokenKind !== SyntaxKind.OpenParenToken + && nextTokenKind !== SyntaxKind.PlusToken + && nextTokenKind !== SyntaxKind.MinusToken + && nextTokenKind !== SyntaxKind.SlashToken + && nextTokenKind !== SyntaxKind.RegularExpressionLiteral + && nextTokenKind !== SyntaxKind.CommaToken + && nextTokenKind !== SyntaxKind.TemplateExpression + && nextTokenKind !== SyntaxKind.TemplateHead + && nextTokenKind !== SyntaxKind.NoSubstitutionTemplateLiteral + && nextTokenKind !== SyntaxKind.DotToken; } function isSemicolonInsertionContext(context: FormattingContext): boolean { diff --git a/src/services/types.ts b/src/services/types.ts index 475594dfa5c..fa2cdc1c821 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -758,7 +758,7 @@ namespace ts { insertSpaceBeforeFunctionParenthesis: false, placeOpenBraceOnNewLineForFunctions: false, placeOpenBraceOnNewLineForControlBlocks: false, - insertTrailingSemicolon: false, + insertTrailingSemicolon: true, }; } diff --git a/tests/cases/fourslash/formatRemoveSemicolons2.ts b/tests/cases/fourslash/formatRemoveSemicolons2.ts index 1371b94151f..742a28a88d8 100644 --- a/tests/cases/fourslash/formatRemoveSemicolons2.ts +++ b/tests/cases/fourslash/formatRemoveSemicolons2.ts @@ -2,20 +2,26 @@ ////namespace ts { //// let x = 0; +//// // //// interface I { //// a: string; //// /** @internal */ //// b: string; //// } +//// let y = 0; // ////} +////let z = 0; // format.setFormatOptions({ ...format.copyFormatOptions(), insertTrailingSemicolon: false }); format.document(); verify.currentFileContentIs(`namespace ts { let x = 0 + // interface I { a: string /** @internal */ b: string } -}`); + let y = 0 // +} +let z = 0 //`); diff --git a/tests/cases/fourslash/formatRemoveSemicolons3.ts b/tests/cases/fourslash/formatRemoveSemicolons3.ts new file mode 100644 index 00000000000..9b2266214e1 --- /dev/null +++ b/tests/cases/fourslash/formatRemoveSemicolons3.ts @@ -0,0 +1,11 @@ +/// + +////(type).declaredProperties = getNamedMembers(members); +////// Start with signatures at empty array in case of recursive types +////(type).declaredCallSignatures = emptyArray; + +format.setFormatOptions({ ...format.copyFormatOptions(), insertTrailingSemicolon: false }); +format.document(); +verify.currentFileContentIs(`(type).declaredProperties = getNamedMembers(members); +// Start with signatures at empty array in case of recursive types +(type).declaredCallSignatures = emptyArray`); \ No newline at end of file