rescan '>' and '/' if necessary

This commit is contained in:
Vladimir Matveev 2014-10-17 16:24:12 -07:00
parent 4e84377187
commit 6fe2b3ea90
2 changed files with 46 additions and 35 deletions

View File

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

View File

@ -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'.