From eb81fb749ac0a3e8f5a6ba17bcba4ff12a739435 Mon Sep 17 00:00:00 2001 From: Kirk Munro Date: Thu, 15 Aug 2019 18:41:41 -0300 Subject: [PATCH] Mark `-parallel` and `-throttlelimit` reserved for `foreach` and `switch` statements (#10328) --- .../engine/parser/SemanticChecks.cs | 39 +++++--- .../resources/ParserStrings.resx | 4 +- .../Scripting/ForeachParallel.Tests.ps1 | 99 +++++++++++++------ .../Scripting/SwitchParallel.Tests.ps1 | 48 +++++++++ 4 files changed, 145 insertions(+), 45 deletions(-) create mode 100644 test/powershell/Language/Scripting/SwitchParallel.Tests.ps1 diff --git a/src/System.Management.Automation/engine/parser/SemanticChecks.cs b/src/System.Management.Automation/engine/parser/SemanticChecks.cs index 54c211e604..66a6e4f805 100644 --- a/src/System.Management.Automation/engine/parser/SemanticChecks.cs +++ b/src/System.Management.Automation/engine/parser/SemanticChecks.cs @@ -458,13 +458,12 @@ namespace System.Management.Automation.Language // 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; @@ -494,20 +493,30 @@ namespace System.Management.Automation.Language // 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); } diff --git a/src/System.Management.Automation/resources/ParserStrings.resx b/src/System.Management.Automation/resources/ParserStrings.resx index adaa86dbcb..4644fa5aa3 100644 --- a/src/System.Management.Automation/resources/ParserStrings.resx +++ b/src/System.Management.Automation/resources/ParserStrings.resx @@ -392,8 +392,8 @@ Possible matches are The switch statement was incomplete. - - The '-parallel' parameter can be used only within a workflow. + + The {0} '-{1}' parameter is reserved for future use. Cannot process the 'switch' statement because of a missing file name argument to the -file option. diff --git a/test/powershell/Language/Scripting/ForeachParallel.Tests.ps1 b/test/powershell/Language/Scripting/ForeachParallel.Tests.ps1 index c0941a3626..c820e947fe 100644 --- a/test/powershell/Language/Scripting/ForeachParallel.Tests.ps1 +++ b/test/powershell/Language/Scripting/ForeachParallel.Tests.ps1 @@ -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' } - } +Describe 'Parallel foreach syntax' -Tags 'CI' { - It 'Should be able to retrieve AST of parallel foreach, works in JobDefinition case' -Skip:$IsCoreCLR { - . .\TestsOnWinFullOnly.ps1 - Run-TestOnWinFull "ForeachParallel:ASTOfParallelForeachOnWorkflow" + 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' + } } -} \ No newline at end of file + + 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' + } + } +} diff --git a/test/powershell/Language/Scripting/SwitchParallel.Tests.ps1 b/test/powershell/Language/Scripting/SwitchParallel.Tests.ps1 new file mode 100644 index 0000000000..9af1cf5b8e --- /dev/null +++ b/test/powershell/Language/Scripting/SwitchParallel.Tests.ps1 @@ -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' + } + } +}