diff --git a/src/server/protocol.ts b/src/server/protocol.ts index d4ad6e7f0f1..c791eebf7d2 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2946,6 +2946,12 @@ namespace ts.server.protocol { Smart = "Smart", } + export enum SemicolonPreference { + Ignore = "ignore", + Insert = "insert", + Remove = "remove", + } + export interface EditorSettings { baseIndentSize?: number; indentSize?: number; @@ -2972,6 +2978,7 @@ namespace ts.server.protocol { placeOpenBraceOnNewLineForFunctions?: boolean; placeOpenBraceOnNewLineForControlBlocks?: boolean; insertSpaceBeforeTypeAnnotation?: boolean; + semicolonPreference?: SemicolonPreference } export interface UserPreferences { diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 08792f76368..8cd9cc9c542 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -426,7 +426,7 @@ namespace ts.formatting { const leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); if (leadingTrivia) { indentTriviaItems(leadingTrivia, initialIndentation, /*indentNextTokenOrTrivia*/ false, - item => processRange(item, sourceFile.getLineAndCharacterOfPosition(item.pos), enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!)); + item => processRange(item, sourceFile.getLineAndCharacterOfPosition(item.pos), enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!)); trimTrailingWhitespacesForRemainingRange(); } } @@ -477,7 +477,7 @@ namespace ts.formatting { parent: Node, parentDynamicIndentation: DynamicIndentation, effectiveParentStartLine: number - ): { indentation: number, delta: number } { + ): { indentation: number, delta: number; } { const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; if (effectiveParentStartLine === startLine) { @@ -867,7 +867,7 @@ namespace ts.formatting { if (currentTokenInfo.leadingTrivia) { const commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); indentNextTokenOrTrivia = indentTriviaItems(currentTokenInfo.leadingTrivia, commentIndentation, indentNextTokenOrTrivia, - item => insertIndentation(item.pos, commentIndentation, /*lineAdded*/ false)); + item => insertIndentation(item.pos, commentIndentation, /*lineAdded*/ false)); } // indent token only if is it is in target range and does not overlap with any error ranges @@ -1317,7 +1317,7 @@ namespace ts.formatting { return SyntaxKind.Unknown; } - let internedSizes: { tabSize: number; indentSize: number }; + let internedSizes: { tabSize: number; indentSize: number; }; let internedTabsIndentation: string[] | undefined; let internedSpacesIndentation: string[] | undefined; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index f4ea350dd8b..71d5f289e24 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -835,10 +835,12 @@ namespace ts.textChanges { function getFormatCodeSettingsForWriting(context: formatting.FormatContext, sourceFile: SourceFile): FormatCodeSettings { return { ...context.options, - // If the user has no semicolon preference defined, try to match whatever’s in the source file - semicolonPreference: !context.options.semicolonPreference || context.options.semicolonPreference === SemicolonPreference.Ignore - ? probablyUsesSemicolons(sourceFile) ? SemicolonPreference.Ignore : SemicolonPreference.Remove - : context.options.semicolonPreference, + // If the user has no semicolon preference defined and the file doesn’t use semicolons, + // make the formatter remove them. Otherwise, ignore semicolons in the formatter because + // the writer will insert them by default. + semicolonPreference: context.options.semicolonPreference === SemicolonPreference.Remove || (!context.options.semicolonPreference || context.options.semicolonPreference === SemicolonPreference.Ignore) && !probablyUsesSemicolons(sourceFile) + ? SemicolonPreference.Remove + : SemicolonPreference.Ignore, }; }