From 092900b62f6aa63de54b8c146e7133cd7307da9a Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 20 Oct 2014 15:53:49 -0700 Subject: [PATCH] adjust formatting scanner implementation --- src/services/formatting/format.ts | 17 ++- src/services/formatting/formattingScanner.ts | 153 +++++++++++-------- src/services/formatting/new/rules.ts | 5 + 3 files changed, 100 insertions(+), 75 deletions(-) diff --git a/src/services/formatting/format.ts b/src/services/formatting/format.ts index 2221674976a..e4d2ba6416d 100644 --- a/src/services/formatting/format.ts +++ b/src/services/formatting/format.ts @@ -190,7 +190,7 @@ module ts.formatting { formattingScanner.advance(); - if (formattingScanner.hasToken()) { + if (formattingScanner.isOnToken()) { var startLine = getNonAdjustedLineAndCharacterFromPosition(enclosingNode.getStart(sourceFile), sourceFile).line; processNode(enclosingNode, enclosingNode, startLine, initialIndentation); } @@ -215,8 +215,8 @@ module ts.formatting { // this eats up last tokens in the node // TODO: resync token info and consume it - while (formattingScanner.hasToken()) { - var tokenInfo = formattingScanner.consumeTokenAndTrailingTrivia(node); + while (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(node); if (node.end >= tokenInfo.token.end) { consumeTokenAndAdvance(tokenInfo, node, childContextNode, indentation); childContextNode = node; @@ -243,10 +243,11 @@ module ts.formatting { } var start = child.getStart(sourceFile); - while (formattingScanner.hasToken()) { - var tokenInfo = formattingScanner.consumeTokenAndTrailingTrivia(node); + while (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(node); if (start >= tokenInfo.token.end) { consumeTokenAndAdvance(tokenInfo, node, childContextNode, indentation); + childContextNode = node; } else { break; @@ -260,7 +261,7 @@ module ts.formatting { // childContextNode = node; //} - if (!formattingScanner.hasToken()) { + if (!formattingScanner.isOnToken()) { return; } @@ -270,7 +271,7 @@ module ts.formatting { // ensure that current token is inside child node if (isToken(child)) { - var tokenInfo = formattingScanner.consumeTokenAndTrailingTrivia(node); + var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end === child.end) { consumeTokenAndAdvance(tokenInfo, node, childContextNode, indentation); childContextNode = node; @@ -347,7 +348,7 @@ module ts.formatting { processTrivia(currentTokenInfo.trailingTrivia, parent, contextNode, indentation); } - if (formattingScanner.lastTrailingTriviaWasNewLine() && indentToken) { + if (lastTriviaWasNewLine && indentToken) { var indentNextTokenOrTrivia = true; if (currentTokenInfo.leadingTrivia) { for (var i = 0, len = currentTokenInfo.leadingTrivia.length; i < len; ++i) { diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index 8a988a9485e..bd95ad9324c 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -3,8 +3,8 @@ module ts.formatting { export interface FormattingScanner { advance(): void; - hasToken(): boolean; - consumeTokenAndTrailingTrivia(n: Node): TokenInfo; + isOnToken(): boolean; + readTokenInfo(n: Node): TokenInfo; lastTrailingTriviaWasNewLine(): boolean; } @@ -13,20 +13,23 @@ module ts.formatting { scanner.setText(sourceFile.text); scanner.setTextPos(enclosingNode.pos); + var wasNewLine: boolean = true; + var leadingTrivia: TextRangeWithKind[]; + var trailingTrivia: TextRangeWithKind[]; + var savedStartPos: number; + var lastTokenInfo: TokenInfo; + return { advance: advance, - consumeTokenAndTrailingTrivia: consumeTokenAndTrailingTrivia, - hasToken: hasToken, + readTokenInfo: readTokenInfo, + isOnToken: isOnToken, lastTrailingTriviaWasNewLine: lastTrailingTriviaWasNewLine } - var leadingTrivia: TextRangeWithKind[]; - var trailingTrivia: TextRangeWithKind[]; - var token: TextRangeWithKind; - var wasNewLine: boolean = true; - var savedStartPos: number; function advance(): void { + lastTokenInfo = undefined; + // accumulate leading trivia and token if (trailingTrivia) { Debug.assert(trailingTrivia.length); @@ -35,7 +38,6 @@ module ts.formatting { leadingTrivia = undefined; trailingTrivia = undefined; - token = undefined; if (scanner.getStartPos() === enclosingNode.pos) { scanner.scan(); @@ -46,99 +48,116 @@ module ts.formatting { while (startPos < range.end) { var t = scanner.getToken(); - if (token && !isTrivia(t)) { + if (!isTrivia(t)) { break; } - // advance to the next token + // consume leading trivia scanner.scan(); - var item = { pos: startPos, end: scanner.getStartPos(), kind: t - }; + } startPos = scanner.getStartPos(); - - if (isTrivia(t)) { - if (token) { - break; - } - else { - if (!leadingTrivia) { - leadingTrivia = []; - } - leadingTrivia.push(item); - } - } - else { - token = item; + + if (!leadingTrivia) { + leadingTrivia = []; } + leadingTrivia.push(item); } savedStartPos = scanner.getStartPos(); } - function consumeTokenAndTrailingTrivia(n: Node): TokenInfo { - Debug.assert(hasToken()); + function startsWithGreaterThanToken(t: SyntaxKind): boolean { + switch(t) { + case SyntaxKind.GreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanToken: + return true; + default: + return false; + } + } + + function readTokenInfo(n: Node): TokenInfo { + if (!isOnToken()) { + return { + leadingTrivia: leadingTrivia, + trailingTrivia: undefined, + token: undefined + }; + + } + if (lastTokenInfo) { + //return lastTokenInfo; + } + if (scanner.getStartPos() !== savedStartPos) { - scanner.setTextPos(savedStartPos) - } - - if (n.kind === SyntaxKind.BinaryExpression && token.kind === SyntaxKind.GreaterThanToken) { - scanner.setTextPos(token.pos); - scanner.scan(); - token.kind = scanner.reScanGreaterToken(); - token.end = scanner.getTextPos(); - scanner.scan(); - } - else if (n.kind === SyntaxKind.RegularExpressionLiteral && token.kind === SyntaxKind.SlashToken) { - scanner.setTextPos(token.pos); - scanner.scan(); - token.kind = scanner.reScanSlashToken(); - token.end = scanner.getTextPos(); + scanner.setTextPos(savedStartPos); scanner.scan(); } - // scan trailing trivia - var startPos = scanner.getStartPos(); - while (startPos < range.end) { - var t = scanner.getToken(); + var current = scanner.getToken(); + var endPos: number; + if (n.kind === SyntaxKind.BinaryExpression && startsWithGreaterThanToken((n).operator) && current === SyntaxKind.GreaterThanToken) { + current = scanner.reScanGreaterToken(); + Debug.assert((n).operator === current); + } + else if (n.kind === SyntaxKind.RegularExpressionLiteral && current === SyntaxKind.SlashToken) { + current = scanner.reScanSlashToken(); + Debug.assert(n.kind === current); + } - if (isTrivia(t) && t !== SyntaxKind.NewLineTrivia) { - if (!trailingTrivia) { - trailingTrivia = []; - } + endPos = scanner.getTextPos(); - var trivia = { - pos: startPos, - end: scanner.getStartPos(), - kind: t - } - trailingTrivia.push(trivia); - } - else { + var token: TextRangeWithKind = { + pos: scanner.getStartPos(), + end: scanner.getTextPos(), + kind: current + } + + while(scanner.getStartPos() < range.end) { + current = scanner.scan(); + if (!isTrivia(current)) { + break; + } + var trivia = { + pos: scanner.getStartPos(), + end: scanner.getTextPos(), + kind: current + }; + + if (!trailingTrivia) { + trailingTrivia = []; + } + + trailingTrivia.push(trivia); + + if (current === SyntaxKind.NewLineTrivia) { break; } - scanner.scan(); - startPos = scanner.getStartPos(); } - return { + return lastTokenInfo = { leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia, token: token } } - function hasToken(): boolean { - return token !== undefined; + function isOnToken(): boolean { + var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken(); + var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos(); + return startPos < range.end && current !== SyntaxKind.EndOfFileToken && !isTrivia(current); } function lastTrailingTriviaWasNewLine(): boolean { return wasNewLine; } } - } \ No newline at end of file diff --git a/src/services/formatting/new/rules.ts b/src/services/formatting/new/rules.ts index a283c2a63b9..612b8b07ad4 100644 --- a/src/services/formatting/new/rules.ts +++ b/src/services/formatting/new/rules.ts @@ -618,6 +618,11 @@ module ts.formatting { case SyntaxKind.ModuleDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.Block: + case SyntaxKind.TryBlock: + case SyntaxKind.CatchBlock: + case SyntaxKind.FinallyBlock: + case SyntaxKind.FunctionBlock: + case SyntaxKind.ModuleBlock: case SyntaxKind.SwitchStatement: return true; }