diff --git a/src/services/formatting/format.ts b/src/services/formatting/format.ts index 7b74dc97513..9962b99dcb0 100644 --- a/src/services/formatting/format.ts +++ b/src/services/formatting/format.ts @@ -362,21 +362,19 @@ module ts.formatting { } if (lastTriviaWasNewLine && indentToken) { - var indentNextTokenOrTrivia = true; - if (currentTokenInfo.leadingTrivia) { for (var i = 0, len = currentTokenInfo.leadingTrivia.length; i < len; ++i) { var triviaItem = currentTokenInfo.leadingTrivia[i]; if (rangeContainsRange(originalRange, triviaItem)) { switch (triviaItem.kind) { case SyntaxKind.MultiLineCommentTrivia: - // TODO + indentMultilineComment(triviaItem, indentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); indentNextTokenOrTrivia = false; break; case SyntaxKind.SingleLineCommentTrivia: if (indentNextTokenOrTrivia) { - insertIndentation(triviaItem.pos, indentation, sourceFile); + insertIndentation(triviaItem.pos, indentation); indentNextTokenOrTrivia = false; } break; @@ -391,7 +389,7 @@ module ts.formatting { } } - insertIndentation(currentTokenInfo.token.pos, indentation, sourceFile); + insertIndentation(currentTokenInfo.token.pos, indentation); //// TODO: remove //var tokenRange = getNonAdjustedLineAndCharacterFromPosition(currentTokenInfo.token.pos, sourceFile); @@ -408,7 +406,7 @@ module ts.formatting { return fetchNextTokenInfo(); } - function insertIndentation(pos: number, indentation: number, sourceFile: SourceFile): void { + function insertIndentation(pos: number, indentation: number): void { var tokenRange = getNonAdjustedLineAndCharacterFromPosition(pos, sourceFile); if (indentation !== tokenRange.character) { var indentationString = getIndentationString(indentation, options); @@ -417,6 +415,65 @@ module ts.formatting { } } + function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean) { + // split comment in lines + var startLine = getNonAdjustedLineAndCharacterFromPosition(commentRange.pos, sourceFile).line; + var endLine = getNonAdjustedLineAndCharacterFromPosition(commentRange.end, sourceFile).line; + + if (startLine === endLine) { + if (!firstLineIsIndented) { + // treat as single line comment + insertIndentation(commentRange.pos, indentation); + } + return; + } + else { + var parts: TextRange[] = []; + var startPos = commentRange.pos; + for (var line = startLine; line < endLine; ++line) { + var endOfLine = getEndLinePosition(line, sourceFile); + parts.push( {pos: startPos, end: endOfLine} ); + startPos = getStartPositionOfLine(line + 1, sourceFile); + } + + parts.push( {pos: startPos, end: commentRange.end} ); + } + + var startLinePos = getStartPositionOfLine(startLine, sourceFile); + + var nonWhitespaceColumnInFirstPart = + SmartIndenter.findFirstNonWhitespaceColumn(startLinePos, parts[0].pos, sourceFile, options); + + if (indentation === nonWhitespaceColumnInFirstPart) { + return; + } + + var startIndex = 0; + if (firstLineIsIndented) { + startIndex = 1; + startLine++; + } + + // shift all parts on the delta size + var delta = indentation - nonWhitespaceColumnInFirstPart; + for (var i = startIndex, len = parts.length; i < len; ++i, ++startLine) { + var startLinePos = getStartPositionOfLine(startLine, sourceFile); + var nonWhitespaceColumn = + i === 0 + ? nonWhitespaceColumnInFirstPart + : SmartIndenter.findFirstNonWhitespaceColumn(parts[i].pos, parts[i].end, sourceFile, options); + + var newIndentation = nonWhitespaceColumn + delta; + if (newIndentation > 0) { + var indentationString = getIndentationString(newIndentation, options); + recordReplace(startLinePos, nonWhitespaceColumn, indentationString); + } + else { + recordDelete(startLinePos, nonWhitespaceColumn); + } + } + } + function processTrivia(trivia: TextRangeWithKind[], parent: Node, contextNode: Node, currentIndentation: number): void { for (var i = 0, len = trivia.length; i < len; ++i) { var triviaItem = trivia[i]; diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 8fa1fc1928e..ff95035ebf9 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -65,41 +65,7 @@ module ts.formatting { return 0; } - - var parent: Node = current.parent; - var parentStart: LineAndCharacter; - - // walk upwards and collect indentations for pairs of parent-child nodes - // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' - while (parent) { - // check if current node is a list item - if yes, take indentation from it - var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1) { - return actualIndentation + indentationDelta; - } - - parentStart = sourceFile.getLineAndCharacterFromPosition(parent.getStart(sourceFile)); - var parentAndChildShareLine = - parentStart.line === currentStart.line || - childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); - - // try to fetch actual indentation for current node from source text - var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); - if (actualIndentation !== -1) { - return actualIndentation + indentationDelta; - } - - // 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) { - indentationDelta += options.IndentSize; - } - - current = parent; - currentStart = parentStart; - parent = current.parent; - } - - return indentationDelta; + return getIndentationForNode(current, currentStart, indentationDelta, sourceFile, options); } export function getIndentationForNode(current: Node, currentStart: LineAndCharacter, indentationDelta: number, sourceFile: SourceFile, options: EditorOptions): number { @@ -287,21 +253,24 @@ module ts.formatting { function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorOptions): number { var lineStart = sourceFile.getPositionFromLineAndCharacter(lineAndCharacter.line, 1); + return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); + } + + export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): number { var column = 0; - for (var i = 0; i < lineAndCharacter.character; ++i) { - var charCode = sourceFile.text.charCodeAt(lineStart + i); - if (!isWhiteSpace(charCode)) { + for (var pos = startPos; pos < endPos; ++pos) { + var ch = sourceFile.text.charCodeAt(pos); + if (!isWhiteSpace(ch)) { return column; } - if (charCode === CharacterCodes.tab) { - column += options.TabSize; + if (ch === CharacterCodes.tab) { + column += options.TabSize + (column % options.TabSize); } else { column++; } } - return column; } diff --git a/src/services/formatting/stringUtilities.ts b/src/services/formatting/stringUtilities.ts index 5f5d0b0fd4a..f6f8fc0319f 100644 --- a/src/services/formatting/stringUtilities.ts +++ b/src/services/formatting/stringUtilities.ts @@ -24,19 +24,21 @@ module ts.formatting { } else { var spacesString: string; - var index = indentation / options.IndentSize; + var quotient = Math.floor(indentation / options.IndentSize); + var remainder = indentation % options.IndentSize; if (!internedSpacesIndentation) { internedSpacesIndentation = []; } - if (internedSpacesIndentation[index] === undefined) { - internedSpacesIndentation[index] = spacesString = repeat(" ", indentation);; + if (internedSpacesIndentation[quotient] === undefined) { + spacesString = repeat(" ", options.IndentSize * quotient); + internedSpacesIndentation[quotient] = spacesString; } else { - spacesString = internedSpacesIndentation[index]; + spacesString = internedSpacesIndentation[quotient]; } - var remainder = indentation % options.IndentSize; + return remainder ? spacesString + repeat(" ", remainder) : spacesString; }