@@ -29,44 +29,26 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
29
29
/// </summary>
30
30
public class AvoidOverwritingBuiltInCmdlets : ConfigurableRule
31
31
{
32
+ /// <summary>
33
+ /// Specify the version of PowerShell to compare against since different versions of PowerShell
34
+ /// ship with different sets of built in cmdlets. The default value for PowerShellVersion is
35
+ /// "core-6.1.0-windows" if PowerShell 6 or later is installed, and "desktop-5.1.14393.206-windows"
36
+ /// if it is not. The version specified aligns with a JSON file in `/path/to/PSScriptAnalyzerModule/Settings`.
37
+ /// These files are of the form, `PSEDITION-PSVERSION-OS.json` where `PSEDITION` can be either `Core` or
38
+ /// `Desktop`, `OS` can be either `Windows`, `Linux` or `MacOS`, and `Version` is the PowerShell version.
39
+ /// </summary>
32
40
[ ConfigurableRuleProperty ( defaultValue : "" ) ]
33
41
public string [ ] PowerShellVersion { get ; set ; }
34
- private Dictionary < string , HashSet < string > > cmdletMap ;
35
- private bool initialized ;
42
+ private readonly Dictionary < string , HashSet < string > > _cmdletMap ;
36
43
37
44
38
45
/// <summary>
39
46
/// Construct an object of AvoidOverwritingBuiltInCmdlets type.
40
47
/// </summary>
41
- public AvoidOverwritingBuiltInCmdlets ( ) : base ( )
48
+ public AvoidOverwritingBuiltInCmdlets ( )
42
49
{
43
- initialized = false ;
44
- cmdletMap = new Dictionary < string , HashSet < string > > ( ) ;
50
+ _cmdletMap = new Dictionary < string , HashSet < string > > ( ) ;
45
51
Enable = true ; // Enable rule by default
46
-
47
- string versionTest = string . Join ( "" , PowerShellVersion ) ;
48
-
49
- if ( versionTest != "core-6.1.0-windows" && versionTest != "desktop-5.1.14393.206-windows" )
50
- {
51
- // PowerShellVersion is not already set to one of the acceptable defaults
52
- // Try launching `pwsh -v` to see if PowerShell 6+ is installed, and use those cmdlets
53
- // as a default. If 6+ is not installed this will throw an error, which when caught will
54
- // allow us to use the PowerShell 5 cmdlets as a default.
55
- try
56
- {
57
- var testProcess = new Process ( ) ;
58
- testProcess . StartInfo . FileName = "pwsh" ;
59
- testProcess . StartInfo . Arguments = "-v" ;
60
- testProcess . StartInfo . CreateNoWindow = true ;
61
- testProcess . StartInfo . UseShellExecute = false ;
62
- testProcess . Start ( ) ;
63
- PowerShellVersion = new [ ] { "core-6.1.0-windows" } ;
64
- }
65
- catch
66
- {
67
- PowerShellVersion = new [ ] { "desktop-5.1.14393.206-windows" } ;
68
- }
69
- }
70
52
}
71
53
72
54
@@ -83,7 +65,7 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
83
65
throw new ArgumentNullException ( nameof ( ast ) ) ;
84
66
}
85
67
86
- var functionDefinitions = ast . FindAll ( testAst => testAst is FunctionDefinitionAst , true ) ;
68
+ IEnumerable < FunctionDefinitionAst > functionDefinitions = ast . FindAll ( testAst => testAst is FunctionDefinitionAst , true ) . OfType < FunctionDefinitionAst > ( ) ;
87
69
if ( functionDefinitions . Count ( ) < 1 )
88
70
{
89
71
// There are no function definitions in this AST and so it's not worth checking the rest of this rule
@@ -93,29 +75,61 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
93
75
else
94
76
{
95
77
var diagnosticRecords = new List < DiagnosticRecord > ( ) ;
96
- if ( ! initialized )
78
+ string versionTest = string . Join ( "" , PowerShellVersion ) ;
79
+
80
+ if ( string . IsNullOrEmpty ( versionTest ) )
97
81
{
98
- Initialize ( ) ;
99
- if ( ! initialized )
82
+ // PowerShellVersion is not already set to one of the acceptable defaults
83
+ // Try launching `pwsh -v` to see if PowerShell 6+ is installed, and use those cmdlets
84
+ // as a default. If 6+ is not installed this will throw an error, which when caught will
85
+ // allow us to use the PowerShell 5 cmdlets as a default.
86
+ var testProcess = new Process ( ) ;
87
+ testProcess . StartInfo . FileName = "pwsh" ;
88
+ testProcess . StartInfo . Arguments = "-v" ;
89
+ testProcess . StartInfo . CreateNoWindow = true ;
90
+ testProcess . StartInfo . UseShellExecute = false ;
91
+
92
+ try
100
93
{
101
- throw new Exception ( "Failed to initialize rule " + GetName ( ) ) ;
94
+ testProcess . Start ( ) ;
95
+ PowerShellVersion = new [ ] { "core-6.1.0-windows" } ;
96
+ }
97
+ catch
98
+ {
99
+ PowerShellVersion = new [ ] { "desktop-5.1.14393.206-windows" } ;
100
+ }
101
+ finally
102
+ {
103
+ testProcess . Dispose ( ) ;
102
104
}
103
105
}
104
106
105
- foreach ( var functionDef in functionDefinitions )
107
+ var psVerList = PowerShellVersion ;
108
+ string settingsPath = Settings . GetShippedSettingsDirectory ( ) ;
109
+
110
+ foreach ( string reference in psVerList )
106
111
{
107
- FunctionDefinitionAst funcDef = functionDef as FunctionDefinitionAst ;
108
- if ( funcDef == null )
112
+ if ( settingsPath == null || ! ContainsReferenceFile ( settingsPath , reference ) )
109
113
{
110
- continue ;
114
+ throw new ArgumentException ( nameof ( PowerShellVersion ) ) ;
111
115
}
116
+ }
117
+
118
+ ProcessDirectory ( settingsPath , psVerList ) ;
119
+
120
+ if ( _cmdletMap . Keys . Count != psVerList . Count ( ) )
121
+ {
122
+ throw new ArgumentException ( nameof ( PowerShellVersion ) ) ;
123
+ }
112
124
113
- string functionName = funcDef . Name ;
114
- foreach ( var map in cmdletMap )
125
+ foreach ( FunctionDefinitionAst functionDef in functionDefinitions )
126
+ {
127
+ string functionName = functionDef . Name ;
128
+ foreach ( KeyValuePair < string , HashSet < string > > cmdletSet in _cmdletMap )
115
129
{
116
- if ( map . Value . Contains ( functionName ) )
130
+ if ( cmdletSet . Value . Contains ( functionName ) )
117
131
{
118
- diagnosticRecords . Add ( CreateDiagnosticRecord ( functionName , map . Key , functionDef . Extent ) ) ;
132
+ diagnosticRecords . Add ( CreateDiagnosticRecord ( functionName , cmdletSet . Key , functionDef . Extent ) ) ;
119
133
}
120
134
}
121
135
}
@@ -140,31 +154,6 @@ private DiagnosticRecord CreateDiagnosticRecord(string FunctionName, string PSVe
140
154
}
141
155
142
156
143
- private void Initialize ( )
144
- {
145
- var psVerList = PowerShellVersion ;
146
-
147
- string settingsPath = Settings . GetShippedSettingsDirectory ( ) ;
148
-
149
- foreach ( string reference in psVerList )
150
- {
151
- if ( settingsPath == null || ! ContainsReferenceFile ( settingsPath , reference ) )
152
- {
153
- return ;
154
- }
155
- }
156
-
157
- ProcessDirectory ( settingsPath , psVerList ) ;
158
-
159
- if ( cmdletMap . Keys . Count != psVerList . Count ( ) )
160
- {
161
- return ;
162
- }
163
-
164
- initialized = true ;
165
- }
166
-
167
-
168
157
private bool ContainsReferenceFile ( string directory , string reference )
169
158
{
170
159
return File . Exists ( Path . Combine ( directory , reference + ".json" ) ) ;
@@ -189,7 +178,7 @@ private void ProcessDirectory(string path, IEnumerable<string> acceptablePlatfor
189
178
continue ;
190
179
}
191
180
192
- cmdletMap . Add ( fileNameWithoutExt , GetCmdletsFromData ( JObject . Parse ( File . ReadAllText ( filePath ) ) ) ) ;
181
+ _cmdletMap . Add ( fileNameWithoutExt , GetCmdletsFromData ( JObject . Parse ( File . ReadAllText ( filePath ) ) ) ) ;
193
182
}
194
183
}
195
184
0 commit comments