-
Notifications
You must be signed in to change notification settings - Fork 406
Description
Summary
PSUseConsistentIndentation incorrectly indents hashtable body content when the hashtable is inside a method call parenthesis (e.g., .Add(@{ ... })). The formatter treats the @{ opening as an additional indentation level relative to the method call position, producing excessive indentation instead of indenting consistently from the line start.
This was originally reported as PowerShell/vscode-powershell#5397, where a maintainer confirmed it belongs in PSScriptAnalyzer. That issue was auto-closed awaiting author feedback.
Steps to Reproduce
# PSScriptAnalyzer 1.24.0 / PowerShell 7.5.4
# Minimal repro - only PSUseConsistentIndentation enabled
$code = @'
$list.Add([PSCustomObject]@{
Name = "Test"
Value = 123
})
'@
$settings = @{
IncludeRules = @("PSUseConsistentIndentation")
Rules = @{
PSUseConsistentIndentation = @{
Enable = $true
IndentationSize = 4
Kind = "space"
}
}
}
Invoke-Formatter -ScriptDefinition $code -Settings $settingsExpected Behavior
Hashtable properties should be indented by one level (4 spaces) from the line start, regardless of where @{ appears on the line:
$list.Add([PSCustomObject]@{
Name = "Test"
Value = 123
})Actual Behavior
Properties are indented to the @{ column position (8 spaces), and the closing }) gets its own indentation level too:
$list.Add([PSCustomObject]@{
Name = "Test"
Value = 123
})Additional Test Cases
The problem compounds with deeper nesting:
# Input:
foreach ($item in $items) {
$results.Add([PSCustomObject]@{
Name = $item.Name
Value = $item.Value
Status = "OK"
})
}
# Formatted (actual) - 12 spaces for hashtable body:
foreach ($item in $items) {
$results.Add([PSCustomObject]@{
Name = $item.Name
Value = $item.Value
Status = "OK"
})
}
# Expected - 8 spaces (one level deeper than the foreach body):
foreach ($item in $items) {
$results.Add([PSCustomObject]@{
Name = $item.Name
Value = $item.Value
Status = "OK"
})
}Standalone hashtables (not inside method calls) format correctly:
# This formats correctly with 4-space indent:
$obj = [PSCustomObject]@{
Name = "Test"
Value = 123
}Root Cause Analysis
PSUseConsistentIndentation appears to count ( as an indentation-increasing token, then also counts @{ as another level. For standalone hashtables like $x = @{, the = doesn't increase indentation so only @{ counts — producing 4 spaces correctly. But inside .Add(@{, the ( adds one level and @{ adds another, producing 8 spaces (2 × 4).
Impact
This is a common PowerShell pattern — building lists of [PSCustomObject] via .Add() is idiomatic. The excessive indentation forces a choice between:
- Disabling
PSUseConsistentIndentationentirely - Accepting unintuitively deep indentation
- Disabling
powershell.codeFormatting.alignPropertyValuePairs(which also disables desirable alignment on standalone hashtables) - Disabling format-on-save for PowerShell files
When combined with PSAlignAssignmentStatement.CheckHashtable, the problem is amplified because value alignment is calculated from the already-wrong base indentation.
Workaround
Setting powershell.codeFormatting.alignPropertyValuePairs: false in VS Code mitigates the worst visual impact but also disables alignment on standalone hashtables where it's desirable.
Environment
- PSScriptAnalyzer: 1.24.0
- PowerShell: 7.5.4
- OS: Linux (also reported on Windows 11 in vscode-powershell#5397)