コード例 #1
0
 /// <summary>
 /// Create an instance of DiagnosticRecord and add it to a list
 /// </summary>
 private void GenerateDiagnosticRecords()
 {
     foreach (var curCmdletCompat in curCmdletCompatibilityMap)
     {
         if (!curCmdletCompat.Value)
         {
             var cmdletName     = curCmdletAst.GetCommandName();
             var platformInfo   = platformSpecMap[curCmdletCompat.Key];
             var funcNameTokens = Helper.Instance.Tokens.Where(
                 token =>
                 Helper.ContainsExtent(curCmdletAst.Extent, token.Extent) &&
                 token.Text.Equals(cmdletName));
             var funcNameToken = funcNameTokens.FirstOrDefault();
             var extent        = funcNameToken == null ? null : funcNameToken.Extent;
             diagnosticRecords.Add(new DiagnosticRecord(
                                       String.Format(
                                           Strings.UseCompatibleCmdletsError,
                                           cmdletName,
                                           platformInfo.PSEdition,
                                           platformInfo.PSVersion,
                                           platformInfo.OS),
                                       extent,
                                       GetName(),
                                       GetDiagnosticSeverity(),
                                       scriptPath,
                                       null,
                                       null));
         }
     }
 }
コード例 #2
0
        /// <summary>
        /// AnalyzeScript: Analyze the ast to check that positional parameters are not used.
        /// </summary>
        public IEnumerable <DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
        {
            if (ast == null)
            {
                throw new ArgumentNullException(Strings.NullAstErrorMessage);
            }

            // Finds all CommandAsts.
            IEnumerable <Ast> foundAsts = ast.FindAll(testAst => testAst is CommandAst, true);

            // Iterrates all CommandAsts and check the command name.
            foreach (Ast foundAst in foundAsts)
            {
                CommandAst cmdAst = (CommandAst)foundAst;
                // Handles the exception caused by commands like, {& $PLINK $args 2> $TempErrorFile}.
                // You can also review the remark section in following document,
                // MSDN: CommandAst.GetCommandName Method
                if (cmdAst.GetCommandName() == null)
                {
                    continue;
                }

                if (Helper.Instance.GetCommandInfo(cmdAst.GetCommandName()) != null &&
                    Helper.Instance.PositionalParameterUsed(cmdAst))
                {
                    yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPositionalParametersError, cmdAst.GetCommandName()),
                                                      cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, cmdAst.GetCommandName()));
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Checks that write-host command is not used
        /// </summary>
        /// <param name="cmdAst"></param>
        /// <returns></returns>
        public override AstVisitAction VisitCommand(CommandAst cmdAst)
        {
            if (cmdAst == null)
            {
                return(AstVisitAction.SkipChildren);
            }

            if (cmdAst.GetCommandName() != null && String.Equals(cmdAst.GetCommandName(), "write-host", StringComparison.OrdinalIgnoreCase))
            {
                records.Add(new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWriteHostError, System.IO.Path.GetFileName(fileName)),
                                                 cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName));
            }

            return(AstVisitAction.Continue);
        }
コード例 #4
0
        private static IEnumerable <FunctionDefinitionAst> FindDefinition(CommandAst reference)
        {
            var scope = GetParentScope(reference);

            if (scope != null)
            {
                // If in the same scope as the reference call, the function must be defined before the call
                var definitions = scope.Statements.OfType <FunctionDefinitionAst>().
                                  Where(def => def.Name.Equals(reference.GetCommandName(), StringComparison.OrdinalIgnoreCase) && def.Extent.EndOffset <= reference.Extent.StartOffset);

                if (definitions.Any())
                {
                    // Since we are in the same scope as the reference, we always go to the last function defined before the call
                    return(new List <FunctionDefinitionAst>()
                    {
                        definitions.Last()
                    });
                }

                while ((scope = GetParentScope(scope)) != null)
                {
                    definitions = scope.Statements.OfType <FunctionDefinitionAst>().Where(def => def.Name.Equals(reference.GetCommandName(), StringComparison.OrdinalIgnoreCase));

                    if (definitions.Any())
                    {
                        return(new List <FunctionDefinitionAst>(definitions));
                    }
                }
            }

            return(null);
        }
