From 686d1c60deb618040211c53c37590cf70187c74a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 21:33:39 -0700 Subject: [PATCH] A more complete isCompletedNode. --- src/harness/fourslash.ts | 8 ++-- src/services/formatting/smartIndenter.ts | 45 +++++++++++++++---- src/services/utilities.ts | 4 ++ tests/cases/fourslash/indentation.ts | 8 ++-- ...artIndentNonterminatedArgumentListAtEOF.ts | 2 +- 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index d8b7c358a55..0ae29a6ec87 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1621,8 +1621,9 @@ module FourSlash { this.taoInvalidReason = 'verifyIndentationAtCurrentPosition NYI'; var actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition); - if (actual != numberOfSpaces) { - this.raiseError('verifyIndentationAtCurrentPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual); + var lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); + if (actual !== numberOfSpaces) { + this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } } @@ -1630,8 +1631,9 @@ module FourSlash { this.taoInvalidReason = 'verifyIndentationAtPosition NYI'; var actual = this.getIndentation(fileName, position); + var lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { - this.raiseError('verifyIndentationAtPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual); + this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index f1d0935c132..38ed4cf8442 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -429,46 +429,74 @@ module ts.formatting { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.TypeLiteral: case SyntaxKind.Block: case SyntaxKind.ModuleBlock: case SyntaxKind.CaseBlock: return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile); case SyntaxKind.CatchClause: return isCompletedNode((n).block, sourceFile); - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.CallSignature: + case SyntaxKind.NewExpression: + if (!(n).arguments) { + return true; + } + // fall through case SyntaxKind.CallExpression: case SyntaxKind.ConstructSignature: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.ParenthesizedType: return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile); + + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return isCompletedNode((n).type, sourceFile); + + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: + case SyntaxKind.CallSignature: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: case SyntaxKind.ArrowFunction: - return !(n).body || isCompletedNode((n).body, sourceFile); + if ((n).body) { + return isCompletedNode((n).body, sourceFile); + } + + return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile) || + (n).typeParameters && hasChildOfKind(n, SyntaxKind.GreaterThanToken, sourceFile) + case SyntaxKind.ModuleDeclaration: return (n).body && isCompletedNode((n).body, sourceFile); + case SyntaxKind.IfStatement: if ((n).elseStatement) { return isCompletedNode((n).elseStatement, sourceFile); } return isCompletedNode((n).thenStatement, sourceFile); + case SyntaxKind.ExpressionStatement: return isCompletedNode((n).expression, sourceFile); + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.IndexSignature: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TupleType: return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile); + case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: - // there is no such thing as terminator token for CaseClause\DefaultClause so for simplicitly always consider them non-completed + // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed return false; + case SyntaxKind.ForStatement: - return isCompletedNode((n).statement, sourceFile); case SyntaxKind.ForInStatement: - return isCompletedNode((n).statement, sourceFile); case SyntaxKind.ForOfStatement: - return isCompletedNode((n).statement, sourceFile); case SyntaxKind.WhileStatement: - return isCompletedNode((n).statement, sourceFile); + return isCompletedNode((n).statement, sourceFile); case SyntaxKind.DoStatement: // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')'; var hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile); @@ -476,6 +504,7 @@ module ts.formatting { return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile); } return isCompletedNode((n).statement, sourceFile); + default: return true; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index e0ff5293546..70c8eada5b7 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -79,6 +79,10 @@ module ts { }; } + export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): boolean { + return !!findChildOfKind(n, kind, sourceFile); + } + export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node { return forEach(n.getChildren(sourceFile), c => c.kind === kind && c); } diff --git a/tests/cases/fourslash/indentation.ts b/tests/cases/fourslash/indentation.ts index 2a2090c1d87..356d076b9f2 100644 --- a/tests/cases/fourslash/indentation.ts +++ b/tests/cases/fourslash/indentation.ts @@ -176,8 +176,8 @@ ////// the purpose of this test is to verity smart indent ////// works for unterminated function arguments at the end of a file. ////function unterminatedListIndentation(a, -////{| "indent": 0 |} +////{| "indent": 4 |} -test.markers().forEach((marker) => { - verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); - }); +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts b/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts index b2b1f746a32..a533eca1d67 100644 --- a/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts +++ b/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts @@ -4,4 +4,4 @@ /////**/ goTo.marker(); -verify.indentationIs(0); +verify.indentationIs(4);