diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index a3acdbdafaa9c..a5135f117831c 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -34,7 +34,7 @@ namespace ts.formatting { * the first token in line so it should be indented */ interface DynamicIndentation { - getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind, container: Node): number; + getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind, container: Node, suppressDelta: boolean): number; getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number, container: Node): number; /** * Indentation for open and close tokens of the node if it is block or another node that needs special indentation @@ -398,7 +398,7 @@ namespace ts.formatting { let previousRangeStartLine: number; let lastIndentedLine: number; - let indentationOnLastIndentedLine: number; + let indentationOnLastIndentedLine = Constants.Unknown; const edits: TextChange[] = []; @@ -539,8 +539,18 @@ namespace ts.formatting { } return tokenIndentation !== Constants.Unknown ? tokenIndentation : indentation; }, - getIndentationForToken: (line, kind, container) => - shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation, + // if list end token is LessThanToken '>' then its delta should be explicitly suppressed + // so that LessThanToken as a binary operator can still be indented. + // foo.then + // < + // number, + // string, + // >(); + // vs + // var a = xValue + // > yValue; + getIndentationForToken: (line, kind, container, suppressDelta) => + !suppressDelta && shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation, getIndentation: () => indentation, getDelta, recomputeIndentation: lineAdded => { @@ -556,7 +566,6 @@ namespace ts.formatting { // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent case SyntaxKind.OpenBraceToken: case SyntaxKind.CloseBraceToken: - case SyntaxKind.OpenParenToken: case SyntaxKind.CloseParenToken: case SyntaxKind.ElseKeyword: case SyntaxKind.WhileKeyword: @@ -737,11 +746,23 @@ namespace ts.formatting { else if (tokenInfo.token.kind === listStartToken) { // consume list start token startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - const indentation = - computeIndentation(tokenInfo.token, startLine, Constants.Unknown, parent, parentDynamicIndentation, parentStartLine); - listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation.indentation, indentation.delta); - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); + consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation, parent); + + let indentationOnListStartToken: number; + if (indentationOnLastIndentedLine !== Constants.Unknown) { + // scanner just processed list start token so consider last indentation as list indentation + // function foo(): { // last indentation was 0, list item will be indented based on this value + // foo: number; + // }: {}; + indentationOnListStartToken = indentationOnLastIndentedLine; + } + else { + const startLinePosition = getLineStartPositionForPosition(tokenInfo.token.pos, sourceFile); + indentationOnListStartToken = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, tokenInfo.token.pos, sourceFile, options); + } + + listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentationOnListStartToken, options.indentSize!); // TODO: GH#18217 } else { // consume any tokens that precede the list as child elements of 'node' using its indentation scope @@ -770,12 +791,12 @@ namespace ts.formatting { // without this check close paren will be interpreted as list end token for function expression which is wrong if (tokenInfo && tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) { // consume list end token - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); + consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent, /*isListEndToken*/ true); } } } - function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation, container: Node): void { + function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation, container: Node, isListEndToken?: boolean): void { Debug.assert(rangeContainsRange(parent, currentTokenInfo.token)); const lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); @@ -813,7 +834,7 @@ namespace ts.formatting { if (indentToken) { const tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? - dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : + dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container, !!isListEndToken) : Constants.Unknown; let indentNextTokenOrTrivia = true; @@ -1227,6 +1248,9 @@ namespace ts.formatting { if ((node).typeArguments === list) { return SyntaxKind.LessThanToken; } + break; + case SyntaxKind.TypeLiteral: + return SyntaxKind.OpenBraceToken; } return SyntaxKind.Unknown; @@ -1238,6 +1262,8 @@ namespace ts.formatting { return SyntaxKind.CloseParenToken; case SyntaxKind.LessThanToken: return SyntaxKind.GreaterThanToken; + case SyntaxKind.OpenBraceToken: + return SyntaxKind.CloseBraceToken; } return SyntaxKind.Unknown; diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index ccc05d8442682..eee8240aa62eb 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -66,6 +66,12 @@ namespace ts.formatting { } } + const containerList = getListByPosition(position, precedingToken.parent, sourceFile); + // use list position if the preceding token is before any list items + if (containerList && !rangeContainsRange(containerList, precedingToken)) { + return getActualIndentationForListStartLine(containerList, sourceFile, options) + options.indentSize!; // TODO: GH#18217 + } + return getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options); } @@ -124,14 +130,13 @@ namespace ts.formatting { } // check if current node is a list item - if yes, take indentation from it - let actualIndentation = getActualIndentationForListItem(current, sourceFile, options); + // do not consider parent-child line sharing yet: + // function foo(a + // | preceding node 'a' does share line with its parent but indentation is expected + const actualIndentation = getActualIndentationForListItem(current, sourceFile, options, /*listIndentsChild*/ true); if (actualIndentation !== Value.Unknown) { return actualIndentation; } - actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== Value.Unknown) { - return actualIndentation + options.indentSize!; // TODO: GH#18217 - } previous = current; current = current.parent; @@ -169,26 +174,20 @@ namespace ts.formatting { useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; } - if (useActualIndentation) { - // check if current node is a list item - if yes, take indentation from it - const actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== Value.Unknown) { - return actualIndentation + indentationDelta; - } - } - const containingListOrParentStart = getContainingListOrParentStart(parent, current, sourceFile); const parentAndChildShareLine = containingListOrParentStart.line === currentStart.line || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); if (useActualIndentation) { - // try to fetch actual indentation for current node from source text - let actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); + // check if current node is a list item - if yes, take indentation from it + let actualIndentation = getActualIndentationForListItem(current, sourceFile, options, !parentAndChildShareLine); if (actualIndentation !== Value.Unknown) { return actualIndentation + indentationDelta; } - actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); + + // try to fetch actual indentation for current node from source text + actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); if (actualIndentation !== Value.Unknown) { return actualIndentation + indentationDelta; } @@ -323,112 +322,109 @@ namespace ts.formatting { return false; } + function getListIfVisualStartEndIsInListRange(list: NodeArray | undefined, start: number, end: number, node: Node, sourceFile: SourceFile) { + return list && rangeContainsVisualStartEnd(list) ? list : undefined; + + // Assumes a list is wrapped by list tokens + function rangeContainsVisualStartEnd(textRange: TextRange): boolean { + const children = node.getChildren(); + for (let i = 1; i < children.length - 1; i++) { + if (children[i].pos === textRange.pos && children[i].end === textRange.end) { + return rangeContainsStartEnd({ pos: children[i - 1].end, end: children[i + 1].getStart(sourceFile) }, start, end); + } + } + return rangeContainsStartEnd(textRange, start, end); + } + } + function getListIfStartEndIsInListRange(list: NodeArray | undefined, start: number, end: number) { return list && rangeContainsStartEnd(list, start, end) ? list : undefined; } export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray | undefined { if (node.parent) { - const { end } = node; - switch (node.parent.kind) { - case SyntaxKind.TypeReference: - return getListIfStartEndIsInListRange((node.parent).typeArguments, node.getStart(sourceFile), end); - case SyntaxKind.ObjectLiteralExpression: - return (node.parent).properties; - case SyntaxKind.ArrayLiteralExpression: - return (node.parent).elements; - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.Constructor: - case SyntaxKind.ConstructorType: - case SyntaxKind.ConstructSignature: { - const start = node.getStart(sourceFile); - return getListIfStartEndIsInListRange((node.parent).typeParameters, start, end) || - getListIfStartEndIsInListRange((node.parent).parameters, start, end); - } - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.JSDocTemplateTag: { - const { typeParameters } = node.parent; - return getListIfStartEndIsInListRange(typeParameters, node.getStart(sourceFile), end); - } - case SyntaxKind.NewExpression: - case SyntaxKind.CallExpression: { - const start = node.getStart(sourceFile); - return getListIfStartEndIsInListRange((node.parent).typeArguments, start, end) || - getListIfStartEndIsInListRange((node.parent).arguments, start, end); - } - case SyntaxKind.VariableDeclarationList: - return getListIfStartEndIsInListRange((node.parent).declarations, node.getStart(sourceFile), end); - case SyntaxKind.NamedImports: - case SyntaxKind.NamedExports: - return getListIfStartEndIsInListRange((node.parent).elements, node.getStart(sourceFile), end); - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - return getListIfStartEndIsInListRange((node.parent).elements, node.getStart(sourceFile), end); - } + return getListByRange(node.getStart(sourceFile), node.getEnd(), node.parent, sourceFile); } return undefined; } - function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings): number { - const containingList = getContainingList(node, sourceFile); - if (containingList) { - const index = containingList.indexOf(node); - if (index !== -1) { - return deriveActualIndentationFromList(containingList, index, sourceFile, options); - } + function getListByPosition(pos: number, node: Node, sourceFile: SourceFile): NodeArray | undefined { + if (!node) { + return; } - return Value.Unknown; + return getListByRange(pos, pos, node, sourceFile); } - function getLineIndentationWhenExpressionIsInMultiLine(node: Node, sourceFile: SourceFile, options: EditorSettings): number { - // actual indentation should not be used when: - // - node is close parenthesis - this is the end of the expression - if (node.kind === SyntaxKind.CloseParenToken) { - return Value.Unknown; - } - - if (node.parent && isCallOrNewExpression(node.parent) && node.parent.expression !== node) { - const fullCallOrNewExpression = node.parent.expression; - const startingExpression = getStartingExpression(fullCallOrNewExpression); - - if (fullCallOrNewExpression === startingExpression) { - return Value.Unknown; + function getListByRange(start: number, end: number, node: Node, sourceFile: SourceFile): NodeArray | undefined { + switch (node.kind) { + case SyntaxKind.TypeReference: + return getListIfVisualStartEndIsInListRange((node).typeArguments, start, end, node, sourceFile); + case SyntaxKind.ObjectLiteralExpression: + return getListIfVisualStartEndIsInListRange((node).properties, start, end, node, sourceFile); + case SyntaxKind.ArrayLiteralExpression: + return getListIfVisualStartEndIsInListRange((node).elements, start, end, node, sourceFile); + case SyntaxKind.TypeLiteral: + return getListIfVisualStartEndIsInListRange((node).members, start, end, node, sourceFile); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: { + return getListIfVisualStartEndIsInListRange((node).typeParameters, start, end, node, sourceFile) || + getListIfVisualStartEndIsInListRange((node).parameters, start, end, node, sourceFile); } - - const fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); - const startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); - - if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { - return Value.Unknown; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.JSDocTemplateTag: { + const { typeParameters } = node; + return getListIfVisualStartEndIsInListRange(typeParameters, start, end, node, sourceFile); } - - return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); + case SyntaxKind.NewExpression: + case SyntaxKind.CallExpression: { + return getListIfVisualStartEndIsInListRange((node).typeArguments, start, end, node, sourceFile) || + getListIfVisualStartEndIsInListRange((node).arguments, start, end, node, sourceFile); + } + case SyntaxKind.VariableDeclarationList: + return getListIfStartEndIsInListRange((node).declarations, start, end); + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + return getListIfVisualStartEndIsInListRange((node).elements, start, end, node, sourceFile); + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + return getListIfVisualStartEndIsInListRange((node).elements, start, end, node, sourceFile); } + } - return Value.Unknown; + function getActualIndentationForListStartLine(list: NodeArray, sourceFile: SourceFile, options: EditorSettings): number { + if (!list) { + return Value.Unknown; + } + return findColumnForFirstNonWhitespaceCharacterInLine(sourceFile.getLineAndCharacterOfPosition(list.pos), sourceFile, options); + } - function getStartingExpression(node: Expression) { - while (true) { - switch (node.kind) { - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - node = (node).expression; - break; - default: - return node; + function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings, listIndentsChild: boolean): number { + if (node.parent && node.parent.kind === SyntaxKind.VariableDeclarationList) { + // VariableDeclarationList has no wrapping tokens + return Value.Unknown; + } + const containingList = getContainingList(node, sourceFile); + if (containingList) { + const index = containingList.indexOf(node); + if (index !== -1) { + const result = deriveActualIndentationFromList(containingList, index, sourceFile, options); + if (result !== Value.Unknown) { + return result; } } + return getActualIndentationForListStartLine(containingList, sourceFile, options) + (listIndentsChild ? options.indentSize! : 0); // TODO: GH#18217 } + return Value.Unknown; } function deriveActualIndentationFromList(list: ReadonlyArray, index: number, sourceFile: SourceFile, options: EditorSettings): number { diff --git a/tests/cases/fourslash/formattingOnChainedCallbacks.ts b/tests/cases/fourslash/formattingOnChainedCallbacks.ts index b8dbc55d8b6cb..1dc2d5bc84a04 100644 --- a/tests/cases/fourslash/formattingOnChainedCallbacks.ts +++ b/tests/cases/fourslash/formattingOnChainedCallbacks.ts @@ -1,52 +1,160 @@ -/// - -////Promise -//// .resolve() -//// .then(() => {/*1*/""/*2*/ -////}).then(() => {/*3*//*4*/ -////})/*semi1*//*semi2*/ - -////function foo() { -//// return Promise.resolve() -//// .then(function () { -//// ""/*a*/ -//// })/*b*/ -////} - -////Promise -//// .then( -//// /*n1*/ -//// ) -//// /*n2*/ -//// .then(); - - -goTo.marker('1'); -edit.insertLine(''); -goTo.marker('2'); -verify.currentLineContentIs(' ""'); -edit.insertLine(''); -verify.indentationIs(8); -goTo.marker('4'); -edit.insertLine(''); -goTo.marker('3'); -verify.currentLineContentIs(' }).then(() => {'); - -goTo.marker("semi1"); -edit.insert(';'); -verify.currentLineContentIs(' });'); -goTo.marker("semi2"); -edit.insert(';'); -verify.currentLineContentIs(' });;'); - -goTo.marker('a'); -edit.insert(';'); -verify.currentLineContentIs(' "";'); -goTo.marker('b'); -edit.insert(';'); -verify.currentLineContentIs(' });'); - -goTo.marker('n1'); -verify.indentationIs(8); -goTo.marker('n2'); -verify.indentationIs(4); \ No newline at end of file +/// + +////Promise +//// .resolve() +//// .then(() => {/*1*/""/*2*/ +////}).then(() => {/*3*//*4*/ +////})/*semi1*//*semi2*/ + +////function foo() { +//// return Promise.resolve() +//// .then(function () { +//// ""/*a*/ +//// })/*b*/ +////} + +////Promise +//// .then( +//// /*n1*/ +//// ) +//// /*n2*/ +//// .then(); + +// @Filename: listSmart.ts +////Promise +//// .resolve().then( +//// /*listSmart1*/ +//// 3, +//// /*listSmart2*/ +//// [ +//// 3 +//// /*listSmart3*/ +//// ] +//// /*listSmart4*/ +//// ); + +// @Filename: listZeroIndent.ts +////Promise.resolve([ +////]).then( +//// /*listZeroIndent1*/ +//// [ +//// /*listZeroIndent2*/ +//// 3 +//// ] +//// ); + +// @Filename: listTypeParameter1.ts +////foo.then +//// < +//// /*listTypeParameter1*/ +//// void +//// /*listTypeParameter2*/ +//// >( +//// function (): void { +//// }, +//// function (): void { +//// } +//// ); + +// @Filename: listComment.ts +////Promise +//// .then( +//// // euphonium +//// "k" +//// // oboe +//// ); + + +goTo.marker('1'); +edit.insertLine(''); +goTo.marker('2'); +verify.currentLineContentIs(' ""'); +edit.insertLine(''); +verify.indentationIs(8); +goTo.marker('4'); +edit.insertLine(''); +goTo.marker('3'); +verify.currentLineContentIs(' }).then(() => {'); + +goTo.marker("semi1"); +edit.insert(';'); +verify.currentLineContentIs(' });'); +goTo.marker("semi2"); +edit.insert(';'); +verify.currentLineContentIs(' });;'); + +goTo.marker('a'); +edit.insert(';'); +verify.currentLineContentIs(' "";'); +goTo.marker('b'); +edit.insert(';'); +verify.currentLineContentIs(' });'); + +goTo.marker('n1'); +verify.indentationIs(8); +goTo.marker('n2'); +verify.indentationIs(4); + +goTo.file("listSmart.ts"); +format.document(); +verify.currentFileContentIs(`Promise + .resolve().then( + + 3, + + [ + 3 + + ] + + );`); +goTo.marker("listSmart1"); +verify.indentationIs(8); +goTo.marker("listSmart2"); +verify.indentationIs(8); +goTo.marker("listSmart3"); +verify.indentationIs(12); +goTo.marker("listSmart4"); +verify.indentationIs(8); + +goTo.file("listZeroIndent.ts"); +format.document(); +verify.currentFileContentIs(`Promise.resolve([ +]).then( + + [ + + 3 + ] +);`); +goTo.marker("listZeroIndent1"); +verify.indentationIs(4); +goTo.marker("listZeroIndent2"); +verify.indentationIs(8); + +goTo.file("listTypeParameter1.ts"); +format.document(); +verify.currentFileContentIs(`foo.then + < + + void + + >( + function(): void { + }, + function(): void { + } + );`); +goTo.marker("listTypeParameter1"); +verify.indentationIs(8); +goTo.marker("listTypeParameter2"); +verify.indentationIs(8); + +goTo.file("listComment.ts"); +format.document(); +verify.currentFileContentIs(`Promise + .then( + // euphonium + "k" + // oboe + );`) diff --git a/tests/cases/fourslash/formattingOnTypeLiteral.ts b/tests/cases/fourslash/formattingOnTypeLiteral.ts new file mode 100644 index 0000000000000..9b7929a5f5eee --- /dev/null +++ b/tests/cases/fourslash/formattingOnTypeLiteral.ts @@ -0,0 +1,37 @@ +/// + +////function _uniteVertices

