Skip to content

Format false branch of ternary operation #5905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ namespace FourSlash {
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceAfterTypeAssertion: false,
indentConditionalExpressionFalseBranch: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
Expand Down
1 change: 1 addition & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,7 @@ namespace ts.server.protocol {
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
insertSpaceAfterTypeAssertion?: boolean;
insertSpaceBeforeFunctionParenthesis?: boolean;
indentConditionalExpressionFalseBranch?: boolean;
placeOpenBraceOnNewLineForFunctions?: boolean;
placeOpenBraceOnNewLineForControlBlocks?: boolean;
}
Expand Down
1 change: 1 addition & 0 deletions src/server/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ namespace ts.server {
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceBeforeFunctionParenthesis: false,
indentConditionalExpressionFalseBranch: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
Expand Down
10 changes: 5 additions & 5 deletions src/services/formatting/formatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ namespace ts.formatting {
break;
}

if (SmartIndenter.shouldIndentChildNode(n, child)) {
if (SmartIndenter.shouldIndentChildNode(n, options, child)) {
return options.indentSize;
}

Expand Down Expand Up @@ -443,7 +443,7 @@ namespace ts.formatting {
effectiveParentStartLine: number): Indentation {

let indentation = inheritedIndentation;
let delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
let delta = SmartIndenter.shouldIndentChildNode(node, options) ? options.indentSize : 0;

if (effectiveParentStartLine === startLine) {
// if node is located on the same line with the parent
Expand Down Expand Up @@ -547,15 +547,15 @@ namespace ts.formatting {
getIndentation: () => indentation,
getDelta: child => getEffectiveDelta(delta, child),
recomputeIndentation: lineAdded => {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, options, node)) {
if (lineAdded) {
indentation += options.indentSize;
}
else {
indentation -= options.indentSize;
}

if (SmartIndenter.shouldIndentChildNode(node)) {
if (SmartIndenter.shouldIndentChildNode(node, options)) {
delta = options.indentSize;
}
else {
Expand All @@ -567,7 +567,7 @@ namespace ts.formatting {

function getEffectiveDelta(delta: number, child: TextRangeWithKind) {
// Delta value should be zero when the node explicitly prevents indentation of the child node
return SmartIndenter.nodeWillIndentChild(node, child, /*indentByDefault*/ true) ? delta : 0;
return SmartIndenter.nodeWillIndentChild(node, child, /*indentByDefault*/ true, options) ? delta : 0;
}
}

Expand Down
17 changes: 9 additions & 8 deletions src/services/formatting/smartIndenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace ts.formatting {
* when inserting some text after open brace we would like to get the value of indentation as if newline was already there.
* However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior,
*/
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number {
export function getIndentation(position: number, sourceFile: SourceFile, options: FormatCodeSettings, assumeNewLineBeforeCloseBrace = false): number {
if (position > sourceFile.text.length) {
return getBaseIndentation(options); // past EOF
}
Expand Down Expand Up @@ -80,7 +80,7 @@ namespace ts.formatting {
let indentationDelta: number;

while (current) {
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) {
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, options, previous)) {
currentStart = getStartLineAndCharacterForNode(current, sourceFile);

const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile);
Expand Down Expand Up @@ -131,7 +131,7 @@ namespace ts.formatting {
ignoreActualIndentationRange: TextRange,
indentationDelta: number,
sourceFile: SourceFile,
options: EditorSettings): number {
options: FormatCodeSettings): number {

let parent: Node = current.parent;
let parentStart: LineAndCharacter;
Expand Down Expand Up @@ -170,7 +170,7 @@ namespace ts.formatting {
}

// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) {
if (shouldIndentChildNode(parent, options, current) && !parentAndChildShareLine) {
indentationDelta += options.indentSize;
}

Expand Down Expand Up @@ -463,7 +463,6 @@ namespace ts.formatting {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.ExportAssignment:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.JsxOpeningElement:
Expand All @@ -488,7 +487,7 @@ namespace ts.formatting {
}

/* @internal */
export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean) {
export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean, options: FormatCodeSettings) {
const childKind = child ? child.kind : SyntaxKind.Unknown;
switch (parent.kind) {
case SyntaxKind.DoStatement:
Expand All @@ -512,6 +511,8 @@ namespace ts.formatting {
((<ImportClause>child).namedBindings && (<ImportClause>child).namedBindings.kind !== SyntaxKind.NamedImports);
case SyntaxKind.JsxElement:
return childKind !== SyntaxKind.JsxClosingElement;
case SyntaxKind.ConditionalExpression:
return options.indentConditionalExpressionFalseBranch || (parent as ConditionalExpression).whenFalse !== child;
}
// No explicit rule for given nodes so the result will follow the default value argument
return indentByDefault;
Expand All @@ -520,8 +521,8 @@ namespace ts.formatting {
/*
Function returns true when the parent node should indent the given child by an explicit rule
*/
export function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind): boolean {
return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false);
export function shouldIndentChildNode(parent: TextRangeWithKind, options: FormatCodeSettings, child?: TextRangeWithKind): boolean {
return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false, options);
}
}
}
2 changes: 1 addition & 1 deletion src/services/textChanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ namespace ts.textChanges {
const delta =
change.options.delta !== undefined
? change.options.delta
: formatting.SmartIndenter.shouldIndentChildNode(change.node)
: formatting.SmartIndenter.shouldIndentChildNode(change.node, formatOptions)
? formatOptions.indentSize
: 0;

Expand Down
3 changes: 2 additions & 1 deletion src/services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ namespace ts {
getOutliningSpans(fileName: string): OutliningSpan[];
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number;
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | FormatCodeSettings): number;

getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
Expand Down Expand Up @@ -472,6 +472,7 @@ namespace ts {
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
insertSpaceAfterTypeAssertion?: boolean;
insertSpaceBeforeFunctionParenthesis?: boolean;
indentConditionalExpressionFalseBranch?: boolean;
placeOpenBraceOnNewLineForFunctions?: boolean;
placeOpenBraceOnNewLineForControlBlocks?: boolean;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/cases/fourslash/formatConditionalExpressions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// <reference path="fourslash.ts"/>

////let v =
//// 0 ? 1 :
//// //
/////*falseBranchExpression*/ 2 ? 3 :
/////*indent*/
//// //
/////*falseBranchToken*/ 2;

format.document();

goTo.marker("falseBranchExpression");
verify.currentLineContentIs(" 2 ? 3 :");
goTo.marker("indent");
verify.indentationIs(8);
goTo.marker("falseBranchToken");
verify.currentLineContentIs(" 2;");
44 changes: 44 additions & 0 deletions tests/cases/fourslash/formattingOptionsChangeTernary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
///<reference path="fourslash.ts"/>

////const expectedScanAction =
//// shouldRescanGreaterThanToken(n)
//// ? ScanAction.RescanGreaterThanToken
//// : shouldRescanSlashToken(n)
//// ? ScanAction.RescanSlashToken
//// : shouldRescanTemplateToken(n)
//// ? ScanAction.RescanTemplateToken
//// : shouldRescanJsxIdentifier(n)
//// ? ScanAction.RescanJsxIdentifier
//// : shouldRescanJsxText(n)
//// ? ScanAction.RescanJsxText
//// : ScanAction.Scan;

format.setOption("indentConditionalExpressionFalseBranch", false);
format.document();
verify.currentFileContentIs(`const expectedScanAction =
shouldRescanGreaterThanToken(n)
? ScanAction.RescanGreaterThanToken
: shouldRescanSlashToken(n)
? ScanAction.RescanSlashToken
: shouldRescanTemplateToken(n)
? ScanAction.RescanTemplateToken
: shouldRescanJsxIdentifier(n)
? ScanAction.RescanJsxIdentifier
: shouldRescanJsxText(n)
? ScanAction.RescanJsxText
: ScanAction.Scan;`)

format.setOption("indentConditionalExpressionFalseBranch", true);
format.document();
verify.currentFileContentIs(`const expectedScanAction =
shouldRescanGreaterThanToken(n)
? ScanAction.RescanGreaterThanToken
: shouldRescanSlashToken(n)
? ScanAction.RescanSlashToken
: shouldRescanTemplateToken(n)
? ScanAction.RescanTemplateToken
: shouldRescanJsxIdentifier(n)
? ScanAction.RescanJsxIdentifier
: shouldRescanJsxText(n)
? ScanAction.RescanJsxText
: ScanAction.Scan;`)