Add error handling for interactive #requires (#6469)

This commit is contained in:
Robert Holt
2018-04-25 18:04:04 -07:00
committed by Dongbo Wang
parent 4b149e4191
commit 63c0d8d783
4 changed files with 61 additions and 6 deletions
@@ -62,19 +62,19 @@ namespace System.Management.Automation
/// Compile a piece of text into a parse tree for later execution.
/// </summary>
/// <param name="script">The text to parse</param>
/// <param name="interactiveCommand"></param>
/// <param name="addToHistory">true iff the scriptblock will be added to history</param>
/// <returns>The parse text as a parsetree node.</returns>
internal ScriptBlock ParseScriptBlock(string script, bool interactiveCommand)
internal ScriptBlock ParseScriptBlock(string script, bool addToHistory)
{
return ParseScriptBlock(script, null, interactiveCommand);
return ParseScriptBlock(script, null, addToHistory);
}
internal ScriptBlock ParseScriptBlock(string script, string fileName, bool interactiveCommand)
internal ScriptBlock ParseScriptBlock(string script, string fileName, bool addToHistory)
{
ParseError[] errors;
var ast = EngineParser.Parse(fileName, script, null, out errors, ParseMode.Default);
if (interactiveCommand)
if (addToHistory)
{
EngineParser.SetPreviousFirstLastToken(Context);
}
@@ -492,6 +492,7 @@ namespace System.Management.Automation.Language
internal string Script;
internal int TokenStart;
internal int CurrentIndex;
internal Token FirstToken;
internal Token LastToken;
internal BitArray SkippedCharOffsets;
internal List<Token> TokenList;
@@ -687,6 +688,7 @@ namespace System.Management.Automation.Language
NestedTokensAdjustment = _nestedTokensAdjustment,
Script = _script,
TokenStart = _tokenStart,
FirstToken = FirstToken,
LastToken = LastToken,
SkippedCharOffsets = _skippedCharOffsets,
TokenList = TokenList,
@@ -708,6 +710,7 @@ namespace System.Management.Automation.Language
_nestedTokensAdjustment = ts.NestedTokensAdjustment;
_script = ts.Script;
_tokenStart = ts.TokenStart;
FirstToken = ts.FirstToken;
LastToken = ts.LastToken;
_skippedCharOffsets = ts.SkippedCharOffsets;
TokenList = ts.TokenList;
@@ -931,4 +931,39 @@ foo``u{2195}abc
$err = { ExecuteCommand "Function foo { [CmdletBinding()] param() DynamicParam {} " } | Should -Throw -ErrorId "IncompleteParseException" -PassThru
$err.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly "MissingEndCurlyBrace"
}
Context "#requires nested scan tokenizer tests" {
BeforeAll {
$settings = [System.Management.Automation.PSInvocationSettings]::new()
$settings.AddToHistory = $true
$ps = [powershell]::Create()
}
AfterAll {
$ps.Dispose()
}
AfterEach {
$ps.Commands.Clear()
}
$testCases = @(
@{ script = "#requires"; firstToken = $null; lastToken = $null },
@{ script = "#requires -Version 5.0`n10"; firstToken = "10"; lastToken = "10" },
@{ script = "Write-Host 'Hello'`n#requires -Version 5.0`n7"; firstToken = "Write-Host"; lastToken = "7" },
@{ script = "Write-Host 'Hello'`n#requires -Version 5.0"; firstToken = "Write-Host"; lastToken = "Hello"}
)
It "Correctly resets the first and last tokens in the tokenizer after nested scan in script" -TestCases $testCases {
param($script, $firstToken, $lastToken)
$ps.AddScript($script)
$ps.AddScript("(`$^,`$`$)")
$tokens = $ps.Invoke(@(), $settings)
$tokens[0] | Should -BeExactly $firstToken
$tokens[1] | Should -BeExactly $lastToken
}
}
}
@@ -27,4 +27,21 @@ Describe "Requires tests" -Tags "CI" {
}
}
}
Context "Interactive requires" {
BeforeAll {
$ps = [powershell]::Create()
}
AfterAll {
$ps.Dispose()
}
It "Successfully does nothing when given '#requires' interactively" {
$settings = [System.Management.Automation.PSInvocationSettings]::new()
$settings.AddToHistory = $true
{ $ps.AddScript("#requires").Invoke(@(), $settings) } | Should -Not -Throw
}
}
}