Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GetDeclaringType to PropertyDefinition and EventDefinition. #111646

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<System.Reflection.Metadata.EventDefinitionHandle>
{
Expand Down Expand Up @@ -2135,6 +2136,7 @@ public readonly partial struct PropertyDefinition
public System.Reflection.Metadata.MethodSignature<TType> DecodeSignature<TType, TGenericContext>(System.Reflection.Metadata.ISignatureTypeProvider<TType, TGenericContext> 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<System.Reflection.Metadata.PropertyDefinitionHandle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,47 @@ 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);
}

int value = this.GetEventListStartFor(row);
if (value == eventRowId)
{
while (row < numOfRows)
{
int newRow = row + 1;
value = this.GetEventListStartFor(newRow);
if (value == eventRowId)
{
row = newRow;
}
else
{
break;
}
}
}

return GetParentType(row);
}
}

internal readonly struct EventPtrTableReader
Expand Down Expand Up @@ -1343,6 +1384,47 @@ 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);
}

int value = this.GetPropertyListStartFor(row);
if (value == propertyRowId)
{
while (row < numOfRows)
{
int newRow = row + 1;
value = this.GetPropertyListStartFor(newRow);
if (value == propertyRowId)
{
row = newRow;
}
else
{
break;
}
}
}

Comment on lines +1408 to +1425
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this is needed for property map table. Unlike typedef table that this code was copied from, the property map should not have rows for types with no properties.

Dtto for event map

return GetParentType(row);
}
}

internal readonly struct PropertyPtrTableReader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ public CustomAttributeHandleCollection GetCustomAttributes()
return new CustomAttributeHandleCollection(_reader, Handle);
}

/// <summary>
/// Returns a handle to the type that declares this event.
/// </summary>
public TypeDefinitionHandle GetDeclaringType()
{
return _reader.GetDeclaringType(Handle);
}

public EventAccessors GetAccessors()
{
int adder = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public TType DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TTyp
return decoder.DecodeFieldSignature(ref blob);
}

/// <summary>
/// Returns a handle to the type that declares this field.
/// </summary>
public TypeDefinitionHandle GetDeclaringType()
{
return _reader.GetDeclaringType(Handle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public MethodImplAttributes ImplAttributes
}
}

/// <summary>
/// Returns a handle to the type that declares this method.
/// </summary>
public TypeDefinitionHandle GetDeclaringType()
{
return _reader.GetDeclaringType(Handle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ public CustomAttributeHandleCollection GetCustomAttributes()
return new CustomAttributeHandleCollection(_reader, Handle);
}

/// <summary>
/// Returns a handle to the type that declares this property.
/// </summary>
public TypeDefinitionHandle GetDeclaringType()
{
return _reader.GetDeclaringType(Handle);
}

public PropertyAccessors GetAccessors()
{
int getter = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,41 @@ public void ValidateTypeDefinitionIsNestedWindowsProjection()
Assert.Equal(typeDef.Attributes.IsNested(), typeDef.IsNested);
}
}

[Fact]
public void ValidateDeclaringType()
{
var reader = MetadataReaderTests.GetMetadataReader(Misc.Members);

foreach (var typeDefHandle in reader.TypeDefinitions)
{
var typeDef = reader.GetTypeDefinition(typeDefHandle);
foreach (var nestedTypeHandle in typeDef.GetNestedTypes())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a sanity check here to make sure that these foreach statement actually loop through at least one? Like:

Assert.True(typeDef.GetNestedTypes().Length > 0);

{
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());
}
}
}
}
}