Fix pure expressions setting $? in pipeline chains (#10836)

This commit is contained in:
Robert Holt authored and Dongbo Wang committed 2019-10-18 14:57:56 -07:00
1 parent 3806c396b1
commit 2f4ed146ae
3 files changed
+24 -4

No files matched your search

@@ -3200,7 +3200,7 @@ namespace System.Management.Automation.Language
ExpressionCache.Constant(0)));
tryBodyExprs.Add(Expression.Label(label0));
tryBodyExprs.Add(Expression.Assign(dispatchIndex, ExpressionCache.Constant(1)));
tryBodyExprs.Add(Compile(currentChain.LhsPipelineChain));
tryBodyExprs.Add(CompilePipelineChainElement((PipelineAst)currentChain.LhsPipelineChain));
// Remainder of try statement body
// L1: dispatchIndex = 2; if ($?) pipeline2;
@@ -3234,7 +3234,7 @@ namespace System.Management.Automation.Language
? s_getDollarQuestion
: s_notDollarQuestion;
tryBodyExprs.Add(Expression.IfThen(dollarQuestionCheck, Compile(currentChain.RhsPipeline)));
tryBodyExprs.Add(Expression.IfThen(dollarQuestionCheck, CompilePipelineChainElement(currentChain.RhsPipeline)));
currentChain = currentChain.Parent as PipelineChainAst;
}
@@ -3277,6 +3277,24 @@ namespace System.Management.Automation.Language
return fullyExpandedBlock;
}
/// <summary>
/// Compile a pipeline as an element in a pipeline chain.
/// Needed since pure expressions won't set $? after them.
/// <seealso cref="CompileTrappableExpression"/> which does something similar.
/// </summary>
/// <param name="pipelineAst">The pipeline in the pipeline chain to compile to an expression.</param>
/// <returns>The compiled expression to execute the pipeline.</returns>
private Expression CompilePipelineChainElement(PipelineAst pipelineAst)
{
if (pipelineAst.PipelineElements.Count == 1 && pipelineAst.PipelineElements[0] is CommandExpressionAst)
{
// A single expression - must set $? after the expression.
return Expression.Block(Compile(pipelineAst), s_setDollarQuestionToTrue);
}
return Compile(pipelineAst);
}
public object VisitPipeline(PipelineAst pipelineAst)
{
var temps = new List<ParameterExpression>();
@@ -790,8 +790,8 @@ namespace System.Management.Automation.Language
#region Flags for operators
/* AndAnd */ TokenFlags.BinaryOperator | TokenFlags.ParseModeInvariant,
/* OrOr */ TokenFlags.BinaryOperator | TokenFlags.ParseModeInvariant,
/* AndAnd */ TokenFlags.ParseModeInvariant,
/* OrOr */ TokenFlags.ParseModeInvariant,
/* Ampersand */ TokenFlags.SpecialOperator | TokenFlags.ParseModeInvariant,
/* Pipe */ TokenFlags.SpecialOperator | TokenFlags.ParseModeInvariant,
/* Comma */ TokenFlags.UnaryOperator | TokenFlags.ParseModeInvariant,
@@ -76,6 +76,8 @@ Describe "Experimental Feature: && and || operators - Feature-Enabled" -Tag CI {
@{ Statement = '"hi" && testexe -returncode 1'; Output = @('hi', '1') }
@{ Statement = 'testexe -returncode 1 && "Hi"'; Output = @('1') }
@{ Statement = 'testexe -returncode 1 || "hi"'; Output = @('1', 'hi') }
@{ Statement = '"hello" && get-item macarena_doesnotexist || "there"; "hello" || "there"'; Output = @('hello', 'there', 'hello') }
@{ Statement = '1 + 1 && "Hi"'; Output = @(2, 'Hi') }
# Pipeline and native command
@{ Statement = '1,2,3 | % { $_ + 1 } && testexe -returncode 0'; Output = @('2','3','4','0') }