コード例 #5
0
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            var name      = commandAst.GetCommandName();
            var elements  = commandAst.CommandElements.Skip(1).ToArray();
            var arguments = new List <Argument>();

            for (var i = 0; i < elements.Length; i++)
            {
                var node     = VisitSyntaxNode(elements[i]);
                var argument = node as Argument;
                if (argument != null && i < elements.Length - 1 && argument.Expression == null)
                {
                    node = VisitSyntaxNode(elements[i + 1]);
                    argument.Expression = node;
                    i++;
                }
                else if (argument == null)
                {
                    argument = new Argument(node);
                }
                arguments.Add(argument);
            }

            _currentNode = ConvertCommand(new Invocation(new IdentifierName(name), new ArgumentList(arguments)));

            return(AstVisitAction.SkipChildren);
        }
コード例 #6
0
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            string commandName = commandAst.GetCommandName();

            if (commandName == null)
            {
                UnsupportedError("Could not get command name", commandAst.Extent);
                return(base.VisitCommand(commandAst));
            }

            if (commandAst.InvocationOperator == TokenKind.Dot)
            {
                AnalyzeDotSourcedFile(commandName);
            }
            else if (commandName == "Import-Module" || commandName == "ipmo")
            {
                // TODO
            }
            else
            {
                AnalyzeCommandInvocation(commandAst, commandName);
            }

            return(base.VisitCommand(commandAst));
        }
コード例 #7
0
        /// <summary>
        /// AnalyzeScript: Analyze the script to check if cmdlet alias is used.
        /// </summary>
        public IEnumerable <DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
        {
            if (ast == null)
            {
                throw new ArgumentNullException(Strings.NullAstErrorMessage);
            }

            // Finds all CommandAsts.
            IEnumerable <Ast> foundAsts = ast.FindAll(testAst => testAst is CommandAst, true);

            // Iterrates all CommandAsts and check the command name.
            foreach (Ast foundAst in foundAsts)
            {
                CommandAst cmdAst    = (CommandAst)foundAst;
                string     aliasName = cmdAst.GetCommandName();
                // Handles the exception caused by commands like, {& $PLINK $args 2> $TempErrorFile}.
                // You can also review the remark section in following document,
                // MSDN: CommandAst.GetCommandName Method
                if (aliasName == null)
                {
                    continue;
                }

                string cmdletName = Microsoft.Windows.Powershell.ScriptAnalyzer.Helper.Instance.GetCmdletNameFromAlias(aliasName);

                if (!String.IsNullOrEmpty(cmdletName))
                {
                    yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingCmdletAliasesError, aliasName, cmdletName),
                                                      cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, aliasName));
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Creates a list containing suggested correction
        /// </summary>
        /// <param name="cmdAst">Command AST of an alias</param>
        /// <param name="cmdletName">Full name of the alias</param>
        /// <returns>Retruns a list of suggested corrections</returns>
        private List <CorrectionExtent> GetCorrectionExtent(CommandAst cmdAst, string cmdletName)
        {
            var ext = cmdAst.Extent;

            if (ext.File == null)
            {
                return(null);
            }
            var    corrections = new List <CorrectionExtent>();
            var    alias       = cmdAst.GetCommandName();
            string description = string.Format(
                CultureInfo.CurrentCulture,
                Strings.AvoidUsingCmdletAliasesCorrectionDescription,
                alias,
                cmdletName);

            corrections.Add(new CorrectionExtent(
                                ext.StartLineNumber,
                                ext.EndLineNumber,
                                cmdAst.CommandElements[0].Extent.StartColumnNumber,
                                cmdAst.CommandElements[0].Extent.EndColumnNumber,
                                cmdletName,
                                ext.File,
                                description));
            return(corrections);
        }
