| | | 1 | | using System.Management.Automation; |
| | | 2 | | using System.Management.Automation.Language; |
| | | 3 | | |
| | | 4 | | namespace Kestrun.OpenApi; |
| | | 5 | | /// <summary> |
| | | 6 | | /// Helper to extract help information from PowerShell functions. |
| | | 7 | | /// </summary> |
| | | 8 | | public static class HelpExtractor |
| | | 9 | | { |
| | | 10 | | /// <summary> |
| | | 11 | | /// Get the parsed comment-based help (CommentHelpInfo) for a PowerShell function |
| | | 12 | | /// using the AST + FunctionDefinitionAst.GetHelpContent(). |
| | | 13 | | /// </summary> |
| | | 14 | | public static CommentHelpInfo? GetHelp(this FunctionInfo fn) |
| | | 15 | | { |
| | 0 | 16 | | if (fn.ScriptBlock?.Ast is null) |
| | | 17 | | { |
| | 0 | 18 | | return null; |
| | | 19 | | } |
| | | 20 | | |
| | | 21 | | // Case 1: the AST *is already* a FunctionDefinitionAst |
| | 0 | 22 | | if (fn.ScriptBlock.Ast is FunctionDefinitionAst directFuncAst) |
| | | 23 | | { |
| | 0 | 24 | | return directFuncAst.GetHelpContent(); |
| | | 25 | | } |
| | | 26 | | |
| | | 27 | | // Case 2: the AST is a ScriptBlockAst (or something else), |
| | | 28 | | // and we need to search for the matching FunctionDefinitionAst |
| | 0 | 29 | | if (fn.ScriptBlock.Ast is ScriptBlockAst scriptAst) |
| | | 30 | | { |
| | 0 | 31 | | var funcAst = scriptAst.Find( |
| | 0 | 32 | | ast => ast is FunctionDefinitionAst f && |
| | 0 | 33 | | f.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase), |
| | 0 | 34 | | searchNestedScriptBlocks: true) as FunctionDefinitionAst; |
| | | 35 | | |
| | 0 | 36 | | return funcAst?.GetHelpContent(); |
| | | 37 | | } |
| | | 38 | | |
| | | 39 | | // Fallback: unknown AST shape |
| | 0 | 40 | | return null; |
| | | 41 | | } |
| | | 42 | | |
| | | 43 | | /// <summary> |
| | | 44 | | /// Get the synopsis from the help information. |
| | | 45 | | /// </summary> |
| | | 46 | | /// <param name="help"> The help information to extract the synopsis from. </param> |
| | | 47 | | /// <returns>The synopsis text. </returns> |
| | | 48 | | public static string GetSynopsis(this CommentHelpInfo? help) |
| | 0 | 49 | | => help?.Synopsis?.Trim() ?? string.Empty; |
| | | 50 | | |
| | | 51 | | /// <summary> |
| | | 52 | | /// Get the description from the help information. |
| | | 53 | | /// </summary> |
| | | 54 | | /// <param name="help"> The help information to extract the description from. </param> |
| | | 55 | | /// <returns>The description text.</returns> |
| | | 56 | | public static string GetDescription(this CommentHelpInfo? help) |
| | 0 | 57 | | => help?.Description?.Trim() ?? string.Empty; |
| | | 58 | | |
| | | 59 | | /// <summary> |
| | | 60 | | /// Get the parameter description from the help information. |
| | | 61 | | /// </summary> |
| | | 62 | | /// <param name="help"> The help information to extract the parameter description from. </param> |
| | | 63 | | /// <param name="name"> The name of the parameter to get the description for. </param> |
| | | 64 | | /// <returns>The parameter description text, or null if not found.</returns> |
| | | 65 | | public static string? GetParameterDescription(this CommentHelpInfo? help, string name) |
| | | 66 | | { |
| | 0 | 67 | | if (help?.Parameters == null || string.IsNullOrEmpty(name)) |
| | | 68 | | { |
| | 0 | 69 | | return null; |
| | | 70 | | } |
| | | 71 | | // Parameter names in CommentHelpInfo are stored in uppercase |
| | 0 | 72 | | var key = name.ToUpperInvariant(); |
| | | 73 | | // Try to get the parameter description |
| | 0 | 74 | | return help.Parameters.TryGetValue(key, out var text) |
| | 0 | 75 | | ? text?.Trim() |
| | 0 | 76 | | : null; |
| | | 77 | | } |
| | | 78 | | } |