Skip to content

Commit 1d46ca4

Browse files
author
Thomas Rayner
committed
updates a/p rjmholt
1 parent 651ed5d commit 1d46ca4

File tree

1 file changed

+57
-68
lines changed

1 file changed

+57
-68
lines changed

Rules/AvoidOverwritingBuiltInCmdlets.cs

+57-68
Original file line numberDiff line numberDiff line change
@@ -29,44 +29,26 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2929
/// </summary>
3030
public class AvoidOverwritingBuiltInCmdlets : ConfigurableRule
3131
{
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>
3240
[ConfigurableRuleProperty(defaultValue: "")]
3341
public string[] PowerShellVersion { get; set; }
34-
private Dictionary<string, HashSet<string>> cmdletMap;
35-
private bool initialized;
42+
private readonly Dictionary<string, HashSet<string>> _cmdletMap;
3643

3744

3845
/// <summary>
3946
/// Construct an object of AvoidOverwritingBuiltInCmdlets type.
4047
/// </summary>
41-
public AvoidOverwritingBuiltInCmdlets() : base()
48+
public AvoidOverwritingBuiltInCmdlets()
4249
{
43-
initialized = false;
44-
cmdletMap = new Dictionary<string, HashSet<string>>();
50+
_cmdletMap = new Dictionary<string, HashSet<string>>();
4551
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-
}
7052
}
7153

7254

@@ -83,7 +65,7 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
8365
throw new ArgumentNullException(nameof(ast));
8466
}
8567

86-
var functionDefinitions = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true);
68+
IEnumerable<FunctionDefinitionAst> functionDefinitions = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true).OfType<FunctionDefinitionAst>();
8769
if (functionDefinitions.Count() < 1)
8870
{
8971
// 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
9375
else
9476
{
9577
var diagnosticRecords = new List<DiagnosticRecord>();
96-
if (!initialized)
78+
string versionTest = string.Join("", PowerShellVersion);
79+
80+
if (string.IsNullOrEmpty(versionTest))
9781
{
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
10093
{
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();
102104
}
103105
}
104106

105-
foreach (var functionDef in functionDefinitions)
107+
var psVerList = PowerShellVersion;
108+
string settingsPath = Settings.GetShippedSettingsDirectory();
109+
110+
foreach (string reference in psVerList)
106111
{
107-
FunctionDefinitionAst funcDef = functionDef as FunctionDefinitionAst;
108-
if (funcDef == null)
112+
if (settingsPath == null || !ContainsReferenceFile(settingsPath, reference))
109113
{
110-
continue;
114+
throw new ArgumentException(nameof(PowerShellVersion));
111115
}
116+
}
117+
118+
ProcessDirectory(settingsPath, psVerList);
119+
120+
if (_cmdletMap.Keys.Count != psVerList.Count())
121+
{
122+
throw new ArgumentException(nameof(PowerShellVersion));
123+
}
112124

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)
115129
{
116-
if (map.Value.Contains(functionName))
130+
if (cmdletSet.Value.Contains(functionName))
117131
{
118-
diagnosticRecords.Add(CreateDiagnosticRecord(functionName, map.Key, functionDef.Extent));
132+
diagnosticRecords.Add(CreateDiagnosticRecord(functionName, cmdletSet.Key, functionDef.Extent));
119133
}
120134
}
121135
}
@@ -140,31 +154,6 @@ private DiagnosticRecord CreateDiagnosticRecord(string FunctionName, string PSVe
140154
}
141155

142156

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-
168157
private bool ContainsReferenceFile(string directory, string reference)
169158
{
170159
return File.Exists(Path.Combine(directory, reference + ".json"));
@@ -189,7 +178,7 @@ private void ProcessDirectory(string path, IEnumerable<string> acceptablePlatfor
189178
continue;
190179
}
191180

192-
cmdletMap.Add(fileNameWithoutExt, GetCmdletsFromData(JObject.Parse(File.ReadAllText(filePath))));
181+
_cmdletMap.Add(fileNameWithoutExt, GetCmdletsFromData(JObject.Parse(File.ReadAllText(filePath))));
193182
}
194183
}
195184

0 commit comments

Comments
 (0)