Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
MamlUtil.cs331 linesDownload Raw Back to help
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Management.Automation.Help;6 7namespace System.Management.Automation8{9    /// <summary>10    /// The MamlUtil class.11    /// </summary>12    internal static class MamlUtil13    {14        /// <summary>15        /// Takes Name value from maml2 and overrides it in maml1.16        /// </summary>17        /// <param name="maml1"></param>18        /// <param name="maml2"></param>19        internal static void OverrideName(PSObject maml1, PSObject maml2)20        {21            PrependPropertyValue(maml1, maml2, new string[] { "Name" }, true);22            PrependPropertyValue(maml1, maml2, new string[] { "Details", "Name" }, true);23        }24 25        /// <summary>26        /// Takes Name value from maml2 and overrides it in maml1.27        /// </summary>28        /// <param name="maml1"></param>29        /// <param name="maml2"></param>30        internal static void OverridePSTypeNames(PSObject maml1, PSObject maml2)31        {32            foreach (var typename in maml2.TypeNames)33            {34                if (typename.StartsWith(DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp, StringComparison.OrdinalIgnoreCase))35                {36                    // Win8: 638494 if the original help is auto-generated, let the Provider help decide the format.37                    return;38                }39            }40 41            maml1.TypeNames.Clear();42            // User request at the top..43            foreach (string typeName in maml2.TypeNames)44            {45                maml1.TypeNames.Add(typeName);46            }47        }48 49        /// <summary>50        /// Adds common properties like PSSnapIn,ModuleName from maml2 to maml1.51        /// </summary>52        /// <param name="maml1"></param>53        /// <param name="maml2"></param>54        internal static void AddCommonProperties(PSObject maml1, PSObject maml2)55        {56            if (maml1.Properties["PSSnapIn"] == null)57            {58                PSPropertyInfo snapInProperty = maml2.Properties["PSSnapIn"];59                if (snapInProperty != null)60                {61                    maml1.Properties.Add(new PSNoteProperty("PSSnapIn", snapInProperty.Value));62                }63            }64 65            if (maml1.Properties["ModuleName"] == null)66            {67                PSPropertyInfo moduleNameProperty = maml2.Properties["ModuleName"];68                if (moduleNameProperty != null)69                {70                    maml1.Properties.Add(new PSNoteProperty("ModuleName", moduleNameProperty.Value));71                }72            }73        }74 75        /// <summary>76        /// Prepend - Modify Syntax element in maml1 using the Syntax element from maml2.77        /// </summary>78        internal static void PrependSyntax(PSObject maml1, PSObject maml2)79        {80            PrependPropertyValue(maml1, maml2, new string[] { "Syntax", "SyntaxItem" }, false);81        }82 83        /// <summary>84        /// Prepend - Modify DetailedDescription element in maml1 using the DetailedDescription element from maml2.85        /// </summary>86        internal static void PrependDetailedDescription(PSObject maml1, PSObject maml2)87        {88            PrependPropertyValue(maml1, maml2, new string[] { "Description" }, false);89        }90 91        /// <summary>92        /// Override - Modify Parameters element in maml1 using the Parameters element from maml2.93        /// This will copy parameters from maml2 that are not present in maml1.94        /// </summary>95        internal static void OverrideParameters(PSObject maml1, PSObject maml2)96        {97            string[] parametersPath = new string[] { "Parameters", "Parameter" };98            // Final collection of PSObjects.99            List<object> maml2items = new List<object>();100 101            // Add maml2 first since we are prepending.102 103            // For maml2: Add as collection or single item. No-op if104            PSPropertyInfo propertyInfo2 = GetPropertyInfo(maml2, parametersPath);105            var array = propertyInfo2.Value as Array;106            if (array != null)107            {108                maml2items.AddRange(array as IEnumerable<object>);109            }110            else111            {112                maml2items.Add(PSObject.AsPSObject(propertyInfo2.Value));113            }114 115            // Extend maml1 to make sure the property-path exists - since we'll be modifying it soon.116            EnsurePropertyInfoPathExists(maml1, parametersPath);117            // For maml1: Add as collection or single item. Do nothing if null or some other type.118            PSPropertyInfo propertyInfo1 = GetPropertyInfo(maml1, parametersPath);119            List<object> maml1items = new List<object>();120            array = propertyInfo1.Value as Array;121            if (array != null)122            {123                maml1items.AddRange(array as IEnumerable<object>);124            }125            else126            {127                maml1items.Add(PSObject.AsPSObject(propertyInfo1.Value));128            }129 130            // copy parameters from maml2 that are not present in maml1131            for (int index = 0; index < maml2items.Count; index++)132            {133                PSObject m2paramObj = PSObject.AsPSObject(maml2items[index]);134                string param2Name = string.Empty;135                PSPropertyInfo m2propertyInfo = m2paramObj.Properties["Name"];136 137                if (m2propertyInfo != null)138                {139                    if (!LanguagePrimitives.TryConvertTo<string>(m2propertyInfo.Value, out param2Name))140                    {141                        continue;142                    }143                }144 145                bool isParamFoundInMaml1 = false;146                foreach (PSObject m1ParamObj in maml1items)147                {148                    string param1Name = string.Empty;149                    PSPropertyInfo m1PropertyInfo = m1ParamObj.Properties["Name"];150 151                    if (m1PropertyInfo != null)152                    {153                        if (!LanguagePrimitives.TryConvertTo<string>(m1PropertyInfo.Value, out param1Name))154                        {155                            continue;156                        }157                    }158 159                    if (param1Name.Equals(param2Name, StringComparison.OrdinalIgnoreCase))160                    {161                        isParamFoundInMaml1 = true;162                    }163                }164 165                if (!isParamFoundInMaml1)166                {167                    maml1items.Add(maml2items[index]);168                }169            }170 171            // Now replace in maml1. If items.Count == 0 do nothing since Value is already null.172            if (maml1items.Count == 1)173            {174                propertyInfo1.Value = maml1items[0];175            }176            else if (maml1items.Count >= 2)177            {178                propertyInfo1.Value = maml1items.ToArray();179            }180        }181 182        /// <summary>183        /// Prepend - Modify Notes element in maml1 using the Notes element from maml2.184        /// </summary>185        internal static void PrependNotes(PSObject maml1, PSObject maml2)186        {187            PrependPropertyValue(maml1, maml2, new string[] { "AlertSet", "Alert" }, false);188        }189 190        /// <summary>191        /// Get property info.192        /// </summary>193        internal static PSPropertyInfo GetPropertyInfo(PSObject psObject, string[] path)194        {195            if (path.Length == 0)196            {197                return null;198            }199 200            for (int i = 0; i < path.Length; ++i)201            {202                string propertyName = path[i];203                PSPropertyInfo propertyInfo = psObject.Properties[propertyName];204                if (i == path.Length - 1)205                {206                    return propertyInfo;207                }208 209                if (propertyInfo == null || propertyInfo.Value is not PSObject)210                {211                    return null;212                }213 214                psObject = (PSObject)propertyInfo.Value;215            }216 217            // We will never reach this line but the compiler needs some reassurance.218            return null;219        }220 221        /// <summary>222        /// Prepend property value.223        /// </summary>224        /// <param name="maml1">225        /// </param>226        /// <param name="maml2">227        /// </param>228        /// <param name="path">229        /// </param>230        /// <param name="shouldOverride">231        /// Should Override the maml1 value from maml2 instead of prepend.232        /// </param>233        internal static void PrependPropertyValue(PSObject maml1, PSObject maml2, string[] path, bool shouldOverride)234        {235            // Final collection of PSObjects.236            List<object> items = new List<object>();237 238            // Add maml2 first since we are prepending.239 240            // For maml2: Add as collection or single item. No-op if241            PSPropertyInfo propertyInfo2 = GetPropertyInfo(maml2, path);242 243            if (propertyInfo2 != null)244            {245                var array = propertyInfo2.Value as Array;246                if (array != null)247                {248                    items.AddRange(propertyInfo2.Value as IEnumerable<object>);249                }250                else251                {252                    items.Add(propertyInfo2.Value);253                }254            }255 256            // Extend maml1 to make sure the property-path exists - since we'll be modifying it soon.257            EnsurePropertyInfoPathExists(maml1, path);258            // For maml1: Add as collection or single item. Do nothing if null or some other type.259            PSPropertyInfo propertyInfo1 = GetPropertyInfo(maml1, path);260 261            if (propertyInfo1 != null)262            {263                if (!shouldOverride)264                {265                    var array = propertyInfo1.Value as Array;266                    if (array != null)267                    {268                        items.AddRange(propertyInfo1.Value as IEnumerable<object>);269                    }270                    else271                    {272                        items.Add(propertyInfo1.Value);273                    }274                }275 276                // Now replace in maml1. If items.Count == 0 do nothing since Value is already null.277                if (items.Count == 1)278                {279                    propertyInfo1.Value = items[0];280                }281                else if (items.Count >= 2)282                {283                    propertyInfo1.Value = items.ToArray();284                }285            }286        }287 288        /// <summary>289        /// Ensure property info path exists.290        /// </summary>291        internal static void EnsurePropertyInfoPathExists(PSObject psObject, string[] path)292        {293            if (path.Length == 0)294            {295                return;296            }297 298            // Walk the path and extend it if necessary.299            for (int i = 0; i < path.Length; ++i)300            {301                string propertyName = path[i];302                PSPropertyInfo propertyInfo = psObject.Properties[propertyName];303 304                // Add a property info here if none was found.305                if (propertyInfo == null)306                {307                    // Add null on the last one, since we don't need to extend path further.308                    object propertyValue = (i < path.Length - 1) ? new PSObject() : null;309                    propertyInfo = new PSNoteProperty(propertyName, propertyValue);310                    psObject.Properties.Add(propertyInfo);311                }312 313                // If we are on the last path element, we are done. Let's not mess with modifying Value.314                if (i == path.Length - 1)315                {316                    return;317                }318 319                // If we are not on the last path element, let's make sure we can extend the path.320                if (propertyInfo.Value == null || propertyInfo.Value is not PSObject)321                {322                    propertyInfo.Value = new PSObject();323                }324 325                // Now move one step further along the path.326                psObject = (PSObject)propertyInfo.Value;327            }328        }329    }330}331