Skip to content

Commit e8b5cfe

Browse files
author
Quoc Truong
committed
Merge pull request #240 from PowerShell/FixSpllatedVariableAndPipeLine
Fix Splatted Variable and Pipeline bug in UseCmdletCorrectly and AvoidUsingPositionalParameter
2 parents d7a833e + 618b07c commit e8b5cfe

File tree

5 files changed

+58
-11
lines changed

5 files changed

+58
-11
lines changed

Engine/Helper.cs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,21 @@ item is TypeDefinitionAst
219219
return false;
220220
}
221221

222+
/// <summary>
223+
/// Given a commandast, checks whether it uses splatted variable
224+
/// </summary>
225+
/// <param name="cmdAst"></param>
226+
/// <returns></returns>
227+
public bool HasSplattedVariable(CommandAst cmdAst)
228+
{
229+
if (cmdAst == null || cmdAst.CommandElements == null)
230+
{
231+
return false;
232+
}
233+
234+
return cmdAst.CommandElements.Any(cmdElem => cmdElem is VariableExpressionAst && (cmdElem as VariableExpressionAst).Splatted);
235+
}
236+
222237
/// <summary>
223238
/// Given a commandast, checks whether positional parameters are used or not.
224239
/// </summary>
@@ -237,6 +252,11 @@ public bool PositionalParameterUsed(CommandAst cmdAst)
237252
IEnumerable<CommandParameterSetInfo> scriptBlocks = null;
238253
bool hasScriptBlockSet = false;
239254

255+
if (HasSplattedVariable(cmdAst))
256+
{
257+
return false;
258+
}
259+
240260
if (commandInfo != null && commandInfo.CommandType == System.Management.Automation.CommandTypes.Cmdlet)
241261
{
242262
try
@@ -286,19 +306,19 @@ public bool PositionalParameterUsed(CommandAst cmdAst)
286306
}
287307
else
288308
{
289-
//Skip if splatting "@" is used
290-
if (ceAst is VariableExpressionAst)
291-
{
292-
if ((ceAst as VariableExpressionAst).Splatted)
293-
{
294-
continue;
295-
}
296-
}
297309
arguments += 1;
298310
}
299311
}
300312
}
301313

314+
// if not the first element in a pipeline, increase the number of arguments by 1
315+
PipelineAst parent = cmdAst.Parent as PipelineAst;
316+
317+
if (parent != null && parent.PipelineElements.Count > 1 && parent.PipelineElements[0] != cmdAst)
318+
{
319+
arguments += 1;
320+
}
321+
302322
return arguments > parameters;
303323
}
304324

Rules/AvoidPositionalParameters.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,23 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
4747
if (Helper.Instance.GetCommandInfo(cmdAst.GetCommandName()) != null
4848
&& Helper.Instance.PositionalParameterUsed(cmdAst))
4949
{
50-
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPositionalParametersError, cmdAst.GetCommandName()),
51-
cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, cmdAst.GetCommandName());
50+
PipelineAst parent = cmdAst.Parent as PipelineAst;
51+
52+
if (parent != null && parent.PipelineElements.Count > 1)
53+
{
54+
// raise if it's the first element in pipeline. otherwise no.
55+
if (parent.PipelineElements[0] == cmdAst)
56+
{
57+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPositionalParametersError, cmdAst.GetCommandName()),
58+
cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, cmdAst.GetCommandName());
59+
}
60+
}
61+
// not in pipeline so just raise it normally
62+
else
63+
{
64+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPositionalParametersError, cmdAst.GetCommandName()),
65+
cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, cmdAst.GetCommandName());
66+
}
5267
}
5368
}
5469
}

Rules/UseCmdletCorrectly.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ private bool IsMandatoryParameterExisted(CommandAst cmdAst)
9292
return true;
9393
}
9494

95+
// ignores if splatted variable is used
96+
if (Helper.Instance.HasSplattedVariable(cmdAst))
97+
{
98+
return true;
99+
}
100+
95101
// Gets parameters from command elements.
96102
ceAsts = cmdAst.CommandElements.Where<CommandElementAst>(foundParamASTs);
97103

Tests/Rules/GoodCmdlet.ps1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ function Get-File
8585
$a
8686
}
8787

88+
$a | Write-Warning
89+
90+
$b = @{"hash"="table"}
91+
92+
Write-Debug @b
93+
8894
return @{"hash"="true"}
8995
}
9096
End

Tests/Rules/UseCmdletCorrectly.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
Wrong-Cmd
33
Write-Verbose -Message "Write Verbose"
44
Write-Verbose "Warning" -OutVariable $test
5-
Write-Verbose "Warning"
5+
Write-Verbose "Warning" | PipeLineCmdlet

0 commit comments

Comments
 (0)