diff --git a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs index a57eee34a15ab2..5e4ccaed0166a9 100644 --- a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs +++ b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs @@ -715,6 +715,7 @@ public readonly partial struct EventDefinition public System.Reflection.Metadata.EntityHandle Type { get { throw null; } } public System.Reflection.Metadata.EventAccessors GetAccessors() { throw null; } public System.Reflection.Metadata.CustomAttributeHandleCollection GetCustomAttributes() { throw null; } + public System.Reflection.Metadata.TypeDefinitionHandle GetDeclaringType() { throw null; } } public readonly partial struct EventDefinitionHandle : System.IEquatable { @@ -2135,6 +2136,7 @@ public readonly partial struct PropertyDefinition public System.Reflection.Metadata.MethodSignature DecodeSignature(System.Reflection.Metadata.ISignatureTypeProvider provider, TGenericContext genericContext) { throw null; } public System.Reflection.Metadata.PropertyAccessors GetAccessors() { throw null; } public System.Reflection.Metadata.CustomAttributeHandleCollection GetCustomAttributes() { throw null; } + public System.Reflection.Metadata.TypeDefinitionHandle GetDeclaringType() { throw null; } public System.Reflection.Metadata.ConstantHandle GetDefaultValue() { throw null; } } public readonly partial struct PropertyDefinitionHandle : System.IEquatable diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/Tables.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/Tables.cs index 9cef4ec444960d..9ce20605985036 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/Tables.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/Tables.cs @@ -1213,6 +1213,29 @@ internal int GetEventListStartFor(int rowId) int rowOffset = (rowId - 1) * this.RowSize; return this.Block.PeekReference(rowOffset + _EventListOffset, _IsEventRefSizeSmall); } + + internal TypeDefinitionHandle FindTypeContainingEvent(int eventRowId, int numberOfEvents) + { + int numOfRows = this.NumberOfRows; + int slot = this.Block.BinarySearchForSlot(numOfRows, this.RowSize, _EventListOffset, (uint)eventRowId, _IsEventRefSizeSmall); + int row = slot + 1; + if (row == 0) + { + return default(TypeDefinitionHandle); + } + + if (row > numOfRows) + { + if (eventRowId <= numberOfEvents) + { + return GetParentType(numOfRows); + } + + return default(TypeDefinitionHandle); + } + + return GetParentType(row); + } } internal readonly struct EventPtrTableReader @@ -1343,6 +1366,29 @@ internal int GetPropertyListStartFor(int rowId) int rowOffset = (rowId - 1) * this.RowSize; return this.Block.PeekReference(rowOffset + _PropertyListOffset, _IsPropertyRefSizeSmall); } + + internal TypeDefinitionHandle FindTypeContainingProperty(int propertyRowId, int numberOfProperties) + { + int numOfRows = this.NumberOfRows; + int slot = this.Block.BinarySearchForSlot(numOfRows, this.RowSize, _PropertyListOffset, (uint)propertyRowId, _IsPropertyRefSizeSmall); + int row = slot + 1; + if (row == 0) + { + return default(TypeDefinitionHandle); + } + + if (row > numOfRows) + { + if (propertyRowId <= numberOfProperties) + { + return GetParentType(numOfRows); + } + + return default(TypeDefinitionHandle); + } + + return GetParentType(row); + } } internal readonly struct PropertyPtrTableReader diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs index 3739ce09cad769..fc0bfd054042e8 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs @@ -1350,6 +1350,26 @@ internal TypeDefinitionHandle GetDeclaringType(FieldDefinitionHandle fieldDef) return TypeDefTable.FindTypeContainingField(fieldRowId, FieldTable.NumberOfRows); } + internal TypeDefinitionHandle GetDeclaringType(EventDefinitionHandle eventDef) + { + if (UseEventPtrTable) + { + eventDef = EventPtrTable.GetEventFor(eventDef.RowId); + } + + return EventMapTable.FindTypeContainingEvent(eventDef.RowId, EventTable.NumberOfRows); + } + + internal TypeDefinitionHandle GetDeclaringType(PropertyDefinitionHandle propertyDef) + { + if (UsePropertyPtrTable) + { + propertyDef = PropertyPtrTable.GetPropertyFor(propertyDef.RowId); + } + + return PropertyMapTable.FindTypeContainingProperty(propertyDef.RowId, PropertyTable.NumberOfRows); + } + public string GetString(DocumentNameBlobHandle handle) { return BlobHeap.GetDocumentName(handle); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/EventDefinition.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/EventDefinition.cs index 0f6dc1e2f8a575..63ec668fd39d1e 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/EventDefinition.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/EventDefinition.cs @@ -57,6 +57,14 @@ public CustomAttributeHandleCollection GetCustomAttributes() return new CustomAttributeHandleCollection(_reader, Handle); } + /// + /// Returns a handle to the type that declares this event. + /// + public TypeDefinitionHandle GetDeclaringType() + { + return _reader.GetDeclaringType(Handle); + } + public EventAccessors GetAccessors() { int adder = 0; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/FieldDefinition.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/FieldDefinition.cs index 62b0137cb28794..a4185ed1d9735f 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/FieldDefinition.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/FieldDefinition.cs @@ -83,6 +83,9 @@ public TType DecodeSignature(ISignatureTypeProvider + /// Returns a handle to the type that declares this field. + /// public TypeDefinitionHandle GetDeclaringType() { return _reader.GetDeclaringType(Handle); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/MethodDefinition.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/MethodDefinition.cs index ec812439f4b38c..029fbd0fa2ca5e 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/MethodDefinition.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/MethodDefinition.cs @@ -109,6 +109,9 @@ public MethodImplAttributes ImplAttributes } } + /// + /// Returns a handle to the type that declares this method. + /// public TypeDefinitionHandle GetDeclaringType() { return _reader.GetDeclaringType(Handle); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/PropertyDefinition.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/PropertyDefinition.cs index 00b28b105103e6..b8a262430d1d51 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/PropertyDefinition.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/PropertyDefinition.cs @@ -69,6 +69,14 @@ public CustomAttributeHandleCollection GetCustomAttributes() return new CustomAttributeHandleCollection(_reader, Handle); } + /// + /// Returns a handle to the type that declares this property. + /// + public TypeDefinitionHandle GetDeclaringType() + { + return _reader.GetDeclaringType(Handle); + } + public PropertyAccessors GetAccessors() { int getter = 0; diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs index 56943320ce5a4e..5cb28645258aed 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs @@ -2723,6 +2723,7 @@ public void MemberCollections_AllMembers() "add_ED1", "remove_ED1", ".ctor", + ".ctor", "get_PE1", "set_PE1", "get_PE2", diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/TypeDefinitionTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/TypeDefinitionTests.cs index 68fcf1fcbcbd39..c9c29effe9dc3d 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/TypeDefinitionTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeSystem/TypeDefinitionTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Reflection.Metadata.Ecma335; using Xunit; namespace System.Reflection.Metadata.Tests @@ -32,5 +33,44 @@ public void ValidateTypeDefinitionIsNestedWindowsProjection() Assert.Equal(typeDef.Attributes.IsNested(), typeDef.IsNested); } } + + [Fact] + public void ValidateDeclaringType() + { + var reader = MetadataReaderTests.GetMetadataReader(Misc.Members); + + Assert.NotEmpty(reader.GetTypesWithEvents()); + Assert.NotEmpty(reader.GetTypesWithProperties()); + + foreach (var typeDefHandle in reader.TypeDefinitions) + { + var typeDef = reader.GetTypeDefinition(typeDefHandle); + foreach (var nestedTypeHandle in typeDef.GetNestedTypes()) + { + var nestedType = reader.GetTypeDefinition(nestedTypeHandle); + Assert.Equal(typeDefHandle, nestedType.GetDeclaringType()); + } + foreach (var fieldHandle in typeDef.GetFields()) + { + var field = reader.GetFieldDefinition(fieldHandle); + Assert.Equal(typeDefHandle, field.GetDeclaringType()); + } + foreach (var methodHandle in typeDef.GetMethods()) + { + var method = reader.GetMethodDefinition(methodHandle); + Assert.Equal(typeDefHandle, method.GetDeclaringType()); + } + foreach (var eventHandle in typeDef.GetEvents()) + { + var eventDef = reader.GetEventDefinition(eventHandle); + Assert.Equal(typeDefHandle, eventDef.GetDeclaringType()); + } + foreach (var propertyHandle in typeDef.GetProperties()) + { + var property = reader.GetPropertyDefinition(propertyHandle); + Assert.Equal(typeDefHandle, property.GetDeclaringType()); + } + } + } } } diff --git a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs index 5aecb9ddc657de..1f6219d7f4d4ac 100644 --- a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs @@ -246,7 +246,7 @@ private unsafe void ValidateSectionData(PEReader reader) { 0x00, 0x20, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0xD0, 0x38, 0x00, 0x00 + 0x00, 0x39, 0x00, 0x00 }, relocBlob1); AssertEx.Equal(relocBlob1, relocBlob2); diff --git a/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.cs b/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.cs index e3e84712dda4ad..4863acc33c30cb 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.cs @@ -21,6 +21,10 @@ public void MD1() { } public int PE1 { get { return 1; } set { } } event System.Action ED1; + + public class N + { + } } public class E diff --git a/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.dll b/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.dll index 0305c90abe773e..e36de22bdf36fe 100644 Binary files a/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.dll and b/src/libraries/System.Reflection.Metadata/tests/Resources/Misc/Members.dll differ