Example #1
0
        /// <summary>
        /// Adds each function definition as a
        /// </summary>
        /// <param name="functionDefinitionAst">A functionDefinitionAst object in the script's AST</param>
        /// <returns>A decision to stop searching if the right symbol was found,
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
        {
            IScriptExtent nameExtent = new ScriptExtent()
            {
                Text              = functionDefinitionAst.Name,
                StartLineNumber   = functionDefinitionAst.Extent.StartLineNumber,
                EndLineNumber     = functionDefinitionAst.Extent.EndLineNumber,
                StartColumnNumber = functionDefinitionAst.Extent.StartColumnNumber,
                EndColumnNumber   = functionDefinitionAst.Extent.EndColumnNumber
            };

            SymbolType symbolType =
                functionDefinitionAst.IsWorkflow ?
                SymbolType.Workflow : SymbolType.Function;

            this.SymbolReferences.Add(
                new SymbolReference(
                    symbolType,
                    nameExtent));

            return(AstVisitAction.Continue);
        }
        /// <summary>
        /// Decides if the current function definition is a reference of the symbol being searched for.
        /// A reference of the symbol will be a of type SymbolType.Function and have the same name as the symbol
        /// </summary>
        /// <param name="functionDefinitionAst">A functionDefinitionAst in the script's AST</param>
        /// <returns>A visit action that continues the search for references</returns>
        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
        {
            (int startColumnNumber, int startLineNumber) = GetStartColumnAndLineNumbersFromAst(functionDefinitionAst);

            IScriptExtent nameExtent = new ScriptExtent()
            {
                Text              = functionDefinitionAst.Name,
                StartLineNumber   = startLineNumber,
                EndLineNumber     = startLineNumber,
                StartColumnNumber = startColumnNumber,
                EndColumnNumber   = startColumnNumber + functionDefinitionAst.Name.Length
            };

            if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
                nameExtent.Text.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
            {
                this.FoundReferences.Add(new SymbolReference(
                                             SymbolType.Function,
                                             nameExtent));
            }
            return(base.VisitFunctionDefinition(functionDefinitionAst));
        }
Example #3
0
        public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
        {
            _currentMethod = new CodeMemberMethod();

            _currentMethod.Name = functionDefinitionAst.Name;

            if (functionDefinitionAst.Parameters != null)
            {
                foreach (var parameter in functionDefinitionAst.Parameters)
                {
                    _currentMethod.Parameters.Add(new CodeParameterDeclarationExpression(parameter.StaticType,
                                                                                         parameter.Name.VariablePath.ToString()));
                }
            }

            _currentClass.Members.Add(_currentMethod);

            foreach (var statement in functionDefinitionAst.Body.EndBlock.Statements)
            {
                var code = Visit(statement);
                if (code is CodeStatement)
                {
                    _currentMethod.Statements.Add(code as CodeStatement);
                }
                if (code is CodeMethodInvokeExpression)
                {
                    _currentMethod.Statements.Add(new CodeExpressionStatement(code as CodeExpression));
                }
                else if (code is CodeExpression)
                {
                    _currentMethod.Statements.Add(code as CodeExpression);
                }
            }

            _currentMethod = null;

            return(unit);
        }
        /// <summary>
        /// Visit function and checks that it has comment help
        /// </summary>
        /// <param name="funcAst"></param>
        /// <returns></returns>
        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst funcAst)
        {
            if (funcAst == null)
            {
                return(AstVisitAction.SkipChildren);
            }

            if (exportedFunctions.Contains(funcAst.Name))
            {
                if (funcAst.GetHelpContent() == null)
                {
                    DiagnosticRecords.Add(
                        new DiagnosticRecord(
                            string.Format(CultureInfo.CurrentCulture, Strings.ProvideCommentHelpError, funcAst.Name),
                            Helper.Instance.GetScriptExtentForFunctionName(funcAst),
                            GetName(),
                            DiagnosticSeverity.Information,
                            fileName));
                }
            }

            return(AstVisitAction.Continue);
        }
