PSScriptAnalyzer: Formatting .where and .foreach methods is incorrect

When using the methods .where and .foreach in VS Code there’s an incorrect indentation of the closing brackets and a space is added after the method.

Expected behavior

@().foreach({

})

Actual behavior

@().foreach( {

    })

image

Environment data

Name                           Value
----                           -----
PSVersion                      5.1.14409.1018
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1018
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

> (Get-Module -ListAvailable PSScriptAnalyzer).Version | ForEach-Object { $_.ToString() }
1.17.1

Related to an issue in the PowerShell repo.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 2
  • Comments: 18 (1 by maintainers)

Most upvoted comments

Yup, IMO this treatment should be like parameters. You wouldn’t allow "foo".Substring( 1, 2 ). You’d fix that to "foo".Substring(1, 2)

Thank you for your time @bergmeister , I appreciate the effort. Would this also be included in the PoserShell Preview extension? As we’re using that one for the the PSReadLine support.

It seems weird that the first indentation is by design. If that would be the case, then the closing bracket needs one indentation too I believe.

Some examples, I think it should be like this:

@().foreach({

})

But if that is not possible, this would be the next best thing:

@().foreach( {

} )

Although we strongly recommend option A if possible. Keeps it more concise.

Also seeing this for ValidateScript. Before:

function Invoke-Build([ValidateScript({ /*...*/ })] $param1)
{ }

And after:

#                                     ⮦Space     ⮦No space
function Invoke-Build([ValidateScript( { /*...*/ })] $param1)
{ }

The spacing within the parenthesis is not symmetrical, and I’d expect it to be.

I just noticed looking at ShowPSAst.psm1, that this is not just unique to the specialized foreach() and where() methods, but also any method which may be passed a scriptblock literal.

        $script:BufferIsDirty = $false
        $scriptView.Add_TextChanged( { $script:BufferIsDirty = $true })
        $scriptView.Add_KeyUp( { OnTextBoxKeyUp @args })

https://github.com/lzybkr/ShowPSAst/blob/master/ShowPSAst.psm1

The file itself is inconsistent with relationship to spacing, I had formatted the script at some point while evaluating it and got the result shown above.

Adding my 2 cents:

$Processes.where( {
        ($_.ProcessName -eq 'PowerShell') -and ($_.Company -like 'Microsoft Corporation*')
    })

The indention here is correct. At the end of the first line the indent level is 2, not 1, because both ( and { each add to the indention, and on the last line, the indention only removes 1 level for the first character (token) starting the line leaving 1 indent, because that’s how logic works. This is because indention removal rules only looks at the first token for the entire line. This is definitely a VS Code thing as its how all other languages I use in VS Code behave as well.

What’s flawed is the lack of space missing from between the } and the ). Either add no space between ( and { (treating the formatting with the ‘special function’ methods specially) or add a space between } and ) so they are treated consistently.

I would vote to remove the space: image The brace is not next to a keyword, so this rule should not apply.

@DarkLite1, you should check out https://github.com/PowerShell/EditorSyntax/pull/156, for a sample of an improved grammar for PowerShell that will resolve issue 4. I have a version of the grammar file already in JSON format ready for VSCode in my own repository list.