( +//// minority: Pinned>, +//// majorityCounter: number, +//// majority: Pinned> +////): { +//// /*start*/ +//// majorityCounter: number; +//// vertecis: Pinned; +//// }>; +//// /*end*/ +//// } { +////} + +format.document(); +verify.currentFileContentIs(`function _uniteVertices

( + minority: Pinned>, + majorityCounter: number, + majority: Pinned> +): { + + majorityCounter: number; + vertecis: Pinned; + }>; + +} { +}`); + +goTo.marker("start"); +verify.indentationIs(4); +goTo.marker("end"); +verify.indentationIs(4); \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInAmdIife.ts b/tests/cases/fourslash/indentationInAmdIife.ts index f735ae57eb219..b6800e5ad6273 100644 --- a/tests/cases/fourslash/indentationInAmdIife.ts +++ b/tests/cases/fourslash/indentationInAmdIife.ts @@ -2,7 +2,7 @@ //// function foo(a?,b?) { b(a); } //// -//// (foo)(1, function() {/*4_0*/ +//// (foo)(1, function() {/*4_1*/ //// }); //// //// // No line-breaks in the expression part of the call expression @@ -20,7 +20,7 @@ //// // Contains line-breaks in the expression part of the call expression. //// //// ( -//// foo)(1, function () {/*4_1*/ +//// foo)(1, function () {/*8_4*/ //// }); //// (foo //// )(1, function () {/*4_3*/ @@ -38,14 +38,14 @@ //// {/*4_4*/ //// }); -for (let i = 0; i < 5; ++i) { +for (let i = 1; i < 5; ++i) { goTo.marker(`4_${i}`); edit.insertLine(""); verify.indentationIs(4); } -for (let i = 1; i < 4; ++i) { +for (let i = 1; i < 5; ++i) { goTo.marker(`8_${i}`); edit.insertLine(""); verify.indentationIs(8); -} \ No newline at end of file +} diff --git a/tests/cases/fourslash/smartIndentObjectBindingPattern01.ts b/tests/cases/fourslash/smartIndentObjectBindingPattern01.ts index a9bae4bbef54b..6fede85c7ff41 100644 --- a/tests/cases/fourslash/smartIndentObjectBindingPattern01.ts +++ b/tests/cases/fourslash/smartIndentObjectBindingPattern01.ts @@ -8,10 +8,8 @@ function verifyIndentationAfterNewLine(marker: string, indentation: number): voi verify.indentationIs(indentation); } -// TODO (arozga): fix this. -// verifyIndentationAfterNewLine("1", 4); -verifyIndentationAfterNewLine("1", 0); +verifyIndentationAfterNewLine("1", 4); verifyIndentationAfterNewLine("2", 8); verifyIndentationAfterNewLine("3", 8); verifyIndentationAfterNewLine("4", 8); -verifyIndentationAfterNewLine("5", 8); \ No newline at end of file +verifyIndentationAfterNewLine("5", 8); diff --git a/tests/cases/fourslash/smartIndentObjectBindingPattern02.ts b/tests/cases/fourslash/smartIndentObjectBindingPattern02.ts index b4c751f58a176..a150751e63355 100644 --- a/tests/cases/fourslash/smartIndentObjectBindingPattern02.ts +++ b/tests/cases/fourslash/smartIndentObjectBindingPattern02.ts @@ -8,11 +8,9 @@ function verifyIndentationAfterNewLine(marker: string, indentation: number): voi verify.indentationIs(indentation); } -// TODO(arozga): fix this -// verifyIndentationAfterNewLine("1", 4); -verifyIndentationAfterNewLine("1", 0); +verifyIndentationAfterNewLine("1", 4); verifyIndentationAfterNewLine("2", 8); verifyIndentationAfterNewLine("3", 8); verifyIndentationAfterNewLine("4", 8); verifyIndentationAfterNewLine("5", 8); -verifyIndentationAfterNewLine("6", 0); \ No newline at end of file +verifyIndentationAfterNewLine("6", 0); diff --git a/tests/cases/fourslash/smartIndentObjectLiteralOpenBracketNewLine.ts b/tests/cases/fourslash/smartIndentObjectLiteralOpenBracketNewLine.ts index d20d7593e54f2..3480272ef5897 100644 --- a/tests/cases/fourslash/smartIndentObjectLiteralOpenBracketNewLine.ts +++ b/tests/cases/fourslash/smartIndentObjectLiteralOpenBracketNewLine.ts @@ -1,11 +1,11 @@ /// -//// var a = -//// {/*1*/} +//// var a =/*1*/ +//// {/*2*/} //// //// var b = { -//// outer: -//// {/*2*/} +//// outer:/*3*/ +//// {/*4*/} //// } function verifyIndentationAfterNewLine(marker: string, indentation: number): void { @@ -15,4 +15,6 @@ function verifyIndentationAfterNewLine(marker: string, indentation: number): voi } verifyIndentationAfterNewLine("1", 0); -verifyIndentationAfterNewLine("2", 4); \ No newline at end of file +verifyIndentationAfterNewLine("2", 4); +verifyIndentationAfterNewLine("3", 4); +verifyIndentationAfterNewLine("4", 8); diff --git a/tests/cases/fourslash/smartIndentOnListEnd.ts b/tests/cases/fourslash/smartIndentOnListEnd.ts new file mode 100644 index 0000000000000..21c6653fa95f1 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnListEnd.ts @@ -0,0 +1,12 @@ +/// + +////var a = [] +/////*1*/ +////| {} +/////*2*/ +////| ""; + +goTo.marker("1"); +verify.indentationIs(4) +goTo.marker("2"); +verify.indentationIs(4) \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts index 73bd7d388c4c1..5e7e033850a40 100644 --- a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts +++ b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts @@ -3,15 +3,18 @@ ////function f/*1*/(/*2*/a: A, /*3*/b:/*4*/B, c/*5*/, d: C/*6*/ -function verifyIndentationAfterNewLine(marker: string, indentation: number): void { +function verifyIndentationAfterNewLine(marker: string, indentation: number, positionWorkaround: number, expectedText: string): void { goTo.marker(marker); edit.insert("\n"); + // The next two lines are to workaround #13433 + goTo.position(positionWorkaround); + verify.textAtCaretIs(expectedText); verify.indentationIs(indentation); } -verifyIndentationAfterNewLine("1", 4); -verifyIndentationAfterNewLine("2", 4); -verifyIndentationAfterNewLine("3", 4); -verifyIndentationAfterNewLine("4", 8); -verifyIndentationAfterNewLine("5", 4); -verifyIndentationAfterNewLine("6", 4); \ No newline at end of file +verifyIndentationAfterNewLine("1", 4, 24, '('); +verifyIndentationAfterNewLine("2", 8, 34, 'a'); +verifyIndentationAfterNewLine("3", 8, 48, 'b'); +verifyIndentationAfterNewLine("4", 12, 63, 'B'); +verifyIndentationAfterNewLine("5", 8, 76, ','); +verifyIndentationAfterNewLine("6", 8, 83, '');