Example #5
0
 public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     throw new UnexpectedElementException();
 }
Example #6
0
 // FunctionDefinitionAst Extension Methods
 // New Methods Available:
 // - CreateNodeFromAST(NodeDepth, NodePosition, Parent) => Creates a Node
 public static FunctionNode CreateNodeFromAst(this FunctionDefinitionAst _ast, int _depth, int _position, Node _parent, Tree _tree)
 {
     return(new FunctionNode(_ast, _depth, _position, _parent, _tree));
 }
Example #7
0
 public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     return(false);
 }
 public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     FunctionCount += 1;
     return(AstVisitAction.Continue);
 }
Example #9
0
 public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     Console.WriteLine("Visited an FunctionDefinitionAst.");
     Console.WriteLine("    " + functionDefinitionAst.ToString().Replace(Environment.NewLine, Environment.NewLine + "    "));
     return(AstVisitAction.Continue);
 }
 public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => null;
Example #11
0
 public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst ast)
 {
     return(AstVisitAction.Continue);
 }
Example #12
0
 private static ImageListKind GetImageListKind(FunctionDefinitionAst funcDef)
 {
     //TODO: More image kinds here
     return(ImageListKind.Method);
 }
Example #13
0
 private static ImageListKind GetImageListKind(FunctionDefinitionAst funcDef)
 {
     return(ImageListKind.Method);
 }
Example #14
0
 public FunctionDefinitionEntryInfo(FunctionDefinitionAst functionDefinition)
 {
     _functionDefinition = functionDefinition;
 }
Example #15
0
        internal static Tuple <List <System.Management.Automation.Language.Token>, List <string> > GetHelpCommentTokens(IParameterMetadataProvider ipmp, Dictionary <Ast, System.Management.Automation.Language.Token[]> scriptBlockTokenCache)
        {
            int num;
            int num2;
            int num3;
            List <System.Management.Automation.Language.Token> commentBlock;
            Ast ast = (Ast)ipmp;
            Ast key = ast;

            while (key.Parent != null)
            {
                key = key.Parent;
            }
            System.Management.Automation.Language.Token[] tokenArray = null;
            scriptBlockTokenCache.TryGetValue(key, out tokenArray);
            if (tokenArray == null)
            {
                ParseError[] errorArray;
                Parser.ParseInput(key.Extent.Text, out tokenArray, out errorArray);
                scriptBlockTokenCache[key] = tokenArray;
            }
            FunctionDefinitionAst ast3 = ast as FunctionDefinitionAst;

            if (ast3 != null)
            {
                int tokenIndex = num = FirstTokenInExtent(tokenArray, ast.Extent, 0);
                commentBlock = GetPrecedingCommentBlock(tokenArray, tokenIndex, 2);
                if (IsCommentHelpText(commentBlock))
                {
                    return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num)));
                }
                num2 = FirstTokenInExtent(tokenArray, ast3.Body.Extent, 0) + 1;
                num3 = LastTokenInExtent(tokenArray, ast.Extent, tokenIndex);
            }
            else if (ast == key)
            {
                num2 = num = 0;
                num3 = tokenArray.Length - 1;
            }
            else
            {
                num2 = num = FirstTokenInExtent(tokenArray, ast.Extent, 0) - 1;
                num3 = LastTokenInExtent(tokenArray, ast.Extent, num2);
            }
            do
            {
                commentBlock = GetCommentBlock(tokenArray, ref num2);
                if (commentBlock.Count == 0)
                {
                    goto Label_0195;
                }
            }while (!IsCommentHelpText(commentBlock));
            if (ast == key)
            {
                NamedBlockAst endBlock = ((ScriptBlockAst)ast).EndBlock;
                if ((endBlock == null) || !endBlock.Unnamed)
                {
                    return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num)));
                }
                StatementAst ast5 = endBlock.Statements.FirstOrDefault <StatementAst>();
                if (ast5 is FunctionDefinitionAst)
                {
                    int num5 = ast5.Extent.StartLineNumber - commentBlock.Last <System.Management.Automation.Language.Token>().Extent.EndLineNumber;
                    if (num5 > 2)
                    {
                        return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num)));
                    }
                    goto Label_0195;
                }
            }
            return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num)));

