@@ -5,8 +5,6 @@ function Invoke-DbatoolsFormatter {
5
5
6
6
. DESCRIPTION
7
7
Uses PSSA's Invoke-Formatter to format the target files and saves it without the BOM.
8
- Preserves manually aligned hashtables and assignment operators.
9
- Only writes files if formatting changes are detected.
10
8
11
9
. PARAMETER Path
12
10
The path to the ps1 file that needs to be formatted
@@ -59,48 +57,6 @@ function Invoke-DbatoolsFormatter {
59
57
$CBHRex = [regex ]' (?smi)\s+\<\#[^#]*\#\>'
60
58
$CBHStartRex = [regex ]' (?<spaces>[ ]+)\<\#'
61
59
$CBHEndRex = [regex ]' (?<spaces>[ ]*)\#\>'
62
-
63
- # Create custom formatter settings that preserve alignment
64
- $customSettings = @ {
65
- IncludeRules = @ (
66
- ' PSPlaceOpenBrace' ,
67
- ' PSPlaceCloseBrace' ,
68
- ' PSUseConsistentIndentation' ,
69
- ' PSUseConsistentWhitespace'
70
- )
71
- Rules = @ {
72
- PSPlaceOpenBrace = @ {
73
- Enable = $true
74
- OnSameLine = $true
75
- NewLineAfter = $true
76
- IgnoreOneLineBlock = $true
77
- }
78
- PSPlaceCloseBrace = @ {
79
- Enable = $true
80
- NewLineAfter = $false
81
- IgnoreOneLineBlock = $true
82
- NoEmptyLineBefore = $false
83
- }
84
- PSUseConsistentIndentation = @ {
85
- Enable = $true
86
- Kind = ' space'
87
- PipelineIndentation = ' IncreaseIndentationForFirstPipeline'
88
- IndentationSize = 4
89
- }
90
- PSUseConsistentWhitespace = @ {
91
- Enable = $true
92
- CheckInnerBrace = $true
93
- CheckOpenBrace = $true
94
- CheckOpenParen = $true
95
- CheckOperator = $false # This is key - don't mess with operator spacing
96
- CheckPipe = $true
97
- CheckPipeForRedundantWhitespace = $false
98
- CheckSeparator = $true
99
- CheckParameter = $false
100
- }
101
- }
102
- }
103
-
104
60
$OSEOL = " `n "
105
61
if ($psVersionTable.Platform -ne ' Unix' ) {
106
62
$OSEOL = " `r`n "
@@ -115,29 +71,13 @@ function Invoke-DbatoolsFormatter {
115
71
Stop-Function - Message " Cannot find or resolve $p " - Continue
116
72
}
117
73
118
- # Skip directories and non-PowerShell files
74
+ # Skip directories
119
75
if (Test-Path - Path $realPath - PathType Container) {
120
76
Write-Message - Level Verbose " Skipping directory: $realPath "
121
77
continue
122
78
}
123
79
124
- if ($realPath -notmatch ' \.ps1$|\.psm1$|\.psd1$' ) {
125
- Write-Message - Level Verbose " Skipping non-PowerShell file: $realPath "
126
- continue
127
- }
128
-
129
- try {
130
- $originalContent = Get-Content - Path $realPath - Raw - Encoding UTF8
131
- } catch {
132
- Stop-Function - Message " Unable to read file $realPath : $ ( $_.Exception.Message ) " - Continue
133
- }
134
-
135
- # If Get-Content failed, originalContent might be null or empty
136
- if (-not $originalContent ) {
137
- Write-Message - Level Verbose " Skipping empty or unreadable file: $realPath "
138
- continue
139
- }
140
-
80
+ $originalContent = Get-Content - Path $realPath - Raw - Encoding UTF8
141
81
$content = $originalContent
142
82
143
83
if ($OSEOL -eq " `r`n " ) {
@@ -150,93 +90,75 @@ function Invoke-DbatoolsFormatter {
150
90
}
151
91
}
152
92
153
- # Strip ending empty lines from both original and working content
93
+ # strip ending empty lines
154
94
$content = $content -replace " (?s)$OSEOL \s*$"
155
- $originalStripped = $originalContent -replace " (?s)$OSEOL \s*$"
156
95
157
- try {
158
- # Format the content
159
- $content = Invoke-Formatter - ScriptDefinition $content - Settings $customSettings - ErrorAction Stop
160
- # Also format the original to compare
161
- $originalFormatted = Invoke-Formatter - ScriptDefinition $originalStripped - Settings $customSettings - ErrorAction Stop
162
- } catch {
163
- Write-Message - Level Warning " Unable to format $realPath : $ ( $_.Exception.Message ) "
164
- continue
96
+ # Preserve aligned assignments before formatting
97
+ # Look for patterns with multiple spaces before OR after the = sign
98
+ $alignedPatterns = [regex ]::Matches($content , ' (?m)^\s*(\$\w+|\w+)\s{2,}=\s*.+$|^\s*(\$\w+|\w+)\s*=\s{2,}.+$' )
99
+ $placeholders = @ {}
100
+
101
+ foreach ($match in $alignedPatterns ) {
102
+ $placeholder = " ___ALIGNMENT_PLACEHOLDER_$ ( $placeholders.Count ) ___"
103
+ $placeholders [$placeholder ] = $match.Value
104
+ $content = $content.Replace ($match.Value , $placeholder )
165
105
}
166
106
167
- # Ensure both contents are strings before processing
168
- if (-not $content -or $content -isnot [string ]) {
169
- Write-Message - Level Warning " Formatter returned unexpected content type for $realPath "
170
- continue
107
+ try {
108
+ $formattedContent = Invoke-Formatter - ScriptDefinition $content - Settings CodeFormattingOTBS - ErrorAction Stop
109
+ if ($formattedContent ) {
110
+ $content = $formattedContent
111
+ }
112
+ } catch {
113
+ # Just silently continue - the formatting might still work partially
171
114
}
172
115
173
- if ( -not $originalFormatted -or $originalFormatted -isnot [ string ]) {
174
- Write-Message - Level Warning " Formatter returned unexpected content type for original in $realPath "
175
- continue
116
+ # Restore the aligned patterns
117
+ foreach ( $key in $placeholders .Keys ) {
118
+ $content = $content .Replace ( $key , $placeholders [ $key ])
176
119
}
177
120
178
- # Apply CBH fix to formatted content
121
+ # match the ending indentation of CBH with the starting one, see #4373
179
122
$CBH = $CBHRex.Match ($content ).Value
180
123
if ($CBH ) {
124
+ # get starting spaces
181
125
$startSpaces = $CBHStartRex.Match ($CBH ).Groups[' spaces' ]
182
126
if ($startSpaces ) {
127
+ # get end
183
128
$newCBH = $CBHEndRex.Replace ($CBH , " $startSpaces #>" )
184
129
if ($newCBH ) {
130
+ # replace the CBH
185
131
$content = $content.Replace ($CBH , $newCBH )
186
132
}
187
133
}
188
134
}
189
-
190
- # Apply CBH fix to original formatted content
191
- $originalCBH = $CBHRex.Match ($originalFormatted ).Value
192
- if ($originalCBH ) {
193
- $startSpaces = $CBHStartRex.Match ($originalCBH ).Groups[' spaces' ]
194
- if ($startSpaces ) {
195
- $newOriginalCBH = $CBHEndRex.Replace ($originalCBH , " $startSpaces #>" )
196
- if ($newOriginalCBH ) {
197
- $originalFormatted = $originalFormatted.Replace ($originalCBH , $newOriginalCBH )
198
- }
199
- }
200
- }
201
-
202
135
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
203
136
$correctCase = @ (
204
137
' DbaInstanceParameter'
205
138
' PSCredential'
206
139
' PSCustomObject'
207
140
' PSItem'
208
141
)
209
-
210
- # Process the formatted content
211
142
$realContent = @ ()
212
143
foreach ($line in $content.Split (" `n " )) {
213
144
foreach ($item in $correctCase ) {
214
145
$line = $line -replace $item , $item
215
146
}
147
+ # trim whitespace lines
216
148
$realContent += $line.Replace (" `t " , " " ).TrimEnd()
217
149
}
218
- $finalContent = $realContent -Join " $OSEOL "
219
150
220
- # Process the original formatted content the same way
221
- $originalProcessed = @ ()
222
- foreach ($line in $originalFormatted.Split (" `n " )) {
223
- foreach ($item in $correctCase ) {
224
- $line = $line -replace $item , $item
225
- }
226
- $originalProcessed += $line.Replace (" `t " , " " ).TrimEnd()
227
- }
228
- $originalFinalContent = $originalProcessed -Join " $OSEOL "
151
+ $newContent = $realContent -Join " $OSEOL "
229
152
230
- # Only write the file if there are actual changes
231
- if ($finalContent -ne $originalFinalContent ) {
232
- try {
233
- Write-Message - Level Verbose " Formatting changes detected in $realPath "
234
- [System.IO.File ]::WriteAllText($realPath , $finalContent , $Utf8NoBomEncoding )
235
- } catch {
236
- Stop-Function - Message " Unable to write file $realPath : $ ( $_.Exception.Message ) " - Continue
237
- }
153
+ # Compare without empty lines to detect real changes
154
+ $originalNonEmpty = ($originalContent -split " [\r\n]+" | Where-Object { $_.Trim () }) -join " "
155
+ $newNonEmpty = ($newContent -split " [\r\n]+" | Where-Object { $_.Trim () }) -join " "
156
+
157
+ if ($originalNonEmpty -ne $newNonEmpty ) {
158
+ [System.IO.File ]::WriteAllText($realPath , $newContent , $Utf8NoBomEncoding )
159
+ Write-Message - Level Verbose " Updated: $realPath "
238
160
} else {
239
- Write-Message - Level Verbose " No formatting changes needed for $realPath "
161
+ Write-Message - Level Verbose " No changes needed: $realPath "
240
162
}
241
163
}
242
164
}
0 commit comments