From 3fc480c0bdc5ae4982fc6fbce4cc8172ddca0268 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 23 Mar 2018 15:38:03 -0700 Subject: [PATCH 1/7] 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 From 1ea2a52b69af5a0c7d96041c14e555118ee39b8a Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 23 Mar 2018 15:54:01 -0700 Subject: [PATCH 2/7] test synthesized object literal formatting --- ...FixClassImplementInterfaceObjectLiteral.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/cases/fourslash/codeFixClassImplementInterfaceObjectLiteral.ts diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceObjectLiteral.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceObjectLiteral.ts new file mode 100644 index 00000000000..f2e05b24f57 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceObjectLiteral.ts @@ -0,0 +1,23 @@ +/// + +//// interface IPerson { +//// coordinate: { +//// x: number; +//// y: number; +//// } +//// } +//// class Person implements IPerson { } + +verify.codeFix({ + description: "Implement interface 'IPerson'", + newFileContent: +`interface IPerson { + coordinate: { + x: number; + y: number; + } +} +class Person implements IPerson { + coordinate: { x: number; y: number; }; +}`, +}); \ No newline at end of file From d41070a9668ec3a6d82036dd544cce3f27f6a37c Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 26 Mar 2018 16:37:55 -0700 Subject: [PATCH 3/7] more tests --- ...formattingObjectLiteralOpenCurlyNewline.ts | 10 +++++--- ...mattingObjectLiteralOpenCurlySingleLine.ts | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts index 8cf96593721..da1594df31a 100644 --- a/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts @@ -5,7 +5,9 @@ //// { //// outerKey: //// { -//// innerKey: 1 +//// innerKey: 1, +//// innerKey2: +//// 2 //// } //// }; //// @@ -17,8 +19,10 @@ var clear = { outerKey: { - innerKey: 1 + innerKey: 1, + innerKey2: + 2 } }; ` -); \ No newline at end of file +); diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts new file mode 100644 index 00000000000..e9382fadfbd --- /dev/null +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts @@ -0,0 +1,23 @@ +/// + +//// +//// let obj1 = +//// { x: 10 }; +//// +//// let obj2 = +//// // leading trivia +//// { y: 10 }; +//// + +format.document(); +verify.currentFileContentIs( +` +let obj1 = +{ x: 10 }; + +let obj2 = + // leading trivia +{ y: 10 }; +` +); + From 6786d7473d8c5794c9b1a40651cd3e5edb51c67b Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 26 Mar 2018 16:53:20 -0700 Subject: [PATCH 4/7] fix test --- .../formattingObjectLiteralOpenCurlySingleLine.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts index e9382fadfbd..ea82efa081e 100644 --- a/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts @@ -2,22 +2,22 @@ //// //// let obj1 = -//// { x: 10 }; +//// { x: 10 }; //// //// let obj2 = //// // leading trivia -//// { y: 10 }; +//// { y: 10 }; //// format.document(); verify.currentFileContentIs( ` let obj1 = -{ x: 10 }; + { x: 10 }; let obj2 = // leading trivia -{ y: 10 }; + { y: 10 }; ` ); From 1ced600efecd61010aac0551aa054f7a19c5d9e1 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 26 Mar 2018 17:53:50 -0700 Subject: [PATCH 5/7] pass in sourceFile and revert child to `TextRangeOfKind` --- src/services/formatting/formatting.ts | 8 ++++---- src/services/formatting/smartIndenter.ts | 23 ++++++++++------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 8b60952d4f6..e1825a4411c 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -328,7 +328,7 @@ namespace ts.formatting { break; } - if (SmartIndenter.shouldIndentChildNode(n, child)) { + if (SmartIndenter.shouldIndentChildNode(n, child, sourceFile)) { return options.indentSize; } @@ -514,7 +514,7 @@ namespace ts.formatting { if ((node).asteriskToken) { return SyntaxKind.AsteriskToken; } - // falls through + // falls through case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: return getNameOfDeclaration(node).kind; @@ -541,7 +541,7 @@ namespace ts.formatting { getIndentation: () => indentation, getDelta, recomputeIndentation: lineAdded => { - if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) { + if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node, sourceFile)) { indentation += lineAdded ? options.indentSize : -options.indentSize; delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; } @@ -583,7 +583,7 @@ namespace ts.formatting { 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; + return SmartIndenter.nodeWillIndentChild(node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; } } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 23256b6b754..99d57668b27 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -112,7 +112,7 @@ namespace ts.formatting { let previous: Node | undefined; let current = precedingToken; while (current) { - if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous, /*isNextChild*/ true)) { + if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous, sourceFile, /*isNextChild*/ true)) { const currentStart = getStartLineAndCharacterForNode(current, sourceFile); const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile); const indentationDelta = nextTokenKind !== NextTokenKind.Unknown @@ -193,7 +193,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, isNextChild) && !parentAndChildShareLine) { + if (shouldIndentChildNode(parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) { indentationDelta += options.indentSize; } @@ -531,21 +531,18 @@ namespace ts.formatting { return false; } - export function nodeWillIndentChild(parent: TextRangeWithKind, child: Node | undefined, indentByDefault: boolean): boolean { + export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | 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; - } + if (sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { + const childStart = skipTrivia(sourceFile.text, child.pos); + const startLine = sourceFile.getLineAndCharacterOfPosition(childStart).line; + const endLine = sourceFile.getLineAndCharacterOfPosition(child.end).line; + return startLine === endLine; } break; case SyntaxKind.DoStatement: @@ -599,8 +596,8 @@ 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?: Node, isNextChild = false): boolean { - return (nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false)) + export function shouldIndentChildNode(parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { + return (nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, sourceFile, /*indentByDefault*/ false)) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } } From 5fb5ff7bf3343a188d5645cdaf4bfa8f5c8d911a Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 29 Mar 2018 15:40:23 -0700 Subject: [PATCH 6/7] add option for object literal indent --- src/services/formatting/formatting.ts | 12 ++--- src/services/formatting/smartIndenter.ts | 24 +++++---- src/services/textChanges.ts | 2 +- src/services/types.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + ...extract-method-formatting-objectliteral.ts | 50 +++++++++++++++++++ ...formattingObjectLiteralOpenCurlyNewline.ts | 16 ++++++ ...mattingObjectLiteralOpenCurlySingleLine.ts | 1 - 8 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 tests/cases/fourslash/extract-method-formatting-objectliteral.ts diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index e1825a4411c..debec04536a 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -328,7 +328,7 @@ namespace ts.formatting { break; } - if (SmartIndenter.shouldIndentChildNode(n, child, sourceFile)) { + if (SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) { return options.indentSize; } @@ -470,7 +470,7 @@ namespace ts.formatting { parentDynamicIndentation: DynamicIndentation, effectiveParentStartLine: number ): { indentation: number, delta: number } { - const delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; + const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0; if (effectiveParentStartLine === startLine) { // if node is located on the same line with the parent @@ -541,9 +541,9 @@ namespace ts.formatting { getIndentation: () => indentation, getDelta, recomputeIndentation: lineAdded => { - if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node, sourceFile)) { + if (node.parent && SmartIndenter.shouldIndentChildNode(options, node.parent, node, sourceFile)) { indentation += lineAdded ? options.indentSize : -options.indentSize; - delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; + delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0; } } }; @@ -581,9 +581,9 @@ namespace ts.formatting { && !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node)); } - function getDelta(child: Node) { + function getDelta(child: TextRangeWithKind) { // Delta value should be zero when the node explicitly prevents indentation of the child node - return SmartIndenter.nodeWillIndentChild(node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; + return SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; } } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 99d57668b27..a82f11f239b 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -112,7 +112,7 @@ namespace ts.formatting { let previous: Node | undefined; let current = precedingToken; while (current) { - if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous, sourceFile, /*isNextChild*/ true)) { + if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { const currentStart = getStartLineAndCharacterForNode(current, sourceFile); const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile); const indentationDelta = nextTokenKind !== NextTokenKind.Unknown @@ -193,7 +193,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, sourceFile, isNextChild) && !parentAndChildShareLine) { + if (shouldIndentChildNode(options, parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) { indentationDelta += options.indentSize; } @@ -531,18 +531,15 @@ namespace ts.formatting { return false; } - export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean { + export function nodeWillIndentChild(settings: FormatCodeSettings | undefined, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean { const childKind = child ? child.kind : SyntaxKind.Unknown; switch (parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.PropertyAssignment: case SyntaxKind.ObjectLiteralExpression: - if (sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { - const childStart = skipTrivia(sourceFile.text, child.pos); - const startLine = sourceFile.getLineAndCharacterOfPosition(childStart).line; - const endLine = sourceFile.getLineAndCharacterOfPosition(child.end).line; - return startLine === endLine; + if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { + return rangeIsOnOneLine(sourceFile, child); } break; case SyntaxKind.DoStatement: @@ -596,9 +593,16 @@ 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?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { - return (nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, sourceFile, /*indentByDefault*/ false)) + export function shouldIndentChildNode(settings: FormatCodeSettings | undefined, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { + return (nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false)) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } + + function rangeIsOnOneLine(sourceFile: SourceFileLike, range: TextRangeWithKind) { + const rangeStart = skipTrivia(sourceFile.text, range.pos); + const startLine = sourceFile.getLineAndCharacterOfPosition(rangeStart).line; + const endLine = sourceFile.getLineAndCharacterOfPosition(range.end).line; + return startLine === endLine; + } } } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 24ff0ba2812..6100727a962 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -670,7 +670,7 @@ namespace ts.textChanges { const delta = options.delta !== undefined ? options.delta - : formatting.SmartIndenter.shouldIndentChildNode(nodeIn) + : formatting.SmartIndenter.shouldIndentChildNode(formatContext.options, nodeIn) ? (formatOptions.indentSize || 0) : 0; const file: SourceFileLike = { text, getLineAndCharacterOfPosition(pos) { return getLineAndCharacterOfPosition(this, pos); } }; diff --git a/src/services/types.ts b/src/services/types.ts index af496cfeb11..7179d947cfd 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -629,6 +629,7 @@ namespace ts { placeOpenBraceOnNewLineForFunctions?: boolean; placeOpenBraceOnNewLineForControlBlocks?: boolean; insertSpaceBeforeTypeAnnotation?: boolean; + indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean; } export interface DefinitionInfo { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f849dc7f664..19cf8f4f0fb 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4654,6 +4654,7 @@ declare namespace ts { placeOpenBraceOnNewLineForFunctions?: boolean; placeOpenBraceOnNewLineForControlBlocks?: boolean; insertSpaceBeforeTypeAnnotation?: boolean; + indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean; } interface DefinitionInfo { fileName: string; diff --git a/tests/cases/fourslash/extract-method-formatting-objectliteral.ts b/tests/cases/fourslash/extract-method-formatting-objectliteral.ts new file mode 100644 index 00000000000..cbde4540233 --- /dev/null +++ b/tests/cases/fourslash/extract-method-formatting-objectliteral.ts @@ -0,0 +1,50 @@ +/// + +//// +//// namespace M { +//// class C { +//// foo() { +//// /*a*/let x = {a:1}; +//// let y = { +//// b: 2 +//// }; +//// let z = +//// { +//// c: 3 +//// };/*b*/ +//// return x.a + y.b + z.c; +//// } +//// } +//// } +//// + +goTo.select('a', 'b'); +edit.applyRefactor({ + refactorName: "Extract Symbol", + actionName: "function_scope_1", + actionDescription: "Extract to method in class 'C'", + newContent: +` +namespace M { + class C { + foo() { + let { x, y, z } = this./*RENAME*/newMethod(); + return x.a + y.b + z.c; + } + + private newMethod() { + let x = { a: 1 }; + let y = { + b: 2 + }; + let z = { + c: 3 + }; + return { x, y, z }; + } + } +} +` +}); + + diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts index da1594df31a..80faace2b09 100644 --- a/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlyNewline.ts @@ -26,3 +26,19 @@ var clear = }; ` ); + +format.setOption("indentMultiLineObjectLiteralBeginningOnBlankLine", true); +format.document(); +verify.currentFileContentIs( +` +var clear = + { + outerKey: + { + innerKey: 1, + innerKey2: + 2 + } + }; +` +); diff --git a/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts b/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts index ea82efa081e..27d1b9f51b2 100644 --- a/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts +++ b/tests/cases/fourslash/formattingObjectLiteralOpenCurlySingleLine.ts @@ -20,4 +20,3 @@ let obj2 = { y: 10 }; ` ); - From 8c88ce712b95bf04ecb64b40e71bd628906cc2f5 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 29 Mar 2018 16:11:17 -0700 Subject: [PATCH 7/7] update baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b859f9f1876..cb7b20b15c4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4406,6 +4406,7 @@ declare namespace ts { placeOpenBraceOnNewLineForFunctions?: boolean; placeOpenBraceOnNewLineForControlBlocks?: boolean; insertSpaceBeforeTypeAnnotation?: boolean; + indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean; } interface DefinitionInfo { fileName: string;