コード例 #9
0
            public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst)
            {
                CommandAst commandParentAst = commandParameterAst.Parent as CommandAst;

                if (commandParentAst != null &&
                    String.Equals(commandParentAst.GetCommandName(), "Import-DscResource", StringComparison.OrdinalIgnoreCase))
                {
                    // Resource can be specified by name, without a module.
                    if (String.Equals(commandParameterAst.ParameterName, "Name", StringComparison.OrdinalIgnoreCase))
                    {
                        ArrayLiteralAst arrayLiteralAst = commandParameterAst.Argument as ArrayLiteralAst;
                        if (arrayLiteralAst != null)
                        {
                            IEnumerable <string> resourceNames = arrayLiteralAst.Elements.OfType <StringConstantExpressionAst>().Select(x => x.Value);
                            foreach (string resourceName in resourceNames)
                            {
                            }
                        }
                    }
                    // Or with ModuleDefinition parameter
                    else if (String.Equals(commandParameterAst.ParameterName, "ModuleDefinition", StringComparison.OrdinalIgnoreCase))
                    {
                        ArrayLiteralAst arrayLiteralAst = commandParameterAst.Argument as ArrayLiteralAst;
                        if (arrayLiteralAst != null)
                        {
                            Modules.AddRange(arrayLiteralAst.Elements.OfType <StringConstantExpressionAst>().Select(x => x.Value));
                        }
                    }
                }
                return(base.VisitCommandParameter(commandParameterAst));
            }
コード例 #10
0
        public override StatementAst VisitCommand(CommandAst commandAst)
        {
            string commandName;

            if (commandAst.InvocationOperator != TokenKind.Dot ||
                commandAst.CommandElements.Count != 1)
            {
                return(base.VisitCommand(commandAst));
            }

            if (!string.IsNullOrEmpty(commandName = commandAst.GetCommandName()))
            {
                if (IsScriptFile(commandName))
                {
                    var wasSuccessful = TryCreateScriptBlockExpression(
                        commandName,
                        commandAst.Extent,
                        out StatementAst result);

                    return(wasSuccessful
                        ? result
                        : base.VisitCommand(commandAst));
                }
            }

            return(base.VisitCommand(commandAst));
        }
コード例 #11
0
        /// <summary>
        /// Determines if CommandAst is for the "New-Alias" command, checking aliases.
        /// </summary>
        /// <param name="commandAst">CommandAst to validate</param>
        /// <returns>True if the CommandAst is for the "New-Alias" command</returns>
        private bool IsNewAliasCmdlet(CommandAst commandAst)
        {
            if (commandAst == null || commandAst.GetCommandName() == null)
            {
                return(false);
            }

            var AliasList = Helper.Instance.CmdletNameAndAliases("New-Alias");

            if (AliasList.Contains(commandAst.GetCommandName()))
            {
                return(true);
            }

            return(false);
        }
コード例 #12
0
 public override AstVisitAction VisitCommand(CommandAst commandAst)  //confirmed
 {
     if (commandAst.ToString().Contains(symbolRef.ScriptRegion.Text))
     {
         ValidateExtend(symbolRef.ScriptRegion.Text, commandAst.GetCommandName(), commandAst);
     }
     return(base.VisitCommand(commandAst));
 }
コード例 #13
0
        public static bool HasProxyCommand(CommandAst commandAst)
        {
            var commandName  = commandAst.GetCommandName();
            var assembly     = Assembly.GetExecutingAssembly();
            var resourceName = $"CodeConverter.PowerShell.ProxyCommands.{commandName}.ps1";

            return(assembly.GetManifestResourceStream(resourceName) != null);
        }
コード例 #14
0
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            var name      = commandAst.GetCommandName();
            var elements  = commandAst.CommandElements.Skip(1).ToArray();
            var arguments = new List <Argument>();

            if (ParameterFinder.HasProxyCommand(commandAst))
            {
                arguments = new List <Argument>();
                var parameters = ParameterFinder.FindBoundParameters(commandAst);
                foreach (var parameter in parameters)
                {
                    if (parameter.Value is Ast)
                    {
                        var ast      = parameter.Value as Ast;
                        var node     = VisitSyntaxNode(ast);
                        var argument = new Argument(parameter.Key, node);
                        arguments.Add(argument);
                    }
                    else if (parameter.Value is ExpressionAst[])
                    {
                        var ast      = (parameter.Value as ExpressionAst[]).First();
                        var node     = VisitSyntaxNode(ast);
                        var argument = new Argument(parameter.Key, node);
                        arguments.Add(argument);
                    }
                    else
                    {
                        var literal  = new Literal(parameter.Value.ToString());
                        var argument = new Argument(parameter.Key, literal);
                        arguments.Add(argument);
                    }
                }
            }
            else
            {
                for (var i = 0; i < elements.Length; i++)
                {
                    var node     = VisitSyntaxNode(elements[i]);
                    var argument = node as Argument;
                    if (argument != null && i < elements.Length - 1 && argument.Expression == null)
                    {
                        node = VisitSyntaxNode(elements[i + 1]);
                        argument.Expression = node;
                        i++;
                    }
                    else if (argument == null)
                    {
                        argument = new Argument(node);
                    }
                    arguments.Add(argument);
                }
            }

            _currentNode = ConvertCommand(new Invocation(new IdentifierName(name), new ArgumentList(arguments)));

            return(AstVisitAction.SkipChildren);
        }
