private static bool FindForEachInCommand(CommandAst commandAst)
        {
            // Command name is always the first element in the CommandAst.
            //  e.g., 'foreach -parallel {}'
            var commandNameElement = (commandAst.CommandElements.Count > 0) ? commandAst.CommandElements[0] : null;

            if (commandNameElement is StringConstantExpressionAst commandName)
            {
                bool found = false;
                foreach (var foreachName in forEachNames)
                {
                    if (commandName.Value.Equals(foreachName, StringComparison.OrdinalIgnoreCase))
                    {
                        found = true;
                        break;
                    }
                }

                if (found)
                {
                    // Verify this is foreach-object with parallel parameter set.
                    var bindingResult = StaticParameterBinder.BindCommand(commandAst);
                    if (bindingResult.BoundParameters.ContainsKey("Parallel"))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 2
0
        private StaticBindingResult GetStaticBindingResult(Dictionary <object, object> dict)
        {
            var attrib     = typeof(NewSensorFactoryDefinition).GetCustomAttribute <CmdletAttribute>();
            var cmdletName = $"{attrib.VerbName}-{attrib.NounName}";

            var commandElements = new List <CommandElementAst>
            {
                AstFactory.StringConstantExpression(cmdletName, StringConstantType.BareWord)
            };

            foreach (var item in dict)
            {
                commandElements.Add(AstFactory.CommandParameter(item.Key.ToString(), null, new EmptyScriptExtent(true)));
                commandElements.Add(AstFactory.ConstantExpression(item.Value));
            }

            var commandPipeline = AstFactory.Pipeline(
                AstFactory.CommandExpression(
                    AstFactory.VariableExpression("sensors")
                    ),
                AstFactory.Command(commandElements)
                );

            var bindingResult = StaticParameterBinder.BindCommand((CommandAst)commandPipeline.PipelineElements[1]);

            if (bindingResult.BindingExceptions.Count > 0)
            {
                var exception = bindingResult.BindingExceptions.First().Value.BindingException;

                throw new ParameterBindingException($"Failed to parse hashtable '{PrettyPrintHashtable(dict)}': {exception.Message.EnsurePeriod()}", exception);
            }

            return(bindingResult);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Analyzes a CommandAst, if it is a New-Alias command, the AST is further analyzed.
        /// </summary>
        /// <param name="commandAst">The CommandAst to be analyzed</param>
        /// <returns>AstVisitAction to continue to analyze the ast's children</returns>
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            if (IsNewAliasCmdlet(commandAst))
            {
                // check the parameters of the New-Alias cmdlet for scope
                var parameterBindings = StaticParameterBinder.BindCommand(commandAst);

                if (parameterBindings.BoundParameters.ContainsKey("Scope"))
                {
                    var scopeValue = parameterBindings.BoundParameters["Scope"].ConstantValue;

                    if ((scopeValue != null) && (scopeValue.ToString().Equals("Global", StringComparison.OrdinalIgnoreCase)))
                    {
                        records.Add(new DiagnosticRecord(
                                        string.Format(CultureInfo.CurrentCulture, Strings.AvoidGlobalAliasesError),
                                        commandAst.Extent,
                                        GetName(),
                                        DiagnosticSeverity.Warning,
                                        fileName));
                    }
                }
            }

            return(AstVisitAction.SkipChildren);
        }
        /// <summary>
        /// Walks the using Ast to verify it is used within a foreach-object -parallel command
        /// and parameter set scope, and not from within a nested foreach-object -parallel call.
        /// </summary>
        /// <param name="usingAst">Using Ast to check.</param>
        /// <param name-"foreachNames">List of foreach-object command names.</param>
        /// <returns>True if using expression is in current call scope.</returns>
        private static bool IsInForeachParallelCallingScope(
            UsingExpressionAst usingAst,
            string[] foreachNames)
        {
            /*
             *  Example:
             *  $Test1 = "Hello"
             *  1 | ForEach-Object -Parallel {
             *     $using:Test1
             *     $Test2 = "Goodbye"
             *     1 | ForEach-Object -Parallel {
             *         $using:Test1    # Invalid using scope
             *         $using:Test2    # Valid using scope
             *     }
             *  }
             */
            Diagnostics.Assert(usingAst != null, "usingAst argument cannot be null.");

            // Search up the parent Ast chain for 'Foreach-Object -Parallel' commands.
            Ast currentParent      = usingAst.Parent;
            int foreachNestedCount = 0;

            while (currentParent != null)
            {
                // Look for Foreach-Object outer commands
                if (currentParent is CommandAst commandAst)
                {
                    foreach (var commandElement in commandAst.CommandElements)
                    {
                        if (commandElement is StringConstantExpressionAst commandName)
                        {
                            bool found = false;
                            foreach (var foreachName in foreachNames)
                            {
                                if (commandName.Value.Equals(foreachName, StringComparison.OrdinalIgnoreCase))
                                {
                                    found = true;
                                    break;
                                }
                            }

                            if (found)
                            {
                                // Verify this is foreach-object with parallel parameter set.
                                var bindingResult = StaticParameterBinder.BindCommand(commandAst);
                                if (bindingResult.BoundParameters.ContainsKey("Parallel"))
                                {
                                    foreachNestedCount++;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (foreachNestedCount > 1)
                {
                    // This using expression Ast is outside the original calling scope.
                    return(false);
                }

                currentParent = currentParent.Parent;
            }

            return(foreachNestedCount == 1);
        }