adjust formatting scanner implementation

This commit is contained in:
Vladimir Matveev 2014-10-20 15:53:49 -07:00
parent 381a2ec425
commit 092900b62f
3 changed files with 100 additions and 75 deletions

View File

@ -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) {

View File

@ -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((<BinaryExpression>n).operator) && current === SyntaxKind.GreaterThanToken) {
current = scanner.reScanGreaterToken();
Debug.assert((<BinaryExpression>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;
}
}
}

View File

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