Label_0195:
            commentBlock = GetPrecedingCommentBlock(tokenArray, num3, tokenArray[num3].Extent.StartLineNumber);
            if (IsCommentHelpText(commentBlock))
            {
                return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num)));
            }
            return(null);
        }
 private IEnumerable <ParameterAst> GetMandatoryParameters(FunctionDefinitionAst functionDefinitionAst)
 {
     return(functionDefinitionAst.GetParameterAsts()?.Where(IsParameterMandatory) ??
            Enumerable.Empty <ParameterAst>());
 }
 public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     throw PSTraceSource.NewArgumentException("ast");
 }
Example #18
0
 public virtual object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     VisitElement(functionDefinitionAst.Body);
     VisitElements(functionDefinitionAst.Parameters);
     return(functionDefinitionAst);
 }
Example #19
0
 /// <summary/>
 public virtual AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => DefaultVisit(functionDefinitionAst);
        private List <CorrectionExtent> GetCorrections(
            int whatIfIndex,
            int confirmIndex,
            ParameterAst[] parameterAsts,
            ParamBlockAst paramBlockAst,
            FunctionDefinitionAst funcDefnAst)
        {
            var filePath          = funcDefnAst.Extent.File;
            var correctionExtents = new List <CorrectionExtent>();

            if (paramBlockAst != null)
            {
                if (whatIfIndex != -1)
                {
                    correctionExtents.Add(GetCorrectionToRemoveParam(whatIfIndex, parameterAsts));
                }

                if (confirmIndex != -1)
                {
                    correctionExtents.Add(GetCorrectionToRemoveParam(confirmIndex, parameterAsts));
                }

                AttributeAst attributeAst = paramBlockAst.GetCmdletBindingAttributeAst();

                // check if it has cmdletbinding attribute
                if (attributeAst != null)
                {
                    NamedAttributeArgumentAst shouldProcessAst = attributeAst.GetSupportsShouldProcessAst();
                    if (shouldProcessAst != null)
                    {
                        ExpressionAst argAst;
                        if (!shouldProcessAst.GetValue(out argAst) &&
                            argAst != null)
                        {
                            // SupportsShouldProcess is set to something other than $true.
                            // Set it to $true
                            correctionExtents.Add(GetCorrectionsToSetShouldProcessToTrue(argAst));
                        }
                    }
                    else
                    {
                        // add supportsshouldprocess to the attribute
                        correctionExtents.Add(GetCorrectionToAddShouldProcess(attributeAst));
                    }
                }
                else
                {
                    // has no cmdletbinding attribute
                    // hence, add the attribute and supportsshouldprocess argument
                    correctionExtents.Add(GetCorrectionToAddAttribute(paramBlockAst));
                }
            }
            else
            {
                // function doesn't have param block
                // remove the parameter list
                // and create an equivalent param block
                // add cmdletbinding attribute and add supportsshouldprocess to it.
                correctionExtents.Add(GetCorrectionToRemoveFuncParamDecl(funcDefnAst, ast, tokens));
                correctionExtents.Add(GetCorrectionToAddParamBlock(funcDefnAst, parameterAsts));
            }

            // This is how we handle multiple edits-
            // create separate edits
            // apply those edits to the original script extent
            // and then give the corrected extent as suggested correction.

            // sort in descending order of start position
            correctionExtents.Sort((x, y) =>
            {
                var xRange = (Range)x;
                var yRange = (Range)y;
                return(xRange.Start < yRange.Start ? 1 : (xRange.Start == yRange.Start ? 0 : -1));
            });

            var editableText       = new EditableText(funcDefnAst.Extent.Text);
            var funcDefAstStartPos = funcDefnAst.Extent.ToRange().Start;

            foreach (var correctionExtent in correctionExtents)
            {
                var shiftedCorrectionExtent = Normalize(funcDefAstStartPos, correctionExtent);
                editableText.ApplyEdit(shiftedCorrectionExtent);
            }

            var result = new List <CorrectionExtent>();

            result.Add(
                new CorrectionExtent(
                    funcDefnAst.Extent.StartLineNumber,
                    funcDefnAst.Extent.EndLineNumber,
                    funcDefnAst.Extent.StartColumnNumber,
                    funcDefnAst.Extent.EndColumnNumber,
                    editableText.ToString(),
                    funcDefnAst.Extent.File));
            return(result);
        }
