public void PinnedAndUnpinnedLocals()
        {
            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(PinnedAndUnpinnedLocalsToDecode).GetTypeInfo().Assembly)))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader reader   = peReader.GetMetadataReader();
                    var            provider = new DisassemblingTypeProvider();

                    TypeDefinitionHandle typeDefHandle = TestMetadataResolver.FindTestType(reader, typeof(PinnedAndUnpinnedLocalsToDecode));
                    TypeDefinition       typeDef       = reader.GetTypeDefinition(typeDefHandle);
                    MethodDefinition     methodDef     = reader.GetMethodDefinition(typeDef.GetMethods().First());

                    Assert.Equal("DoSomething", reader.GetString(methodDef.Name));

                    MethodBodyBlock     body           = peReader.GetMethodBody(methodDef.RelativeVirtualAddress);
                    StandaloneSignature localSignature = reader.GetStandaloneSignature(body.LocalSignature);

                    ImmutableArray <string> localTypes = localSignature.DecodeLocalSignature(provider, genericContext: null);

                    // Compiler can generate temporaries or re-order so just check the ones we expect are there.
                    // (They could get optimized away too. If that happens in practice, change this test to use hard-coded signatures.)
                    Assert.Contains("uint8[] pinned", localTypes);
                    Assert.Contains("uint8[]", localTypes);
                }
        }
        public void WrongSignatureType()
        {
            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(VarArgsToDecode).GetTypeInfo().Assembly)))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader reader   = peReader.GetMetadataReader();
                    var            provider = new DisassemblingTypeProvider();
                    var            decoder  = new SignatureDecoder <string, DisassemblingGenericContext>(provider, reader, genericContext: null);

                    BlobReader fieldSignature    = reader.GetBlobReader(reader.GetFieldDefinition(MetadataTokens.FieldDefinitionHandle(1)).Signature);
                    BlobReader methodSignature   = reader.GetBlobReader(reader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle(1)).Signature);
                    BlobReader propertySignature = reader.GetBlobReader(reader.GetPropertyDefinition(MetadataTokens.PropertyDefinitionHandle(1)).Signature);

                    Assert.Throws <BadImageFormatException>(() => decoder.DecodeMethodSignature(ref fieldSignature));
                    Assert.Throws <BadImageFormatException>(() => decoder.DecodeFieldSignature(ref methodSignature));
                    Assert.Throws <BadImageFormatException>(() => decoder.DecodeLocalSignature(ref propertySignature));
                }
        }
        public void SimpleSignatureProviderCoverage()
        {
            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(SignaturesToDecode <>).GetTypeInfo().Assembly)))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader       reader     = peReader.GetMetadataReader();
                    var                  provider   = new DisassemblingTypeProvider();
                    TypeDefinitionHandle typeHandle = TestMetadataResolver.FindTestType(reader, typeof(SignaturesToDecode <>));
                    Assert.Equal("System.Reflection.Metadata.Decoding.Tests.SignatureDecoderTests/SignaturesToDecode`1", provider.GetTypeFromHandle(reader, genericContext: null, handle: typeHandle));

                    TypeDefinition type = reader.GetTypeDefinition(typeHandle);
                    Dictionary <string, string> expectedFields        = GetExpectedFieldSignatures();
                    ImmutableArray <string>     genericTypeParameters = type.GetGenericParameters().Select(h => reader.GetString(reader.GetGenericParameter(h).Name)).ToImmutableArray();

                    var genericTypeContext = new DisassemblingGenericContext(genericTypeParameters, ImmutableArray <string> .Empty);

                    foreach (var fieldHandle in type.GetFields())
                    {
                        FieldDefinition field     = reader.GetFieldDefinition(fieldHandle);
                        string          fieldName = reader.GetString(field.Name);
                        string          expected;
                        Assert.True(expectedFields.TryGetValue(fieldName, out expected), "Unexpected field: " + fieldName);
                        Assert.Equal(expected, field.DecodeSignature(provider, genericTypeContext));
                    }

                    Dictionary <string, string> expectedMethods = GetExpectedMethodSignatures();
                    foreach (var methodHandle in type.GetMethods())
                    {
                        MethodDefinition method = reader.GetMethodDefinition(methodHandle);

                        ImmutableArray <string> genericMethodParameters = method.GetGenericParameters().Select(h => reader.GetString(reader.GetGenericParameter(h).Name)).ToImmutableArray();
                        var genericMethodContext = new DisassemblingGenericContext(genericTypeParameters, genericMethodParameters);

                        string methodName = reader.GetString(method.Name);
                        string expected;
                        Assert.True(expectedMethods.TryGetValue(methodName, out expected), "Unexpected method: " + methodName);
                        MethodSignature <string> signature = method.DecodeSignature(provider, genericMethodContext);
                        Assert.True(signature.Header.Kind == SignatureKind.Method);

                        if (methodName.StartsWith("Generic"))
                        {
                            Assert.Equal(1, signature.GenericParameterCount);
                        }
                        else
                        {
                            Assert.Equal(0, signature.GenericParameterCount);
                        }

                        Assert.True(signature.GenericParameterCount <= 1 && (methodName != "GenericMethodParameter" || signature.GenericParameterCount == 1));
                        Assert.Equal(expected, provider.GetFunctionPointerType(signature));
                    }

                    Dictionary <string, string> expectedProperties = GetExpectedPropertySignatures();
                    foreach (var propertyHandle in type.GetProperties())
                    {
                        PropertyDefinition property     = reader.GetPropertyDefinition(propertyHandle);
                        string             propertyName = reader.GetString(property.Name);
                        string             expected;
                        Assert.True(expectedProperties.TryGetValue(propertyName, out expected), "Unexpected property: " + propertyName);
                        MethodSignature <string> signature = property.DecodeSignature(provider, genericTypeContext);
                        Assert.True(signature.Header.Kind == SignatureKind.Property);
                        Assert.Equal(expected, provider.GetFunctionPointerType(signature));
                    }

                    Dictionary <string, string> expectedEvents = GetExpectedEventSignatures();
                    foreach (var eventHandle in type.GetEvents())
                    {
                        EventDefinition @event    = reader.GetEventDefinition(eventHandle);
                        string          eventName = reader.GetString(@event.Name);
                        string          expected;
                        Assert.True(expectedEvents.TryGetValue(eventName, out expected), "Unexpected event: " + eventName);

                        Assert.Equal(expected, provider.GetTypeFromHandle(reader, genericTypeContext, @event.Type));
                    }

                    Assert.Equal($"[{CollectionsAssemblyName}]System.Collections.Generic.List`1<!T>", provider.GetTypeFromHandle(reader, genericTypeContext, handle: type.BaseType));
                }
        }