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