|
25 | 25 | [string]
|
26 | 26 | $ModuleRoot
|
27 | 27 | )
|
28 |
| - |
| 28 | + |
29 | 29 | process
|
30 | 30 | {
|
31 | 31 | #region Find Language Files : $languageFiles
|
|
40 | 40 | }
|
41 | 41 | }
|
42 | 42 | #endregion Find Language Files : $languageFiles
|
43 |
| - |
| 43 | + |
44 | 44 | #region Find Keys : $foundKeys
|
45 | 45 | $foundKeys = foreach ($file in (Get-ChildItem -Path $ModuleRoot -Recurse | Where-Object Extension -match '^\.ps1$|^\.psm1$'))
|
46 | 46 | {
|
47 | 47 | $ast = (Read-PSMDScript -Path $file.FullName).Ast
|
| 48 | + #region Command Parameters |
48 | 49 | $commandAsts = $ast.FindAll({
|
49 | 50 | if ($args[0] -isnot [System.Management.Automation.Language.CommandAst]) { return $false }
|
50 | 51 | if ($args[0].CommandElements[0].Value -notmatch '^Invoke-PSFProtectedCommand$|^Write-PSFMessage$|^Stop-PSFFunction$') { return $false }
|
51 | 52 | if (-not ($args[0].CommandElements.ParameterName -match '^String$|^ActionString$')) { return $false }
|
52 | 53 | $true
|
53 | 54 | }, $true)
|
54 |
| - |
| 55 | + |
55 | 56 | foreach ($commandAst in $commandAsts)
|
56 | 57 | {
|
57 | 58 | $stringParam = $commandAst.CommandElements | Where-Object ParameterName -match '^String$|^ActionString$'
|
58 | 59 | $stringParamValue = $commandAst.CommandElements[($commandAst.CommandElements.IndexOf($stringParam) + 1)].Value
|
59 |
| - |
| 60 | + |
60 | 61 | $stringValueParam = $commandAst.CommandElements | Where-Object ParameterName -match '^StringValues$|^ActionStringValues$'
|
61 | 62 | if ($stringValueParam)
|
62 | 63 | {
|
|
72 | 73 | StringValues = $stringValueParamValue
|
73 | 74 | }
|
74 | 75 | }
|
75 |
| - |
76 |
| - # Additional checks for splatted commands |
77 |
| - # find all splatted commands |
78 |
| - $splattedVariables = $ast.FindAll( { |
79 |
| - if ($args[0] -isnot [System.Management.Automation.Language.VariableExpressionAst ]) { return $false } |
80 |
| - if (-not ($args[0].Splatted -eq $true)) { return $false } |
81 |
| - $true |
82 |
| - }, $true) |
83 |
| - |
84 |
| - foreach ($splattedVariable in $splattedVariables) |
85 |
| - { |
86 |
| - #get the variable name |
87 |
| - $splatParamName = $splattedVariable.VariablePath.UserPath |
88 |
| - if ($splatParamName) |
89 |
| - { |
90 |
| - # match the $param = @{ |
91 |
| - $splatParamNameRegex = "^\s?\`$$($splatParamName)\s?=\s?\@\{" |
92 |
| - # get all variable assignments where the |
93 |
| - # left side matches our param |
94 |
| - # operator is = |
95 |
| - # matches our assignment regex |
96 |
| - $splatAssignmentAsts = $ast.FindAll( { |
97 |
| - if ($args[0] -isnot [System.Management.Automation.Language.AssignmentStatementAst ]) { return $false } |
98 |
| - if (-not ($args[0].Left -match $splatParamName)) { return $false } |
99 |
| - if (-not ($args[0].Operator -eq 'Equals')) { return $false } |
100 |
| - if (-not ($args[0].Extent -match $splatParamNameRegex)) { return $false } |
101 |
| - $true |
102 |
| - }, $true) |
103 |
| - foreach ($splatAssignmentAst in $splatAssignmentAsts) |
104 |
| - { |
105 |
| - # get the hashtable |
106 |
| - $splatHashTable = $splatAssignmentAst.Right.Expression |
107 |
| - # see if its an empty assignment or null |
108 |
| - if ($splatHashTable -and $splatHashTable.KeyValuePairs.Count -gt 0) |
109 |
| - { |
110 |
| - # find any String or ActionString |
111 |
| - $splatParam = $splatAssignmentAst.Right.Expression.KeyValuePairs | Where-Object Item1 -match '^String$|^ActionString$' |
112 |
| - if ($splatParam) |
113 |
| - { |
114 |
| - # The kvp.item.extent.text returns nested quotes where as the commandast.extent.text doesn't so strip them off |
115 |
| - $splatParamValue = $splatParam.Item2.Extent.Text.Trim('"').Trim("'") |
116 |
| - # find any StringValue or ActionStringValue |
117 |
| - $splatValueParam = $splatAssignmentAst.Right.Expression.KeyValuePairs | Where-Object Item1 -match '^StringValues$|^ActionStringValues$' |
118 |
| - } |
119 |
| - if ($splatValueParam) |
120 |
| - { |
121 |
| - # The kvp.item.extent.text returns nested quotes whereas the commandast.extent.text doesn't so strip them off |
122 |
| - $splatValueParamValue = $splatValueParam.Item2.Extent.Text.Trim('"').Trim("'") |
123 |
| - } |
124 |
| - else { $splatValueParamValue = '' } |
125 |
| - |
126 |
| - [PSCustomObject]@{ |
127 |
| - PSTypeName = 'PSModuleDevelopment.String.ParsedItem' |
128 |
| - File = $file.FullName |
129 |
| - Line = $splatHashTable.Extent.StartLineNumber |
130 |
| - CommandName = $splattedVariable.Parent.CommandElements[0].Value |
131 |
| - String = $splatParamValue |
132 |
| - StringValues = $splatValueParamValue |
133 |
| - } |
134 |
| - } |
135 |
| - } |
136 |
| - } |
137 |
| - } |
138 |
| - |
| 76 | + #endregion Command Parameters |
| 77 | + |
| 78 | + #region Splatted Variables |
| 79 | + $splattedVariables = $ast.FindAll({ |
| 80 | + if ($args[0] -isnot [System.Management.Automation.Language.VariableExpressionAst]) { return $false } |
| 81 | + if (-not ($args[0].Splatted -eq $true)) { return $false } |
| 82 | + try { if ($args[0].Parent.CommandElements[0].Value -notmatch '^Invoke-PSFProtectedCommand$|^Write-PSFMessage$|^Stop-PSFFunction$') { return $false } } |
| 83 | + catch { return $false } |
| 84 | + $true |
| 85 | + }, $true) |
| 86 | + |
| 87 | + foreach ($splattedVariable in $splattedVariables) |
| 88 | + { |
| 89 | + $splatParamName = $splattedVariable.VariablePath.UserPath |
| 90 | + |
| 91 | + $splatAssignmentAsts = $ast.FindAll({ |
| 92 | + if ($args[0] -isnot [System.Management.Automation.Language.AssignmentStatementAst]) { return $false } |
| 93 | + if ($args[0].Left.VariablePath.userPath -ne $splatParamName) { return $false } |
| 94 | + if ($args[0].Operator -ne 'Equals') { return $false } |
| 95 | + if ($args[0].Right.Expression -isnot [System.Management.Automation.Language.HashtableAst]) { return $false } |
| 96 | + $keys = $args[0].Right.Expression.KeyValuePairs.Item1.Value |
| 97 | + if (($keys -notcontains 'String') -and ($keys -notcontains 'ActionString')) { return $false } |
| 98 | + |
| 99 | + $true |
| 100 | + }, $true) |
| 101 | + |
| 102 | + foreach ($splatAssignmentAst in $splatAssignmentAsts) |
| 103 | + { |
| 104 | + $splatHashTable = $splatAssignmentAst.Right.Expression |
| 105 | + |
| 106 | + $splatParam = $splathashTable.KeyValuePairs | Where-Object Item1 -in 'String', 'ActionString' |
| 107 | + $splatValueParam = $splathashTable.KeyValuePairs | Where-Object Item1 -in 'StringValues', 'ActionStringValues' |
| 108 | + if ($splatValueParam) |
| 109 | + { |
| 110 | + $splatValueParamValue = $splatValueParam.Item2.Extent.Text |
| 111 | + } |
| 112 | + else { $splatValueParamValue = '' } |
| 113 | + |
| 114 | + [PSCustomObject]@{ |
| 115 | + PSTypeName = 'PSModuleDevelopment.String.ParsedItem' |
| 116 | + File = $file.FullName |
| 117 | + Line = $splatHashTable.Extent.StartLineNumber |
| 118 | + CommandName = $splattedVariable.Parent.CommandElements[0].Value |
| 119 | + String = $splatParam.Item2.Extent.Text.Trim("'").Trim('"') |
| 120 | + StringValues = $splatValueParamValue |
| 121 | + } |
| 122 | + } |
| 123 | + } |
| 124 | + #endregion Splatted Variables |
| 125 | + |
| 126 | + #region Attributes |
139 | 127 | $validateAsts = $ast.FindAll({
|
140 | 128 | if ($args[0] -isnot [System.Management.Automation.Language.AttributeAst]) { return $false }
|
141 | 129 | if ($args[0].TypeName -notmatch '^PsfValidateScript$|^PsfValidatePattern$') { return $false }
|
142 | 130 | if (-not ($args[0].NamedArguments.ArgumentName -eq 'ErrorString')) { return $false }
|
143 | 131 | $true
|
144 | 132 | }, $true)
|
145 |
| - |
| 133 | + |
146 | 134 | foreach ($validateAst in $validateAsts)
|
147 | 135 | {
|
148 | 136 | [PSCustomObject]@{
|
|
154 | 142 | StringValues = '<user input>, <validation item>'
|
155 | 143 | }
|
156 | 144 | }
|
| 145 | + #endregion Attributes |
157 | 146 | }
|
158 | 147 | #endregion Find Keys : $foundKeys
|
159 |
| - |
| 148 | + |
160 | 149 | #region Report Findings
|
161 | 150 | $totalResults = foreach ($languageFile in $languageFiles.Keys)
|
162 | 151 | {
|
|
169 | 158 | $results[$foundKey.String].Entries += $foundKey
|
170 | 159 | continue
|
171 | 160 | }
|
172 |
| - |
| 161 | + |
173 | 162 | $results[$foundKey.String] = [PSCustomObject] @{
|
174 | 163 | PSTypeName = 'PSmoduleDevelopment.String.LanguageFinding'
|
175 | 164 | Language = $languageFile
|
|
183 | 172 | }
|
184 | 173 | $results.Values
|
185 | 174 | #endregion Phase 1: Matching parsed strings to language file
|
186 |
| - |
| 175 | + |
187 | 176 | #region Phase 2: Finding unneeded strings
|
188 | 177 | foreach ($key in $languageFiles[$languageFile].Keys)
|
189 | 178 | {
|
|
0 commit comments