Example #21
0
 public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     Console.WriteLine("Visited an FunctionDefinitionAst.");
     return(functionDefinitionAst);
 }
 public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     // TODO: add function definition explanation
     AstExplainer(functionDefinitionAst);
     return(base.VisitFunctionDefinition(functionDefinitionAst));
 }
Example #23
0
        /// <summary>
        /// Visit function and checks that it is a cmdlet. If yes, then checks that any object returns must have a type declared
        /// in the output type (the only exception is if the type is object)
        /// </summary>
        /// <param name="funcAst"></param>
        /// <returns></returns>
        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst funcAst)
        {
            if (funcAst == null || funcAst.Body == null || funcAst.Body.ParamBlock == null ||
                funcAst.Body.ParamBlock.Attributes == null || funcAst.Body.ParamBlock.Attributes.Count == 0 ||
                !funcAst.Body.ParamBlock.Attributes.Any(attr => attr.TypeName.GetReflectionType() == typeof(CmdletBindingAttribute)))
            {
                return(AstVisitAction.Continue);
            }

            HashSet <string> outputTypes = new HashSet <string>();

            foreach (AttributeAst attrAst in funcAst.Body.ParamBlock.Attributes)
            {
                if (attrAst.TypeName != null && attrAst.TypeName.GetReflectionType() == typeof(OutputTypeAttribute) &&
                    attrAst.PositionalArguments != null)
                {
                    foreach (ExpressionAst expAst in attrAst.PositionalArguments)
                    {
                        if (expAst is StringConstantExpressionAst)
                        {
                            Type type = Type.GetType((expAst as StringConstantExpressionAst).Value);
                            if (type != null)
                            {
                                outputTypes.Add(type.FullName);
                            }
                        }
                        else
                        {
                            TypeExpressionAst typeAst = expAst as TypeExpressionAst;
                            if (typeAst != null && typeAst.TypeName != null)
                            {
                                if (typeAst.TypeName.GetReflectionType() != null)
                                {
                                    outputTypes.Add(typeAst.TypeName.GetReflectionType().FullName);
                                }
                                else
                                {
                                    outputTypes.Add(typeAst.TypeName.FullName);
                                }
                            }
                        }
                    }
                }
            }

            #if PSV3
            List <Tuple <string, StatementAst> > returnTypes = FindPipelineOutput.OutputTypes(funcAst);
            #else
            List <Tuple <string, StatementAst> > returnTypes = FindPipelineOutput.OutputTypes(funcAst, _classes);
            #endif

            HashSet <string> specialTypes = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            specialTypes.Add(typeof(Unreached).FullName);
            specialTypes.Add(typeof(Undetermined).FullName);
            specialTypes.Add(typeof(object).FullName);
            specialTypes.Add(typeof(void).FullName);
            specialTypes.Add(typeof(PSCustomObject).FullName);
            specialTypes.Add(typeof(PSObject).FullName);

            foreach (Tuple <string, StatementAst> returnType in returnTypes)
            {
                string typeName = returnType.Item1;

                if (String.IsNullOrEmpty(typeName) ||
                    specialTypes.Contains(typeName) ||
                    outputTypes.Contains(typeName, StringComparer.OrdinalIgnoreCase))
                {
                    continue;
                }
                else
                {
                    DiagnosticRecords.Add(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseOutputTypeCorrectlyError,
                                                                             funcAst.Name, typeName), returnType.Item2.Extent, GetName(), DiagnosticSeverity.Information, fileName));
                }
            }

            return(AstVisitAction.Continue);
        }
