From 6fe2b3ea90752623bcae92189843c15693b460b3 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 17 Oct 2014 16:24:12 -0700 Subject: [PATCH] rescan '>' and '/' if necessary --- src/services/formatting/format.ts | 35 +++++++++++++----- src/services/formatting/smartIndenter.ts | 46 +++++++++++------------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/services/formatting/format.ts b/src/services/formatting/format.ts index 9962b99dcb0..7a620c6b1ab 100644 --- a/src/services/formatting/format.ts +++ b/src/services/formatting/format.ts @@ -169,6 +169,16 @@ module ts.formatting { return { line: lineAndChar.line - 1, character: lineAndChar.character - 1 }; } + function rescanIfNecessary(scanner: Scanner, parent: Node): void { + var t = scanner.getToken(); + if (parent.kind === SyntaxKind.BinaryExpression && t === SyntaxKind.GreaterThanToken) { + scanner.reScanGreaterToken(); + } + else if (parent.kind === SyntaxKind.RegularExpressionLiteral && t === SyntaxKind.SlashToken) { + scanner.reScanSlashToken(); + } + } + function formatSpan(originalRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions, @@ -192,9 +202,9 @@ module ts.formatting { var lastTriviaWasNewLine = true; var edits: TextChange[] = []; - // advance the scaner scanner.scan(); - var currentTokenInfo = fetchNextTokenInfo(); + + var currentTokenInfo = fetchNextTokenInfo(enclosingNode); if (currentTokenInfo.token) { var startLine = getNonAdjustedLineAndCharacterFromPosition(enclosingNode.getStart(sourceFile), sourceFile).line; @@ -225,7 +235,12 @@ module ts.formatting { ); while (currentTokenInfo.token && node.end >= currentTokenInfo.token.end) { - currentTokenInfo = consumeCurrentToken(node, childContextNode, indentation); + if (SmartIndenter.nodeContentIsAlwaysIndented(node)) { + currentTokenInfo = consumeCurrentToken(node, childContextNode, indentation); + } + else { + currentTokenInfo = consumeCurrentToken(node, childContextNode, indentation); + } childContextNode = node; } @@ -273,7 +288,7 @@ module ts.formatting { var increaseIndentation = childStartLine !== nodeStartLine && !SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(node, child, childStartLine, sourceFile) && - SmartIndenter.nodeContentIsIndented(node, child); + SmartIndenter.shouldIndentChildNode(node, child); processNode(child, childContextNode, childStartLine, increaseIndentation ? indentation + options.IndentSize : indentation); childContextNode = node; @@ -281,11 +296,12 @@ module ts.formatting { } } - function fetchNextTokenInfo(): TokenInfo { + function fetchNextTokenInfo(parent: Node): TokenInfo { if (currentTokenInfo) { + var trivia = currentTokenInfo.trailingTrivia; lastTriviaWasNewLine = - currentTokenInfo.trailingTrivia && - currentTokenInfo.trailingTrivia[currentTokenInfo.trailingTrivia.length - 1].kind === SyntaxKind.NewLineTrivia; + trivia && + trivia[trivia.length - 1].kind === SyntaxKind.NewLineTrivia; } var leadingTrivia: TextRangeWithKind[]; @@ -296,6 +312,8 @@ module ts.formatting { var initialStartPos = startPos; while (startPos < originalRange.end) { + rescanIfNecessary(scanner, parent); + var t = scanner.getToken(); if (tokenRange && !isTrivia(t)) { @@ -303,7 +321,6 @@ module ts.formatting { break; } - // advance the cursor scanner.scan(); var item = { pos: startPos, end: scanner.getStartPos(), kind: t }; @@ -403,7 +420,7 @@ module ts.formatting { } - return fetchNextTokenInfo(); + return fetchNextTokenInfo(parent); } function insertIndentation(pos: number, indentation: number): void { diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index ff95035ebf9..4021c8b6788 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -37,7 +37,7 @@ module ts.formatting { var indentationDelta: number; while (current) { - if (positionBelongsToNode(current, position, sourceFile) && nodeContentIsIndented(current, previous)) { + if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) { currentStart = getStartLineAndCharacterForNode(current, sourceFile); if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) { @@ -93,7 +93,7 @@ module 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 (nodeContentIsIndented(parent, current) && !parentAndChildShareLine) { + if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) { indentationDelta += options.IndentSize; } @@ -274,33 +274,11 @@ module ts.formatting { return column; } - export function nodeContentIsIndented(parent: Node, child: Node): boolean { - switch (parent.kind) { + export function nodeContentIsAlwaysIndented(n: Node): boolean { + switch (n.kind) { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: - return true; - case SyntaxKind.ModuleDeclaration: - // ModuleBlock should take care of indentation - return false; - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.Method: - case SyntaxKind.FunctionExpression: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.Constructor: - // FunctionBlock should take care of indentation - return false; - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForStatement: - return child && child.kind !== SyntaxKind.Block; - case SyntaxKind.IfStatement: - return child && child.kind !== SyntaxKind.Block; - case SyntaxKind.TryStatement: - // TryBlock\CatchBlock\FinallyBlock should take care of indentation - return false; case SyntaxKind.ArrayLiteral: case SyntaxKind.Block: case SyntaxKind.FunctionBlock: @@ -324,6 +302,22 @@ module ts.formatting { } } + export function shouldIndentChildNode(parent: Node, child: Node): boolean { + if (nodeContentIsAlwaysIndented(parent)) { + return true; + } + switch (parent.kind) { + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.IfStatement: + return child && child.kind !== SyntaxKind.Block; + default: + return false; + } + } + /* * Checks if node ends with 'expectedLastToken'. * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'.