Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
PSType.cs1521 linesDownload Raw Back to parser
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.Diagnostics.CodeAnalysis;7using System.Globalization;8using System.Linq;9using System.Management.Automation.Internal;10using System.Reflection;11using System.Reflection.Emit;12using System.Threading;13 14using Microsoft.PowerShell;15 16namespace System.Management.Automation.Language17{18    internal static class TypeDefiner19    {20        internal const string DynamicClassAssemblyName = "PowerShell Class Assembly";21        internal const string DynamicClassAssemblyFullNamePrefix = "PowerShell Class Assembly,";22 23        private static int s_globalCounter = 0;24 25        private static readonly CustomAttributeBuilder s_hiddenCustomAttributeBuilder =26            new CustomAttributeBuilder(typeof(HiddenAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>());27 28        private static readonly string s_sessionStateKeeperFieldName = "__sessionStateKeeper";29        internal static readonly string SessionStateFieldName = "__sessionState";30 31        private static readonly MethodInfo s_sessionStateKeeper_GetSessionState =32            typeof(SessionStateKeeper).GetMethod("GetSessionState", BindingFlags.Instance | BindingFlags.Public);33 34        private static bool TryConvertArg(object arg, Type type, out object result, Parser parser, IScriptExtent errorExtent)35        {36            // This code could be added to LanguagePrimitives.ConvertTo37            if (arg != null && arg.GetType() == type)38            {39                result = arg;40                return true;41            }42 43            if (!LanguagePrimitives.TryConvertTo(arg, type, out result))44            {45                parser.ReportError(errorExtent,46                    nameof(ParserStrings.CannotConvertValue),47                    ParserStrings.CannotConvertValue,48                    ToStringCodeMethods.Type(type));49                return false;50            }51 52            return true;53        }54 55        private static CustomAttributeBuilder GetAttributeBuilder(Parser parser, AttributeAst attributeAst, AttributeTargets attributeTargets)56        {57            var attributeType = attributeAst.TypeName.GetReflectionAttributeType();58            Diagnostics.Assert(attributeType != null, "Semantic checks should have verified attribute type exists");59 60            Diagnostics.Assert(61                attributeType.GetCustomAttribute<AttributeUsageAttribute>(true) == null ||62                (attributeType.GetCustomAttribute<AttributeUsageAttribute>(true).ValidOn & attributeTargets) != 0, "Semantic checks should have verified attribute usage");63 64            var positionalArgs = new object[attributeAst.PositionalArguments.Count];65            var cvv = new ConstantValueVisitor { AttributeArgument = false };66            for (var i = 0; i < attributeAst.PositionalArguments.Count; i++)67            {68                var posArg = attributeAst.PositionalArguments[i];69                positionalArgs[i] = posArg.Accept(cvv);70            }71 72            var ctorInfos = attributeType.GetConstructors();73            var newConstructors = DotNetAdapter.GetMethodInformationArray(ctorInfos);74 75            string errorId = null;76            string errorMsg = null;77            bool expandParamsOnBest;78            bool callNonVirtually;79            var positionalArgCount = positionalArgs.Length;80 81            var bestMethod = Adapter.FindBestMethod(82                newConstructors,83                invocationConstraints: null,84                allowCastingToByRefLikeType: false,85                positionalArgs,86                ref errorId,87                ref errorMsg,88                out expandParamsOnBest,89                out callNonVirtually);90 91            if (bestMethod == null)92            {93                parser.ReportError(new ParseError(attributeAst.Extent, errorId,94                    string.Format(CultureInfo.InvariantCulture, errorMsg, attributeType.Name, attributeAst.PositionalArguments.Count)));95                return null;96            }97 98            var constructorInfo = (ConstructorInfo)bestMethod.method;99 100            var parameterInfo = constructorInfo.GetParameters();101            var ctorArgs = new object[parameterInfo.Length];102            object arg;103            for (var argIndex = 0; argIndex < parameterInfo.Length; ++argIndex)104            {105                var resultType = parameterInfo[argIndex].ParameterType;106 107                // The extension method 'CustomAttributeExtensions.GetCustomAttributes(ParameterInfo, Type, Boolean)' has inconsistent108                // behavior on its return value in both FullCLR and CoreCLR. According to MSDN, if the attribute cannot be found, it109                // should return an empty collection. However, it returns null in some rare cases [when the parameter isn't backed by110                // actual metadata].111                // This inconsistent behavior affects OneCore powershell because we are using the extension method here when compiling112                // against CoreCLR. So we need to add a null check until this is fixed in CLR.113                var paramArrayAttrs = parameterInfo[argIndex].GetCustomAttributes(typeof(ParamArrayAttribute), true);114                if (paramArrayAttrs != null && paramArrayAttrs.Length > 0 && expandParamsOnBest)115                {116                    var elementType = parameterInfo[argIndex].ParameterType.GetElementType();117                    var paramsArray = Array.CreateInstance(elementType, positionalArgCount - argIndex);118                    ctorArgs[argIndex] = paramsArray;119 120                    for (var i = 0; i < paramsArray.Length; ++i, ++argIndex)121                    {122                        if (!TryConvertArg(positionalArgs[argIndex], elementType, out arg,123                            parser, attributeAst.PositionalArguments[argIndex].Extent))124                        {125                            return null;126                        }127 128                        paramsArray.SetValue(arg, i);129                    }130 131                    break;132                }133 134                if (!TryConvertArg(positionalArgs[argIndex], resultType, out arg,135                    parser, attributeAst.PositionalArguments[argIndex].Extent))136                {137                    return null;138                }139 140                ctorArgs[argIndex] = arg;141            }142 143            if (attributeAst.NamedArguments.Count == 0)144            {145                return new CustomAttributeBuilder(constructorInfo, ctorArgs);146            }147 148            var propertyInfoList = new List<PropertyInfo>();149            var propertyArgs = new List<object>();150            var fieldInfoList = new List<FieldInfo>();151            var fieldArgs = new List<object>();152            foreach (var namedArg in attributeAst.NamedArguments)153            {154                var name = namedArg.ArgumentName;155                var members = attributeType.GetMember(name, MemberTypes.Field | MemberTypes.Property,156                    BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);157                Diagnostics.Assert(members.Length == 1 && (members[0] is PropertyInfo || members[0] is FieldInfo),158                    "Semantic checks should have ensured names attribute argument exists");159 160                arg = namedArg.Argument.Accept(cvv);161 162                var propertyInfo = members[0] as PropertyInfo;163                if (propertyInfo != null)164                {165                    Diagnostics.Assert(propertyInfo.GetSetMethod() != null, "Semantic checks ensures property is settable");166 167                    if (!TryConvertArg(arg, propertyInfo.PropertyType, out arg, parser, namedArg.Argument.Extent))168                    {169                        return null;170                    }171 172                    propertyInfoList.Add(propertyInfo);173                    propertyArgs.Add(arg);174                    continue;175                }176 177                var fieldInfo = (FieldInfo)members[0];178                Diagnostics.Assert(!fieldInfo.IsInitOnly && !fieldInfo.IsLiteral, "Semantic checks ensures field is settable");179 180                if (!TryConvertArg(arg, fieldInfo.FieldType, out arg, parser, namedArg.Argument.Extent))181                {182                    return null;183                }184 185                fieldInfoList.Add(fieldInfo);186                fieldArgs.Add(arg);187            }188 189            return new CustomAttributeBuilder(constructorInfo, ctorArgs,190                propertyInfoList.ToArray(), propertyArgs.ToArray(),191                fieldInfoList.ToArray(), fieldArgs.ToArray());192        }193 194        internal static void DefineCustomAttributes(TypeBuilder member, ReadOnlyCollection<AttributeAst> attributes, Parser parser, AttributeTargets attributeTargets)195        {196            if (attributes != null)197            {198                foreach (var attr in attributes)199                {200                    var cabuilder = GetAttributeBuilder(parser, attr, attributeTargets);201                    if (cabuilder != null)202                    {203                        member.SetCustomAttribute(cabuilder);204                    }205                }206            }207        }208 209        internal static void DefineCustomAttributes(PropertyBuilder member, ReadOnlyCollection<AttributeAst> attributes, Parser parser, AttributeTargets attributeTargets)210        {211            if (attributes != null)212            {213                foreach (var attr in attributes)214                {215                    var cabuilder = GetAttributeBuilder(parser, attr, attributeTargets);216                    if (cabuilder != null)217                    {218                        member.SetCustomAttribute(cabuilder);219                    }220                }221            }222        }223 224        internal static void DefineCustomAttributes(ConstructorBuilder member, ReadOnlyCollection<AttributeAst> attributes, Parser parser, AttributeTargets attributeTargets)225        {226            if (attributes != null)227            {228                foreach (var attr in attributes)229                {230                    var cabuilder = GetAttributeBuilder(parser, attr, attributeTargets);231                    if (cabuilder != null)232                    {233                        member.SetCustomAttribute(cabuilder);234                    }235                }236            }237        }238 239        internal static void DefineCustomAttributes(MethodBuilder member, ReadOnlyCollection<AttributeAst> attributes, Parser parser, AttributeTargets attributeTargets)240        {241            if (attributes != null)242            {243                foreach (var attr in attributes)244                {245                    var cabuilder = GetAttributeBuilder(parser, attr, attributeTargets);246                    if (cabuilder != null)247                    {248                        member.SetCustomAttribute(cabuilder);249                    }250                }251            }252        }253 254        internal static void DefineCustomAttributes(EnumBuilder member, ReadOnlyCollection<AttributeAst> attributes, Parser parser, AttributeTargets attributeTargets)255        {256            if (attributes != null)257            {258                foreach (var attr in attributes)259                {260                    var cabuilder = GetAttributeBuilder(parser, attr, attributeTargets);261                    if (cabuilder != null)262                    {263                        member.SetCustomAttribute(cabuilder);264                    }265                }266            }267        }268 269        private sealed class DefineTypeHelper270        {271            private readonly Parser _parser;272            internal readonly TypeDefinitionAst _typeDefinitionAst;273            internal readonly TypeBuilder _typeBuilder;274            internal readonly FieldBuilder _sessionStateField;275            internal readonly FieldBuilder _sessionStateKeeperField;276            internal readonly ModuleBuilder _moduleBuilder;277            internal readonly TypeBuilder _staticHelpersTypeBuilder;278            private readonly Dictionary<string, PropertyMemberAst> _definedProperties;279            private readonly Dictionary<string, List<Tuple<FunctionMemberAst, Type[]>>> _definedMethods;280            private Dictionary<Tuple<string, Type>, PropertyInfo> _abstractProperties;281            internal readonly List<(string fieldName, IParameterMetadataProvider bodyAst, bool isStatic)> _fieldsToInitForMemberFunctions;282            private bool _baseClassHasDefaultCtor;283 284            /// <summary>285            /// If type has fatal errors we cannot construct .NET type from it.286            /// TypeBuilder.CreateTypeInfo() would throw exception.287            /// </summary>288            public bool HasFatalErrors { get; private set; }289 290            public DefineTypeHelper(Parser parser, ModuleBuilder module, TypeDefinitionAst typeDefinitionAst, string typeName)291            {292                _moduleBuilder = module;293                _parser = parser;294                _typeDefinitionAst = typeDefinitionAst;295 296                List<Type> interfaces;297                var baseClass = this.GetBaseTypes(parser, typeDefinitionAst, out interfaces);298 299                _typeBuilder = module.DefineType(typeName, Reflection.TypeAttributes.Class | Reflection.TypeAttributes.Public, baseClass, interfaces.ToArray());300                _staticHelpersTypeBuilder = module.DefineType(string.Create(CultureInfo.InvariantCulture, $"{typeName}_<staticHelpers>"), Reflection.TypeAttributes.Class);301                DefineCustomAttributes(_typeBuilder, typeDefinitionAst.Attributes, _parser, AttributeTargets.Class);302                _typeDefinitionAst.Type = _typeBuilder;303 304                _fieldsToInitForMemberFunctions = new List<(string, IParameterMetadataProvider, bool)>();305                _definedMethods = new Dictionary<string, List<Tuple<FunctionMemberAst, Type[]>>>(StringComparer.OrdinalIgnoreCase);306                _definedProperties = new Dictionary<string, PropertyMemberAst>(StringComparer.OrdinalIgnoreCase);307 308                _sessionStateField = _typeBuilder.DefineField(SessionStateFieldName, typeof(SessionStateInternal), FieldAttributes.Private);309                _sessionStateKeeperField = _staticHelpersTypeBuilder.DefineField(s_sessionStateKeeperFieldName, typeof(SessionStateKeeper), FieldAttributes.Assembly | FieldAttributes.Static);310            }311 312            /// <summary>313            /// Return base class type, never return null.314            /// </summary>315            /// <param name="parser"></param>316            /// <param name="typeDefinitionAst"></param>317            /// <param name="interfaces">Return declared interfaces.</param>318            /// <returns></returns>319            private Type GetBaseTypes(Parser parser, TypeDefinitionAst typeDefinitionAst, out List<Type> interfaces)320            {321                // Define base types and report errors.322                Type baseClass = null;323                interfaces = new List<Type>();324 325                // Default base class is System.Object and it has a default ctor.326                _baseClassHasDefaultCtor = true;327                if (typeDefinitionAst.BaseTypes.Count > 0)328                {329                    // base class330                    var baseTypeAsts = typeDefinitionAst.BaseTypes;331                    var firstBaseTypeAst = baseTypeAsts[0];332 333                    if (firstBaseTypeAst.TypeName.IsArray)334                    {335                        parser.ReportError(firstBaseTypeAst.Extent,336                            nameof(ParserStrings.SubtypeArray),337                            ParserStrings.SubtypeArray,338                            firstBaseTypeAst.TypeName.FullName);339                        // fall to the default base type340                    }341                    else342                    {343                        baseClass = firstBaseTypeAst.TypeName.GetReflectionType();344                        if (baseClass == null)345                        {346                            parser.ReportError(firstBaseTypeAst.Extent,347                                nameof(ParserStrings.TypeNotFound),348                                ParserStrings.TypeNotFound,349                                firstBaseTypeAst.TypeName.FullName);350                            // fall to the default base type351                        }352                        else353                        {354                            if (baseClass.IsSealed)355                            {356                                parser.ReportError(firstBaseTypeAst.Extent,357                                    nameof(ParserStrings.SealedBaseClass),358                                    ParserStrings.SealedBaseClass,359                                    baseClass.Name);360                                // ignore base type if it's sealed.361                                baseClass = null;362                            }363                            else if (baseClass.IsGenericType && !baseClass.IsConstructedGenericType)364                            {365                                parser.ReportError(firstBaseTypeAst.Extent,366                                    nameof(ParserStrings.SubtypeUnclosedGeneric),367                                    ParserStrings.SubtypeUnclosedGeneric,368                                    baseClass.Name);369                                // ignore base type, we cannot inherit from unclosed generic.370                                baseClass = null;371                            }372                            else if (baseClass.IsInterface)373                            {374                                // First Ast can represent interface as well as BaseClass.375                                interfaces.Add(baseClass);376                                baseClass = null;377                            }378                        }379                    }380 381                    if (baseClass != null)382                    {383                        // All PS classes are TypeName instances.384                        // For PS classes we cannot use reflection API, because type is not created yet.385                        var baseTypeName = firstBaseTypeAst.TypeName as TypeName;386                        if (baseTypeName != null)387                        {388                            _baseClassHasDefaultCtor = baseTypeName.HasDefaultCtor();389                        }390                        else391                        {392                            _baseClassHasDefaultCtor = baseClass.HasDefaultCtor();393                        }394                    }395 396                    for (int i = 0; i < baseTypeAsts.Count; i++)397                    {398                        if (baseTypeAsts[i].TypeName.IsArray)399                        {400                            parser.ReportError(baseTypeAsts[i].Extent,401                                nameof(ParserStrings.SubtypeArray),402                                ParserStrings.SubtypeArray,403                                baseTypeAsts[i].TypeName.FullName);404                            this.HasFatalErrors = true;405                        }406                    }407 408                    for (int i = 1; i < baseTypeAsts.Count; i++)409                    {410                        if (baseTypeAsts[i].TypeName.IsArray)411                        {412                            parser.ReportError(baseTypeAsts[i].Extent,413                                nameof(ParserStrings.SubtypeArray),414                                ParserStrings.SubtypeArray,415                                baseTypeAsts[i].TypeName.FullName);416                        }417                        else418                        {419                            Type interfaceType = baseTypeAsts[i].TypeName.GetReflectionType();420                            if (interfaceType == null)421                            {422                                parser.ReportError(baseTypeAsts[i].Extent,423                                    nameof(ParserStrings.TypeNotFound),424                                    ParserStrings.TypeNotFound,425                                    baseTypeAsts[i].TypeName.FullName);426                            }427                            else428                            {429                                if (interfaceType.IsInterface)430                                {431                                    interfaces.Add(interfaceType);432                                }433                                else434                                {435                                    parser.ReportError(baseTypeAsts[i].Extent,436                                        nameof(ParserStrings.InterfaceNameExpected),437                                        ParserStrings.InterfaceNameExpected,438                                        interfaceType.Name);439                                }440                            }441                        }442                    }443                }444 445                return baseClass ?? typeof(object);446            }447 448            private bool ShouldImplementProperty(string name, Type type, [NotNullWhen(true)] out PropertyInfo interfaceProperty)449            {450                if (_abstractProperties == null)451                {452                    _abstractProperties = new Dictionary<Tuple<string, Type>, PropertyInfo>();453                    var allInterfaces = new HashSet<Type>();454 455                    // TypeBuilder.GetInterfaces() returns only the interfaces that was explicitly passed to its constructor.456                    // During compilation the interface hierarchy is flattened, so we only need to resolve one level of ancestral interfaces.457                    foreach (var interfaceType in _typeBuilder.GetInterfaces())458                    {459                        foreach (var parentInterface in interfaceType.GetInterfaces())460                        {461                            allInterfaces.Add(parentInterface);462                        }463 464                        allInterfaces.Add(interfaceType);465                    }466 467                    foreach (var interfaceType in allInterfaces)468                    {469                        foreach (var property in interfaceType.GetProperties())470                        {471                            _abstractProperties.Add(Tuple.Create(property.Name, property.PropertyType), property);472                        }473                    }474 475                    if (_typeBuilder.BaseType.IsAbstract)476                    {477                        foreach (var property in _typeBuilder.BaseType.GetProperties())478                        {479                            if (property.GetAccessors().Any(m => m.IsAbstract))480                            {481                                _abstractProperties.Add(Tuple.Create(property.Name, property.PropertyType), property);482                            }483                        }484                    }485                }486 487                return _abstractProperties.TryGetValue(Tuple.Create(name, type), out interfaceProperty);488            }489 490            public void DefineMembers()491            {492                // If user didn't provide any instance ctors or static ctor we will generate default ctor or static ctor respectively.493                // We can avoid explicit default ctor and static ctor, if we don't have any properties to initialize.494                bool needStaticCtor = false;495                bool needDefaultCtor = false;496                bool hasAnyMethods = false;497                List<FunctionMemberAst> staticCtors = new List<FunctionMemberAst>();498                List<FunctionMemberAst> instanceCtors = new List<FunctionMemberAst>();499 500                foreach (var member in _typeDefinitionAst.Members)501                {502                    var propertyMemberAst = member as PropertyMemberAst;503                    if (propertyMemberAst != null)504                    {505                        DefineProperty(propertyMemberAst);506                        if (propertyMemberAst.InitialValue != null)507                        {508                            if (propertyMemberAst.IsStatic)509                            {510                                needStaticCtor = true;511                            }512                            else513                            {514                                needDefaultCtor = true;515                            }516                        }517                    }518                    else519                    {520                        FunctionMemberAst method = member as FunctionMemberAst;521                        Diagnostics.Assert(method != null, StringUtil.Format("Unexpected subtype of MemberAst '{0}'. Expect `{1}`",522                            member.GetType().Name, typeof(FunctionMemberAst).GetType().Name));523                        if (method.IsConstructor)524                        {525                            if (method.IsStatic)526                            {527                                staticCtors.Add(method);528                            }529                            else530                            {531                                instanceCtors.Add(method);532                            }533                        }534 535                        hasAnyMethods = true;536 537                        DefineMethod(method);538                    }539                }540 541                // inside ctor we put logic to capture session state from execution context,542                // we cannot delegate default ctor creation to _typeBuilder, if we have any methods.543                // If there are only static methods, we still want to capture context to allow static method calls on instances in the right context.544                if (hasAnyMethods)545                {546                    needDefaultCtor = true;547                }548 549                if (needStaticCtor)550                {551                    foreach (var ctor in staticCtors)552                    {553                        var parameters = ((IParameterMetadataProvider)ctor.Body).Parameters;554                        // We report error for static ctors with parameters, even with default values.555                        // We don't take them into account.556                        if (parameters == null || parameters.Count == 0)557                        {558                            needStaticCtor = false;559                        }560                    }561                }562 563                if (needDefaultCtor)564                {565                    needDefaultCtor = instanceCtors.Count == 0;566                }567 568                //// Now we can decide to create explicit default ctors or report error.569 570                if (needStaticCtor)571                {572                    var staticCtorAst = new CompilerGeneratedMemberFunctionAst(PositionUtilities.EmptyExtent, _typeDefinitionAst, SpecialMemberFunctionType.StaticConstructor);573                    DefineConstructor(staticCtorAst, null, true, Reflection.MethodAttributes.Private | Reflection.MethodAttributes.Static, Type.EmptyTypes);574                }575 576                if (_baseClassHasDefaultCtor)577                {578                    if (needDefaultCtor)579                    {580                        var defaultCtorAst = new CompilerGeneratedMemberFunctionAst(PositionUtilities.EmptyExtent, _typeDefinitionAst, SpecialMemberFunctionType.DefaultConstructor);581                        DefineConstructor(defaultCtorAst, null, true, Reflection.MethodAttributes.Public, Type.EmptyTypes);582                    }583                }584                else585                {586                    if (instanceCtors.Count == 0)587                    {588                        _parser.ReportError(_typeDefinitionAst.Extent,589                            nameof(ParserStrings.BaseClassNoDefaultCtor),590                            ParserStrings.BaseClassNoDefaultCtor,591                            _typeBuilder.BaseType.Name);592                        this.HasFatalErrors = true;593                    }594                }595            }596 597            private void DefineProperty(PropertyMemberAst propertyMemberAst)598            {599                if (_definedProperties.ContainsKey(propertyMemberAst.Name))600                {601                    _parser.ReportError(propertyMemberAst.Extent,602                        nameof(ParserStrings.MemberAlreadyDefined),603                        ParserStrings.MemberAlreadyDefined,604                        propertyMemberAst.Name);605                    return;606                }607 608                _definedProperties.Add(propertyMemberAst.Name, propertyMemberAst);609 610                Type type;611                if (propertyMemberAst.PropertyType == null)612                {613                    type = typeof(object);614                }615                else616                {617                    type = propertyMemberAst.PropertyType.TypeName.GetReflectionType();618                    Diagnostics.Assert(type != null, "Semantic checks should have ensure type can't be null");619                }620 621                PropertyBuilder property = this.EmitPropertyIl(propertyMemberAst, type);622                // Define custom attributes on the property, not on the backingField623                DefineCustomAttributes(property, propertyMemberAst.Attributes, _parser, AttributeTargets.Field | AttributeTargets.Property);624            }625 626            private PropertyBuilder EmitPropertyIl(PropertyMemberAst propertyMemberAst, Type type)627            {628                // backing field is always private.629                var backingFieldAttributes = FieldAttributes.Private;630                // The property set and property get methods require a special set of attributes.631                var getSetAttributes = Reflection.MethodAttributes.SpecialName | Reflection.MethodAttributes.HideBySig;632                getSetAttributes |= propertyMemberAst.IsPublic ? Reflection.MethodAttributes.Public : Reflection.MethodAttributes.Private;633                MethodInfo implementingGetter = null;634                MethodInfo implementingSetter = null;635                if (ShouldImplementProperty(propertyMemberAst.Name, type, out PropertyInfo interfaceProperty))636                {637                    if (propertyMemberAst.IsStatic)638                    {639                        implementingGetter = interfaceProperty.GetGetMethod();640                        implementingSetter = interfaceProperty.GetSetMethod();641                    }642                    else643                    {644                        getSetAttributes |= Reflection.MethodAttributes.Virtual;645                    }646                }647 648                if (propertyMemberAst.IsStatic)649                {650                    backingFieldAttributes |= FieldAttributes.Static;651                    getSetAttributes |= Reflection.MethodAttributes.Static;652                }653                // C# naming convention for backing fields.654                string backingFieldName = string.Create(CultureInfo.InvariantCulture, $"<{propertyMemberAst.Name}>k__BackingField");655                var backingField = _typeBuilder.DefineField(backingFieldName, type, backingFieldAttributes);656 657                bool hasValidateAttributes = false;658                if (propertyMemberAst.Attributes != null)659                {660                    for (int i = 0; i < propertyMemberAst.Attributes.Count; i++)661                    {662                        Type attributeType = propertyMemberAst.Attributes[i].TypeName.GetReflectionAttributeType();663                        if (attributeType != null && attributeType.IsSubclassOf(typeof(ValidateArgumentsAttribute)))664                        {665                            hasValidateAttributes = true;666                            break;667                        }668                    }669                }670 671                // The last argument of DefineProperty is null, because the property has no parameters.672                PropertyBuilder property = _typeBuilder.DefineProperty(propertyMemberAst.Name, Reflection.PropertyAttributes.None, type, null);673 674                // Define the "get" accessor method.675                MethodBuilder getMethod = _typeBuilder.DefineMethod(string.Concat("get_", propertyMemberAst.Name), getSetAttributes, type, Type.EmptyTypes);676                ILGenerator getIlGen = getMethod.GetILGenerator();677                if (propertyMemberAst.IsStatic)678                {679                    // static680                    getIlGen.Emit(OpCodes.Ldsfld, backingField);681                    getIlGen.Emit(OpCodes.Ret);682                }683                else684                {685                    // instance686                    getIlGen.Emit(OpCodes.Ldarg_0);687                    getIlGen.Emit(OpCodes.Ldfld, backingField);688                    getIlGen.Emit(OpCodes.Ret);689                }690 691                if (implementingGetter != null)692                {693                    _typeBuilder.DefineMethodOverride(getMethod, implementingGetter);694                }695 696                // Define the "set" accessor method.697                MethodBuilder setMethod = _typeBuilder.DefineMethod(string.Concat("set_", propertyMemberAst.Name), getSetAttributes, null, new Type[] { type });698                ILGenerator setIlGen = setMethod.GetILGenerator();699 700                if (hasValidateAttributes)701                {702                    Type typeToLoad = _typeBuilder;703                    setIlGen.Emit(OpCodes.Ldtoken, typeToLoad);704                    setIlGen.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); // load current Type on stack705                    setIlGen.Emit(OpCodes.Ldstr, propertyMemberAst.Name); // load name of Property706                    setIlGen.Emit(propertyMemberAst.IsStatic ? OpCodes.Ldarg_0 : OpCodes.Ldarg_1); // load set value707                    if (type.IsValueType)708                    {709                        setIlGen.Emit(OpCodes.Box, type);710                    }711 712                    setIlGen.Emit(OpCodes.Call, CachedReflectionInfo.ClassOps_ValidateSetProperty);713                }714 715                if (propertyMemberAst.IsStatic)716                {717                    setIlGen.Emit(OpCodes.Ldarg_0);718                    setIlGen.Emit(OpCodes.Stsfld, backingField);719                }720                else721                {722                    setIlGen.Emit(OpCodes.Ldarg_0);723                    setIlGen.Emit(OpCodes.Ldarg_1);724                    setIlGen.Emit(OpCodes.Stfld, backingField);725                }726 727                setIlGen.Emit(OpCodes.Ret);728 729                if (implementingSetter != null)730                {731                    _typeBuilder.DefineMethodOverride(setMethod, implementingSetter);732                }733 734                // Map the two methods created above to our PropertyBuilder to735                // their corresponding behaviors, "get" and "set" respectively.736                property.SetGetMethod(getMethod);737                property.SetSetMethod(setMethod);738 739                if (propertyMemberAst.IsHidden)740                {741                    property.SetCustomAttribute(s_hiddenCustomAttributeBuilder);742                }743 744                return property;745            }746 747            private bool CheckForDuplicateOverload(FunctionMemberAst functionMemberAst, Type[] newParameters)748            {749                List<Tuple<FunctionMemberAst, Type[]>> overloads;750                if (!_definedMethods.TryGetValue(functionMemberAst.Name, out overloads))751                {752                    overloads = new List<Tuple<FunctionMemberAst, Type[]>>();753                    _definedMethods.Add(functionMemberAst.Name, overloads);754                }755                else756                {757                    foreach (var overload in overloads)758                    {759                        var overloadParameters = overload.Item2;760 761                        // This test won't be correct when defaults are supported762                        if (newParameters.Length != overloadParameters.Length)763                        {764                            continue;765                        }766 767                        var sameSignature = true;768                        for (int i = 0; i < newParameters.Length; i++)769                        {770                            if (newParameters[i] != overloadParameters[i])771                            {772                                sameSignature = false;773                                break;774                            }775                        }776 777                        if (sameSignature)778                        {779                            // If both are both static/instance, it's an error.780                            // Otherwise, signatures can match only for the constructor.781                            if (overload.Item1.IsStatic == functionMemberAst.IsStatic ||782                                !functionMemberAst.IsConstructor)783                            {784                                _parser.ReportError(functionMemberAst.NameExtent ?? functionMemberAst.Extent,785                                    nameof(ParserStrings.MemberAlreadyDefined),786                                    ParserStrings.MemberAlreadyDefined,787                                    functionMemberAst.Name);788                                return true;789                            }790                        }791                    }792                }793 794                overloads.Add(Tuple.Create(functionMemberAst, newParameters));795                return false;796            }797 798            private Type[] GetParameterTypes(FunctionMemberAst functionMemberAst)799            {800                var parameters = ((IParameterMetadataProvider)functionMemberAst).Parameters;801                if (parameters == null)802                {803                    return Type.EmptyTypes;804                }805 806                bool anyErrors = false;807                var result = new Type[parameters.Count];808                for (var i = 0; i < parameters.Count; i++)809                {810                    var typeConstraint = parameters[i].Attributes.OfType<TypeConstraintAst>().FirstOrDefault();811                    var paramType = (typeConstraint != null)812                                        ? typeConstraint.TypeName.GetReflectionType()813                                        : typeof(object);814                    if (paramType == null)815                    {816                        _parser.ReportError(typeConstraint.Extent,817                            nameof(ParserStrings.TypeNotFound),818                            ParserStrings.TypeNotFound,819                            typeConstraint.TypeName.FullName);820                        anyErrors = true;821                    }822                    else if (paramType == typeof(void) || paramType.IsGenericTypeDefinition)823                    {824                        _parser.ReportError(typeConstraint.Extent,825                            nameof(ParserStrings.TypeNotAllowedForParameter),826                            ParserStrings.TypeNotAllowedForParameter,827                            typeConstraint.TypeName.FullName);828                        anyErrors = true;829                    }830 831                    result[i] = paramType;832                }833 834                return anyErrors ? null : result;835            }836 837            private bool MethodExistsOnBaseClassAndFinal(string methodName, Type[] parameterTypes)838            {839                Type baseType = _typeBuilder.BaseType;840 841                // If baseType is PS class, then method will be virtual, once we define it.842                if (baseType is TypeBuilder)843                {844                    return false;845                }846 847                var mi = baseType.GetMethod(methodName, parameterTypes);848                return mi != null && mi.IsFinal;849            }850 851            private void DefineMethod(FunctionMemberAst functionMemberAst)852            {853                var parameterTypes = GetParameterTypes(functionMemberAst);854                if (parameterTypes == null)855                {856                    // There must have been an error, just return857                    return;858                }859 860                if (CheckForDuplicateOverload(functionMemberAst, parameterTypes))861                {862                    return;863                }864 865                if (functionMemberAst.IsConstructor)866                {867                    var methodAttributes = Reflection.MethodAttributes.Public;868                    if (functionMemberAst.IsStatic)869                    {870                        var parameters = functionMemberAst.Parameters;871                        if (parameters.Count > 0)872                        {873                            IScriptExtent errorExtent = Parser.ExtentOf(parameters[0], parameters.Last());874                            _parser.ReportError(errorExtent,875                                nameof(ParserStrings.StaticConstructorCantHaveParameters),876                                ParserStrings.StaticConstructorCantHaveParameters);877                            return;878                        }879 880                        methodAttributes |= Reflection.MethodAttributes.Static;881                    }882 883                    DefineConstructor(functionMemberAst, functionMemberAst.Attributes, functionMemberAst.IsHidden, methodAttributes, parameterTypes);884                    return;885                }886 887                var attributes = functionMemberAst.IsPublic888                                     ? Reflection.MethodAttributes.Public889                                     : Reflection.MethodAttributes.Private;890                if (functionMemberAst.IsStatic)891                {892                    attributes |= Reflection.MethodAttributes.Static;893                }894                else895                {896                    if (this.MethodExistsOnBaseClassAndFinal(functionMemberAst.Name, parameterTypes))897                    {898                        attributes |= Reflection.MethodAttributes.HideBySig;899                        attributes |= Reflection.MethodAttributes.NewSlot;900                    }901 902                    attributes |= Reflection.MethodAttributes.Virtual;903                }904 905                var returnType = functionMemberAst.GetReturnType();906                if (returnType == null)907                {908                    _parser.ReportError(functionMemberAst.ReturnType.Extent,909                        nameof(ParserStrings.TypeNotFound),910                        ParserStrings.TypeNotFound,911                        functionMemberAst.ReturnType.TypeName.FullName);912                    return;913                }914 915                var method = _typeBuilder.DefineMethod(functionMemberAst.Name, attributes, returnType, parameterTypes);916                DefineCustomAttributes(method, functionMemberAst.Attributes, _parser, AttributeTargets.Method);917                if (functionMemberAst.IsHidden)918                {919                    method.SetCustomAttribute(s_hiddenCustomAttributeBuilder);920                }921 922                var ilGenerator = method.GetILGenerator();923                DefineMethodBody(functionMemberAst, ilGenerator, GetMetaDataName(method.Name, parameterTypes.Length), functionMemberAst.IsStatic, parameterTypes, returnType,924                    (i, n) => method.DefineParameter(i, ParameterAttributes.None, n));925            }926 927            private void DefineConstructor(IParameterMetadataProvider ipmp, ReadOnlyCollection<AttributeAst> attributeAsts, bool isHidden, Reflection.MethodAttributes methodAttributes, Type[] parameterTypes)928            {929                bool isStatic = (methodAttributes & Reflection.MethodAttributes.Static) != 0;930                var ctor = isStatic931                    ? _typeBuilder.DefineTypeInitializer()932                    : _typeBuilder.DefineConstructor(methodAttributes, CallingConventions.Standard, parameterTypes);933                DefineCustomAttributes(ctor, attributeAsts, _parser, AttributeTargets.Constructor);934                if (isHidden)935                {936                    ctor.SetCustomAttribute(s_hiddenCustomAttributeBuilder);937                }938 939                var ilGenerator = ctor.GetILGenerator();940 941                if (!isStatic)942                {943                    ilGenerator.Emit(OpCodes.Ldarg_0); // load 'this' on stack for Stfld call944 945                    ilGenerator.Emit(OpCodes.Ldnull);946                    ilGenerator.Emit(OpCodes.Ldfld, _sessionStateKeeperField);947                    ilGenerator.EmitCall(OpCodes.Call, s_sessionStateKeeper_GetSessionState, null); // load 'sessionState' on stack for Stfld call948 949                    ilGenerator.Emit(OpCodes.Stfld, _sessionStateField);950                }951 952                DefineMethodBody(ipmp, ilGenerator, GetMetaDataName(ctor.Name, parameterTypes.Length), isStatic, parameterTypes, typeof(void),953                    (i, n) => ctor.DefineParameter(i, ParameterAttributes.None, n));954            }955 956            private static string GetMetaDataName(string name, int numberOfParameters)957            {958                int currentId = Interlocked.Increment(ref s_globalCounter);959                string metaDataName = name + "_" + numberOfParameters + "_" + currentId;960                return metaDataName;961            }962 963            private void DefineMethodBody(964                IParameterMetadataProvider ipmp,965                ILGenerator ilGenerator,966                string metadataToken,967                bool isStatic,968                Type[] parameterTypes,969                Type returnType,970                Action<int, string> parameterNameSetter)971            {972                var wrapperFieldName = string.Create(CultureInfo.InvariantCulture, $"<{metadataToken}>");973                var scriptBlockWrapperField = _staticHelpersTypeBuilder.DefineField(wrapperFieldName,974                                                                       typeof(ScriptBlockMemberMethodWrapper),975                                                                       FieldAttributes.Assembly | FieldAttributes.Static);976 977                ilGenerator.Emit(OpCodes.Ldsfld, scriptBlockWrapperField);978                if (isStatic)979                {980                    ilGenerator.Emit(OpCodes.Ldnull);                   // pass null (no this)981                    ilGenerator.Emit(OpCodes.Ldnull);                   // pass null (no sessionStateInternal)982                }983                else984                {985                    EmitLdarg(ilGenerator, 0);                            // pass this986                    ilGenerator.Emit(OpCodes.Ldarg_0);                    // pass 'this' for Ldfld call987                    ilGenerator.Emit(OpCodes.Ldfld, _sessionStateField);  // pass sessionStateInternal988                }989 990                int parameterCount = parameterTypes.Length;991                if (parameterCount > 0)992                {993                    var parameters = ipmp.Parameters;994                    var local = ilGenerator.DeclareLocal(typeof(object[]));995 996                    EmitLdc(ilGenerator, parameterCount);               // Create an array to hold all997                    ilGenerator.Emit(OpCodes.Newarr, typeof(object));  //     of the parameters998                    ilGenerator.Emit(OpCodes.Stloc, local);             // Save array for repeated use999                    int j = isStatic ? 0 : 1;1000                    for (int i = 0; i < parameterCount; i++, j++)1001                    {1002                        ilGenerator.Emit(OpCodes.Ldloc, local);           // load array1003                        EmitLdc(ilGenerator, i);                          // index to save at1004                        EmitLdarg(ilGenerator, j);                        // load argument (skipping this)1005                        if (parameterTypes[i].IsValueType)  // value types must be boxed1006                        {1007                            ilGenerator.Emit(OpCodes.Box, parameterTypes[i]);1008                        }1009 1010                        ilGenerator.Emit(OpCodes.Stelem_Ref);           // save the argument in the array1011 1012                        // Set the parameter name, mostly for Get-Member1013                        // Parameters are indexed beginning with the number 1 for the first parameter1014                        parameterNameSetter(i + 1, parameters[i].Name.VariablePath.UserPath);1015                    }1016 1017                    ilGenerator.Emit(OpCodes.Ldloc, local);         // load array1018                }1019                else1020                {1021                    ilGenerator.Emit(OpCodes.Ldsfld, typeof(ScriptBlockMemberMethodWrapper).GetField("_emptyArgumentArray", BindingFlags.Static | BindingFlags.Public));1022                }1023 1024                MethodInfo invokeHelper;1025                if (returnType == typeof(void))1026                {1027                    invokeHelper = typeof(ScriptBlockMemberMethodWrapper).GetMethod("InvokeHelper", BindingFlags.Instance | BindingFlags.Public);1028                }1029                else1030                {1031                    invokeHelper = typeof(ScriptBlockMemberMethodWrapper).GetMethod("InvokeHelperT", BindingFlags.Instance | BindingFlags.Public).MakeGenericMethod(returnType);1032                }1033 1034                ilGenerator.Emit(OpCodes.Tailcall);1035                ilGenerator.EmitCall(OpCodes.Call, invokeHelper, null);1036                ilGenerator.Emit(OpCodes.Ret);1037 1038                _fieldsToInitForMemberFunctions.Add((wrapperFieldName, ipmp, isStatic));1039            }1040        }1041 1042        private sealed class DefineEnumHelper1043        {1044            private readonly Parser _parser;1045            private readonly TypeDefinitionAst _enumDefinitionAst;1046            private readonly ModuleBuilder _moduleBuilder;1047            private readonly string _typeName;1048 1049            internal DefineEnumHelper(Parser parser, ModuleBuilder module, TypeDefinitionAst enumDefinitionAst, string typeName)1050            {1051                _parser = parser;1052                _enumDefinitionAst = enumDefinitionAst;1053                _moduleBuilder = module;1054                _typeName = typeName;1055            }1056 1057            internal static List<DefineEnumHelper> Sort(List<DefineEnumHelper> defineEnumHelpers, Parser parser)1058            {1059                // This function does a topological sort of the enums to be defined.  This is needed so we1060                // can allow one enum member to use the value of another w/o needing to worry about the order1061                // they are declared in.  For example:1062                //1063                //     enum E1 { e1 = [E2]::e2 }1064                //     enum E2 { e2 = 42 }1065                //1066                // We also want to report an error for recursive expressions, e.g.1067                //1068                //     enum E1 { e1 = [E2]::e2 }1069                //     enum E2 { e2 = [E1]::e1 }1070                //1071                // Note that this code is not as permissive as it could be, e.g. we could (but do not) allow:1072                //1073                //     enum E1 { e1 = [E2]::e2 }1074                //     enum E2 {1075                //         e2 = 421076                //         e2a = [E1]::e11077                //     }1078                //1079                // In this case, there is no cycle in the constant values despite E1 referencing E2 and vice versa.1080                //1081                // The basic algorithm is to create a graph where the edges represent a dependency, using this example:1082                //1083                //     enum E1 { e1 = [E2]::e2 }1084                //     enum E2 { e2 = 42 }1085                //1086                // We have an edge E1->E2.  E2 has no dependencies.1087 1088                if (defineEnumHelpers.Count == 1)1089                {1090                    return defineEnumHelpers;1091                }1092 1093                // There won't be many nodes in our graph, so we just use a dictionary with a list of edges instead1094                // of something cleaner.1095                var graph = new Dictionary<TypeDefinitionAst, Tuple<DefineEnumHelper, List<TypeDefinitionAst>>>();1096 1097                // Add all of our nodes to the graph1098                foreach (var helper in defineEnumHelpers)1099                {1100                    graph.Add(helper._enumDefinitionAst, Tuple.Create(helper, new List<TypeDefinitionAst>()));1101                }1102 1103                // Now find any edges.1104                foreach (var helper in defineEnumHelpers)1105                {1106                    foreach (var enumerator in helper._enumDefinitionAst.Members)1107                    {1108                        var initExpr = ((PropertyMemberAst)enumerator).InitialValue;1109                        if (initExpr == null)1110                        {1111                            // No initializer, so no dependency (this is incorrect assumption if1112                            // we wanted to be more general like C#.)1113                            continue;1114                        }1115 1116                        // The expression may have multiple member expressions, e.g. [E]::e1 + [E]::e21117                        foreach (var memberExpr in initExpr.FindAll(static ast => ast is MemberExpressionAst, false))1118                        {1119                            var typeExpr = ((MemberExpressionAst)memberExpr).Expression as TypeExpressionAst;1120                            if (typeExpr != null)1121                            {1122                                // We only want to add edges for enums being defined in the current scope.1123                                // We detect this by seeing if the ast is in our graph or not.1124                                var typeName = typeExpr.TypeName as TypeName;1125                                if (typeName != null1126                                    && typeName._typeDefinitionAst != null1127                                    && typeName._typeDefinitionAst != helper._enumDefinitionAst  // Don't add self edges1128                                    && graph.ContainsKey(typeName._typeDefinitionAst))1129                                {1130                                    var edgeList = graph[helper._enumDefinitionAst].Item2;1131                                    if (!edgeList.Contains(typeName._typeDefinitionAst))  // Only add 1 edge per enum1132                                    {1133                                        edgeList.Add(typeName._typeDefinitionAst);1134                                    }1135                                }1136                            }1137                        }1138                    }1139                }1140 1141                // Our graph is built.  The ready list will hold nodes that don't depend on anything not already1142                // in the result list.  We start with a list of nodes with no edges (no dependencies).1143                var result = new List<DefineEnumHelper>(defineEnumHelpers.Count);1144                var readyList = new List<DefineEnumHelper>(defineEnumHelpers.Count);1145                readyList.AddRange(from value in graph.Values where value.Item2.Count == 0 select value.Item1);1146                while (readyList.Count > 0)1147                {1148                    var node = readyList[readyList.Count - 1];1149                    readyList.RemoveAt(readyList.Count - 1);1150                    result.Add(node);1151 1152                    // Remove all edges to this node as it is in our result list now.1153                    foreach (var value in graph.Values)1154                    {1155                        value.Item2.Remove(node._enumDefinitionAst);1156 1157                        // If we removed the last edge, we can put this node on the ready list (assuming it1158                        // wasn't already there or in our result list.)1159                        if (value.Item2.Count == 0 && !result.Contains(value.Item1) && !readyList.Contains(value.Item1))1160                        {1161                            readyList.Add(value.Item1);1162                        }1163                    }1164                }1165 1166                if (result.Count < defineEnumHelpers.Count)1167                {1168                    // There was a cycle, report an error on each enum.1169                    foreach (var helper in defineEnumHelpers)1170                    {1171                        if (!result.Contains(helper))1172                        {1173                            parser.ReportError(helper._enumDefinitionAst.Extent,1174                                nameof(ParserStrings.CycleInEnumInitializers),1175                                ParserStrings.CycleInEnumInitializers);1176                        }1177                    }1178                }1179                else1180                {1181                    Diagnostics.Assert(result.Count == defineEnumHelpers.Count, "Logic error if we have more outgoing results than incoming");1182                }1183 1184                return result;1185            }1186 1187            internal void DefineEnum()1188            {1189                var typeConstraintAst = _enumDefinitionAst.BaseTypes.FirstOrDefault();1190                var underlyingType = typeConstraintAst == null ? typeof(int) : typeConstraintAst.TypeName.GetReflectionType();1191 1192                var definedEnumerators = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1193                var enumBuilder = _moduleBuilder.DefineEnum(_typeName, Reflection.TypeAttributes.Public, underlyingType);1194                DefineCustomAttributes(enumBuilder, _enumDefinitionAst.Attributes, _parser, AttributeTargets.Enum);1195 1196                dynamic value = 0;1197                dynamic maxValue = 0;1198                switch (Type.GetTypeCode(underlyingType))1199                {1200                    case TypeCode.Byte:

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