Skip to content

Commit 63c0d8d

Browse files
rjmholtdaxian-dbw
authored andcommitted
Add error handling for interactive #requires (#6469)
1 parent 4b149e4 commit 63c0d8d

File tree

4 files changed

+61
-6
lines changed

4 files changed

+61
-6
lines changed

src/System.Management.Automation/engine/AutomationEngine.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,19 @@ internal string Expand(string s)
6262
/// Compile a piece of text into a parse tree for later execution.
6363
/// </summary>
6464
/// <param name="script">The text to parse</param>
65-
/// <param name="interactiveCommand"></param>
65+
/// <param name="addToHistory">true iff the scriptblock will be added to history</param>
6666
/// <returns>The parse text as a parsetree node.</returns>
67-
internal ScriptBlock ParseScriptBlock(string script, bool interactiveCommand)
67+
internal ScriptBlock ParseScriptBlock(string script, bool addToHistory)
6868
{
69-
return ParseScriptBlock(script, null, interactiveCommand);
69+
return ParseScriptBlock(script, null, addToHistory);
7070
}
7171

72-
internal ScriptBlock ParseScriptBlock(string script, string fileName, bool interactiveCommand)
72+
internal ScriptBlock ParseScriptBlock(string script, string fileName, bool addToHistory)
7373
{
7474
ParseError[] errors;
7575
var ast = EngineParser.Parse(fileName, script, null, out errors, ParseMode.Default);
7676

77-
if (interactiveCommand)
77+
if (addToHistory)
7878
{
7979
EngineParser.SetPreviousFirstLastToken(Context);
8080
}

src/System.Management.Automation/engine/parser/tokenizer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ internal class TokenizerState
492492
internal string Script;
493493
internal int TokenStart;
494494
internal int CurrentIndex;
495+
internal Token FirstToken;
495496
internal Token LastToken;
496497
internal BitArray SkippedCharOffsets;
497498
internal List<Token> TokenList;
@@ -687,6 +688,7 @@ internal TokenizerState StartNestedScan(UnscannedSubExprToken nestedText)
687688
NestedTokensAdjustment = _nestedTokensAdjustment,
688689
Script = _script,
689690
TokenStart = _tokenStart,
691+
FirstToken = FirstToken,
690692
LastToken = LastToken,
691693
SkippedCharOffsets = _skippedCharOffsets,
692694
TokenList = TokenList,
@@ -708,6 +710,7 @@ internal void FinishNestedScan(TokenizerState ts)
708710
_nestedTokensAdjustment = ts.NestedTokensAdjustment;
709711
_script = ts.Script;
710712
_tokenStart = ts.TokenStart;
713+
FirstToken = ts.FirstToken;
711714
LastToken = ts.LastToken;
712715
_skippedCharOffsets = ts.SkippedCharOffsets;
713716
TokenList = ts.TokenList;

test/powershell/Language/Parser/Parser.Tests.ps1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,4 +931,39 @@ foo``u{2195}abc
931931
$err = { ExecuteCommand "Function foo { [CmdletBinding()] param() DynamicParam {} " } | Should -Throw -ErrorId "IncompleteParseException" -PassThru
932932
$err.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly "MissingEndCurlyBrace"
933933
}
934+
935+
Context "#requires nested scan tokenizer tests" {
936+
BeforeAll {
937+
$settings = [System.Management.Automation.PSInvocationSettings]::new()
938+
$settings.AddToHistory = $true
939+
940+
$ps = [powershell]::Create()
941+
}
942+
943+
AfterAll {
944+
$ps.Dispose()
945+
}
946+
947+
AfterEach {
948+
$ps.Commands.Clear()
949+
}
950+
951+
$testCases = @(
952+
@{ script = "#requires"; firstToken = $null; lastToken = $null },
953+
@{ script = "#requires -Version 5.0`n10"; firstToken = "10"; lastToken = "10" },
954+
@{ script = "Write-Host 'Hello'`n#requires -Version 5.0`n7"; firstToken = "Write-Host"; lastToken = "7" },
955+
@{ script = "Write-Host 'Hello'`n#requires -Version 5.0"; firstToken = "Write-Host"; lastToken = "Hello"}
956+
)
957+
958+
It "Correctly resets the first and last tokens in the tokenizer after nested scan in script" -TestCases $testCases {
959+
param($script, $firstToken, $lastToken)
960+
961+
$ps.AddScript($script)
962+
$ps.AddScript("(`$^,`$`$)")
963+
$tokens = $ps.Invoke(@(), $settings)
964+
965+
$tokens[0] | Should -BeExactly $firstToken
966+
$tokens[1] | Should -BeExactly $lastToken
967+
}
968+
}
934969
}

test/powershell/Language/Scripting/Requires.Tests.ps1

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,21 @@ Describe "Requires tests" -Tags "CI" {
2727
}
2828
}
2929

30-
}
30+
Context "Interactive requires" {
31+
32+
BeforeAll {
33+
$ps = [powershell]::Create()
34+
}
35+
36+
AfterAll {
37+
$ps.Dispose()
38+
}
39+
40+
It "Successfully does nothing when given '#requires' interactively" {
41+
$settings = [System.Management.Automation.PSInvocationSettings]::new()
42+
$settings.AddToHistory = $true
43+
44+
{ $ps.AddScript("#requires").Invoke(@(), $settings) } | Should -Not -Throw
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)