Merge pull request #28340 from saschanaz/listindent-revive

List position based formatting
This commit is contained in:
Daniel Rosenwasser 2018-11-09 15:34:16 -08:00 committed by GitHub
commit 02ca5bebbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 374 additions and 194 deletions

View File

@ -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 ((<TypeReferenceNode>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;

View File

@ -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<Node> | 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<Node> | undefined, start: number, end: number) {
return list && rangeContainsStartEnd(list, start, end) ? list : undefined;
}
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined {
if (node.parent) {
const { end } = node;
switch (node.parent.kind) {
case SyntaxKind.TypeReference:
return getListIfStartEndIsInListRange((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), end);
case SyntaxKind.ObjectLiteralExpression:
return (<ObjectLiteralExpression>node.parent).properties;
case SyntaxKind.ArrayLiteralExpression:
return (<ArrayLiteralExpression>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((<SignatureDeclaration>node.parent).typeParameters, start, end) ||
getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).parameters, start, end);
}
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.JSDocTemplateTag: {
const { typeParameters } = <ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag>node.parent;
return getListIfStartEndIsInListRange(typeParameters, node.getStart(sourceFile), end);
}
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression: {
const start = node.getStart(sourceFile);
return getListIfStartEndIsInListRange((<CallExpression | NewExpression>node.parent).typeArguments, start, end) ||
getListIfStartEndIsInListRange((<CallExpression | NewExpression>node.parent).arguments, start, end);
}
case SyntaxKind.VariableDeclarationList:
return getListIfStartEndIsInListRange((<VariableDeclarationList>node.parent).declarations, node.getStart(sourceFile), end);
case SyntaxKind.NamedImports:
case SyntaxKind.NamedExports:
return getListIfStartEndIsInListRange((<NamedImportsOrExports>node.parent).elements, node.getStart(sourceFile), end);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return getListIfStartEndIsInListRange((<ObjectBindingPattern | ArrayBindingPattern>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 {
function getListByPosition(pos: number, node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined {
if (!node) {
return;
}
return getListByRange(pos, pos, node, sourceFile);
}
function getListByRange(start: number, end: number, node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined {
switch (node.kind) {
case SyntaxKind.TypeReference:
return getListIfVisualStartEndIsInListRange((<TypeReferenceNode>node).typeArguments, start, end, node, sourceFile);
case SyntaxKind.ObjectLiteralExpression:
return getListIfVisualStartEndIsInListRange((<ObjectLiteralExpression>node).properties, start, end, node, sourceFile);
case SyntaxKind.ArrayLiteralExpression:
return getListIfVisualStartEndIsInListRange((<ArrayLiteralExpression>node).elements, start, end, node, sourceFile);
case SyntaxKind.TypeLiteral:
return getListIfVisualStartEndIsInListRange((<TypeLiteralNode>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((<SignatureDeclaration>node).typeParameters, start, end, node, sourceFile) ||
getListIfVisualStartEndIsInListRange((<SignatureDeclaration>node).parameters, start, end, node, sourceFile);
}
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.JSDocTemplateTag: {
const { typeParameters } = <ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag>node;
return getListIfVisualStartEndIsInListRange(typeParameters, start, end, node, sourceFile);
}
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression: {
return getListIfVisualStartEndIsInListRange((<CallExpression>node).typeArguments, start, end, node, sourceFile) ||
getListIfVisualStartEndIsInListRange((<CallExpression>node).arguments, start, end, node, sourceFile);
}
case SyntaxKind.VariableDeclarationList:
return getListIfStartEndIsInListRange((<VariableDeclarationList>node).declarations, start, end);
case SyntaxKind.NamedImports:
case SyntaxKind.NamedExports:
return getListIfVisualStartEndIsInListRange((<NamedImportsOrExports>node).elements, start, end, node, sourceFile);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return getListIfVisualStartEndIsInListRange((<ObjectBindingPattern | ArrayBindingPattern>node).elements, start, end, node, sourceFile);
}
}
function getActualIndentationForListStartLine(list: NodeArray<Node>, sourceFile: SourceFile, options: EditorSettings): number {
if (!list) {
return Value.Unknown;
}
return findColumnForFirstNonWhitespaceCharacterInLine(sourceFile.getLineAndCharacterOfPosition(list.pos), sourceFile, options);
}
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) {
return deriveActualIndentationFromList(containingList, index, sourceFile, options);
}
}
return Value.Unknown;
}
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;
}
const fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end);
const startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end);
if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) {
return Value.Unknown;
}
return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options);
}
return Value.Unknown;
function getStartingExpression(node: Expression) {
while (true) {
switch (node.kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
node = (<PropertyAccessExpression | CallExpression | NewExpression | ElementAccessExpression | PropertyAccessExpression>node).expression;
break;
default:
return node;
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<Node>, index: number, sourceFile: SourceFile, options: EditorSettings): number {

View File

@ -1,52 +1,160 @@
/// <reference path='fourslash.ts' />
////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);
/// <reference path='fourslash.ts' />
////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
);`)

View File

@ -0,0 +1,37 @@
/// <reference path='fourslash.ts' />
////function _uniteVertices<p extends string, a>(
//// minority: Pinned<p, Vertex<a>>,
//// majorityCounter: number,
//// majority: Pinned<p, Vertex<a>>
////): {
//// /*start*/
//// majorityCounter: number;
//// vertecis: Pinned<p, {
//// oldVertexId: VertexId;
//// vertex: Vertex<a>;
//// }>;
//// /*end*/
//// } {
////}
format.document();
verify.currentFileContentIs(`function _uniteVertices<p extends string, a>(
minority: Pinned<p, Vertex<a>>,
majorityCounter: number,
majority: Pinned<p, Vertex<a>>
): {
majorityCounter: number;
vertecis: Pinned<p, {
oldVertexId: VertexId;
vertex: Vertex<a>;
}>;
} {
}`);
goTo.marker("start");
verify.indentationIs(4);
goTo.marker("end");
verify.indentationIs(4);

View File

@ -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);
}
}

View File

@ -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);
verifyIndentationAfterNewLine("5", 8);

View File

@ -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);
verifyIndentationAfterNewLine("6", 0);

View File

@ -1,11 +1,11 @@
/// <reference path='fourslash.ts'/>
//// 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);
verifyIndentationAfterNewLine("2", 4);
verifyIndentationAfterNewLine("3", 4);
verifyIndentationAfterNewLine("4", 8);

View File

@ -0,0 +1,12 @@
/// <reference path='fourslash.ts'/>
////var a = []
/////*1*/
////| {}
/////*2*/
////| "";
goTo.marker("1");
verify.indentationIs(4)
goTo.marker("2");
verify.indentationIs(4)

View File

@ -3,15 +3,18 @@
////function f<A,B,C>/*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);
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, '');