Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
DefaultCommandHelpObjectBuilder.cs935 linesDownload Raw Back to help
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Diagnostics;8using System.Globalization;9using System.Management.Automation.Internal;10using System.Management.Automation.Runspaces;11using System.Reflection;12using System.Text;13 14namespace System.Management.Automation.Help15{16    /// <summary>17    /// Positional parameter comparer.18    /// </summary>19    internal class PositionalParameterComparer : IComparer20    {21        /// <summary>22        /// </summary>23        /// <param name="x"></param>24        /// <param name="y"></param>25        /// <returns></returns>26        public int Compare(object x, object y)27        {28            CommandParameterInfo a = x as CommandParameterInfo;29            CommandParameterInfo b = y as CommandParameterInfo;30 31            Debug.Assert(a != null && b != null);32 33            return (a.Position - b.Position);34        }35    }36 37    /// <summary>38    /// The help object builder class attempts to create a full HelpInfo object from39    /// a CmdletInfo object. This is used to generate the default UX when no help content40    /// is present in the box. This class mimics the exact same structure as that of a MAML41    /// node, so that the default UX does not introduce regressions.42    /// </summary>43    internal static class DefaultCommandHelpObjectBuilder44    {45        internal static readonly string TypeNameForDefaultHelp = "ExtendedCmdletHelpInfo";46        /// <summary>47        /// Generates a HelpInfo PSObject from a CmdletInfo object.48        /// </summary>49        /// <param name="input">Command info.</param>50        /// <returns>HelpInfo PSObject.</returns>51        internal static PSObject GetPSObjectFromCmdletInfo(CommandInfo input)52        {53            // Create a copy of commandInfo for GetCommandCommand so that we can generate parameter54            // sets based on Dynamic Parameters (+ optional arguments)55            CommandInfo commandInfo = input.CreateGetCommandCopy(null);56 57            PSObject obj = new PSObject();58 59            obj.TypeNames.Clear();60            obj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#{commandInfo.ModuleName}#command"));61            obj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#{commandInfo.ModuleName}"));62            obj.TypeNames.Add(DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp);63            obj.TypeNames.Add("CmdletHelpInfo");64            obj.TypeNames.Add("HelpInfo");65 66            if (commandInfo is CmdletInfo cmdletInfo)67            {68                bool common = false;69                if (cmdletInfo.Parameters != null)70                {71                    common = HasCommonParameters(cmdletInfo.Parameters);72                }73 74                obj.Properties.Add(new PSNoteProperty("CommonParameters", common));75                AddDetailsProperties(obj, cmdletInfo.Name, cmdletInfo.Noun, cmdletInfo.Verb, TypeNameForDefaultHelp);76                AddSyntaxProperties(obj, cmdletInfo.Name, cmdletInfo.ParameterSets, common, TypeNameForDefaultHelp);77                AddParametersProperties(obj, cmdletInfo.Parameters, common, TypeNameForDefaultHelp);78                AddInputTypesProperties(obj, cmdletInfo.Parameters);79                AddRelatedLinksProperties(obj, commandInfo.CommandMetadata.HelpUri);80 81                try82                {83                    AddOutputTypesProperties(obj, cmdletInfo.OutputType);84                }85                catch (PSInvalidOperationException)86                {87                    AddOutputTypesProperties(obj, new ReadOnlyCollection<PSTypeName>(new List<PSTypeName>()));88                }89 90                AddAliasesProperties(obj, cmdletInfo.Name, cmdletInfo.Context);91 92                if (HasHelpInfoUri(cmdletInfo.Module, cmdletInfo.ModuleName))93                {94                    AddRemarksProperties(obj, cmdletInfo.Name, cmdletInfo.CommandMetadata.HelpUri);95                }96                else97                {98                    obj.Properties.Add(new PSNoteProperty("remarks", HelpDisplayStrings.None));99                }100 101                obj.Properties.Add(new PSNoteProperty("PSSnapIn", cmdletInfo.PSSnapIn));102            }103            else if (commandInfo is FunctionInfo funcInfo)104            {105                bool common = HasCommonParameters(funcInfo.Parameters);106 107                obj.Properties.Add(new PSNoteProperty("CommonParameters", common));108                AddDetailsProperties(obj, funcInfo.Name, string.Empty, string.Empty, TypeNameForDefaultHelp);109                AddSyntaxProperties(obj, funcInfo.Name, funcInfo.ParameterSets, common, TypeNameForDefaultHelp);110                AddParametersProperties(obj, funcInfo.Parameters, common, TypeNameForDefaultHelp);111                AddInputTypesProperties(obj, funcInfo.Parameters);112                AddRelatedLinksProperties(obj, funcInfo.CommandMetadata.HelpUri);113 114                try115                {116                    AddOutputTypesProperties(obj, funcInfo.OutputType);117                }118                catch (PSInvalidOperationException)119                {120                    AddOutputTypesProperties(obj, new ReadOnlyCollection<PSTypeName>(new List<PSTypeName>()));121                }122 123                AddAliasesProperties(obj, funcInfo.Name, funcInfo.Context);124 125                if (HasHelpInfoUri(funcInfo.Module, funcInfo.ModuleName))126                {127                    AddRemarksProperties(obj, funcInfo.Name, funcInfo.CommandMetadata.HelpUri);128                }129                else130                {131                    obj.Properties.Add(new PSNoteProperty("remarks", HelpDisplayStrings.None));132                }133            }134 135            obj.Properties.Add(new PSNoteProperty("alertSet", null));136            obj.Properties.Add(new PSNoteProperty("description", null));137            obj.Properties.Add(new PSNoteProperty("examples", null));138            obj.Properties.Add(new PSNoteProperty("Synopsis", commandInfo.Syntax));139            obj.Properties.Add(new PSNoteProperty("ModuleName", commandInfo.ModuleName));140            obj.Properties.Add(new PSNoteProperty("nonTerminatingErrors", string.Empty));141            obj.Properties.Add(new PSNoteProperty("xmlns:command", "http://schemas.microsoft.com/maml/dev/command/2004/10"));142            obj.Properties.Add(new PSNoteProperty("xmlns:dev", "http://schemas.microsoft.com/maml/dev/2004/10"));143            obj.Properties.Add(new PSNoteProperty("xmlns:maml", "http://schemas.microsoft.com/maml/2004/10"));144 145            return obj;146        }147 148        /// <summary>149        /// Adds the details properties.150        /// </summary>151        /// <param name="obj">HelpInfo object.</param>152        /// <param name="name">Command name.</param>153        /// <param name="noun">Command noun.</param>154        /// <param name="verb">Command verb.</param>155        /// <param name="typeNameForHelp">Type name for help.</param>156        /// <param name="synopsis">Synopsis.</param>157        internal static void AddDetailsProperties(PSObject obj, string name, string noun, string verb, string typeNameForHelp,158            string synopsis = null)159        {160            PSObject mshObject = new PSObject();161 162            mshObject.TypeNames.Clear();163            mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#details"));164 165            mshObject.Properties.Add(new PSNoteProperty("name", name));166            mshObject.Properties.Add(new PSNoteProperty("noun", noun));167            mshObject.Properties.Add(new PSNoteProperty("verb", verb));168 169            // add synopsis170            if (!string.IsNullOrEmpty(synopsis))171            {172                PSObject descriptionObject = new PSObject();173                descriptionObject.TypeNames.Clear();174                descriptionObject.TypeNames.Add("MamlParaTextItem");175                descriptionObject.Properties.Add(new PSNoteProperty("Text", synopsis));176                mshObject.Properties.Add(new PSNoteProperty("Description", descriptionObject));177            }178 179            obj.Properties.Add(new PSNoteProperty("details", mshObject));180        }181 182        /// <summary>183        /// Adds the syntax properties.184        /// </summary>185        /// <param name="obj">HelpInfo object.</param>186        /// <param name="cmdletName">Command name.</param>187        /// <param name="parameterSets">Parameter sets.</param>188        /// <param name="common">Common parameters.</param>189        /// <param name="typeNameForHelp">Type name for help.</param>190        internal static void AddSyntaxProperties(PSObject obj, string cmdletName, ReadOnlyCollection<CommandParameterSetInfo> parameterSets, bool common, string typeNameForHelp)191        {192            PSObject mshObject = new PSObject();193 194            mshObject.TypeNames.Clear();195            mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#syntax"));196 197            AddSyntaxItemProperties(mshObject, cmdletName, parameterSets, common, typeNameForHelp);198 199            obj.Properties.Add(new PSNoteProperty("Syntax", mshObject));200        }201 202        /// <summary>203        /// Add the syntax item properties.204        /// </summary>205        /// <param name="obj">HelpInfo object.</param>206        /// <param name="cmdletName">Cmdlet name, you can't get this from parameterSets.</param>207        /// <param name="parameterSets">A collection of parameter sets.</param>208        /// <param name="common">Common parameters.</param>209        /// <param name="typeNameForHelp">Type name for help.</param>210        private static void AddSyntaxItemProperties(PSObject obj, string cmdletName, ReadOnlyCollection<CommandParameterSetInfo> parameterSets, bool common, string typeNameForHelp)211        {212            ArrayList mshObjects = new ArrayList();213 214            foreach (CommandParameterSetInfo parameterSet in parameterSets)215            {216                PSObject mshObject = new PSObject();217 218                mshObject.TypeNames.Clear();219                mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#syntaxItem"));220 221                mshObject.Properties.Add(new PSNoteProperty("name", cmdletName));222                mshObject.Properties.Add(new PSNoteProperty("CommonParameters", common));223 224                Collection<CommandParameterInfo> parameters = new Collection<CommandParameterInfo>();225                // GenerateParameters parameters in display order226                // ie., Positional followed by227                //      Named Mandatory (in alpha numeric) followed by228                //      Named (in alpha numeric)229                parameterSet.GenerateParametersInDisplayOrder(parameters.Add, delegate { });230 231                AddSyntaxParametersProperties(mshObject, parameters, common, parameterSet.Name);232 233                mshObjects.Add(mshObject);234            }235 236            obj.Properties.Add(new PSNoteProperty("syntaxItem", mshObjects.ToArray()));237        }238 239        /// <summary>240        /// Add the syntax parameters properties (these parameters are used to create the syntax section)241        /// </summary>242        /// <param name="obj">HelpInfo object.</param>243        /// <param name="parameters">244        /// a collection of parameters in display order245        /// ie., Positional followed by246        ///      Named Mandatory (in alpha numeric) followed by247        ///      Named (in alpha numeric)248        /// </param>249        /// <param name="common">Common parameters.</param>250        /// <param name="parameterSetName">Name of the parameter set for which the syntax is generated.</param>251        private static void AddSyntaxParametersProperties(PSObject obj, IEnumerable<CommandParameterInfo> parameters,252            bool common, string parameterSetName)253        {254            ArrayList mshObjects = new ArrayList();255 256            foreach (CommandParameterInfo parameter in parameters)257            {258                if (common && Cmdlet.CommonParameters.Contains(parameter.Name))259                {260                    continue;261                }262 263                PSObject mshObject = new PSObject();264 265                mshObject.TypeNames.Clear();266                mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#parameter"));267 268                Collection<Attribute> attributes = new Collection<Attribute>(parameter.Attributes);269 270                AddParameterProperties(mshObject, parameter.Name, new Collection<string>(parameter.Aliases),271                    parameter.IsDynamic, parameter.ParameterType, attributes, parameterSetName);272 273                Collection<ValidateSetAttribute> validateSet = GetValidateSetAttribute(attributes);274                List<string> names = new List<string>();275 276                foreach (ValidateSetAttribute set in validateSet)277                {278                    foreach (string value in set.ValidValues)279                    {280                        names.Add(value);281                    }282                }283 284                if (names.Count != 0)285                {286                    AddParameterValueGroupProperties(mshObject, names.ToArray());287                }288                else289                {290                    if (parameter.ParameterType.IsEnum && (Enum.GetNames(parameter.ParameterType) != null))291                    {292                        AddParameterValueGroupProperties(mshObject, Enum.GetNames(parameter.ParameterType));293                    }294                    else if (parameter.ParameterType.IsArray)295                    {296                        if (parameter.ParameterType.GetElementType().IsEnum &&297                            Enum.GetNames(parameter.ParameterType.GetElementType()) != null)298                        {299                            AddParameterValueGroupProperties(mshObject, Enum.GetNames(parameter.ParameterType.GetElementType()));300                        }301                    }302                    else if (parameter.ParameterType.IsGenericType)303                    {304                        Type[] types = parameter.ParameterType.GetGenericArguments();305 306                        if (types.Length != 0)307                        {308                            Type type = types[0];309 310                            if (type.IsEnum && (Enum.GetNames(type) != null))311                            {312                                AddParameterValueGroupProperties(mshObject, Enum.GetNames(type));313                            }314                            else if (type.IsArray)315                            {316                                if (type.GetElementType().IsEnum &&317                                    Enum.GetNames(type.GetElementType()) != null)318                                {319                                    AddParameterValueGroupProperties(mshObject, Enum.GetNames(type.GetElementType()));320                                }321                            }322                        }323                    }324                }325 326                mshObjects.Add(mshObject);327            }328 329            obj.Properties.Add(new PSNoteProperty("parameter", mshObjects.ToArray()));330        }331 332        /// <summary>333        /// Adds a parameter value group (for enums)334        /// </summary>335        /// <param name="obj">Object.</param>336        /// <param name="values">Parameter group values.</param>337        private static void AddParameterValueGroupProperties(PSObject obj, string[] values)338        {339            PSObject paramValueGroup = new PSObject();340 341            paramValueGroup.TypeNames.Clear();342            paramValueGroup.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#parameterValueGroup"));343 344            ArrayList paramValue = new ArrayList(values);345 346            paramValueGroup.Properties.Add(new PSNoteProperty("parameterValue", paramValue.ToArray()));347            obj.Properties.Add(new PSNoteProperty("parameterValueGroup", paramValueGroup));348        }349 350        /// <summary>351        /// Add the parameters properties (these parameters are used to create the parameters section)352        /// </summary>353        /// <param name="obj">HelpInfo object.</param>354        /// <param name="parameters">Parameters.</param>355        /// <param name="common">Common parameters.</param>356        /// <param name="typeNameForHelp">Type name for help.</param>357        internal static void AddParametersProperties(PSObject obj, Dictionary<string, ParameterMetadata> parameters, bool common, string typeNameForHelp)358        {359            PSObject paramsObject = new PSObject();360 361            paramsObject.TypeNames.Clear();362            paramsObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#parameters"));363 364            ArrayList paramObjects = new ArrayList();365 366            ArrayList sortedParameters = new ArrayList();367 368            if (parameters != null)369            {370                foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)371                {372                    sortedParameters.Add(parameter.Key);373                }374            }375 376            sortedParameters.Sort(StringComparer.Ordinal);377 378            foreach (string parameter in sortedParameters)379            {380                if (common && Cmdlet.CommonParameters.Contains(parameter))381                {382                    continue;383                }384 385                PSObject paramObject = new PSObject();386 387                paramObject.TypeNames.Clear();388                paramObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#parameter"));389 390                AddParameterProperties(paramObject, parameter, parameters[parameter].Aliases,391                    parameters[parameter].IsDynamic, parameters[parameter].ParameterType, parameters[parameter].Attributes);392 393                paramObjects.Add(paramObject);394            }395 396            paramsObject.Properties.Add(new PSNoteProperty("parameter", paramObjects.ToArray()));397            obj.Properties.Add(new PSNoteProperty("parameters", paramsObject));398        }399 400        /// <summary>401        /// Adds the parameter properties.402        /// </summary>403        /// <param name="obj">HelpInfo object.</param>404        /// <param name="name">Parameter name.</param>405        /// <param name="aliases">Parameter aliases.</param>406        /// <param name="dynamic">Is dynamic parameter?</param>407        /// <param name="type">Parameter type.</param>408        /// <param name="attributes">Parameter attributes.</param>409        /// <param name="parameterSetName">Name of the parameter set for which the syntax is generated.</param>410        private static void AddParameterProperties(PSObject obj, string name, Collection<string> aliases, bool dynamic,411            Type type, Collection<Attribute> attributes, string parameterSetName = null)412        {413            Collection<ParameterAttribute> attribs = GetParameterAttribute(attributes);414 415            obj.Properties.Add(new PSNoteProperty("name", name));416 417            if (attribs.Count == 0)418            {419                obj.Properties.Add(new PSNoteProperty("required", string.Empty));420                obj.Properties.Add(new PSNoteProperty("pipelineInput", string.Empty));421                obj.Properties.Add(new PSNoteProperty("isDynamic", string.Empty));422                obj.Properties.Add(new PSNoteProperty("parameterSetName", string.Empty));423                obj.Properties.Add(new PSNoteProperty("description", string.Empty));424                obj.Properties.Add(new PSNoteProperty("position", string.Empty));425                obj.Properties.Add(new PSNoteProperty("aliases", string.Empty));426                obj.Properties.Add(new PSNoteProperty("globbing", string.Empty));427            }428            else429            {430                ParameterAttribute paramAttribute = attribs[0];431                if (!string.IsNullOrEmpty(parameterSetName))432                {433                    foreach (var attrib in attribs)434                    {435                        if (string.Equals(attrib.ParameterSetName, parameterSetName, StringComparison.OrdinalIgnoreCase))436                        {437                            paramAttribute = attrib;438                            break;439                        }440                    }441                }442 443                obj.Properties.Add(new PSNoteProperty("required", CultureInfo.CurrentCulture.TextInfo.ToLower(paramAttribute.Mandatory.ToString())));444                obj.Properties.Add(new PSNoteProperty("pipelineInput", GetPipelineInputString(paramAttribute)));445                obj.Properties.Add(new PSNoteProperty("isDynamic", CultureInfo.CurrentCulture.TextInfo.ToLower(dynamic.ToString())));446                AddParameterGlobbingProperties(obj, attributes);447 448                if (paramAttribute.ParameterSetName.Equals(ParameterAttribute.AllParameterSets, StringComparison.OrdinalIgnoreCase))449                {450                    obj.Properties.Add(new PSNoteProperty("parameterSetName", StringUtil.Format(HelpDisplayStrings.AllParameterSetsName)));451                }452                else453                {454                    StringBuilder sb = new StringBuilder();455 456                    for (int i = 0; i < attribs.Count; i++)457                    {458                        sb.Append(attribs[i].ParameterSetName);459 460                        if (i != (attribs.Count - 1))461                        {462                            sb.Append(", ");463                        }464                    }465 466                    obj.Properties.Add(new PSNoteProperty("parameterSetName", sb.ToString()));467                }468 469                if (paramAttribute.HelpMessage != null)470                {471                    StringBuilder sb = new StringBuilder();472 473                    sb.AppendLine(paramAttribute.HelpMessage);474 475                    obj.Properties.Add(new PSNoteProperty("description", sb.ToString()));476                }477 478                // We do not show switch parameters in the syntax section479                // (i.e. [-Syntax] not [-Syntax <SwitchParameter>]480                if (type != typeof(SwitchParameter))481                {482                    AddParameterValueProperties(obj, type, attributes);483                }484 485                AddParameterTypeProperties(obj, type, attributes);486 487                if (paramAttribute.Position == int.MinValue)488                {489                    obj.Properties.Add(new PSNoteProperty("position",490                        StringUtil.Format(HelpDisplayStrings.NamedParameter)));491                }492                else493                {494                    obj.Properties.Add(new PSNoteProperty("position",495                        paramAttribute.Position.ToString(CultureInfo.InvariantCulture)));496                }497 498                if (aliases.Count == 0)499                {500                    obj.Properties.Add(new PSNoteProperty("aliases", StringUtil.Format(501                        HelpDisplayStrings.None)));502                }503                else504                {505                    StringBuilder sb = new StringBuilder();506 507                    for (int i = 0; i < aliases.Count; i++)508                    {509                        sb.Append(aliases[i]);510 511                        if (i != (aliases.Count - 1))512                        {513                            sb.Append(", ");514                        }515                    }516 517                    obj.Properties.Add(new PSNoteProperty("aliases", sb.ToString()));518                }519            }520        }521 522        /// <summary>523        /// Adds the globbing properties.524        /// </summary>525        /// <param name="obj">HelpInfo object.</param>526        /// <param name="attributes">The attributes of the parameter (needed to look for PSTypeName).</param>527        private static void AddParameterGlobbingProperties(PSObject obj, IEnumerable<Attribute> attributes)528        {529            bool globbing = false;530 531            foreach (var attrib in attributes)532            {533                if (attrib is SupportsWildcardsAttribute)534                {535                    globbing = true;536                    break;537                }538            }539 540            obj.Properties.Add(new PSNoteProperty("globbing", CultureInfo.CurrentCulture.TextInfo.ToLower(globbing.ToString())));541        }542 543        /// <summary>544        /// Adds the parameterType properties.545        /// </summary>546        /// <param name="obj">HelpInfo object.</param>547        /// <param name="parameterType">The type of a parameter.</param>548        /// <param name="attributes">The attributes of the parameter (needed to look for PSTypeName).</param>549        private static void AddParameterTypeProperties(PSObject obj, Type parameterType, IEnumerable<Attribute> attributes)550        {551            PSObject mshObject = new PSObject();552 553            mshObject.TypeNames.Clear();554            mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#type"));555 556            var parameterTypeString = CommandParameterSetInfo.GetParameterTypeString(parameterType, attributes);557            mshObject.Properties.Add(new PSNoteProperty("name", parameterTypeString));558 559            obj.Properties.Add(new PSNoteProperty("type", mshObject));560        }561 562        /// <summary>563        /// Adds the parameterValue properties.564        /// </summary>565        /// <param name="obj">HelpInfo object.</param>566        /// <param name="parameterType">The type of a parameter.</param>567        /// <param name="attributes">The attributes of the parameter (needed to look for PSTypeName).</param>568        private static void AddParameterValueProperties(PSObject obj, Type parameterType, IEnumerable<Attribute> attributes)569        {570            PSObject mshObject;571 572            if (parameterType != null)573            {574                Type type = Nullable.GetUnderlyingType(parameterType) ?? parameterType;575                var parameterTypeString = CommandParameterSetInfo.GetParameterTypeString(parameterType, attributes);576                mshObject = new PSObject(parameterTypeString);577                mshObject.Properties.Add(new PSNoteProperty("variableLength", parameterType.IsArray));578            }579            else580            {581                mshObject = new PSObject("System.Object");582                mshObject.Properties.Add(new PSNoteProperty("variableLength",583                    StringUtil.Format(HelpDisplayStrings.FalseShort)));584            }585 586            mshObject.Properties.Add(new PSNoteProperty("required", "true"));587 588            obj.Properties.Add(new PSNoteProperty("parameterValue", mshObject));589        }590 591        /// <summary>592        /// Adds the InputTypes properties.593        /// </summary>594        /// <param name="obj">HelpInfo object.</param>595        /// <param name="parameters">Command parameters.</param>596        internal static void AddInputTypesProperties(PSObject obj, Dictionary<string, ParameterMetadata> parameters)597        {598            Collection<string> inputs = new Collection<string>();599 600            if (parameters != null)601            {602                foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)603                {604                    Collection<ParameterAttribute> attribs = GetParameterAttribute(parameter.Value.Attributes);605 606                    foreach (ParameterAttribute attrib in attribs)607                    {608                        if (attrib.ValueFromPipeline || attrib.ValueFromPipelineByPropertyName)609                        {610                            if (!inputs.Contains(parameter.Value.ParameterType.FullName))611                            {612                                inputs.Add(parameter.Value.ParameterType.FullName);613                            }614                        }615                    }616                }617            }618 619            if (inputs.Count == 0)620            {621                inputs.Add(StringUtil.Format(HelpDisplayStrings.None));622            }623 624            StringBuilder sb = new StringBuilder();625 626            foreach (string input in inputs)627            {628                sb.AppendLine(input);629            }630 631            PSObject inputTypesObj = new PSObject();632 633            inputTypesObj.TypeNames.Clear();634            inputTypesObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#inputTypes"));635 636            PSObject inputTypeObj = new PSObject();637 638            inputTypeObj.TypeNames.Clear();639            inputTypeObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#inputType"));640 641            PSObject typeObj = new PSObject();642 643            typeObj.TypeNames.Clear();644            typeObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#type"));645 646            typeObj.Properties.Add(new PSNoteProperty("name", sb.ToString()));647            inputTypeObj.Properties.Add(new PSNoteProperty("type", typeObj));648            inputTypesObj.Properties.Add(new PSNoteProperty("inputType", inputTypeObj));649            obj.Properties.Add(new PSNoteProperty("inputTypes", inputTypesObj));650        }651 652        /// <summary>653        /// Adds the OutputTypes properties.654        /// </summary>655        /// <param name="obj">HelpInfo object.</param>656        /// <param name="outputTypes">Output types.</param>657        private static void AddOutputTypesProperties(PSObject obj, ReadOnlyCollection<PSTypeName> outputTypes)658        {659            PSObject returnValuesObj = new PSObject();660 661            returnValuesObj.TypeNames.Clear();662            returnValuesObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#returnValues"));663 664            PSObject returnValueObj = new PSObject();665 666            returnValueObj.TypeNames.Clear();667            returnValueObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#returnValue"));668 669            PSObject typeObj = new PSObject();670 671            typeObj.TypeNames.Clear();672            typeObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#type"));673 674            if (outputTypes.Count == 0)675            {676                typeObj.Properties.Add(new PSNoteProperty("name", "System.Object"));677            }678            else679            {680                StringBuilder sb = new StringBuilder();681 682                foreach (PSTypeName outputType in outputTypes)683                {684                    sb.AppendLine(outputType.Name);685                }686 687                typeObj.Properties.Add(new PSNoteProperty("name", sb.ToString()));688            }689 690            returnValueObj.Properties.Add(new PSNoteProperty("type", typeObj));691            returnValuesObj.Properties.Add(new PSNoteProperty("returnValue", returnValueObj));692            obj.Properties.Add(new PSNoteProperty("returnValues", returnValuesObj));693        }694 695        /// <summary>696        /// Adds the aliases properties.697        /// </summary>698        /// <param name="obj">HelpInfo object.</param>699        /// <param name="name">Command name.</param>700        /// <param name="context">Execution context.</param>701        private static void AddAliasesProperties(PSObject obj, string name, ExecutionContext context)702        {703            StringBuilder sb = new StringBuilder();704 705            bool found = false;706 707            if (context != null)708            {709                foreach (string alias in context.SessionState.Internal.GetAliasesByCommandName(name))710                {711                    found = true;712                    sb.AppendLine(alias);713                }714            }715 716            if (!found)717            {718                sb.AppendLine(StringUtil.Format(HelpDisplayStrings.None));719            }720 721            obj.Properties.Add(new PSNoteProperty("aliases", sb.ToString()));722        }723 724        /// <summary>725        /// Adds the remarks properties.726        /// </summary>727        /// <param name="obj">HelpInfo object.</param>728        /// <param name="cmdletName"></param>729        /// <param name="helpUri"></param>730        private static void AddRemarksProperties(PSObject obj, string cmdletName, string helpUri)731        {732            if (string.IsNullOrEmpty(helpUri))733            {734                obj.Properties.Add(new PSNoteProperty("remarks", StringUtil.Format(HelpDisplayStrings.GetLatestHelpContentWithoutHelpUri, cmdletName)));735            }736            else737            {738                obj.Properties.Add(new PSNoteProperty("remarks", StringUtil.Format(HelpDisplayStrings.GetLatestHelpContent, cmdletName, helpUri)));739            }740        }741 742        /// <summary>743        /// Adds the related links properties.744        /// </summary>745        /// <param name="obj"></param>746        /// <param name="relatedLink"></param>747        internal static void AddRelatedLinksProperties(PSObject obj, string relatedLink)748        {749            if (!string.IsNullOrEmpty(relatedLink))750            {751                PSObject navigationLinkObj = new PSObject();752 753                navigationLinkObj.TypeNames.Clear();754                navigationLinkObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#navigationLinks"));755 756                navigationLinkObj.Properties.Add(new PSNoteProperty("uri", relatedLink));757 758                List<PSObject> navigationLinkValues = new List<PSObject> { navigationLinkObj };759 760                // check if obj already has relatedLinks property761                PSNoteProperty relatedLinksPO = obj.Properties["relatedLinks"] as PSNoteProperty;762                if ((relatedLinksPO != null) && (relatedLinksPO.Value != null))763                {764                    PSObject relatedLinksValue = PSObject.AsPSObject(relatedLinksPO.Value);765                    PSNoteProperty navigationLinkPO = relatedLinksValue.Properties["navigationLink"] as PSNoteProperty;766                    if ((navigationLinkPO != null) && (navigationLinkPO.Value != null))767                    {768                        PSObject navigationLinkValue = navigationLinkPO.Value as PSObject;769                        if (navigationLinkValue != null)770                        {771                            navigationLinkValues.Add(navigationLinkValue);772                        }773                        else774                        {775                            PSObject[] navigationLinkValueArray = navigationLinkPO.Value as PSObject[];776                            if (navigationLinkValueArray != null)777                            {778                                foreach (var psObject in navigationLinkValueArray)779                                {780                                    navigationLinkValues.Add(psObject);781                                }782                            }783                        }784                    }785                }786 787                PSObject relatedLinksObj = new PSObject();788 789                relatedLinksObj.TypeNames.Clear();790                relatedLinksObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#relatedLinks"));791                relatedLinksObj.Properties.Add(new PSNoteProperty("navigationLink", navigationLinkValues.ToArray()));792 793                obj.Properties.Add(new PSNoteProperty("relatedLinks", relatedLinksObj));794            }795        }796 797        /// <summary>798        /// Gets the parameter attribute from parameter metadata.799        /// </summary>800        /// <param name="attributes">Parameter attributes.</param>801        /// <returns>Collection of parameter attributes.</returns>802        private static Collection<ParameterAttribute> GetParameterAttribute(Collection<Attribute> attributes)803        {804            Collection<ParameterAttribute> paramAttributes = new Collection<ParameterAttribute>();805 806            foreach (Attribute attribute in attributes)807            {808                ParameterAttribute paramAttribute = (object)attribute as ParameterAttribute;809 810                if (paramAttribute != null)811                {812                    paramAttributes.Add(paramAttribute);813                }814            }815 816            return paramAttributes;817        }818 819        /// <summary>820        /// Gets the validate set attribute from parameter metadata.821        /// </summary>822        /// <param name="attributes">Parameter attributes.</param>823        /// <returns>Collection of parameter attributes.</returns>824        private static Collection<ValidateSetAttribute> GetValidateSetAttribute(Collection<Attribute> attributes)825        {826            Collection<ValidateSetAttribute> validateSetAttributes = new Collection<ValidateSetAttribute>();827 828            foreach (Attribute attribute in attributes)829            {830                ValidateSetAttribute validateSetAttribute = (object)attribute as ValidateSetAttribute;831 832                if (validateSetAttribute != null)833                {834                    validateSetAttributes.Add(validateSetAttribute);835                }836            }837 838            return validateSetAttributes;839        }840 841        /// <summary>842        /// Gets the pipeline input type.843        /// </summary>844        /// <param name="paramAttrib">Parameter attribute.</param>845        /// <returns>Pipeline input type.</returns>846        private static string GetPipelineInputString(ParameterAttribute paramAttrib)847        {848            Debug.Assert(paramAttrib != null);849 850            ArrayList values = new ArrayList();851 852            if (paramAttrib.ValueFromPipeline)853            {854                values.Add(StringUtil.Format(HelpDisplayStrings.PipelineByValue));855            }856 857            if (paramAttrib.ValueFromPipelineByPropertyName)858            {859                values.Add(StringUtil.Format(HelpDisplayStrings.PipelineByPropertyName));860            }861 862            if (paramAttrib.ValueFromRemainingArguments)863            {864                values.Add(StringUtil.Format(HelpDisplayStrings.PipelineFromRemainingArguments));865            }866 867            if (values.Count == 0)868            {869                return StringUtil.Format(HelpDisplayStrings.FalseShort);870            }871 872            StringBuilder sb = new StringBuilder();873 874            sb.Append(StringUtil.Format(HelpDisplayStrings.TrueShort));875            sb.Append(" (");876 877            for (int i = 0; i < values.Count; i++)878            {879                sb.Append((string)values[i]);880 881                if (i != (values.Count - 1))882                {883                    sb.Append(", ");884                }885            }886 887            sb.Append(')');888 889            return sb.ToString();890        }891 892        /// <summary>893        /// Checks if a set of parameters contains any of the common parameters.894        /// </summary>895        /// <param name="parameters">Parameters to check.</param>896        /// <returns>True if it contains common parameters, false otherwise.</returns>897        internal static bool HasCommonParameters(Dictionary<string, ParameterMetadata> parameters)898        {899            Collection<string> commonParams = new Collection<string>();900 901            foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)902            {903                if (Cmdlet.CommonParameters.Contains(parameter.Value.Name))904                {905                    commonParams.Add(parameter.Value.Name);906                }907            }908 909            return (commonParams.Count == Cmdlet.CommonParameters.Count);910        }911 912        /// <summary>913        /// Checks if the module contains HelpInfoUri.914        /// </summary>915        /// <param name="module"></param>916        /// <param name="moduleName"></param>917        /// <returns></returns>918        private static bool HasHelpInfoUri(PSModuleInfo module, string moduleName)919        {920            // The core module is really a SnapIn, so module will be null921            if (!string.IsNullOrEmpty(moduleName) && moduleName.Equals(InitialSessionState.CoreModule, StringComparison.OrdinalIgnoreCase))922            {923                return true;924            }925 926            if (module == null)927            {928                return false;929            }930 931            return !string.IsNullOrEmpty(module.HelpInfoUri);932        }933    }934}935