diff --git a/Rules/AvoidAlias.cs b/Rules/AvoidAlias.cs index 087e6bfc8..ba069453b 100644 --- a/Rules/AvoidAlias.cs +++ b/Rules/AvoidAlias.cs @@ -207,7 +207,9 @@ private bool IsDscResourceDeclaration(CommandAst cmdAst) if (parent is FunctionDefinitionAst || parent is HashtableAst || parent is AssignmentStatementAst - || parent is ParenExpressionAst) + || parent is ParenExpressionAst + || parent is SubExpressionAst + || parent is ArrayExpressionAst) { return false; } @@ -228,7 +230,9 @@ private bool IsDscResourceDeclaration(CommandAst cmdAst) if (parent is FunctionDefinitionAst || parent is HashtableAst || parent is AssignmentStatementAst - || parent is ParenExpressionAst) + || parent is ParenExpressionAst + || parent is SubExpressionAst + || parent is ArrayExpressionAst) { return false; } @@ -305,14 +309,16 @@ private ScriptBlockExpressionAst GetDscResourceBody(CommandAst cmdAst) if (cmdAst.InvocationOperator != TokenKind.Unknown || cmdAst.CommandElements.Count < 2 || !(cmdAst.CommandElements[1] is ExpressionAst) - || cmdAst.CommandElements[1].Extent.Text == "=") + || cmdAst.CommandElements[1].Extent.Text == "=" + || cmdAst.Redirections.Count != 0) { return null; } if (!(cmdAst.Parent is PipelineAst commandPipeline) || commandPipeline.PipelineElements.Count != 1 - || commandPipeline.PipelineElements[0] != cmdAst) + || commandPipeline.PipelineElements[0] != cmdAst + || !(commandPipeline.Parent is NamedBlockAst || commandPipeline.Parent is StatementBlockAst)) { return null; } diff --git a/Tests/Rules/AvoidUsingAlias.tests.ps1 b/Tests/Rules/AvoidUsingAlias.tests.ps1 index 2f2614a40..2bdd55b33 100644 --- a/Tests/Rules/AvoidUsingAlias.tests.ps1 +++ b/Tests/Rules/AvoidUsingAlias.tests.ps1 @@ -201,6 +201,37 @@ Configuration PackageTest { $violations[5].Extent.Text | Should -Be 'Verb' $violations[6].Extent.Text | Should -Be 'gci' } + + It "does not mistake executable pipelines for DSC resources in fallback configuration ASTs" { + $target = @' +{ + Write-Output $(Verb Argument {}) + @(Verb Argument {}) + Verb Argument {} > $null + if (Verb Argument {}) {} + return Verb Argument {} + if ($true) { + Verb SameLineResource {} + Verb NextLineResource + { + } + } +} +'@ + $ast = [System.Management.Automation.Language.Parser]::ParseInput($target, [ref]$null, [ref]$null) + $body = $ast.EndBlock.Statements[0].PipelineElements[0].Expression.Copy() + $configuration = [System.Management.Automation.Language.ConfigurationDefinitionAst]::new( + $ast.Extent, $body, 'Resource', + [System.Management.Automation.Language.StringConstantExpressionAst]::new($ast.Extent, 'Test', 'BareWord')) + $rule = [Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.AvoidAlias]::new() + + $violations = @($rule.AnalyzeScript($configuration, $null)) + + $violations.Count | Should -Be 5 + $violations | ForEach-Object { + $_.SuggestedCorrections[0].Text | Should -Be 'Get-Verb' + } + } } Context "Settings file provides allowlist" {