diff --git a/Rules/UseConsistentIndentation.cs b/Rules/UseConsistentIndentation.cs index 4dc2ed6ca..b36e2c91f 100644 --- a/Rules/UseConsistentIndentation.cs +++ b/Rules/UseConsistentIndentation.cs @@ -387,6 +387,14 @@ private static int GetCommentRunIndentationOffset( int firstCommentIndex = tokenIndex; int currentLine = tokens[tokenIndex].Extent.StartLineNumber; int precedingIndex = tokenIndex - 1; + while (precedingIndex >= 0 && + tokens[precedingIndex].Kind == TokenKind.Comment && + tokens[precedingIndex].Extent.StartLineNumber == currentLine) + { + firstCommentIndex = precedingIndex; + precedingIndex--; + } + while (precedingIndex >= 0 && (tokens[precedingIndex].Kind == TokenKind.NewLine || tokens[precedingIndex].Kind == TokenKind.LineContinuation)) @@ -395,17 +403,32 @@ private static int GetCommentRunIndentationOffset( if (precedingIndex < 0 || tokens[precedingIndex].Kind != TokenKind.Comment || HasCodeAfterCommentOnSameLine(tokens, precedingIndex) || - tokens[precedingIndex].Extent.EndLineNumber != currentLine - 1 || - (precedingIndex > 0 && - tokens[precedingIndex - 1].Kind != TokenKind.NewLine && - tokens[precedingIndex - 1].Kind != TokenKind.LineContinuation)) + tokens[precedingIndex].Extent.EndLineNumber != currentLine - 1) { break; } - firstCommentIndex = precedingIndex; - currentLine = tokens[precedingIndex].Extent.StartLineNumber; - precedingIndex--; + int previousCommentLine = tokens[precedingIndex].Extent.StartLineNumber; + int firstCommentOnPreviousLine = precedingIndex; + int precedingCommentIndex = precedingIndex - 1; + while (precedingCommentIndex >= 0 && + tokens[precedingCommentIndex].Kind == TokenKind.Comment && + tokens[precedingCommentIndex].Extent.StartLineNumber == previousCommentLine) + { + firstCommentOnPreviousLine = precedingCommentIndex; + precedingCommentIndex--; + } + + if (precedingCommentIndex >= 0 && + tokens[precedingCommentIndex].Kind != TokenKind.NewLine && + tokens[precedingCommentIndex].Kind != TokenKind.LineContinuation) + { + break; + } + + firstCommentIndex = firstCommentOnPreviousLine; + currentLine = previousCommentLine; + precedingIndex = precedingCommentIndex; } commentRunStartsAfterLineContinuation = @@ -413,19 +436,34 @@ private static int GetCommentRunIndentationOffset( tokens[firstCommentIndex - 1].Kind == TokenKind.LineContinuation; commentRunStartsAfterPipeline = PreviousLineEndedWithPipe(tokens, firstCommentIndex, tokens[firstCommentIndex]); - int leastIndentedColumn = tokens[firstCommentIndex].Extent.StartColumnNumber; - for (int nextCommentIndex = firstCommentIndex + 2; - nextCommentIndex < tokens.Length && - (tokens[nextCommentIndex - 1].Kind == TokenKind.NewLine || - tokens[nextCommentIndex - 1].Kind == TokenKind.LineContinuation) && - tokens[nextCommentIndex].Kind == TokenKind.Comment && - !HasCodeAfterCommentOnSameLine(tokens, nextCommentIndex) && - tokens[nextCommentIndex].Extent.StartLineNumber == tokens[nextCommentIndex - 2].Extent.EndLineNumber + 1; - nextCommentIndex += 2) + int leastIndentedColumn = int.MaxValue; + int nextCommentIndex = firstCommentIndex; + while (nextCommentIndex < tokens.Length && + tokens[nextCommentIndex].Kind == TokenKind.Comment) { - leastIndentedColumn = Math.Min( - leastIndentedColumn, - tokens[nextCommentIndex].Extent.StartColumnNumber); + int currentCommentLine = tokens[nextCommentIndex].Extent.StartLineNumber; + while (nextCommentIndex < tokens.Length && + tokens[nextCommentIndex].Kind == TokenKind.Comment && + tokens[nextCommentIndex].Extent.StartLineNumber == currentCommentLine) + { + leastIndentedColumn = Math.Min( + leastIndentedColumn, + tokens[nextCommentIndex].Extent.StartColumnNumber); + nextCommentIndex++; + } + + if (nextCommentIndex + 1 >= tokens.Length || + (tokens[nextCommentIndex].Kind != TokenKind.NewLine && + tokens[nextCommentIndex].Kind != TokenKind.LineContinuation) || + tokens[nextCommentIndex + 1].Kind != TokenKind.Comment || + HasCodeAfterCommentOnSameLine(tokens, nextCommentIndex + 1) || + tokens[nextCommentIndex + 1].Extent.StartLineNumber != + tokens[nextCommentIndex - 1].Extent.EndLineNumber + 1) + { + break; + } + + nextCommentIndex++; } return tokens[tokenIndex].Extent.StartColumnNumber - diff --git a/Tests/Rules/UseConsistentIndentation.tests.ps1 b/Tests/Rules/UseConsistentIndentation.tests.ps1 index cd295dca8..18439de07 100644 --- a/Tests/Rules/UseConsistentIndentation.tests.ps1 +++ b/Tests/Rules/UseConsistentIndentation.tests.ps1 @@ -268,6 +268,19 @@ Write-Output ` Should -Be $scriptDefinition } + It 'Should preserve indentation when a comment-only line contains multiple block comments' { + $scriptDefinition = @' +if ($a) { + <# first #> <# second #> + # nested +} +'@ + $settings.Rules.PSUseConsistentIndentation.PipelineIndentation = 'NoIndentation' + + Invoke-Formatter -ScriptDefinition $scriptDefinition -Settings $settings | + Should -Be $scriptDefinition + } + It 'Should preserve continuation indentation before a block-comment-prefixed argument' { $scriptDefinition = @' Write-Output ` @@ -280,6 +293,32 @@ Write-Output ` Should -Be $scriptDefinition } + It 'Should preserve continuation indentation after multiple inline block comments' { + $scriptDefinition = @' +Write-Output ` + <# first #> <# second #> + -InputObject 'value' +'@ + $settings.Rules.PSUseConsistentIndentation.PipelineIndentation = 'NoIndentation' + + Invoke-Formatter -ScriptDefinition $scriptDefinition -Settings $settings | + Should -Be $scriptDefinition + } + + It 'Should preserve indentation with many adjacent block comments' { + $comments = (1..16 | ForEach-Object { "<# comment $_ #>" }) -join ' ' + $scriptDefinition = @( + 'if ($a) {' + " $comments" + ' # nested' + '}' + ) -join "`n" + $settings.Rules.PSUseConsistentIndentation.PipelineIndentation = 'NoIndentation' + + Invoke-Formatter -ScriptDefinition $scriptDefinition -Settings $settings | + Should -Be $scriptDefinition + } + It 'Should preserve indentation when the first comment is not the least-indented with indentation' -TestCases @( @{ Kind = 'space'; Indentation = ' ' } @{ Kind = 'tab'; Indentation = "`t" }