From 3fc480c0bdc5ae4982fc6fbce4cc8172ddca0268 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 23 Mar 2018 15:38:03 -0700 Subject: [PATCH] cSharp-style formatting for multi-line object literals --- src/services/formatting/formatting.ts | 2 +- src/services/formatting/smartIndenter.ts | 18 ++++++++-- ...formattingObjectLiteralOpenCurlyNewline.ts | 24 +++++++++++++ ...tingObjectLiteralOpenCurlyNewlineTyping.ts | 36 +++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts create mode 100644 tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewlineTyping.ts diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 967015a88c1..8b60952d4f6 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -581,7 +581,7 @@ namespace ts.formatting { && !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node)); } - function getDelta(child: TextRangeWithKind) { + function getDelta(child: Node) { // Delta value should be zero when the node explicitly prevents indentation of the child node return SmartIndenter.nodeWillIndentChild(node, child, /*indentByDefault*/ true) ? delta : 0; } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 7904db0969f..23256b6b754 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -531,9 +531,23 @@ namespace ts.formatting { return false; } - export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind | undefined, indentByDefault: boolean): boolean { + export function nodeWillIndentChild(parent: TextRangeWithKind, child: Node | undefined, indentByDefault: boolean): boolean { const childKind = child ? child.kind : SyntaxKind.Unknown; + switch (parent.kind) { + case SyntaxKind.VariableDeclaration: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ObjectLiteralExpression: + if (childKind === SyntaxKind.ObjectLiteralExpression) { + const sourceFile = child.getSourceFile(); + if (sourceFile) { + // May not be defined for synthesized nodes. + const startLine = sourceFile.getLineAndCharacterOfPosition(child.getStart()).line; + const endLine = sourceFile.getLineAndCharacterOfPosition(child.getEnd()).line; + return startLine === endLine; + } + } + break; case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: case SyntaxKind.ForInStatement: @@ -585,7 +599,7 @@ namespace ts.formatting { * True when the parent node should indent the given child by an explicit rule. * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child. */ - export function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind, isNextChild = false): boolean { + export function shouldIndentChildNode(parent: TextRangeWithKind, child?: Node, isNextChild = false): boolean { return (nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false)) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts new file mode 100644 index 00000000000..8cf96593721 --- /dev/null +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts @@ -0,0 +1,24 @@ +/// + +//// +//// var clear = +//// { +//// outerKey: +//// { +//// innerKey: 1 +//// } +//// }; +//// + +format.document(); +verify.currentFileContentIs( +` +var clear = +{ + outerKey: + { + innerKey: 1 + } +}; +` +); \ No newline at end of file diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewlineTyping.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewlineTyping.ts new file mode 100644 index 00000000000..ba21c91dba9 --- /dev/null +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewlineTyping.ts @@ -0,0 +1,36 @@ +/// + +//// +//// var varName =/**/ +//// + +goTo.marker(); +edit.insert("\n{"); +verify.currentFileContentIs( +` +var varName = + { +` +); + +edit.insert("\na: 1"); +format.document(); +verify.currentFileContentIs( +` +var varName = +{ + a: 1 +` +); + +edit.insert("\n};"); + +format.document(); +verify.currentFileContentIs( +` +var varName = +{ + a: 1 +}; +` +); \ No newline at end of file