Skip to content

Commit 83394d6

Browse files
Jos KoelewijnJos Koelewijn
Jos Koelewijn
authored and
Jos Koelewijn
committed
clean up and finetune rule
1 parent 23183d2 commit 83394d6

File tree

1 file changed

+31
-39
lines changed

1 file changed

+31
-39
lines changed

Rules/AvoidUnInitializedVarsInNewRunspaces.cs

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

44
using System;
@@ -111,61 +111,53 @@ public string GetSourceName()
111111
/// <returns>An enumerable containing diagnostic records</returns>
112112
private IEnumerable<DiagnosticRecord> AnalyzeScriptBlockAst(ScriptBlockAst scriptBlockAst, string fileName)
113113
{
114+
// TODO: add other Cmdlets like invoke-command later?
114115
var foreachObjectCmdletNamesAndAliases = Helper.Instance.CmdletNameAndAliases("Foreach-Object");
115116

116-
// Find all commandAst objects for `Foreach-Object -Parallel`. As for parametername matching, there are three
117+
// Find all commandAst objects for `Foreach-Object -Parallel`. As for parameter name matching, there are three
117118
// parameters starting with a 'p': Parallel, PipelineVariable and Process, so we use startsWith 'pa' as the shortest unambiguous form.
118119
// Because we are already going trough all ScriptBlockAst objects, we do not need to look for nested script blocks here.
119-
if (!(scriptBlockAst.FindAll(
120+
var foreachObjectParallelCommandAsts = scriptBlockAst.FindAll(
120121
predicate: c => c is CommandAst commandAst &&
121-
foreachObjectCmdletNamesAndAliases.Contains(commandAst.GetCommandName(), StringComparer.OrdinalIgnoreCase) &&
122-
commandAst.CommandElements.Any(
123-
e => e is CommandParameterAst parameterAst &&
124-
parameterAst.ParameterName.StartsWith("pa", StringComparison.OrdinalIgnoreCase)),
125-
searchNestedScriptBlocks: true) is IEnumerable<Ast> foreachObjectParallelAsts))
122+
foreachObjectCmdletNamesAndAliases.Contains(
123+
commandAst.GetCommandName(), StringComparer.OrdinalIgnoreCase) &&
124+
commandAst.CommandElements.Any(
125+
e => e is CommandParameterAst parameterAst &&
126+
parameterAst.ParameterName.StartsWith("pa", StringComparison.OrdinalIgnoreCase)),
127+
searchNestedScriptBlocks: false).Select(a=>a as CommandAst);
128+
129+
foreach (var commandAst in foreachObjectParallelCommandAsts)
126130
{
127-
yield break;
128-
}
129-
130-
foreach (var ast in foreachObjectParallelAsts)
131-
{
132-
var commandAst = ast as CommandAst;
133-
134-
if (commandAst == null)
135-
{
136-
continue;
137-
}
138-
131+
if (commandAst == null)
132+
yield break;
133+
134+
// Find all variables that are assigned within this ScriptBlock
139135
var varsInAssignments = commandAst.FindAll(
140-
predicate: a => a is AssignmentStatementAst assignment &&
141-
assignment.Left.FindAll(
142-
predicate: aa => aa is VariableExpressionAst,
143-
searchNestedScriptBlocks: true) != null,
144-
searchNestedScriptBlocks: true);
145-
146-
var commandElements = commandAst.CommandElements;
147-
var nonAssignedNonUsingVars = new List<Ast>() { };
148-
foreach (var cmdEl in commandElements)
149-
{
150-
nonAssignedNonUsingVars.AddRange(
151-
cmdEl.FindAll(
152-
predicate: aa => aa is VariableExpressionAst varAst &&
153-
!(varAst.Parent is UsingExpressionAst) &&
154-
!varsInAssignments.Contains(varAst), true));
155-
}
136+
predicate: a => a is VariableExpressionAst varExpr &&
137+
varExpr.Parent is AssignmentStatementAst assignment &&
138+
assignment.Left.Equals(varExpr),
139+
searchNestedScriptBlocks: true).
140+
Select(a => a as VariableExpressionAst);
141+
142+
// Find all variables that are not locally assigned, and don't have $using: directive
143+
var nonAssignedNonUsingVars = commandAst.CommandElements.
144+
SelectMany(a => a.FindAll(
145+
predicate: aa => aa is VariableExpressionAst varAst &&
146+
!(varAst.Parent is UsingExpressionAst) &&
147+
!varsInAssignments.Contains(varAst),
148+
searchNestedScriptBlocks: true).
149+
Select(aaa => aaa as VariableExpressionAst));
156150

157151
foreach (var variableExpression in nonAssignedNonUsingVars)
158152
{
159-
var _temp = variableExpression as VariableExpressionAst;
160-
161153
yield return new DiagnosticRecord(
162154
message: string.Format(CultureInfo.CurrentCulture,
163155
Strings.AvoidUnInitializedVarsInNewRunspacesError, variableExpression.ToString()),
164156
extent: variableExpression.Extent,
165157
ruleName: GetName(),
166158
severity: DiagnosticSeverity.Warning,
167159
scriptPath: fileName,
168-
ruleId: _temp?.ToString());
160+
ruleId: variableExpression.ToString());
169161
}
170162
}
171163
}

0 commit comments

Comments
 (0)