コード例 #15
0
        /// <summary>
        /// AnalyzeScript: Analyze the ast to check that positional parameters are not used.
        /// </summary>
        public IEnumerable <DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
        {
            if (ast == null)
            {
                throw new ArgumentNullException(Strings.NullAstErrorMessage);
            }

            // Find all function definitions in the script and add them to the set.
            IEnumerable <Ast> functionDefinitionAsts = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true);
            HashSet <String>  declaredFunctionNames  = new HashSet <String>();

            foreach (FunctionDefinitionAst functionDefinitionAst in functionDefinitionAsts)
            {
                if (string.IsNullOrEmpty(functionDefinitionAst.Name))
                {
                    continue;
                }
                declaredFunctionNames.Add(functionDefinitionAst.Name);
            }

            // Finds all CommandAsts.
            IEnumerable <Ast> foundAsts = ast.FindAll(testAst => testAst is CommandAst, true);

            // Iterates all CommandAsts and check the command name.
            foreach (Ast foundAst in foundAsts)
            {
                CommandAst cmdAst = (CommandAst)foundAst;
                // Handles the exception caused by commands like, {& $PLINK $args 2> $TempErrorFile}.
                // You can also review the remark section in following document,
                // MSDN: CommandAst.GetCommandName Method
                if (cmdAst.GetCommandName() == null)
                {
                    continue;
                }

                if ((Helper.Instance.IsCmdlet(cmdAst) || declaredFunctionNames.Contains(cmdAst.GetCommandName())) &&
                    (Helper.Instance.PositionalParameterUsed(cmdAst, true)))
                {
                    PipelineAst parent = cmdAst.Parent as PipelineAst;

                    if (parent != null && parent.PipelineElements.Count > 1)
                    {
                        // raise if it's the first element in pipeline. otherwise no.
                        if (parent.PipelineElements[0] == cmdAst)
                        {
                            yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPositionalParametersError, cmdAst.GetCommandName()),
                                                              cmdAst.Extent, GetName(), DiagnosticSeverity.Information, fileName, cmdAst.GetCommandName()));
                        }
                    }
                    // not in pipeline so just raise it normally
                    else
                    {
                        yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPositionalParametersError, cmdAst.GetCommandName()),
                                                          cmdAst.Extent, GetName(), DiagnosticSeverity.Information, fileName, cmdAst.GetCommandName()));
                    }
                }
            }
        }
        /// <summary>
        /// Condition on the cmdlet that must be satisfied for the error to be raised
        /// </summary>
        /// <param name="CmdAst"></param>
        /// <returns></returns>
        public override bool CommandCondition(CommandAst CmdAst)
        {
            if (CTSTCmdlet == null)
            {
                CTSTCmdlet = Helper.Instance.CmdletNameAndAliases("convertto-securestring");
            }

            return(CmdAst != null && CmdAst.GetCommandName() != null && CTSTCmdlet.Contains(CmdAst.GetCommandName(), StringComparer.OrdinalIgnoreCase));
        }
コード例 #17
0
        /// <summary>
        /// Test if the given Ast is a regular CommandAst with arguments
        /// </summary>
        /// <param name="ast">the PowerShell Ast to test</param>
        /// <returns>true if the Ast represents a PowerShell command with arguments, false otherwise</returns>
        private static bool IsNamedCommandWithArguments(Ast ast)
        {
            CommandAst commandAst = ast as CommandAst;

            return(commandAst != null &&
                   commandAst.InvocationOperator != TokenKind.Dot &&
                   PesterSymbolReference.GetCommandType(commandAst.GetCommandName()).HasValue&&
                   commandAst.CommandElements.Count >= 2);
        }
