System.Management.Pash.Implementation.ExecutionVisitor.VisitPipeline C# (CSharp) Method

VisitPipeline() public method

public VisitPipeline ( System.Management.Automation.Language.PipelineAst pipelineAst ) : AstVisitAction
pipelineAst System.Management.Automation.Language.PipelineAst
return AstVisitAction
        public override AstVisitAction VisitPipeline(PipelineAst pipelineAst)
        {
            // shouldn't happen, but anyway
            if (!pipelineAst.PipelineElements.Any())
            {
                return AstVisitAction.SkipChildren;
            }
            // Pipeline uses global execution context, so we should set its WriteSideEffects flag, and restore it after.
            // TODO: I'm not very sure about that changing context and WriteSideEffectsToPipeline stuff
            var pipeLineContext = ExecutionContext.CurrentRunspace.ExecutionContext;
            bool writeSideEffects = pipeLineContext.WriteSideEffectsToPipeline;
            try
            {
                pipeLineContext.WriteSideEffectsToPipeline = _writeSideEffectsToPipeline;
                var pipeline = ExecutionContext.CurrentRunspace.CreateNestedPipeline();
                int startAt = 0; // set to 1 if first element is an expression
                int pipelineCommandCount = pipelineAst.PipelineElements.Count;

                // first element of pipeline can be an expression that needs to be evaluated
                var expression = pipelineAst.PipelineElements[0] as CommandExpressionAst;
                if (expression != null)
                {
                    // evaluate it and get results
                    var subVisitor = this.CloneSub(_writeSideEffectsToPipeline);
                    expression.Expression.Visit(subVisitor);
                    var results = subVisitor._pipelineCommandRuntime.OutputStream.Read();
                    // if we only have that one expression and no commands, write expression to output and return
                    if (pipelineCommandCount == 1)
                    {
                        _pipelineCommandRuntime.WriteObject(results, true);
                        VisitRedirections(expression);
                        return AstVisitAction.SkipChildren;
                    }
                    // otherwise write value to input of pipeline to be processed
                    if (results.Count == 1)
                    {
                        // "unroll" an input array: write all enumerated elements seperately to the pipeline
                        pipeline.Input.Write(results[0], true);
                    }
                    else
                    {
                        pipeline.Input.Write(results, true);
                    }
                    startAt = 1;
                }
                else // if there was no expression we take the input of the context's input stream
                {
                    foreach (var input in ExecutionContext.InputStream.Read())
                    {
                        pipeline.Input.Write(input);
                    }
                }

                // all other elements *need* to be commands (same in PS). Make that sure and add them to the pipeline
                for (int curCommand = startAt; curCommand < pipelineCommandCount; curCommand++)
                {
                    var commandAst = pipelineAst.PipelineElements[curCommand] as CommandAst;
                    if (commandAst == null)
                    {
                        throw new NotSupportedException("Invalid command in pipeline."
                            + " Only the first element of a pipeline can be an expression.");
                    }
                    var command = GetCommand(commandAst);

                    commandAst.CommandElements
                    // the first CommandElements is the command itself. The rest are parameters/arguments
                    .Skip(1)
                        .Select(ConvertCommandElementToCommandParameter)
                        .ForEach(command.Parameters.Add);

                    command.RedirectionVisitor = new RedirectionVisitor(this, commandAst.Redirections);

                    pipeline.Commands.Add(command);
                }

                // now execute the pipeline
                ExecutionContext.PushPipeline(pipeline);
                // rerouting the output and error stream would be easier, but Pipeline doesn't
                // have an interface for this. So let's catch the exception for now, read the streams
                // and rethrow it afterwards
                Exception exception = null;
                Collection<PSObject> pipeResults = null;
                try
                {
                    pipeResults = pipeline.Invoke();
                }
                catch (Exception e)
                {
                    exception = e;
                    pipeResults = pipeline.Output.NonBlockingRead();
                }
                // read output and error and write them as results of the current commandRuntime
                foreach (var curResult in pipeResults)
                {
                    _pipelineCommandRuntime.WriteObject(curResult);
                }
                var errors = pipeline.Error.NonBlockingRead();
                foreach (var curError in errors)
                {
                    _pipelineCommandRuntime.ErrorStream.Write(curError);
                }
                ExecutionContext.PopPipeline();
                if (exception != null)
                {
                    throw exception;
                }
            }
            finally
            {
                pipeLineContext.WriteSideEffectsToPipeline = writeSideEffects;
            }

            return AstVisitAction.SkipChildren;
        }
ExecutionVisitor