Skip to content

Commit

Permalink
Fix Indentation of mulitline command with backticks after comment line (
Browse files Browse the repository at this point in the history
PowerShell#1318)

* try increase indentation after comment

* make line after comment in multi line command with line continuation indent correctly and add tests. TODO: make it work for more than 1 line as well

* Make it work for continued lines as well. Question: what if line continuations and pipelines are mixed?

* tweak c# style and add more test cases

* rename indices for better readability to address PR feedback
  • Loading branch information
bergmeister committed Aug 21, 2019
1 parent b34eec7 commit 45cdba0
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 13 deletions.
31 changes: 18 additions & 13 deletions Rules/UseConsistentIndentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
var indentationLevel = 0;
var onNewLine = true;
var pipelineAsts = ast.FindAll(testAst => testAst is PipelineAst && (testAst as PipelineAst).PipelineElements.Count > 1, true);
for (int k = 0; k < tokens.Length; k++)
for (int tokenIndex = 0; tokenIndex < tokens.Length; tokenIndex++)
{
var token = tokens[k];
var token = tokens[tokenIndex];

if (token.Kind == TokenKind.EndOfInput)
{
Expand All @@ -151,8 +151,8 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
break;

case TokenKind.Pipe:
bool pipelineIsFollowedByNewlineOrLineContinuation = k < tokens.Length - 1 && k > 0 &&
(tokens[k + 1].Kind == TokenKind.NewLine || tokens[k + 1].Kind == TokenKind.LineContinuation);
bool pipelineIsFollowedByNewlineOrLineContinuation = tokenIndex < tokens.Length - 1 && tokenIndex > 0 &&
(tokens[tokenIndex + 1].Kind == TokenKind.NewLine || tokens[tokenIndex + 1].Kind == TokenKind.LineContinuation);
if (!pipelineIsFollowedByNewlineOrLineContinuation)
{
break;
Expand All @@ -164,7 +164,7 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
}
if (pipelineIndentationStyle == PipelineIndentationStyle.IncreaseIndentationForFirstPipeline)
{
bool isFirstPipeInPipeline = pipelineAsts.Any(pipelineAst => PositionIsEqual(((PipelineAst)pipelineAst).PipelineElements[0].Extent.EndScriptPosition, tokens[k - 1].Extent.EndScriptPosition));
bool isFirstPipeInPipeline = pipelineAsts.Any(pipelineAst => PositionIsEqual(((PipelineAst)pipelineAst).PipelineElements[0].Extent.EndScriptPosition, tokens[tokenIndex - 1].Extent.EndScriptPosition));
if (isFirstPipeInPipeline)
{
AddViolation(token, indentationLevel++, diagnosticRecords, ref onNewLine);
Expand All @@ -191,19 +191,24 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
var tempIndentationLevel = indentationLevel;

// Check if the preceding character is an escape character
if (k > 0 && tokens[k - 1].Kind == TokenKind.LineContinuation)
if (tokenIndex > 0 && tokens[tokenIndex - 1].Kind == TokenKind.LineContinuation)
{
++tempIndentationLevel;
}
else

// check for comments in between multi-line commands with line continuation
if (tokenIndex > 2 && tokens[tokenIndex - 1].Kind == TokenKind.NewLine
&& tokens[tokenIndex - 2].Kind == TokenKind.Comment)
{
// Ignore comments
// Since the previous token is a newline token we start
// looking for comments at the token before the newline token.
int j = k - 2;
while (j > 0 && tokens[j].Kind == TokenKind.Comment)
int searchForPrecedingLineContinuationIndex = tokenIndex - 2;
while (searchForPrecedingLineContinuationIndex > 0 && tokens[searchForPrecedingLineContinuationIndex].Kind == TokenKind.Comment)
{
searchForPrecedingLineContinuationIndex--;
}

if (searchForPrecedingLineContinuationIndex >= 0 && tokens[searchForPrecedingLineContinuationIndex].Kind == TokenKind.LineContinuation)
{
--j;
tempIndentationLevel++;
}
}

Expand Down
51 changes: 51 additions & 0 deletions Tests/Rules/UseConsistentIndentation.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,25 @@ $testRootDirectory = Split-Path -Parent $directory

Import-Module (Join-Path $testRootDirectory "PSScriptAnalyzerTestHelper.psm1")


Describe "UseConsistentIndentation" {
BeforeAll {
function Invoke-FormatterAssertion {
param(
[string] $ScriptDefinition,
[string] $ExcpectedScriptDefinition,
[int] $NumberOfExpectedWarnings,
[hashtable] $Settings
)

# Unit test just using this rule only
$violations = Invoke-ScriptAnalyzer -ScriptDefinition $scriptDefinition -Settings $settings
$violations.Count | Should -Be $NumberOfExpectedWarnings -Because $ScriptDefinition
Invoke-Formatter -ScriptDefinition $scriptDefinition -Settings $settings | Should -Be $expected -Because $ScriptDefinition
# Integration test with all default formatting rules
Invoke-Formatter -ScriptDefinition $scriptDefinition | Should -Be $expected -Because $ScriptDefinition
}
}
BeforeEach {
$indentationUnit = ' '
$indentationSize = 4
Expand Down Expand Up @@ -107,6 +125,39 @@ function foo {
}

Context "When a multi-line command is given" {

It "When a comment is in the middle of a multi-line statement with preceding and succeeding line continuations" {
$scriptDefinition = @'
foo `
# comment
-bar `
-baz
'@
$expected = @'
foo `
# comment
-bar `
-baz
'@
Invoke-FormatterAssertion $scriptDefinition $expected 3 $settings
}

It "When a comment is in the middle of a multi-line statement with preceding pipeline and succeeding line continuation " {
$scriptDefinition = @'
foo |
# comment
bar `
-baz
'@
$expected = @'
foo |
# comment
bar `
-baz
'@
Invoke-FormatterAssertion $scriptDefinition $expected 3 $settings
}

It "Should find a violation if a pipleline element is not indented correctly" {
$def = @'
get-process |
Expand Down

0 comments on commit 45cdba0

Please sign in to comment.