コード例 #18
0
        /// <summary>
        /// Attempt to process a <see cref="CommandAst" /> as a custom command.
        /// </summary>
        /// <param name="commandAst">The <see cref="CommandAst" /> to process.</param>
        /// <param name="visitor">
        /// The <see cref="CompileVisitor" /> requesting the expression.
        /// </param>
        /// <param name="expression">
        /// The <see cref="Expression" /> result if a command handler was found.
        /// </param>
        /// <returns><c>true</c> if a commmand handler was matched, otherwise <c>false</c>.</returns>
        public bool TryProcessAst(CommandAst commandAst, CompileVisitor visitor, out Expression expression)
        {
            if (_commandRegistry.TryGetValue(commandAst.GetCommandName(), out ICommandHandler handler))
            {
                expression = handler.ProcessAst(commandAst, visitor);
                return(true);
            }

            expression = null;
            return(false);
        }
コード例 #19
0
            public override AstVisitAction VisitCommand(CommandAst commandAst)
            {
                string commandName = commandAst?.GetCommandName();

                if (commandName == null)
                {
                    return(AstVisitAction.Continue);
                }

                if (_commandsToIgnore.Contains(commandName))
                {
                    return(AstVisitAction.Continue);
                }

                // Note:
                // The "right" way to eliminate user-defined commands would be to build
                // a list of:
                //  - all functions defined above this point
                //  - all modules imported
                // However, looking for imported modules could prove very expensive
                // and we would still miss things like assignments to the function: provider.
                // Instead, we look to see if a command of the given name is present in any
                // known profile, which is something of a hack.

                // This is not present in any known profiles, so assume it is user defined
                if (!_anyProfile.Runtime.Commands.ContainsKey(commandName))
                {
                    return(AstVisitAction.Continue);
                }

                // Check each target platform
                foreach (CompatibilityProfileData targetProfile in _compatibilityTargets)
                {
                    // If the target has this command, everything is good
                    if (targetProfile.Runtime.Commands.TryGetValue(commandName, out IReadOnlyList <CommandData> matchedCommands))
                    {
                        // Now check that the parameters on the command are available on all target platforms
                        CheckCommandInvocationParameters(targetProfile, commandName, commandAst, matchedCommands);
                        continue;
                    }

                    var diagnostic = CommandCompatibilityDiagnostic.Create(
                        commandName,
                        targetProfile.Platform,
                        commandAst.Extent,
                        _analyzedFileName,
                        _rule);

                    _diagnosticAccumulator.Add(diagnostic);
                }

                return(AstVisitAction.Continue);
            }
コード例 #20
0
        /// <summary>
        /// Create an instance of DiagnosticRecord and add it to a list
        /// </summary>
        private void GenerateDiagnosticRecords()
        {
            bool referenceCompatibility = curCmdletCompatibilityMap[reference];

            // If the command is present in reference platform but not in any of the target platforms.
            // Or if the command is not present in reference platform but present in any of the target platforms
            // then declare it as an incompatible cmdlet.
            // If it is present neither in reference platform nor any target platforms, then it is probably a
            // non-builtin command and hence do not declare it as an incompatible cmdlet.
            // Since we do not check for aliases, the XOR-ing will also make sure that aliases are not flagged
            // as they will be found neither in reference platform nor in target platforms
            foreach (var platform in ruleParameters.compatibility)
            {
                var curCmdletCompat = curCmdletCompatibilityMap[platform];
                if (!curCmdletCompat && referenceCompatibility)
                {
                    var cmdletName     = curCmdletAst.GetCommandName();
                    var platformInfo   = platformSpecMap[platform];
                    var funcNameTokens = Helper.Instance.Tokens.Where(
                        token =>
                        Helper.ContainsExtent(curCmdletAst.Extent, token.Extent) &&
                        token.Text.Equals(cmdletName));
                    var funcNameToken = funcNameTokens.FirstOrDefault();
                    var extent        = funcNameToken == null ? null : funcNameToken.Extent;
                    diagnosticRecords.Add(new DiagnosticRecord(
                                              String.Format(
                                                  Strings.UseCompatibleCmdletsError,
                                                  cmdletName,
                                                  platformInfo.PSEdition,
                                                  platformInfo.PSVersion,
                                                  platformInfo.OS),
                                              extent,
                                              GetName(),
                                              GetDiagnosticSeverity(),
                                              scriptPath,
                                              null,
                                              null));
                }
            }
        }