Example #24
0
 public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst ast)
 {
     return(DoNextAction(ast));
 }
Example #25
0
        public async Task <CommentHelpRequestResult> Handle(CommentHelpRequestParams request, CancellationToken cancellationToken)
        {
            var result = new CommentHelpRequestResult();

            if (!_workspaceService.TryGetFile(request.DocumentUri, out ScriptFile scriptFile))
            {
                return(result);
            }

            int triggerLine = (int)request.TriggerPosition.Line + 1;

            FunctionDefinitionAst functionDefinitionAst = _symbolsService.GetFunctionDefinitionForHelpComment(
                scriptFile,
                triggerLine,
                out string helpLocation);

            if (functionDefinitionAst == null)
            {
                return(result);
            }

            IScriptExtent funcExtent = functionDefinitionAst.Extent;
            string        funcText   = funcExtent.Text;

            if (helpLocation.Equals("begin"))
            {
                // check if the previous character is `<` because it invalidates
                // the param block the follows it.
                IList <string> lines = ScriptFile.GetLinesInternal(funcText);
                int            relativeTriggerLine0b = triggerLine - funcExtent.StartLineNumber;
                if (relativeTriggerLine0b > 0 && lines[relativeTriggerLine0b].IndexOf("<", StringComparison.OrdinalIgnoreCase) > -1)
                {
                    lines[relativeTriggerLine0b] = string.Empty;
                }

                funcText = string.Join("\n", lines);
            }

            List <ScriptFileMarker> analysisResults = await _analysisService.GetSemanticMarkersAsync(
                funcText,
                AnalysisService.GetCommentHelpRuleSettings(
                    enable: true,
                    exportedOnly: false,
                    blockComment: request.BlockComment,
                    vscodeSnippetCorrection: true,
                    placement: helpLocation));

            string helpText = analysisResults?.FirstOrDefault()?.Correction?.Edits[0].Text;

            if (helpText == null)
            {
                return(result);
            }

            result.Content = ScriptFile.GetLinesInternal(helpText).ToArray();

            if (helpLocation != null &&
                !helpLocation.Equals("before", StringComparison.OrdinalIgnoreCase))
            {
                // we need to trim the leading `{` and newline when helpLocation=="begin"
                // we also need to trim the leading newline when helpLocation=="end"
                result.Content = result.Content.Skip(1).ToArray();
            }

            return(result);
        }
Example #26
0
 public override StatementAst VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 => VisitStatement(base.VisitFunctionDefinition(functionDefinitionAst));
Example #27
0
        /// <summary>
        /// Finds a function definition that follows or contains the given line number.
        /// </summary>
        /// <param name="scriptFile">Open script file.</param>
        /// <param name="lineNumber">The 1 based line on which to look for function definition.</param>
        /// <param name="helpLocation"></param>
        /// <returns>If found, returns the function definition, otherwise, returns null.</returns>
        public FunctionDefinitionAst GetFunctionDefinitionForHelpComment(
            ScriptFile scriptFile,
            int lineNumber,
            out string helpLocation)
        {
            // check if the next line contains a function definition
            FunctionDefinitionAst funcDefnAst = GetFunctionDefinitionAtLine(scriptFile, lineNumber + 1);

            if (funcDefnAst != null)
            {
                helpLocation = "before";
                return(funcDefnAst);
            }

            // find all the script definitions that contain the line `lineNumber`
            IEnumerable <Ast> foundAsts = scriptFile.ScriptAst.FindAll(
                ast =>
            {
                var fdAst = ast as FunctionDefinitionAst;
                if (fdAst == null)
                {
                    return(false);
                }

                return(fdAst.Body.Extent.StartLineNumber < lineNumber &&
                       fdAst.Body.Extent.EndLineNumber > lineNumber);
            },
                true);

            if (foundAsts == null || !foundAsts.Any())
            {
                helpLocation = null;
                return(null);
            }

            // of all the function definitions found, return the innermost function
            // definition that contains `lineNumber`
            foreach (FunctionDefinitionAst foundAst in foundAsts.Cast <FunctionDefinitionAst>())
            {
                if (funcDefnAst == null)
                {
                    funcDefnAst = foundAst;
                    continue;
                }

                if (funcDefnAst.Extent.StartOffset >= foundAst.Extent.StartOffset &&
                    funcDefnAst.Extent.EndOffset <= foundAst.Extent.EndOffset)
                {
                    funcDefnAst = foundAst;
                }
            }

            // TODO use tokens to check for non empty character instead of just checking for line offset
            if (funcDefnAst.Body.Extent.StartLineNumber == lineNumber - 1)
            {
                helpLocation = "begin";
                return(funcDefnAst);
            }

            if (funcDefnAst.Body.Extent.EndLineNumber == lineNumber + 1)
            {
                helpLocation = "end";
                return(funcDefnAst);
            }

            // If we didn't find a function definition, then return null
            helpLocation = null;
            return(null);
        }
