Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
ScriptWriter.cs2284 linesDownload Raw Back to cmdletization
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Collections.ObjectModel;8using System.Globalization;9using System.IO;10using System.Linq;11using System.Text;12using System.Text.RegularExpressions;13using System.Xml;14using System.Xml.Schema;15 16using Microsoft.PowerShell.Cmdletization.Xml;17using System.Management.Automation;18using System.Management.Automation.Language;19using Microsoft.PowerShell.Commands;20using Dbg = System.Management.Automation.Diagnostics;21 22namespace Microsoft.PowerShell.Cmdletization23{24    internal sealed class ScriptWriter25    {26        #region Static code reused for reading cmdletization xml27 28        private static readonly XmlReaderSettings s_xmlReaderSettings;29 30        static ScriptWriter()31        {32            //33            // XmlReaderSettings34            //35            ScriptWriter.s_xmlReaderSettings = new XmlReaderSettings();36            // general settings37            ScriptWriter.s_xmlReaderSettings.CheckCharacters = true;38            ScriptWriter.s_xmlReaderSettings.CloseInput = false;39            ScriptWriter.s_xmlReaderSettings.ConformanceLevel = ConformanceLevel.Document;40            ScriptWriter.s_xmlReaderSettings.IgnoreComments = true;41            ScriptWriter.s_xmlReaderSettings.IgnoreProcessingInstructions = true;42            ScriptWriter.s_xmlReaderSettings.IgnoreWhitespace = false;43            ScriptWriter.s_xmlReaderSettings.MaxCharactersFromEntities = 16384; // generous guess for the upper bound44            ScriptWriter.s_xmlReaderSettings.MaxCharactersInDocument = 128 * 1024 * 1024; // generous guess for the upper bound45 46#if CORECLR // The XML Schema file 'cmdlets-over-objects.xsd' is missing in Github, and it's likely the resource string47            // 'CmdletizationCoreResources.Xml_cmdletsOverObjectsXsd' needs to be reworked to work in .NET Core.48            ScriptWriter.s_xmlReaderSettings.DtdProcessing = DtdProcessing.Ignore;49#else50            ScriptWriter.s_xmlReaderSettings.DtdProcessing = DtdProcessing.Parse; // Allowing DTD parsing with limits of MaxCharactersFromEntities/MaxCharactersInDocument51            ScriptWriter.s_xmlReaderSettings.XmlResolver = null; // do not fetch external documents52            // xsd schema related settings53            ScriptWriter.s_xmlReaderSettings.ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints |54                                                XmlSchemaValidationFlags.ReportValidationWarnings;55            ScriptWriter.s_xmlReaderSettings.ValidationType = ValidationType.Schema;56            string cmdletizationXsd = CmdletizationCoreResources.Xml_cmdletsOverObjectsXsd;57            XmlReader cmdletizationSchemaReader = XmlReader.Create(new StringReader(cmdletizationXsd), ScriptWriter.s_xmlReaderSettings);58            ScriptWriter.s_xmlReaderSettings.Schemas = new XmlSchemaSet();59            ScriptWriter.s_xmlReaderSettings.Schemas.Add(null, cmdletizationSchemaReader);60            ScriptWriter.s_xmlReaderSettings.Schemas.XmlResolver = null; // do not fetch external documents61#endif62        }63 64        #endregion Static code reused for reading cmdletization xml65 66        #region Constructors / setup code67 68        [Flags]69        internal enum GenerationOptions70        {71            TypesPs1Xml = 1,72            FormatPs1Xml = 2,73            HelpXml = 4,74        }75 76        private readonly PowerShellMetadata _cmdletizationMetadata;77        private readonly string _moduleName;78        private readonly Type _objectModelWrapper;79        private readonly Type _objectInstanceType;80        private readonly InvocationInfo _invocationInfo;81        private readonly GenerationOptions _generationOptions;82 83        internal ScriptWriter(84            TextReader cmdletizationXmlReader,85            string moduleName,86            string defaultObjectModelWrapper,87            InvocationInfo invocationInfo,88            GenerationOptions generationOptions)89        {90            Dbg.Assert(cmdletizationXmlReader != null, "Caller should verify that cmdletizationXmlReader != null");91            Dbg.Assert(!string.IsNullOrEmpty(moduleName), "Caller should verify that moduleName != null");92            Dbg.Assert(invocationInfo != null, "Caller should verify that invocationInfo != null");93            Dbg.Assert(!string.IsNullOrEmpty(defaultObjectModelWrapper), "Caller should verify that defaultObjectModelWrapper != null");94 95            XmlReader xmlReader = XmlReader.Create(cmdletizationXmlReader, ScriptWriter.s_xmlReaderSettings);96            try97            {98                var xmlSerializer = new PowerShellMetadataSerializer();99                _cmdletizationMetadata = (PowerShellMetadata)xmlSerializer.Deserialize(xmlReader);100            }101            catch (InvalidOperationException e)102            {103                if (e.InnerException is XmlSchemaException schemaException)104                {105                    throw new XmlException(schemaException.Message, schemaException, schemaException.LineNumber, schemaException.LinePosition);106                }107 108                if (e.InnerException is XmlException xmlException)109                {110                    throw xmlException;111                }112 113                if (e.InnerException != null)114                {115                    string message = string.Format(116                        CultureInfo.CurrentCulture,117                        CmdletizationCoreResources.ScriptWriter_ConcatenationOfDeserializationExceptions,118                        e.Message,119                        e.InnerException.Message);120 121                    throw new InvalidOperationException(message, e.InnerException);122                }123 124                throw;125            }126 127            string objectModelWrapperName = _cmdletizationMetadata.Class.CmdletAdapter ?? defaultObjectModelWrapper;128            _objectModelWrapper = (Type)LanguagePrimitives.ConvertTo(objectModelWrapperName, typeof(Type), CultureInfo.InvariantCulture);129            if (_objectModelWrapper.IsGenericType)130            {131                string message = string.Format(132                    CultureInfo.CurrentCulture,133                    CmdletizationCoreResources.ScriptWriter_ObjectModelWrapperIsStillGeneric,134                    objectModelWrapperName);135                throw new XmlException(message);136            }137 138            Type baseType = _objectModelWrapper;139            while ((!baseType.IsGenericType) || baseType.GetGenericTypeDefinition() != typeof(CmdletAdapter<>))140            {141                baseType = baseType.BaseType;142                if (baseType == typeof(object))143                {144                    string message = string.Format(145                        CultureInfo.CurrentCulture,146                        CmdletizationCoreResources.ScriptWriter_ObjectModelWrapperNotDerivedFromObjectModelWrapper,147                        objectModelWrapperName,148                        typeof(CmdletAdapter<>).FullName);149                    throw new XmlException(message);150                }151            }152 153            _objectInstanceType = baseType.GetGenericArguments()[0];154 155            _moduleName = moduleName;156            _invocationInfo = invocationInfo;157            _generationOptions = generationOptions;158        }159 160        #endregion Constructors / setup code161 162        #region psm1163 164        private const string HeaderTemplate = @"165#requires -version 3.0166 167try {{ Microsoft.PowerShell.Core\Set-StrictMode -Off }} catch {{ }}168 169$script:MyModule = $MyInvocation.MyCommand.ScriptBlock.Module170 171$script:ClassName = '{0}'172$script:ClassVersion = '{1}'173$script:ModuleVersion = '{2}'174$script:ObjectModelWrapper = [{3}]175 176$script:PrivateData = [System.Collections.Generic.Dictionary[string,string]]::new()177 178Microsoft.PowerShell.Core\Export-ModuleMember -Function @()179        ";180 181        private void WriteModulePreamble(TextWriter output)182        {183            output.WriteLine(184                ScriptWriter.HeaderTemplate,185                CodeGeneration.EscapeSingleQuotedStringContent(_cmdletizationMetadata.Class.ClassName),186                CodeGeneration.EscapeSingleQuotedStringContent(_cmdletizationMetadata.Class.ClassVersion ?? string.Empty),187                CodeGeneration.EscapeSingleQuotedStringContent(new Version(_cmdletizationMetadata.Class.Version).ToString()),188                CodeGeneration.EscapeSingleQuotedStringContent(_objectModelWrapper.FullName));189 190            if (_cmdletizationMetadata.Class.CmdletAdapterPrivateData != null)191            {192                foreach (ClassMetadataData data in _cmdletizationMetadata.Class.CmdletAdapterPrivateData)193                {194                    output.WriteLine(195                        "$script:PrivateData.Add('{0}', '{1}')",196                        CodeGeneration.EscapeSingleQuotedStringContent(data.Name),197                        CodeGeneration.EscapeSingleQuotedStringContent(data.Value));198                }199            }200        }201 202        private void WriteBindCommonParametersFunction(TextWriter output)203        {204            output.WriteLine(@"205function __cmdletization_BindCommonParameters206{207    param(208        $__cmdletization_objectModelWrapper,209        $myPSBoundParameters210    )211                ");212 213            foreach (ParameterMetadata commonParameter in this.GetCommonParameters().Values)214            {215                output.WriteLine(@"216        if ($myPSBoundParameters.ContainsKey('{0}')) {{217            $__cmdletization_objectModelWrapper.PSObject.Properties['{0}'].Value = $myPSBoundParameters['{0}']218        }}219                    ",220                     CodeGeneration.EscapeSingleQuotedStringContent(commonParameter.Name));221            }222 223            output.WriteLine(@"224}225                ");226        }227 228        private string GetCmdletName(CommonCmdletMetadata cmdletMetadata)229        {230            string noun = cmdletMetadata.Noun ?? _cmdletizationMetadata.Class.DefaultNoun;231            string verb = cmdletMetadata.Verb;232            return verb + "-" + noun;233        }234 235        private static string GetCmdletAttributes(CommonCmdletMetadata cmdletMetadata)236        {237            // Generate the script for the Alias and Obsolete Attribute if any is declared in CDXML238            StringBuilder attributes = new(150);239            if (cmdletMetadata.Aliases != null)240            {241                attributes.Append("[Alias('" + string.Join("','", cmdletMetadata.Aliases.Select(static alias => CodeGeneration.EscapeSingleQuotedStringContent(alias))) + "')]");242            }243 244            if (cmdletMetadata.Obsolete != null)245            {246                string obsoleteMsg = (cmdletMetadata.Obsolete.Message != null)247                    ? ("'" + CodeGeneration.EscapeSingleQuotedStringContent(cmdletMetadata.Obsolete.Message) + "'")248                    : string.Empty;249                string newline = (attributes.Length > 0) ? Environment.NewLine : string.Empty;250                attributes.Append(CultureInfo.InvariantCulture, $"{newline}[Obsolete({obsoleteMsg})]");251            }252 253            return attributes.ToString();254        }255 256        private Dictionary<string, ParameterMetadata> GetCommonParameters()257        {258            Dictionary<string, ParameterMetadata> commonParameters = new(StringComparer.OrdinalIgnoreCase);259 260            InternalParameterMetadata internalParameterMetadata = new(_objectModelWrapper, false);261            foreach (CompiledCommandParameter compiledCommandParameter in internalParameterMetadata.BindableParameters.Values)262            {263                ParameterMetadata parameterMetadata = new(compiledCommandParameter);264                foreach (ParameterSetMetadata psetMetadata in parameterMetadata.ParameterSets.Values)265                {266                    if (psetMetadata.ValueFromPipeline)267                    {268                        string message = string.Format(269                            CultureInfo.InvariantCulture,270                            CmdletizationCoreResources.ScriptWriter_ObjectModelWrapperUsesIgnoredParameterMetadata,271                            _objectModelWrapper.FullName,272                            parameterMetadata.Name,273                            "ValueFromPipeline");274                        throw new XmlException(message);275                    }276 277                    if (psetMetadata.ValueFromPipelineByPropertyName)278                    {279                        string message = string.Format(280                            CultureInfo.InvariantCulture,281                            CmdletizationCoreResources.ScriptWriter_ObjectModelWrapperUsesIgnoredParameterMetadata,282                            _objectModelWrapper.FullName,283                            parameterMetadata.Name,284                            "ValueFromPipelineByPropertyName");285                        throw new XmlException(message);286                    }287 288                    if (psetMetadata.ValueFromRemainingArguments)289                    {290                        string message = string.Format(291                            CultureInfo.InvariantCulture,292                            CmdletizationCoreResources.ScriptWriter_ObjectModelWrapperUsesIgnoredParameterMetadata,293                            _objectModelWrapper.FullName,294                            parameterMetadata.Name,295                            "ValueFromRemainingArguments");296                        throw new XmlException(message);297                    }298 299                    psetMetadata.ValueFromPipeline = false;300                    psetMetadata.ValueFromPipelineByPropertyName = false;301                    psetMetadata.ValueFromRemainingArguments = false;302                }303 304                commonParameters.Add(parameterMetadata.Name, parameterMetadata);305            }306 307            List<string> commonParameterSets = GetCommonParameterSets(commonParameters);308            if (commonParameterSets.Count > 1)309            {310                string message = string.Format(311                    CultureInfo.InvariantCulture,312                    CmdletizationCoreResources.ScriptWriter_ObjectModelWrapperDefinesMultipleParameterSets,313                    _objectModelWrapper.FullName);314                throw new XmlException(message);315            }316 317            foreach (ParameterMetadata parameter in commonParameters.Values)318            {319                if ((parameter.ParameterSets.Count == 1) && (parameter.ParameterSets.ContainsKey(ParameterAttribute.AllParameterSets)))320                {321                    ParameterSetMetadata oldParameterSetMetadata = parameter.ParameterSets[ParameterAttribute.AllParameterSets];322 323                    parameter.ParameterSets.Clear();324                    foreach (string parameterSetName in commonParameterSets)325                    {326                        parameter.ParameterSets.Add(parameterSetName, oldParameterSetMetadata);327                    }328                }329            }330 331            return commonParameters;332        }333 334        private static List<string> GetCommonParameterSets(Dictionary<string, ParameterMetadata> commonParameters)335        {336            Dictionary<string, object> parameterSetNames = new(StringComparer.OrdinalIgnoreCase);337            foreach (ParameterMetadata parameter in commonParameters.Values)338            {339                foreach (string parameterSetName in parameter.ParameterSets.Keys)340                {341                    if (!parameterSetName.Equals(ParameterAttribute.AllParameterSets))342                    {343                        parameterSetNames[parameterSetName] = null;344                    }345                }346            }347 348            if (parameterSetNames.Count == 0)349            {350                parameterSetNames.Add(ParameterAttribute.AllParameterSets, null);351            }352 353            List<string> result = new(parameterSetNames.Keys);354            result.Sort(StringComparer.Ordinal); // to have a deterministic order of parameter sets (also means that Ordinal instead of OrdinalIgnoreCase is ok)355            return result;356        }357 358        private string GetMethodParameterSet(StaticMethodMetadata staticMethod)359        {360            Dbg.Assert(staticMethod != null, "Caller should verify that staticMethod != null");361            return staticMethod.CmdletParameterSet ?? GetMethodParameterSet((CommonMethodMetadata)staticMethod);362        }363 364        private List<string> GetMethodParameterSets(StaticCmdletMetadata staticCmdlet)365        {366            Dictionary<string, object> parameterSetNames = new(StringComparer.OrdinalIgnoreCase);367 368            foreach (StaticMethodMetadata method in staticCmdlet.Method)369            {370                string parameterSetName = GetMethodParameterSet(method);371                if (parameterSetNames.ContainsKey(parameterSetName))372                {373                    string message = string.Format(374                        CultureInfo.InvariantCulture,375                        CmdletizationCoreResources.ScriptWriter_DuplicateParameterSetInStaticCmdlet,376                        this.GetCmdletName(staticCmdlet.CmdletMetadata),377                        parameterSetName);378                    throw new XmlException(message);379                }380 381                parameterSetNames.Add(parameterSetName, null);382            }383 384            return new List<string>(parameterSetNames.Keys);385        }386 387        private readonly Dictionary<CommonMethodMetadata, int> _staticMethodMetadataToUniqueId = new();388 389        private string GetMethodParameterSet(CommonMethodMetadata methodMetadata)390        {391            Dbg.Assert(methodMetadata != null, "Caller should verify that instanceMethod != null");392 393            int uniqueId;394            if (!_staticMethodMetadataToUniqueId.TryGetValue(methodMetadata, out uniqueId))395            {396                uniqueId = _staticMethodMetadataToUniqueId.Count;397                _staticMethodMetadataToUniqueId.Add(methodMetadata, uniqueId);398            }399 400            return methodMetadata.MethodName + uniqueId;401        }402 403        private List<string> GetMethodParameterSets(InstanceCmdletMetadata instanceCmdlet)404        {405            Dictionary<string, object> parameterSetNames = new(StringComparer.OrdinalIgnoreCase);406 407            InstanceMethodMetadata method = instanceCmdlet.Method;408            string parameterSetName = GetMethodParameterSet(method);409            parameterSetNames.Add(parameterSetName, null);410 411            return new List<string>(parameterSetNames.Keys);412        }413 414        private GetCmdletParameters GetGetCmdletParameters(InstanceCmdletMetadata instanceCmdlet)415        {416            if (instanceCmdlet == null)417            {418                if ((_cmdletizationMetadata.Class.InstanceCmdlets.GetCmdlet != null) &&419                    (_cmdletizationMetadata.Class.InstanceCmdlets.GetCmdlet.GetCmdletParameters != null))420                {421                    return _cmdletizationMetadata.Class.InstanceCmdlets.GetCmdlet.GetCmdletParameters;422                }423            }424            else425            {426                if (instanceCmdlet.GetCmdletParameters != null)427                {428                    return instanceCmdlet.GetCmdletParameters;429                }430            }431 432            return _cmdletizationMetadata.Class.InstanceCmdlets.GetCmdletParameters;433        }434 435        private List<string> GetQueryParameterSets(InstanceCmdletMetadata instanceCmdlet)436        {437            Dictionary<string, object> parameterSetNames = new(StringComparer.OrdinalIgnoreCase);438 439            var parameters = new List<CmdletParameterMetadataForGetCmdletParameter>();440            bool anyQueryParameters = false;441 442            GetCmdletParameters getCmdletParameters = GetGetCmdletParameters(instanceCmdlet);443            if (getCmdletParameters.QueryableProperties != null)444            {445                foreach (PropertyMetadata property in getCmdletParameters.QueryableProperties)446                {447                    if (property.Items != null)448                    {449                        foreach (PropertyQuery query in property.Items)450                        {451                            anyQueryParameters = true;452                            if (query.CmdletParameterMetadata != null)453                            {454                                parameters.Add(query.CmdletParameterMetadata);455                            }456                        }457                    }458                }459            }460 461            if (getCmdletParameters.QueryableAssociations != null)462            {463                foreach (Association association in getCmdletParameters.QueryableAssociations)464                {465                    if (association.AssociatedInstance != null)466                    {467                        anyQueryParameters = true;468                        if (association.AssociatedInstance.CmdletParameterMetadata != null)469                        {470                            parameters.Add(association.AssociatedInstance.CmdletParameterMetadata);471                        }472                    }473                }474            }475 476            if (getCmdletParameters.QueryOptions != null)477            {478                foreach (QueryOption option in getCmdletParameters.QueryOptions)479                {480                    anyQueryParameters = true;481                    if (option.CmdletParameterMetadata != null)482                    {483                        parameters.Add(option.CmdletParameterMetadata);484                    }485                }486            }487 488            foreach (CmdletParameterMetadataForGetCmdletParameter parameter in parameters)489            {490                if (parameter.CmdletParameterSets != null)491                {492                    foreach (string parameterSetName in parameter.CmdletParameterSets)493                    {494                        parameterSetNames[parameterSetName] = null;495                    }496                }497            }498 499            if (anyQueryParameters && (parameterSetNames.Count == 0))500            {501                parameterSetNames.Add(ScriptWriter.SingleQueryParameterSetName, null);502                getCmdletParameters.DefaultCmdletParameterSet = ScriptWriter.SingleQueryParameterSetName;503            }504 505            if (instanceCmdlet != null)506            {507                parameterSetNames.Add(ScriptWriter.InputObjectQueryParameterSetName, null);508            }509 510            return new List<string>(parameterSetNames.Keys);511        }512 513        private Type GetDotNetType(TypeMetadata typeMetadata)514        {515            Dbg.Assert(typeMetadata != null, "Caller should verify typeMetadata != null");516 517            string psTypeText;518            EnumMetadataEnum matchingEnum = null;519 520            if (_cmdletizationMetadata.Enums is not null)521            {522                string psType = typeMetadata.PSType;523                foreach (EnumMetadataEnum e in _cmdletizationMetadata.Enums)524                {525                    int index = psType.IndexOf(e.EnumName, StringComparison.Ordinal);526                    if (index == -1)527                    {528                        // Fast return if 'PSType' doesn't contain the enum name at all.529                        continue;530                    }531 532                    bool matchFound = false;533                    if (index == 0)534                    {535                        // Handle 2 common cases here (cover over 99% of how enum name is used in 'PSType'):536                        //  - 'PSType' is exactly the enum name.537                        //  - 'PSType' is the array format of the enum.538                        ReadOnlySpan<char> remains = psType.AsSpan(e.EnumName.Length);539                        matchFound = remains.Length is 0 || remains.Equals("[]", StringComparison.Ordinal);540                    }541 542                    if (!matchFound)543                    {544                        // Now we have to fall back to the expensive regular expression matching, because 'PSType'545                        // could be a composite type like 'Nullable<enum_name>' or 'Dictionary<enum_name, object>',546                        // but we don't want the case where the enum name is part of another type's name.547                        matchFound = Regex.IsMatch(psType, $@"\b{Regex.Escape(e.EnumName)}\b");548                    }549 550                    if (matchFound)551                    {552                        if (matchingEnum is null)553                        {554                            matchingEnum = e;555                            continue;556                        }557 558                        // If more than one matching enum names were found, we treat it as no match found.559                        matchingEnum = null;560                        break;561                    }562                }563            }564 565            if (matchingEnum != null)566            {567                psTypeText = typeMetadata.PSType.Replace(matchingEnum.EnumName, EnumWriter.GetEnumFullName(matchingEnum));568            }569            else570            {571                psTypeText = typeMetadata.PSType;572            }573 574            Type dotNetType = (Type)LanguagePrimitives.ConvertTo(psTypeText, typeof(Type), CultureInfo.InvariantCulture);575            return dotNetType;576        }577 578        private ParameterMetadata GetParameter(579            string parameterSetName,580            string objectModelParameterName,581            TypeMetadata parameterTypeMetadata,582            CmdletParameterMetadata parameterCmdletization,583            bool isValueFromPipeline,584            bool isValueFromPipelineByPropertyName)585        {586            string parameterName;587            if ((parameterCmdletization != null) && (!string.IsNullOrEmpty(parameterCmdletization.PSName)))588            {589                parameterName = parameterCmdletization.PSName;590            }591            else592            {593                parameterName = objectModelParameterName;594            }595 596            ParameterMetadata parameterMetadata = new(parameterName);597            parameterMetadata.ParameterType = GetDotNetType(parameterTypeMetadata);598            if (typeof(PSCredential).Equals(parameterMetadata.ParameterType))599            {600                parameterMetadata.Attributes.Add(new CredentialAttribute());601            }602 603            if (parameterTypeMetadata.ETSType != null)604            {605                parameterMetadata.Attributes.Add(new PSTypeNameAttribute(parameterTypeMetadata.ETSType));606            }607 608            if (parameterCmdletization != null)609            {610                if (parameterCmdletization.Aliases != null)611                {612                    foreach (string alias in parameterCmdletization.Aliases)613                    {614                        if (!string.IsNullOrEmpty(alias))615                        {616                            parameterMetadata.Aliases.Add(alias);617                        }618                    }619                }620 621                if (parameterCmdletization.AllowEmptyCollection != null)622                {623                    parameterMetadata.Attributes.Add(new AllowEmptyCollectionAttribute());624                }625 626                if (parameterCmdletization.AllowEmptyString != null)627                {628                    parameterMetadata.Attributes.Add(new AllowEmptyStringAttribute());629                }630 631                if (parameterCmdletization.AllowNull != null)632                {633                    parameterMetadata.Attributes.Add(new AllowNullAttribute());634                }635 636                if (parameterCmdletization.ValidateCount != null)637                {638                    int min = (int)LanguagePrimitives.ConvertTo(parameterCmdletization.ValidateCount.Min, typeof(int), CultureInfo.InvariantCulture);639                    int max = (int)LanguagePrimitives.ConvertTo(parameterCmdletization.ValidateCount.Max, typeof(int), CultureInfo.InvariantCulture);640                    parameterMetadata.Attributes.Add(new ValidateCountAttribute(min, max));641                }642 643                if (parameterCmdletization.ValidateLength != null)644                {645                    int min = (int)LanguagePrimitives.ConvertTo(parameterCmdletization.ValidateLength.Min, typeof(int), CultureInfo.InvariantCulture);646                    int max = (int)LanguagePrimitives.ConvertTo(parameterCmdletization.ValidateLength.Max, typeof(int), CultureInfo.InvariantCulture);647                    parameterMetadata.Attributes.Add(new ValidateLengthAttribute(min, max));648                }649 650                if (parameterCmdletization.Obsolete != null)651                {652                    string obsoleteMessage = parameterCmdletization.Obsolete.Message;653                    parameterMetadata.Attributes.Add(obsoleteMessage != null ? new ObsoleteAttribute(obsoleteMessage) : new ObsoleteAttribute());654                }655 656                if (parameterCmdletization.ValidateNotNull != null)657                {658                    parameterMetadata.Attributes.Add(new ValidateNotNullAttribute());659                }660 661                if (parameterCmdletization.ValidateNotNullOrEmpty != null)662                {663                    parameterMetadata.Attributes.Add(new ValidateNotNullOrEmptyAttribute());664                }665 666                if (parameterCmdletization.ValidateRange != null)667                {668                    Type parameterType = parameterMetadata.ParameterType;669                    Type elementType;670                    if (parameterType == null)671                    {672                        elementType = typeof(string);673                    }674                    else675                    {676                        elementType = parameterType.HasElementType ? parameterType.GetElementType() : parameterType;677                    }678 679                    object min = LanguagePrimitives.ConvertTo(parameterCmdletization.ValidateRange.Min, elementType, CultureInfo.InvariantCulture);680                    object max = LanguagePrimitives.ConvertTo(parameterCmdletization.ValidateRange.Max, elementType, CultureInfo.InvariantCulture);681                    parameterMetadata.Attributes.Add(new ValidateRangeAttribute(min, max));682                }683 684                if (parameterCmdletization.ValidateSet != null)685                {686                    List<string> allowedValues = new();687                    foreach (string allowedValue in parameterCmdletization.ValidateSet)688                    {689                        allowedValues.Add(allowedValue);690                    }691 692                    parameterMetadata.Attributes.Add(new ValidateSetAttribute(allowedValues.ToArray()));693                }694            }695 696            int position = int.MinValue;697            ParameterSetMetadata.ParameterFlags parameterFlags = 0;698            if (parameterCmdletization != null)699            {700                if (!string.IsNullOrEmpty(parameterCmdletization.Position))701                {702                    position = (int)LanguagePrimitives.ConvertTo(parameterCmdletization.Position, typeof(int), CultureInfo.InvariantCulture);703                }704 705                if (parameterCmdletization.IsMandatorySpecified && parameterCmdletization.IsMandatory)706                {707                    parameterFlags |= ParameterSetMetadata.ParameterFlags.Mandatory;708                }709            }710 711            if (isValueFromPipeline)712            {713                parameterFlags |= ParameterSetMetadata.ParameterFlags.ValueFromPipeline;714            }715 716            if (isValueFromPipelineByPropertyName)717            {718                parameterFlags |= ParameterSetMetadata.ParameterFlags.ValueFromPipelineByPropertyName;719            }720 721            parameterMetadata.ParameterSets.Add(parameterSetName, new ParameterSetMetadata(position, parameterFlags, null));722 723            return parameterMetadata;724        }725 726        private ParameterMetadata GetParameter(727            string parameterSetName,728            string objectModelParameterName,729            TypeMetadata parameterType,730            CmdletParameterMetadataForInstanceMethodParameter parameterCmdletization)731        {732            return GetParameter(733                parameterSetName,734                objectModelParameterName,735                parameterType,736                parameterCmdletization,737                false, /* isValueFromPipeline */738                parameterCmdletization != null && parameterCmdletization.ValueFromPipelineByPropertyNameSpecified && parameterCmdletization.ValueFromPipelineByPropertyName);739        }740 741        private ParameterMetadata GetParameter(742            IEnumerable<string> queryParameterSets,743            string objectModelParameterName,744            TypeMetadata parameterType,745            CmdletParameterMetadataForGetCmdletParameter parameterCmdletization)746        {747            ParameterMetadata result = GetParameter(748                ParameterAttribute.AllParameterSets,749                objectModelParameterName,750                parameterType,751                parameterCmdletization,752                parameterCmdletization != null && parameterCmdletization.ValueFromPipelineSpecified && parameterCmdletization.ValueFromPipeline,753                parameterCmdletization != null && parameterCmdletization.ValueFromPipelineByPropertyNameSpecified && parameterCmdletization.ValueFromPipelineByPropertyName);754 755            ParameterSetMetadata parameterSetMetadata = result.ParameterSets[ParameterAttribute.AllParameterSets];756            result.ParameterSets.Clear();757            if (parameterCmdletization != null && parameterCmdletization.CmdletParameterSets != null && parameterCmdletization.CmdletParameterSets.Length > 0)758            {759                queryParameterSets = parameterCmdletization.CmdletParameterSets;760            }761 762            foreach (string parameterSetName in queryParameterSets)763            {764                if (parameterSetName.Equals(ScriptWriter.InputObjectQueryParameterSetName, StringComparison.OrdinalIgnoreCase))765                {766                    continue;767                }768 769                result.ParameterSets.Add(parameterSetName, parameterSetMetadata);770            }771 772            return result;773        }774 775        private ParameterMetadata GetParameter(776            string parameterSetName,777            string objectModelParameterName,778            TypeMetadata parameterType,779            CmdletParameterMetadataForStaticMethodParameter parameterCmdletization)780        {781            return GetParameter(782                parameterSetName,783                objectModelParameterName,784                parameterType,785                parameterCmdletization,786                parameterCmdletization != null && parameterCmdletization.ValueFromPipelineSpecified && parameterCmdletization.ValueFromPipeline,787                parameterCmdletization != null && parameterCmdletization.ValueFromPipelineByPropertyNameSpecified && parameterCmdletization.ValueFromPipelineByPropertyName);788        }789 790        private void SetParameters(CommandMetadata commandMetadata, params Dictionary<string, ParameterMetadata>[] allParameters)791        {792            commandMetadata.Parameters.Clear();793            foreach (Dictionary<string, ParameterMetadata> parameters in allParameters)794            {795                foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)796                {797                    if (commandMetadata.Parameters.ContainsKey(parameter.Key))798                    {799                        if (this.GetCommonParameters().ContainsKey(parameter.Key))800                        {801                            string message = string.Format(802                                CultureInfo.InvariantCulture, // parameter name803                                CmdletizationCoreResources.ScriptWriter_ParameterNameConflictsWithCommonParameters,804                                parameter.Key,805                                commandMetadata.Name,806                                _objectModelWrapper.FullName);807                            throw new XmlException(message);808                        }809                        else810                        {811                            string message = string.Format(812                                CultureInfo.InvariantCulture, // parameter name813                                CmdletizationCoreResources.ScriptWriter_ParameterNameConflictsWithQueryParameters,814                                parameter.Key,815                                commandMetadata.Name,816                                "<GetCmdletParameters>");817                            throw new XmlException(message);818                        }819                    }820 821                    commandMetadata.Parameters.Add(parameter.Key, parameter.Value);822                }823            }824        }825 826        private CommandMetadata GetCommandMetadata(CommonCmdletMetadata cmdletMetadata)827        {828            string defaultParameterSetName = null;829            if (cmdletMetadata is StaticCmdletMetadataCmdletMetadata staticCmdletMetadata)830            {831                if (!string.IsNullOrEmpty(staticCmdletMetadata.DefaultCmdletParameterSet))832                {833                    defaultParameterSetName = staticCmdletMetadata.DefaultCmdletParameterSet;834                }835            }836 837            var confirmImpact = System.Management.Automation.ConfirmImpact.None;838            if (cmdletMetadata.ConfirmImpactSpecified)839            {840                confirmImpact = (System.Management.Automation.ConfirmImpact)(int)cmdletMetadata.ConfirmImpact;841            }842 843            Dictionary<string, ParameterMetadata> parameters = new(StringComparer.OrdinalIgnoreCase);844 845            CommandMetadata commandMetadata = new(846                                   name: this.GetCmdletName(cmdletMetadata),847                            commandType: CommandTypes.Cmdlet,848                       isProxyForCmdlet: true,849                defaultParameterSetName: defaultParameterSetName, // this can only be figured out for static cmdlets - instance cmdlets have to set that separately850                  supportsShouldProcess: confirmImpact != System.Management.Automation.ConfirmImpact.None,851                          confirmImpact: confirmImpact,852                         supportsPaging: false,853                   supportsTransactions: false,854                      positionalBinding: false,855                             parameters: parameters);856 857            if (!string.IsNullOrEmpty(cmdletMetadata.HelpUri))858            {859                commandMetadata.HelpUri = cmdletMetadata.HelpUri;860            }861 862            return commandMetadata;863        }864 865        private static string EscapeModuleNameForHelpComment(string name)866        {867            Dbg.Assert(name != null, "Caller should verify name != null");868 869            StringBuilder result = new(name.Length);870            foreach (char c in name)871            {872                if (!"\"'`$#".Contains(c)873                    && !char.IsControl(c)874                    && !char.IsWhiteSpace(c))875                {876                    result.Append(c);877                }878            }879 880            return result.ToString();881        }882 883        private static List<List<string>> GetCombinations(params IEnumerable<string>[] x)884        {885            Dbg.Assert(x != null, "Caller to verify that x != null");886            Dbg.Assert(x.Length > 0, "Caller to verify that x.Length > 0");887 888            if (x.Length == 1)889            {890                List<List<string>> result = new();891                foreach (string s in x[0])892                {893                    List<string> subresult = new();894                    subresult.Add(s);895                    result.Add(subresult);896                }897 898                return result;899            }900            else901            {902                IEnumerable<string>[] smallX = new IEnumerable<string>[x.Length - 1];903                Array.Copy(x, 0, smallX, 0, smallX.Length);904                List<List<string>> smallResult = GetCombinations(smallX);905 906                List<List<string>> result = new();907                foreach (List<string> smallSubresult in smallResult)908                {909                    foreach (string s in x[x.Length - 1])910                    {911                        List<string> newsubresult = new(smallSubresult);912                        newsubresult.Add(s);913                        result.Add(newsubresult);914                    }915                }916 917                return result;918            }919        }920 921        private static void EnsureOrderOfPositionalParameters(922            Dictionary<string, ParameterMetadata> beforeParameters,923            Dictionary<string, ParameterMetadata> afterParameters)924        {925            int maxBeforePosition = int.MinValue;926            foreach (ParameterMetadata beforeParameter in beforeParameters.Values)927            {928                foreach (ParameterSetMetadata beforeParameterSet in beforeParameter.ParameterSets.Values)929                {930                    maxBeforePosition = Math.Max(beforeParameterSet.Position, maxBeforePosition);931                }932            }933 934            int minAfterPosition = int.MaxValue;935            foreach (ParameterMetadata afterParameter in afterParameters.Values)936            {937                foreach (ParameterSetMetadata afterParameterSet in afterParameter.ParameterSets.Values)938                {939                    if (afterParameterSet.Position != int.MinValue)940                    {941                        minAfterPosition = Math.Min(afterParameterSet.Position, minAfterPosition);942                    }943                }944            }945 946            if ((maxBeforePosition >= 0) && (minAfterPosition <= maxBeforePosition))947            {948                int delta = (1001 - minAfterPosition % 1000);949                foreach (ParameterMetadata afterParameter in afterParameters.Values)950                {951                    foreach (ParameterSetMetadata afterParameterSet in afterParameter.ParameterSets.Values)952                    {953                        if (afterParameterSet.Position != int.MinValue)954                        {955                            checked { afterParameterSet.Position += delta; }956                        }957                    }958                }959            }960        }961 962        private const string StaticCommonParameterSetTemplate = "{1}"; // "{0}::{1}";963        private const string StaticMethodParameterSetTemplate = "{0}"; // "{1}::{0}";964 965        private const string InstanceCommonParameterSetTemplate = "{1}"; // "{0}::{1}::{2}";966        private const string InstanceQueryParameterSetTemplate = "{0}"; // "{1}::{0}::{2}";967        private const string InstanceMethodParameterSetTemplate = "{2}"; // "{1}::{2}::{0}";968 969        private const string InputObjectQueryParameterSetName = "InputObject (cdxml)";970        private const string SingleQueryParameterSetName = "Query (cdxml)";971 972        private static void MultiplyParameterSets(973            Dictionary<string, ParameterMetadata> parameters,974            string parameterSetNameTemplate, // {0} is the original parameter set, other ones are taken from the otherParameterSets array975            params IEnumerable<string>[] otherParameterSets)976        {977            List<List<string>> combinations = GetCombinations(otherParameterSets);978 979            foreach (ParameterMetadata parameter in parameters.Values)980            {981                List<KeyValuePair<string, ParameterSetMetadata>> oldParameterSets = new(parameter.ParameterSets);982 983                parameter.ParameterSets.Clear();984                foreach (KeyValuePair<string, ParameterSetMetadata> oldParameterSet in oldParameterSets)985                {986                    foreach (List<string> combination in combinations)987                    {988                        string[] formattingArray = new string[otherParameterSets.Length + 1];989                        formattingArray[0] = oldParameterSet.Key;990                        combination.CopyTo(formattingArray, 1);991                        string newParameterSetName = string.Format(CultureInfo.InvariantCulture, parameterSetNameTemplate, formattingArray);992 993                        parameter.ParameterSets.Add(newParameterSetName, oldParameterSet.Value);994                    }995                }996            }997        }998 999        private static IEnumerable<string> MultiplyParameterSets(1000            string mainParameterSet,1001            string parameterSetNameTemplate, // {0} is the original parameter set, other ones are taken from the otherParameterSets array1002            params IEnumerable<string>[] otherParameterSets)1003        {1004            List<string> result = new();1005 1006            List<List<string>> combinations = GetCombinations(otherParameterSets);1007            foreach (List<string> combination in combinations)1008            {1009                string[] formattingArray = new string[otherParameterSets.Length + 1];1010                formattingArray[0] = mainParameterSet;1011                combination.CopyTo(formattingArray, 1);1012                string newParameterSetName = string.Format(CultureInfo.InvariantCulture, parameterSetNameTemplate, formattingArray);1013                result.Add(newParameterSetName);1014            }1015 1016            return result;1017        }1018 1019        private static MethodParameterBindings GetMethodParameterKind(InstanceMethodParameterMetadata methodParameter)1020        {1021            Dbg.Assert(methodParameter != null, "Caller should verify methodParameter != null");1022 1023            MethodParameterBindings bindings = 0;1024            if (methodParameter.CmdletParameterMetadata != null)1025            {1026                bindings |= MethodParameterBindings.In;1027            }1028 1029            if (methodParameter.CmdletOutputMetadata != null)1030            {1031                if (methodParameter.CmdletOutputMetadata.ErrorCode == null)1032                {1033                    bindings |= MethodParameterBindings.Out;1034                }1035                else1036                {1037                    bindings |= MethodParameterBindings.Error;1038                }1039            }1040 1041            return bindings;1042        }1043 1044        private static MethodParameterBindings GetMethodParameterKind(StaticMethodParameterMetadata methodParameter)1045        {1046            Dbg.Assert(methodParameter != null, "Caller should verify methodParameter != null");1047 1048            MethodParameterBindings bindings = 0;1049            if (methodParameter.CmdletParameterMetadata != null)1050            {1051                bindings |= MethodParameterBindings.In;1052            }1053 1054            if (methodParameter.CmdletOutputMetadata != null)1055            {1056                if (methodParameter.CmdletOutputMetadata.ErrorCode == null)1057                {1058                    bindings |= MethodParameterBindings.Out;1059                }1060                else1061                {1062                    bindings |= MethodParameterBindings.Error;1063                }1064            }1065 1066            return bindings;1067        }1068 1069        private static MethodParameterBindings GetMethodParameterKind(CommonMethodMetadataReturnValue returnValue)1070        {1071            Dbg.Assert(returnValue != null, "Caller should verify returnValue != null");1072 1073            MethodParameterBindings bindings = 0;1074            if (returnValue.CmdletOutputMetadata != null)1075            {1076                if (returnValue.CmdletOutputMetadata.ErrorCode == null)1077                {1078                    bindings |= MethodParameterBindings.Out;1079                }1080                else1081                {1082                    bindings |= MethodParameterBindings.Error;1083                }1084            }1085 1086            return bindings;1087        }1088 1089        private static void GenerateSingleMethodParameterProcessing(1090            TextWriter output,1091            string prefix,1092            string cmdletParameterName,1093            Type cmdletParameterType,1094            string etsParameterTypeName,1095            string cmdletParameterDefaultValue,1096            string methodParameterName,1097            MethodParameterBindings methodParameterBindings)1098        {1099            Dbg.Assert(output != null, "Called should verify output != null");1100            Dbg.Assert(prefix != null, "Called should verify output != null");1101            // cmdletParameterName can be null for 'out' parameters1102            string cmdletParameterTypeName = (cmdletParameterType ?? typeof(object)).FullName;1103            Dbg.Assert(methodParameterName != null, "Caller should verify methodParameterName != null");1104 1105            if (cmdletParameterDefaultValue != null)1106            {1107                output.WriteLine(1108                    "{0}[object]$__cmdletization_defaultValue = [System.Management.Automation.LanguagePrimitives]::ConvertTo('{1}', '{2}')",1109                    prefix,1110                    CodeGeneration.EscapeSingleQuotedStringContent(cmdletParameterDefaultValue),1111                    CodeGeneration.EscapeSingleQuotedStringContent(cmdletParameterTypeName));1112                output.WriteLine(1113                    "{0}[object]$__cmdletization_defaultValueIsPresent = $true",1114                    prefix);1115            }1116            else1117            {1118                output.WriteLine(1119                    "{0}[object]$__cmdletization_defaultValue = $null",1120                    prefix);1121                output.WriteLine(1122                    "{0}[object]$__cmdletization_defaultValueIsPresent = $false",1123                    prefix);1124            }1125 1126            if ((methodParameterBindings & MethodParameterBindings.In) == MethodParameterBindings.In)1127            {1128                Dbg.Assert(cmdletParameterName != null, "Called should verify cmdletParameterName!=null for 'in' parameters");1129 1130                output.WriteLine(1131                    "{0}if ($PSBoundParameters.ContainsKey('{1}')) {{",1132                    prefix,1133                    CodeGeneration.EscapeSingleQuotedStringContent(cmdletParameterName));1134                output.WriteLine(1135                    "{0}  [object]$__cmdletization_value = ${{{1}}}",1136                    prefix,1137                    CodeGeneration.EscapeVariableName(cmdletParameterName));1138                output.WriteLine(1139                    "{0}  $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{{Name = '{1}'; ParameterType = '{2}'; Bindings = '{3}'; Value = $__cmdletization_value; IsValuePresent = $true}}",1140                    prefix,1141                    CodeGeneration.EscapeSingleQuotedStringContent(methodParameterName),1142                    CodeGeneration.EscapeSingleQuotedStringContent(cmdletParameterTypeName),1143                    CodeGeneration.EscapeSingleQuotedStringContent(methodParameterBindings.ToString()));1144                output.WriteLine("{0}}} else {{", prefix);1145            }1146 1147            output.WriteLine(1148                "{0}  $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{{Name = '{1}'; ParameterType = '{2}'; Bindings = '{3}'; Value = $__cmdletization_defaultValue; IsValuePresent = $__cmdletization_defaultValueIsPresent}}",1149                prefix,1150                CodeGeneration.EscapeSingleQuotedStringContent(methodParameterName),1151                CodeGeneration.EscapeSingleQuotedStringContent(cmdletParameterTypeName),1152                CodeGeneration.EscapeSingleQuotedStringContent(methodParameterBindings.ToString()));1153 1154            if ((methodParameterBindings & MethodParameterBindings.In) == MethodParameterBindings.In)1155            {1156                output.WriteLine("{0}}}", prefix);1157            }1158 1159            if (!string.IsNullOrEmpty(etsParameterTypeName))1160            {1161                output.WriteLine(1162                    "{0}$__cmdletization_methodParameter.ParameterTypeName = '{1}'",1163                    prefix,1164                    CodeGeneration.EscapeSingleQuotedStringContent(etsParameterTypeName));1165            }1166 1167            output.WriteLine("{0}$__cmdletization_methodParameters.Add($__cmdletization_methodParameter)", prefix);1168            output.WriteLine();1169        }1170 1171        private void GenerateMethodParametersProcessing(1172            StaticCmdletMetadata staticCmdlet,1173            IEnumerable<string> commonParameterSets,1174            out string scriptCode,1175            out Dictionary<string, ParameterMetadata> methodParameters,1176            out string outputTypeAttributeDeclaration)1177        {1178            methodParameters = new Dictionary<string, ParameterMetadata>(StringComparer.OrdinalIgnoreCase);1179            StringBuilder outputTypeAttributeDeclarationBuilder = new();1180            StringWriter output = new(CultureInfo.InvariantCulture);1181 1182            output.WriteLine("      $__cmdletization_methodParameters = [System.Collections.Generic.List[Microsoft.PowerShell.Cmdletization.MethodParameter]]::new()");1183            output.WriteLine();1184 1185            bool multipleMethods = staticCmdlet.Method.Length > 1;1186            if (multipleMethods)1187            {1188                output.WriteLine("      switch -exact ($PSCmdlet.ParameterSetName) { ");1189            }1190 1191            foreach (StaticMethodMetadata method in staticCmdlet.Method)1192            {1193                if (multipleMethods)1194                {1195                    output.Write("        { @(");1196                    bool firstParameterSet = true;1197                    foreach (1198                        string parameterSetName in1199                            MultiplyParameterSets(1200                                GetMethodParameterSet(method), StaticMethodParameterSetTemplate, commonParameterSets))

Showing the first 1,200 of 2284 lines. Download the file for the rest.