Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions src/System.Management.Automation/engine/parser/SemanticChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,12 @@ public override AstVisitAction VisitSwitchStatement(SwitchStatementAst switchSta
// Parallel flag not allowed
if ((switchStatementAst.Flags & SwitchFlags.Parallel) == SwitchFlags.Parallel)
{
bool reportError = !switchStatementAst.IsInWorkflow();
if (reportError)
{
_parser.ReportError(switchStatementAst.Extent,
nameof(ParserStrings.ParallelNotSupported),
ParserStrings.ParallelNotSupported);
}
_parser.ReportError(
switchStatementAst.Extent,
nameof(ParserStrings.KeywordParameterReservedForFutureUse),
ParserStrings.KeywordParameterReservedForFutureUse,
"switch",
"parallel");
}

return AstVisitAction.Continue;
Expand Down Expand Up @@ -494,20 +493,30 @@ public override AstVisitAction VisitForEachStatement(ForEachStatementAst forEach
// Parallel flag not allowed
if ((forEachStatementAst.Flags & ForEachFlags.Parallel) == ForEachFlags.Parallel)
{
bool reportError = !forEachStatementAst.IsInWorkflow();
if (reportError)
{
_parser.ReportError(forEachStatementAst.Extent,
nameof(ParserStrings.ParallelNotSupported),
ParserStrings.ParallelNotSupported);
}
_parser.ReportError(
forEachStatementAst.Extent,
nameof(ParserStrings.KeywordParameterReservedForFutureUse),
ParserStrings.KeywordParameterReservedForFutureUse,
"foreach",
"parallel");
}

if (forEachStatementAst.ThrottleLimit != null)
{
_parser.ReportError(
forEachStatementAst.Extent,
nameof(ParserStrings.KeywordParameterReservedForFutureUse),
ParserStrings.KeywordParameterReservedForFutureUse,
"foreach",
"throttlelimit");
}

// Throttle limit must be combined with Parallel flag
if ((forEachStatementAst.ThrottleLimit != null) &&
((forEachStatementAst.Flags & ForEachFlags.Parallel) != ForEachFlags.Parallel))
{
_parser.ReportError(forEachStatementAst.Extent,
_parser.ReportError(
forEachStatementAst.Extent,
nameof(ParserStrings.ThrottleLimitRequiresParallelFlag),
ParserStrings.ThrottleLimitRequiresParallelFlag);
}
Expand Down
4 changes: 2 additions & 2 deletions src/System.Management.Automation/resources/ParserStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ Possible matches are</value>
<data name="IncompleteSwitchStatement" xml:space="preserve">
<value>The switch statement was incomplete.</value>
</data>
<data name="ParallelNotSupported" xml:space="preserve">
<value>The '-parallel' parameter can be used only within a workflow.</value>
<data name="KeywordParameterReservedForFutureUse" xml:space="preserve">
<value>The {0} '-{1}' parameter is reserved for future use.</value>
</data>
<data name="MissingFilenameOption" xml:space="preserve">
<value>Cannot process the 'switch' statement because of a missing file name argument to the -file option.</value>
Expand Down
101 changes: 72 additions & 29 deletions test/powershell/Language/Scripting/ForeachParallel.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,41 +1,84 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
Describe "Parallel foreach syntax" -Tags "CI" {

Context 'Should be able to retrieve AST of parallel foreach, error in regular case' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -parallel ($foo in $bar) {}', [ref] $null, [ref] $errors)
It '$errors.Count' { $errors.Count | Should -Be 1 }
It '$ast.EndBlock.Statements[0].Flags' { $ast.EndBlock.Statements[0].Flags | Should -BeExactly 'Parallel' }
}

It 'Should be able to retrieve AST of parallel foreach, works in JobDefinition case' -Skip:$IsCoreCLR {
. .\TestsOnWinFullOnly.ps1
Run-TestOnWinFull "ForeachParallel:ASTOfParallelForeachOnWorkflow"
Describe 'Parallel foreach syntax' -Tags 'CI' {

Context 'Should be able to retrieve AST of parallel foreach' {
BeforeAll {
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -parallel ($foo in $bar) {}', [ref]$null, [ref]$null)
}

It '$ast.EndBlock.Statements[0].Flags' {
$ast.EndBlock.Statements[0].Flags | Should -BeExactly 'Parallel'
}
}

Context 'Supports newlines before and after' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
"foreach `n-parallel `n(`$foo in `$bar) {}", [ref] $null, [ref] $null)
It '$errors.Count' { $errors.Count | Should -Be 0 }
It '$ast.EndBlock.Statements[0].Flags' { $ast.EndBlock.Statements[0].Flags | Should -BeExactly 'Parallel' }
BeforeAll {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
"foreach `n-parallel `n(`$foo in `$bar) {}", [ref] $null, [ref] $null)
}

It '$errors.Count' {
$errors.Count | Should -Be 0
}

It '$ast.EndBlock.Statements[0].Flags' {
$ast.EndBlock.Statements[0].Flags | Should -BeExactly 'Parallel'
}
}

Context 'Generates an error on invalid parameter' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -bogus ($input in $bar) { }', [ref]$null, [ref]$errors)
It '$errors.Count' { $errors.Count | Should -Be 1 }
It '$errors[0].ErrorId' { $errors[0].ErrorId | Should -BeExactly 'InvalidForeachFlag' }
BeforeAll {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -bogus ($input in $bar) { }', [ref]$null, [ref]$errors)
}

It '$errors.Count' {
$errors.Count | Should -Be 1
}

It '$errors[0].ErrorId' {
$errors[0].ErrorId | Should -BeExactly 'InvalidForeachFlag'
}
}

Context 'Generate an error on -parallel that is not a workflow' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -parallel ($input in $bar) { }', [ref]$null, [ref]$errors)
It '$errors.Count' { $errors.Count | Should -Be 1 }
It '$errors[0].ErrorId' { $errors[0].ErrorId | Should -BeExactly 'ParallelNotSupported' }
Context 'Generate an error on -parallel' {
BeforeAll {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -parallel ($input in $bar) { }', [ref]$null, [ref]$errors)
}

It '$errors.Count' {
$errors.Count | Should -Be 1
}

It '$errors[0].ErrorId' {
$errors[0].ErrorId | Should -Be 'KeywordParameterReservedForFutureUse'
}
}

Context 'Generate an error on -throttlelimit' {
BeforeAll {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -throttlelimit 2 ($input in $bar) { }', [ref]$null, [ref]$errors)
}

It '$errors.Count' {
$errors.Count | Should -Be 2
}

It '$errors[0].ErrorId' {
$errors[0].ErrorId | Should -Be 'KeywordParameterReservedForFutureUse'
}

It '$errors[1].ErrorId' {
$errors[1].ErrorId | Should -Be 'ThrottleLimitRequiresParallelFlag'
}
}
}
}
48 changes: 48 additions & 0 deletions test/powershell/Language/Scripting/SwitchParallel.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

Describe 'Parallel switch syntax' -Tags 'CI' {

Context 'Should be able to retrieve AST of parallel switch' {
BeforeAll {
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'switch -parallel ($foo) {1 {break}}', [ref] $null, [ref] $null)
}

It '$ast.EndBlock.Statements[0].Flags' {
$ast.EndBlock.Statements[0].Flags | Should -BeExactly 'Parallel'
}
}

Context 'Generates an error on invalid parameter' {
BeforeAll {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'switch -bogus ($foo) {1 {break}}', [ref]$null, [ref]$errors)
}

It '$errors.Count' {
$errors.Count | Should -Be 1
}

It '$errors[0].ErrorId' {
$errors[0].ErrorId | Should -BeExactly 'InvalidSwitchFlag'
}
}

Context 'Generate an error on -parallel' {
BeforeAll {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'switch -parallel ($foo) {1 {break}}', [ref]$null, [ref]$errors)
}

It '$errors.Count' {
$errors.Count | Should -Be 1
}

It '$errors[0].ErrorId' {
$errors[0].ErrorId | Should -Be 'KeywordParameterReservedForFutureUse'
}
}
}