Example #1
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);
        }
        /// <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)
                {
                    // 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
                       ));
        }
Example #3
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
                       ));
        }
        IEnumerable <SymbolReference> IDocumentSymbolProvider.ProvideDocumentSymbols(
            ScriptFile scriptFile)
        {
            if (!scriptFile.FilePath.EndsWith(
                    "tests.ps1",
                    StringComparison.OrdinalIgnoreCase))
            {
                return(Enumerable.Empty <SymbolReference>());
            }

            var commandAsts = scriptFile.ScriptAst.FindAll(ast =>
            {
                CommandAst commandAst = ast as CommandAst;

                return
                (commandAst != null &&
                 commandAst.InvocationOperator != TokenKind.Dot &&
                 PesterSymbolReference.GetCommandType(commandAst.GetCommandName()).HasValue&&
                 commandAst.CommandElements.Count >= 2);
            },
                                                           true);

            return(commandAsts.Select(
                       ast =>
            {
                // By this point we know the Ast is a CommandAst with 2 or more CommandElements
                int testNameParamIndex = 1;
                CommandAst testAst = (CommandAst)ast;

                // The -Name parameter
                for (int i = 1; i < testAst.CommandElements.Count; i++)
                {
                    CommandParameterAst paramAst = testAst.CommandElements[i] as CommandParameterAst;
                    if (paramAst != null &&
                        paramAst.ParameterName.Equals("Name", StringComparison.OrdinalIgnoreCase))
                    {
                        testNameParamIndex = i + 1;
                        break;
                    }
                }

                if (testNameParamIndex > testAst.CommandElements.Count - 1)
                {
                    return null;
                }

                StringConstantExpressionAst stringAst =
                    testAst.CommandElements[testNameParamIndex] as StringConstantExpressionAst;

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

                string testDefinitionLine =
                    scriptFile.GetLine(
                        ast.Extent.StartLineNumber);

                return
                new PesterSymbolReference(
                    scriptFile,
                    testAst.GetCommandName(),
                    testDefinitionLine,
                    stringAst.Value,
                    ast.Extent);
            }).Where(s => s != null));
        }