Example #28
0
 /// <summary>
 /// Adds each function defintion as a
 /// </summary>
 /// <param name="functionDefinitionAst">A functionDefinitionAst object in the script's AST</param>
 /// <returns>A decision to stop searching if the right symbol was found,
 /// or a decision to continue if it wasn't found</returns>
 public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 {
     return(this.findSymbolsVisitor.VisitFunctionDefinition(functionDefinitionAst));
 }
Example #29
0
        public async Task <CommentHelpRequestResult> Handle(CommentHelpRequestParams request, CancellationToken cancellationToken)
        {
            CommentHelpRequestResult result = new();

            if (!_workspaceService.TryGetFile(request.DocumentUri, out ScriptFile scriptFile))
            {
                return(result);
            }

            int triggerLine = request.TriggerPosition.Line + 1;

            FunctionDefinitionAst functionDefinitionAst = SymbolsService.GetFunctionDefinitionForHelpComment(
                scriptFile,
                triggerLine,
                out string helpLocation);

            if (functionDefinitionAst == null)
            {
                return(result);
            }

            IScriptExtent funcExtent = functionDefinitionAst.Extent;
            string        funcText   = funcExtent.Text;

            if (helpLocation.Equals("begin"))
            {
                // check if the previous character is `<` because it invalidates
                // the param block the follows it.
                IList <string> lines = ScriptFile.GetLinesInternal(funcText);
                int            relativeTriggerLine0b = triggerLine - funcExtent.StartLineNumber;
                if (relativeTriggerLine0b > 0 && lines[relativeTriggerLine0b].IndexOf("<", StringComparison.OrdinalIgnoreCase) > -1)
                {
                    lines[relativeTriggerLine0b] = string.Empty;
                }

                funcText = string.Join("\n", lines);
            }

            string helpText = await _analysisService.GetCommentHelpText(funcText, helpLocation, forBlockComment : request.BlockComment).ConfigureAwait(false);

            if (helpText == null)
            {
                return(result);
            }

            List <string> helpLines = ScriptFile.GetLinesInternal(helpText);

            if (helpLocation != null &&
                !helpLocation.Equals("before", StringComparison.OrdinalIgnoreCase))
            {
                // we need to trim the leading `{` and newline when helpLocation=="begin"
                helpLines.RemoveAt(helpLines.Count - 1);

                // we also need to trim the leading newline when helpLocation=="end"
                helpLines.RemoveAt(0);
            }

            // Trim trailing newline from help text.
            if (string.IsNullOrEmpty(helpLines[helpLines.Count - 1]))
            {
                helpLines.RemoveAt(helpLines.Count - 1);
            }

            result.Content = helpLines.ToArray();
            return(result);
        }
 object ICustomAstVisitor.VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
 => ProcessRewriter(VisitFunctionDefinition, functionDefinitionAst);