コード例 #21
0
        Command GetCommand(CommandAst commandAst)
        {
            if (commandAst.CommandElements.First() is ScriptBlockExpressionAst)
            {
                var scriptBlockAst = (commandAst.CommandElements.First() as ScriptBlockExpressionAst).ScriptBlock;
                return(new Command(scriptBlockAst));
            }

            else
            {
                return(new Command(commandAst.GetCommandName()));
            }
        }
コード例 #22
0
ファイル: AvoidAlias.cs プロジェクト: peteri/PSScriptAnalyzer
        /// <summary>
        /// AnalyzeScript: Analyze the script to check if cmdlet alias is used.
        /// </summary>
        public IEnumerable <DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
        {
            if (ast == null)
            {
                throw new ArgumentNullException(Strings.NullAstErrorMessage);
            }
            if (!isPropertiesSet)
            {
                SetProperties();
            }
            // Finds all CommandAsts.
            IEnumerable <Ast> foundAsts = ast.FindAll(testAst => testAst is CommandAst, true);

            // Iterates all CommandAsts and check the command name.
            foreach (Ast foundAst in foundAsts)
            {
                CommandAst cmdAst = (CommandAst)foundAst;

                // Check if the command ast should be ignored
                if (IgnoreCommandast(cmdAst))
                {
                    continue;
                }

                string aliasName = cmdAst.GetCommandName();

                // Handles the exception caused by commands like, {& $PLINK $args 2> $TempErrorFile}.
                // You can also review the remark section in following document,
                // MSDN: CommandAst.GetCommandName Method
                if (aliasName == null ||
                    whiteList.Contains(aliasName))
                {
                    continue;
                }

                string cmdletName = Helper.Instance.GetCmdletNameFromAlias(aliasName);
                if (!String.IsNullOrEmpty(cmdletName))
                {
                    yield return(new DiagnosticRecord(
                                     string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingCmdletAliasesError, aliasName, cmdletName),
                                     GetCommandExtent(cmdAst),
                                     GetName(),
                                     DiagnosticSeverity.Warning,
                                     fileName,
                                     aliasName,
                                     suggestedCorrections: GetCorrectionExtent(cmdAst, cmdletName)));
                }
            }
        }
コード例 #23
0
        /// <summary>
        /// Convert a CommandAst known to represent a Pester command and a reference to the scriptfile
        /// it is in into symbol representing a Pester call for code lens
        /// </summary>
        /// <param name="scriptFile">the scriptfile the Pester call occurs in</param>
        /// <param name="pesterCommandAst">the CommandAst representing the Pester call</param>
        /// <returns>a symbol representing the Pester call containing metadata for CodeLens to use</returns>
        private static PesterSymbolReference ConvertPesterAstToSymbolReference(ScriptFile scriptFile, CommandAst pesterCommandAst)
        {
            string            testLine    = scriptFile.GetLine(pesterCommandAst.Extent.StartLineNumber);
            PesterCommandType?commandName = PesterSymbolReference.GetCommandType(pesterCommandAst.GetCommandName());

            if (commandName == null)
            {
                return(null);
            }

            // Search for a name for the test
            // If the test has more than one argument for names, we set it to null
            string testName       = null;
            bool   alreadySawName = false;

            for (int i = 1; i < pesterCommandAst.CommandElements.Count; i++)
            {
                CommandElementAst currentCommandElement = pesterCommandAst.CommandElements[i];

                // Check for an explicit "-Name" parameter
                if (currentCommandElement is CommandParameterAst)
                {
                    // Found -Name parameter, move to next element which is the argument for -TestName
                    i++;

                    if (!alreadySawName && TryGetTestNameArgument(pesterCommandAst.CommandElements[i], out testName))
                    {
                        alreadySawName = true;
                    }

                    continue;
                }

                // Otherwise, if an argument is given with no parameter, we assume it's the name
                // If we've already seen a name, we set the name to null
                if (!alreadySawName && TryGetTestNameArgument(pesterCommandAst.CommandElements[i], out testName))
                {
                    alreadySawName = true;
                }
            }

            return(new PesterSymbolReference(
                       scriptFile,
                       commandName.Value,
                       testLine,
                       testName,
                       pesterCommandAst.Extent
                       ));
        }
