Repository navigation
PSUseConsistentIndentation: Indentation wrong if pipeline is wrapped in parentheses #1407
Description
Activity
bergmeister commented
on Feb 9, 2020 CollaboratorMore actionsThanks for raising it and the level of detail. Very interesting and important. Next week is busy for me, but it's definitely on my tracker to investigate more. In the meantime I verified that the behaviour repros in master as well.
At first I thought this could be due to code ofPipelineIndentationbut I also see it happens with any available setting of that option, therefore I am thinking there is also a chance it might be something else.- added and removed
on Feb 11, 2020 bergmeister commented
on Mar 3, 2020 CollaboratorMore actionsA more minimalistic repro is:
(foo | bar { baz })The parenthesis are 'causing' it to happen. I will investigate now what the root cause is in terms of code
Reacted by Felix Beckerbergmeister commented
on Mar 3, 2020 CollaboratorMore actionsUpdate: The indentation being one level too much on line 2 and 3 of the above minimal repro is being 'caused' by the left parenthesis and left brace both causing the indentation to increase by one level, which is one level too much here due to them both applying in this scenario. The code that does this is here:
PSScriptAnalyzer/Rules/UseConsistentIndentation.cs
Lines 145 to 152 in f389aa4
switch (token.Kind) { case TokenKind.AtCurly: case TokenKind.AtParen: case TokenKind.LParen: case TokenKind.LCurly: case TokenKind.DollarParen: AddViolation(token, indentationLevel++, diagnosticRecords, ref onNewLine);
I didn't write this code but I think the idea is to provide indentation for the following scenarios that both apply in this special case# Indentation after brace if ($foo) { bar } # Indendation of multi-line condition if ($foo -and $bar) { ... }
Do you agree with my reasoning of isolating this special case or do you see more cases?
This behaviour is actually not new and happens also with older version such as e.g. 1.17.1 and 1.18.1, therefore is not a regression or related to the new
PipelineIndentationsetting.
Unfortunately the formatter rules are token based, therefore writing or modifying logic is very hard as logical decisions are generic and often lack context of the surrounding syntax. I will have a think but I cannot guarantee I can think of a good solution to this without breaking something else....Sydney Smith (@SydneyhSmith) Since this is not a regression, I consider it to have lower priority, is it worthwhile having a label of its own?
bergmeister commented
on Apr 4, 2020 CollaboratorMore actionsFelix Becker (@felixfbecker) Thinking about this again, it feels like the best fix for this would be to tweak the logic for
(parenthesis to only increase indentation on the next line if it is being preceded by certain language keywords that have an opening parenthesis afterwards, which are:if,elseif,else,for,foreach,whileorswitch.
What do you think Rob Holt (@rjmholt) ?You probably still want to allow something like this though:
$result = ( Get-Something | Get-SomethingElse | Get-Another ).Property
(it would look bad if line 2 was not indented)
bergmeister commented
on May 1, 2020 CollaboratorMore actionsFelix Becker (@felixfbecker) Good thinking. Thinking harder about the different use cases, it feels like
(should not increase indentation when the(opening parenthesis is preceded by aTokenwith aKindproperty ofTokenKind.NewLineunless it is followed by aTokenwith aKindproperty ofTokenKind.NewLine. PowerShell's tokenizer skips whitespace btw. What do you think? I opened a PR with that below.We should identify some cases where we think parens should and shouldn't increase indentation before proceeding I think, so that we don't end up oscillating between solutions that go too far in either direction.
I don't often use parens like this myself, so I don't have as good a feel for it as you might.
My thinking is:
- This rule should care about ASTs, not tokens, since
if ($x -and $y)is different to($x -and $y)in my mind in terms of how I indent them. The more specific we try to get to a syntactic structure, the more work we must do building the context for tokens, which is what ASTs are designed to be. - Hanging clauses in a condition seems to be something that demands a newline and indentation in some cases
- Indentation in other paren expressions should probably only be increased for scriptblocks or something that isn't intrinsic to the parens; the parens should be invisible to the formatter
- The example in PSUseConsistentIndentation: Indentation wrong if pipeline is wrapped in parentheses #1407 (comment) is fairly pathological I think, since paren expressions only allow one expression, so there's no benefit to putting things on new lines like that. I'm not sure what to do about that scenario particularly, but it seems to be its own scenario separate from paren indentation
- This rule should care about ASTs, not tokens, since
Before submitting a bug report:
Steps to reproduce
Format one of these files:
https://github.com/pcgeek86/PSGitHub/blob/5fa152568f3218843bbec97c5604d6b16b03066f/Functions/Private/ConvertTo-ColoredPatch.ps1
https://github.com/pcgeek86/PSGitHub/blob/5fa152568f3218843bbec97c5604d6b16b03066f/Functions/Public/Merge-GitHubPullRequest.ps1
https://github.com/pcgeek86/PSGitHub/blob/5fa152568f3218843bbec97c5604d6b16b03066f/Functions/Public/New-GitHubReleaseAsset.ps1
https://github.com/pcgeek86/PSGitHub/blob/5fa152568f3218843bbec97c5604d6b16b03066f/Functions/Public/New-GitHubReview.ps1
https://github.com/pcgeek86/PSGitHub/blob/5fa152568f3218843bbec97c5604d6b16b03066f/Functions/Public/Set-GitHubToken.ps1
with
Expected behavior
Should stay the same
Actual behavior
Following indentation is too much, one for every pair of () it seems, e.g.:
Environment data