コード例 #24
0
        /// <summary>
        /// Convert a CommandAst known to represent a Pester command and a reference to the scriptfile
        /// it is in into symbol representing a Pester call for code lens
        /// </summary>
        /// <param name="scriptFile">the scriptfile the Pester call occurs in</param>
        /// <param name="pesterCommandAst">the CommandAst representing the Pester call</param>
        /// <returns>a symbol representing the Pester call containing metadata for CodeLens to use</returns>
        private static PesterSymbolReference ConvertPesterAstToSymbolReference(ScriptFile scriptFile, CommandAst pesterCommandAst)
        {
            string            testLine    = scriptFile.GetLine(pesterCommandAst.Extent.StartLineNumber);
            PesterCommandType?commandName = PesterSymbolReference.GetCommandType(pesterCommandAst.GetCommandName());

            if (commandName == null)
            {
                return(null);
            }

            // Search for a name for the test
            // If the test has more than one argument for names, we set it to null
            string testName       = null;
            bool   alreadySawName = false;

            for (int i = 1; i < pesterCommandAst.CommandElements.Count; i++)
            {
                CommandElementAst currentCommandElement = pesterCommandAst.CommandElements[i];

                // Check for an explicit "-Name" parameter
                if (currentCommandElement is CommandParameterAst parameterAst)
                {
                    i++;
                    if (parameterAst.ParameterName == "Name" && i < pesterCommandAst.CommandElements.Count)
                    {
                        testName       = alreadySawName ? null : (pesterCommandAst.CommandElements[i] as StringConstantExpressionAst)?.Value;
                        alreadySawName = true;
                    }
                    continue;
                }

                // Otherwise, if an argument is given with no parameter, we assume it's the name
                // If we've already seen a name, we set the name to null
                if (pesterCommandAst.CommandElements[i] is StringConstantExpressionAst testNameStrAst)
                {
                    testName       = alreadySawName ? null : testNameStrAst.Value;
                    alreadySawName = true;
                }
            }

            return(new PesterSymbolReference(
                       scriptFile,
                       commandName.Value,
                       testLine,
                       testName,
                       pesterCommandAst.Extent
                       ));
        }
コード例 #25
0
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            string moduleName = string.Empty;
            string cmdName    = commandAst.GetCommandName() ?? string.Empty;

            if (cmdName.IndexOf('\\') != -1)
            {
                var s = cmdName.Split('\\');
                moduleName = s[0];
                cmdName    = s[1];
            }

            string resolvedCmd = Helpers.ResolveAlias(cmdName) ?? cmdName;

            HelpEntity helpResult;

            if (string.IsNullOrEmpty(moduleName))
            {
                var helpResults = HelpTableQueryRange(resolvedCmd);
                helpResult = helpResults?.FirstOrDefault();
                if (helpResults.Count > 1)
                {
                    this.errorMessage = $"The command '{helpResult?.CommandName}' is present in more than one module: '{string.Join("', '", helpResults.Select(r => r.ModuleName))}'. Explicitly prepend the module name to the command to select one: '{helpResults.First().ModuleName}\\{helpResult?.CommandName}'";
                }
            }
            else
            {
                helpResult = HelpTableQuery(resolvedCmd, moduleName);
                if (string.IsNullOrEmpty(helpResult?.ModuleName))
                {
                    helpResult = new()
                    {
                        ModuleName = moduleName
                    };
                }
            }

            var description = helpResult?.Synopsis?.ToString();

            if (string.IsNullOrEmpty(description))
            {
                // Try to find out if this may be a cmdlet
                if (resolvedCmd.IndexOf('-') > 0)
                {
                    var approvedVerbs = GetApprovedVerbs();
                    var possibleVerb  = resolvedCmd[..resolvedCmd.IndexOf('-')];
コード例 #26
0
        /// <summary>
        /// For a command like "gci -path c:", returns the extent of "gci" in the command
        /// </summary>
        private IScriptExtent GetCommandExtent(CommandAst commandAst)
        {
            var cmdName = commandAst.GetCommandName();

            foreach (var cmdElement in commandAst.CommandElements)
            {
                var stringConstExpressinAst = cmdElement as StringConstantExpressionAst;
                if (stringConstExpressinAst != null)
                {
                    if (stringConstExpressinAst.Value.Equals(cmdName))
                    {
                        return(stringConstExpressinAst.Extent);
                    }
                }
            }
            return(commandAst.Extent);
        }
コード例 #27
0
        /// <summary>
        /// Visit CommandAst. Skip if name of command is in
        /// namestobeskipped
        /// </summary>
        /// <param name="commandAst"></param>
        /// <returns></returns>
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            if (commandAst == null || commandAst.GetCommandName() == null)
            {
                return(AstVisitAction.SkipChildren);
            }

            if (commandAst.CommandElements != null && commandAst.CommandElements.Count > 0)
            {
                var firstCommand = commandAst.CommandElements[0];
                if (NamesToBeSkipped.Contains(firstCommand.Extent.Text, StringComparer.OrdinalIgnoreCase))
                {
                    return(AstVisitAction.SkipChildren);
                }
            }

            return(AstVisitAction.Continue);
        }
コード例 #28
0
            public override AstVisitAction VisitCommand(CommandAst commandAst)
            {
                var commandName = commandAst.GetCommandName();

                if (commandName != null)
                {
                    if (_singleton._engineIntrinsics != null)
                    {
                        var commandInfo = _singleton._engineIntrinsics.InvokeCommand.GetCommand(commandName, CommandTypes.All);
                        if (commandInfo == null && !_singleton.UnresolvedCommandCouldSucceed(commandName, _rootAst))
                        {
                            _singleton._current = commandAst.CommandElements[0].Extent.EndOffset;
                            detectedError       = string.Format(CultureInfo.CurrentCulture, PSReadLineResources.CommandNotFoundError, commandName);
                            return(AstVisitAction.StopVisit);
                        }
                    }

                    if (commandAst.CommandElements.Any(e => e is ScriptBlockExpressionAst))
                    {
                        if (_singleton._options.CommandsToValidateScriptBlockArguments == null ||
                            !_singleton._options.CommandsToValidateScriptBlockArguments.Contains(commandName))
                        {
                            return(AstVisitAction.SkipChildren);
                        }
                    }
                }

                if (_singleton._options.CommandValidationHandler != null)
                {
                    try
                    {
                        _singleton._options.CommandValidationHandler(commandAst);
                    }
                    catch (Exception e)
                    {
                        detectedError = e.Message;
                    }
                }

                return(!string.IsNullOrWhiteSpace(detectedError)
                    ? AstVisitAction.StopVisit
                    : AstVisitAction.Continue);
            }
コード例 #29
0
        public static Dictionary <string, object> FindBoundParameters(CommandAst commandAst)
        {
            var commandName = commandAst.GetCommandName();

            var assembly     = Assembly.GetExecutingAssembly();
            var resourceName = "CodeConverter.PowerShell.GetBoundParameters.ps1";

            string getBoundParameterScript;

            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
                using (StreamReader reader = new StreamReader(stream))
                {
                    getBoundParameterScript = reader.ReadToEnd();
                }

            resourceName = $"CodeConverter.PowerShell.ProxyCommands.{commandName}.ps1";
            string proxyCommand;

            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
                using (StreamReader reader = new StreamReader(stream))
                {
                    proxyCommand = reader.ReadToEnd();
                }

            var result = new Dictionary <string, object>();

            using (var powerShell = System.Management.Automation.PowerShell.Create())
            {
                powerShell.AddScript(getBoundParameterScript);
                powerShell.Invoke();
                powerShell.AddCommand("Get-BoundParameter");
                powerShell.AddParameter("commandAst", commandAst);
                powerShell.AddParameter("proxyCommand", proxyCommand);
                var psobject = powerShell.Invoke();

                foreach (var param in psobject.Select(m => m.BaseObject).Cast <Hashtable>())
                {
                    result.Add(param["Name"] as string, param["Ast"]);
                }
            }

            return(result);
        }
コード例 #30
0
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            CountOfCommands++;
            var commandName = commandAst.GetCommandName();

            if (commandName != null)
            {
                int commandCount;
                CommandsCalled.TryGetValue(commandName, out commandCount);
                CommandsCalled[commandName] = commandCount + 1;
            }

            if (commandAst.InvocationOperator == TokenKind.Dot)
            {
                CountOfDotSourcedCommands++;
            }

            return(AstVisitAction.Continue);
        }