| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System.Collections.Generic; |
| | | 5 | | using System.Diagnostics; |
| | | 6 | | using System.Reflection.Internal; |
| | | 7 | | |
| | | 8 | | namespace System.Reflection.Metadata.Ecma335 |
| | | 9 | | { |
| | | 10 | | /// <summary> |
| | | 11 | | /// Provides extension methods for working with certain raw elements of the ECMA-335 metadata tables and heaps. |
| | | 12 | | /// </summary> |
| | | 13 | | public static class MetadataReaderExtensions |
| | | 14 | | { |
| | | 15 | | /// <summary> |
| | | 16 | | /// Returns the number of rows in the specified table. |
| | | 17 | | /// </summary> |
| | | 18 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 19 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="tableIndex"/> is not a valid table index.</exc |
| | | 20 | | public static int GetTableRowCount(this MetadataReader reader, TableIndex tableIndex) |
| | 0 | 21 | | { |
| | 0 | 22 | | if (reader is null) |
| | 0 | 23 | | { |
| | 0 | 24 | | Throw.ArgumentNull(nameof(reader)); |
| | | 25 | | } |
| | | 26 | | |
| | 0 | 27 | | if ((int)tableIndex >= MetadataTokens.TableCount) |
| | 0 | 28 | | { |
| | 0 | 29 | | Throw.TableIndexOutOfRange(); |
| | | 30 | | } |
| | | 31 | | |
| | 0 | 32 | | return reader.TableRowCounts[(int)tableIndex]; |
| | 0 | 33 | | } |
| | | 34 | | |
| | | 35 | | /// <summary> |
| | | 36 | | /// Returns the size of a row in the specified table. |
| | | 37 | | /// </summary> |
| | | 38 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 39 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="tableIndex"/> is not a valid table index.</exc |
| | | 40 | | public static int GetTableRowSize(this MetadataReader reader, TableIndex tableIndex) |
| | 0 | 41 | | { |
| | 0 | 42 | | if (reader is null) |
| | 0 | 43 | | { |
| | 0 | 44 | | Throw.ArgumentNull(nameof(reader)); |
| | | 45 | | } |
| | | 46 | | |
| | 0 | 47 | | return tableIndex switch |
| | 0 | 48 | | { |
| | 0 | 49 | | TableIndex.Module => reader.ModuleTable.RowSize, |
| | 0 | 50 | | TableIndex.TypeRef => reader.TypeRefTable.RowSize, |
| | 0 | 51 | | TableIndex.TypeDef => reader.TypeDefTable.RowSize, |
| | 0 | 52 | | TableIndex.FieldPtr => reader.FieldPtrTable.RowSize, |
| | 0 | 53 | | TableIndex.Field => reader.FieldTable.RowSize, |
| | 0 | 54 | | TableIndex.MethodPtr => reader.MethodPtrTable.RowSize, |
| | 0 | 55 | | TableIndex.MethodDef => reader.MethodDefTable.RowSize, |
| | 0 | 56 | | TableIndex.ParamPtr => reader.ParamPtrTable.RowSize, |
| | 0 | 57 | | TableIndex.Param => reader.ParamTable.RowSize, |
| | 0 | 58 | | TableIndex.InterfaceImpl => reader.InterfaceImplTable.RowSize, |
| | 0 | 59 | | TableIndex.MemberRef => reader.MemberRefTable.RowSize, |
| | 0 | 60 | | TableIndex.Constant => reader.ConstantTable.RowSize, |
| | 0 | 61 | | TableIndex.CustomAttribute => reader.CustomAttributeTable.RowSize, |
| | 0 | 62 | | TableIndex.FieldMarshal => reader.FieldMarshalTable.RowSize, |
| | 0 | 63 | | TableIndex.DeclSecurity => reader.DeclSecurityTable.RowSize, |
| | 0 | 64 | | TableIndex.ClassLayout => reader.ClassLayoutTable.RowSize, |
| | 0 | 65 | | TableIndex.FieldLayout => reader.FieldLayoutTable.RowSize, |
| | 0 | 66 | | TableIndex.StandAloneSig => reader.StandAloneSigTable.RowSize, |
| | 0 | 67 | | TableIndex.EventMap => reader.EventMapTable.RowSize, |
| | 0 | 68 | | TableIndex.EventPtr => reader.EventPtrTable.RowSize, |
| | 0 | 69 | | TableIndex.Event => reader.EventTable.RowSize, |
| | 0 | 70 | | TableIndex.PropertyMap => reader.PropertyMapTable.RowSize, |
| | 0 | 71 | | TableIndex.PropertyPtr => reader.PropertyPtrTable.RowSize, |
| | 0 | 72 | | TableIndex.Property => reader.PropertyTable.RowSize, |
| | 0 | 73 | | TableIndex.MethodSemantics => reader.MethodSemanticsTable.RowSize, |
| | 0 | 74 | | TableIndex.MethodImpl => reader.MethodImplTable.RowSize, |
| | 0 | 75 | | TableIndex.ModuleRef => reader.ModuleRefTable.RowSize, |
| | 0 | 76 | | TableIndex.TypeSpec => reader.TypeSpecTable.RowSize, |
| | 0 | 77 | | TableIndex.ImplMap => reader.ImplMapTable.RowSize, |
| | 0 | 78 | | TableIndex.FieldRva => reader.FieldRvaTable.RowSize, |
| | 0 | 79 | | TableIndex.EncLog => reader.EncLogTable.RowSize, |
| | 0 | 80 | | TableIndex.EncMap => reader.EncMapTable.RowSize, |
| | 0 | 81 | | TableIndex.Assembly => reader.AssemblyTable.RowSize, |
| | 0 | 82 | | TableIndex.AssemblyProcessor => reader.AssemblyProcessorTable.RowSize, |
| | 0 | 83 | | TableIndex.AssemblyOS => reader.AssemblyOSTable.RowSize, |
| | 0 | 84 | | TableIndex.AssemblyRef => reader.AssemblyRefTable.RowSize, |
| | 0 | 85 | | TableIndex.AssemblyRefProcessor => reader.AssemblyRefProcessorTable.RowSize, |
| | 0 | 86 | | TableIndex.AssemblyRefOS => reader.AssemblyRefOSTable.RowSize, |
| | 0 | 87 | | TableIndex.File => reader.FileTable.RowSize, |
| | 0 | 88 | | TableIndex.ExportedType => reader.ExportedTypeTable.RowSize, |
| | 0 | 89 | | TableIndex.ManifestResource => reader.ManifestResourceTable.RowSize, |
| | 0 | 90 | | TableIndex.NestedClass => reader.NestedClassTable.RowSize, |
| | 0 | 91 | | TableIndex.GenericParam => reader.GenericParamTable.RowSize, |
| | 0 | 92 | | TableIndex.MethodSpec => reader.MethodSpecTable.RowSize, |
| | 0 | 93 | | TableIndex.GenericParamConstraint => reader.GenericParamConstraintTable.RowSize, |
| | 0 | 94 | | |
| | 0 | 95 | | // debug tables |
| | 0 | 96 | | TableIndex.Document => reader.DocumentTable.RowSize, |
| | 0 | 97 | | TableIndex.MethodDebugInformation => reader.MethodDebugInformationTable.RowSize, |
| | 0 | 98 | | TableIndex.LocalScope => reader.LocalScopeTable.RowSize, |
| | 0 | 99 | | TableIndex.LocalVariable => reader.LocalVariableTable.RowSize, |
| | 0 | 100 | | TableIndex.LocalConstant => reader.LocalConstantTable.RowSize, |
| | 0 | 101 | | TableIndex.ImportScope => reader.ImportScopeTable.RowSize, |
| | 0 | 102 | | TableIndex.StateMachineMethod => reader.StateMachineMethodTable.RowSize, |
| | 0 | 103 | | TableIndex.CustomDebugInformation => reader.CustomDebugInformationTable.RowSize, |
| | 0 | 104 | | |
| | 0 | 105 | | _ => throw new ArgumentOutOfRangeException(nameof(tableIndex)), |
| | 0 | 106 | | }; |
| | 0 | 107 | | } |
| | | 108 | | |
| | | 109 | | /// <summary> |
| | | 110 | | /// Returns the offset from the start of metadata to the specified table. |
| | | 111 | | /// </summary> |
| | | 112 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 113 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="tableIndex"/> is not a valid table index.</exc |
| | | 114 | | public static unsafe int GetTableMetadataOffset(this MetadataReader reader, TableIndex tableIndex) |
| | 0 | 115 | | { |
| | 0 | 116 | | if (reader is null) |
| | 0 | 117 | | { |
| | 0 | 118 | | Throw.ArgumentNull(nameof(reader)); |
| | | 119 | | } |
| | | 120 | | |
| | 0 | 121 | | return (int)(reader.GetTableMetadataBlock(tableIndex).Pointer - reader.Block.Pointer); |
| | 0 | 122 | | } |
| | | 123 | | |
| | | 124 | | private static MemoryBlock GetTableMetadataBlock(this MetadataReader reader, TableIndex tableIndex) |
| | 0 | 125 | | { |
| | 0 | 126 | | Debug.Assert(reader != null); |
| | | 127 | | |
| | 0 | 128 | | return tableIndex switch |
| | 0 | 129 | | { |
| | 0 | 130 | | TableIndex.Module => reader.ModuleTable.Block, |
| | 0 | 131 | | TableIndex.TypeRef => reader.TypeRefTable.Block, |
| | 0 | 132 | | TableIndex.TypeDef => reader.TypeDefTable.Block, |
| | 0 | 133 | | TableIndex.FieldPtr => reader.FieldPtrTable.Block, |
| | 0 | 134 | | TableIndex.Field => reader.FieldTable.Block, |
| | 0 | 135 | | TableIndex.MethodPtr => reader.MethodPtrTable.Block, |
| | 0 | 136 | | TableIndex.MethodDef => reader.MethodDefTable.Block, |
| | 0 | 137 | | TableIndex.ParamPtr => reader.ParamPtrTable.Block, |
| | 0 | 138 | | TableIndex.Param => reader.ParamTable.Block, |
| | 0 | 139 | | TableIndex.InterfaceImpl => reader.InterfaceImplTable.Block, |
| | 0 | 140 | | TableIndex.MemberRef => reader.MemberRefTable.Block, |
| | 0 | 141 | | TableIndex.Constant => reader.ConstantTable.Block, |
| | 0 | 142 | | TableIndex.CustomAttribute => reader.CustomAttributeTable.Block, |
| | 0 | 143 | | TableIndex.FieldMarshal => reader.FieldMarshalTable.Block, |
| | 0 | 144 | | TableIndex.DeclSecurity => reader.DeclSecurityTable.Block, |
| | 0 | 145 | | TableIndex.ClassLayout => reader.ClassLayoutTable.Block, |
| | 0 | 146 | | TableIndex.FieldLayout => reader.FieldLayoutTable.Block, |
| | 0 | 147 | | TableIndex.StandAloneSig => reader.StandAloneSigTable.Block, |
| | 0 | 148 | | TableIndex.EventMap => reader.EventMapTable.Block, |
| | 0 | 149 | | TableIndex.EventPtr => reader.EventPtrTable.Block, |
| | 0 | 150 | | TableIndex.Event => reader.EventTable.Block, |
| | 0 | 151 | | TableIndex.PropertyMap => reader.PropertyMapTable.Block, |
| | 0 | 152 | | TableIndex.PropertyPtr => reader.PropertyPtrTable.Block, |
| | 0 | 153 | | TableIndex.Property => reader.PropertyTable.Block, |
| | 0 | 154 | | TableIndex.MethodSemantics => reader.MethodSemanticsTable.Block, |
| | 0 | 155 | | TableIndex.MethodImpl => reader.MethodImplTable.Block, |
| | 0 | 156 | | TableIndex.ModuleRef => reader.ModuleRefTable.Block, |
| | 0 | 157 | | TableIndex.TypeSpec => reader.TypeSpecTable.Block, |
| | 0 | 158 | | TableIndex.ImplMap => reader.ImplMapTable.Block, |
| | 0 | 159 | | TableIndex.FieldRva => reader.FieldRvaTable.Block, |
| | 0 | 160 | | TableIndex.EncLog => reader.EncLogTable.Block, |
| | 0 | 161 | | TableIndex.EncMap => reader.EncMapTable.Block, |
| | 0 | 162 | | TableIndex.Assembly => reader.AssemblyTable.Block, |
| | 0 | 163 | | TableIndex.AssemblyProcessor => reader.AssemblyProcessorTable.Block, |
| | 0 | 164 | | TableIndex.AssemblyOS => reader.AssemblyOSTable.Block, |
| | 0 | 165 | | TableIndex.AssemblyRef => reader.AssemblyRefTable.Block, |
| | 0 | 166 | | TableIndex.AssemblyRefProcessor => reader.AssemblyRefProcessorTable.Block, |
| | 0 | 167 | | TableIndex.AssemblyRefOS => reader.AssemblyRefOSTable.Block, |
| | 0 | 168 | | TableIndex.File => reader.FileTable.Block, |
| | 0 | 169 | | TableIndex.ExportedType => reader.ExportedTypeTable.Block, |
| | 0 | 170 | | TableIndex.ManifestResource => reader.ManifestResourceTable.Block, |
| | 0 | 171 | | TableIndex.NestedClass => reader.NestedClassTable.Block, |
| | 0 | 172 | | TableIndex.GenericParam => reader.GenericParamTable.Block, |
| | 0 | 173 | | TableIndex.MethodSpec => reader.MethodSpecTable.Block, |
| | 0 | 174 | | TableIndex.GenericParamConstraint => reader.GenericParamConstraintTable.Block, |
| | 0 | 175 | | |
| | 0 | 176 | | // debug tables |
| | 0 | 177 | | TableIndex.Document => reader.DocumentTable.Block, |
| | 0 | 178 | | TableIndex.MethodDebugInformation => reader.MethodDebugInformationTable.Block, |
| | 0 | 179 | | TableIndex.LocalScope => reader.LocalScopeTable.Block, |
| | 0 | 180 | | TableIndex.LocalVariable => reader.LocalVariableTable.Block, |
| | 0 | 181 | | TableIndex.LocalConstant => reader.LocalConstantTable.Block, |
| | 0 | 182 | | TableIndex.ImportScope => reader.ImportScopeTable.Block, |
| | 0 | 183 | | TableIndex.StateMachineMethod => reader.StateMachineMethodTable.Block, |
| | 0 | 184 | | TableIndex.CustomDebugInformation => reader.CustomDebugInformationTable.Block, |
| | 0 | 185 | | |
| | 0 | 186 | | _ => throw new ArgumentOutOfRangeException(nameof(tableIndex)), |
| | 0 | 187 | | }; |
| | 0 | 188 | | } |
| | | 189 | | |
| | | 190 | | /// <summary> |
| | | 191 | | /// Returns the size of the specified heap. |
| | | 192 | | /// </summary> |
| | | 193 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 194 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="heapIndex"/> is not a valid heap index.</excep |
| | | 195 | | public static int GetHeapSize(this MetadataReader reader, HeapIndex heapIndex) |
| | 0 | 196 | | { |
| | 0 | 197 | | if (reader is null) |
| | 0 | 198 | | { |
| | 0 | 199 | | Throw.ArgumentNull(nameof(reader)); |
| | | 200 | | } |
| | | 201 | | |
| | 0 | 202 | | return reader.GetMetadataBlock(heapIndex).Length; |
| | 0 | 203 | | } |
| | | 204 | | |
| | | 205 | | /// <summary> |
| | | 206 | | /// Returns the offset from the start of metadata to the specified heap. |
| | | 207 | | /// </summary> |
| | | 208 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 209 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="heapIndex"/> is not a valid heap index.</excep |
| | | 210 | | public static unsafe int GetHeapMetadataOffset(this MetadataReader reader, HeapIndex heapIndex) |
| | 0 | 211 | | { |
| | 0 | 212 | | if (reader is null) |
| | 0 | 213 | | { |
| | 0 | 214 | | Throw.ArgumentNull(nameof(reader)); |
| | | 215 | | } |
| | | 216 | | |
| | 0 | 217 | | return (int)(reader.GetMetadataBlock(heapIndex).Pointer - reader.Block.Pointer); |
| | 0 | 218 | | } |
| | | 219 | | |
| | | 220 | | /// <summary> |
| | | 221 | | /// Returns the size of the specified heap. |
| | | 222 | | /// </summary> |
| | | 223 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 224 | | /// <exception cref="ArgumentOutOfRangeException"><paramref name="heapIndex"/> is not a valid heap index.</excep |
| | | 225 | | private static MemoryBlock GetMetadataBlock(this MetadataReader reader, HeapIndex heapIndex) |
| | 0 | 226 | | { |
| | 0 | 227 | | Debug.Assert(reader != null); |
| | | 228 | | |
| | 0 | 229 | | return heapIndex switch |
| | 0 | 230 | | { |
| | 0 | 231 | | HeapIndex.UserString => reader.UserStringHeap.Block, |
| | 0 | 232 | | HeapIndex.String => reader.StringHeap.Block, |
| | 0 | 233 | | HeapIndex.Blob => reader.BlobHeap.Block, |
| | 0 | 234 | | HeapIndex.Guid => reader.GuidHeap.Block, |
| | 0 | 235 | | _ => throw new ArgumentOutOfRangeException(nameof(heapIndex)), |
| | 0 | 236 | | }; |
| | 0 | 237 | | } |
| | | 238 | | |
| | | 239 | | /// <summary> |
| | | 240 | | /// Returns the a handle to the UserString that follows the given one in the UserString heap or a nil handle if |
| | | 241 | | /// </summary> |
| | | 242 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 243 | | public static UserStringHandle GetNextHandle(this MetadataReader reader, UserStringHandle handle) |
| | 0 | 244 | | { |
| | 0 | 245 | | if (reader is null) |
| | 0 | 246 | | { |
| | 0 | 247 | | Throw.ArgumentNull(nameof(reader)); |
| | | 248 | | } |
| | | 249 | | |
| | 0 | 250 | | return reader.UserStringHeap.GetNextHandle(handle); |
| | 0 | 251 | | } |
| | | 252 | | |
| | | 253 | | /// <summary> |
| | | 254 | | /// Returns the a handle to the Blob that follows the given one in the Blob heap or a nil handle if it is the la |
| | | 255 | | /// </summary> |
| | | 256 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 257 | | public static BlobHandle GetNextHandle(this MetadataReader reader, BlobHandle handle) |
| | 0 | 258 | | { |
| | 0 | 259 | | if (reader is null) |
| | 0 | 260 | | { |
| | 0 | 261 | | Throw.ArgumentNull(nameof(reader)); |
| | | 262 | | } |
| | | 263 | | |
| | 0 | 264 | | return reader.BlobHeap.GetNextHandle(handle); |
| | 0 | 265 | | } |
| | | 266 | | |
| | | 267 | | /// <summary> |
| | | 268 | | /// Returns the a handle to the String that follows the given one in the String heap or a nil handle if it is th |
| | | 269 | | /// </summary> |
| | | 270 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 271 | | public static StringHandle GetNextHandle(this MetadataReader reader, StringHandle handle) |
| | 0 | 272 | | { |
| | 0 | 273 | | if (reader is null) |
| | 0 | 274 | | { |
| | 0 | 275 | | Throw.ArgumentNull(nameof(reader)); |
| | | 276 | | } |
| | | 277 | | |
| | 0 | 278 | | return reader.StringHeap.GetNextHandle(handle); |
| | 0 | 279 | | } |
| | | 280 | | |
| | | 281 | | /// <summary> |
| | | 282 | | /// Enumerates entries of EnC log. |
| | | 283 | | /// </summary> |
| | | 284 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 285 | | public static IEnumerable<EditAndContinueLogEntry> GetEditAndContinueLogEntries(this MetadataReader reader) |
| | 0 | 286 | | { |
| | 0 | 287 | | if (reader is null) |
| | 0 | 288 | | { |
| | 0 | 289 | | Throw.ArgumentNull(nameof(reader)); |
| | | 290 | | } |
| | | 291 | | |
| | 0 | 292 | | return Core(reader); |
| | | 293 | | |
| | | 294 | | static IEnumerable<EditAndContinueLogEntry> Core(MetadataReader reader) |
| | 0 | 295 | | { |
| | 0 | 296 | | for (int rid = 1; rid <= reader.EncLogTable.NumberOfRows; rid++) |
| | 0 | 297 | | { |
| | 0 | 298 | | yield return new EditAndContinueLogEntry( |
| | 0 | 299 | | new EntityHandle(reader.EncLogTable.GetToken(rid)), |
| | 0 | 300 | | reader.EncLogTable.GetFuncCode(rid)); |
| | 0 | 301 | | } |
| | 0 | 302 | | } |
| | 0 | 303 | | } |
| | | 304 | | |
| | | 305 | | /// <summary> |
| | | 306 | | /// Enumerates entries of EnC map. |
| | | 307 | | /// </summary> |
| | | 308 | | /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception> |
| | | 309 | | public static IEnumerable<EntityHandle> GetEditAndContinueMapEntries(this MetadataReader reader) |
| | 0 | 310 | | { |
| | 0 | 311 | | if (reader is null) |
| | 0 | 312 | | { |
| | 0 | 313 | | Throw.ArgumentNull(nameof(reader)); |
| | | 314 | | } |
| | | 315 | | |
| | 0 | 316 | | return Core(reader); |
| | | 317 | | |
| | | 318 | | static IEnumerable<EntityHandle> Core(MetadataReader reader) |
| | 0 | 319 | | { |
| | 0 | 320 | | for (int rid = 1; rid <= reader.EncMapTable.NumberOfRows; rid++) |
| | 0 | 321 | | { |
| | 0 | 322 | | yield return new EntityHandle(reader.EncMapTable.GetToken(rid)); |
| | 0 | 323 | | } |
| | 0 | 324 | | } |
| | 0 | 325 | | } |
| | | 326 | | |
| | | 327 | | /// <summary> |
| | | 328 | | /// Enumerate types that define one or more properties. |
| | | 329 | | /// </summary> |
| | | 330 | | /// <returns> |
| | | 331 | | /// The resulting sequence corresponds exactly to entries in PropertyMap table, |
| | | 332 | | /// i.e. n-th returned <see cref="TypeDefinitionHandle"/> is stored in n-th row of PropertyMap. |
| | | 333 | | /// </returns> |
| | | 334 | | public static IEnumerable<TypeDefinitionHandle> GetTypesWithProperties(this MetadataReader reader) |
| | 0 | 335 | | { |
| | 0 | 336 | | if (reader is null) |
| | 0 | 337 | | { |
| | 0 | 338 | | Throw.ArgumentNull(nameof(reader)); |
| | | 339 | | } |
| | | 340 | | |
| | 0 | 341 | | return Core(reader); |
| | | 342 | | |
| | | 343 | | static IEnumerable<TypeDefinitionHandle> Core(MetadataReader reader) |
| | 0 | 344 | | { |
| | 0 | 345 | | for (int rid = 1; rid <= reader.PropertyMapTable.NumberOfRows; rid++) |
| | 0 | 346 | | { |
| | 0 | 347 | | yield return reader.PropertyMapTable.GetParentType(rid); |
| | 0 | 348 | | } |
| | 0 | 349 | | } |
| | 0 | 350 | | } |
| | | 351 | | |
| | | 352 | | /// <summary> |
| | | 353 | | /// Enumerate types that define one or more events. |
| | | 354 | | /// </summary> |
| | | 355 | | /// <returns> |
| | | 356 | | /// The resulting sequence corresponds exactly to entries in EventMap table, |
| | | 357 | | /// i.e. n-th returned <see cref="TypeDefinitionHandle"/> is stored in n-th row of EventMap. |
| | | 358 | | /// </returns> |
| | | 359 | | public static IEnumerable<TypeDefinitionHandle> GetTypesWithEvents(this MetadataReader reader) |
| | 0 | 360 | | { |
| | 0 | 361 | | if (reader is null) |
| | 0 | 362 | | { |
| | 0 | 363 | | Throw.ArgumentNull(nameof(reader)); |
| | | 364 | | } |
| | | 365 | | |
| | 0 | 366 | | return Core(reader); |
| | | 367 | | |
| | | 368 | | static IEnumerable<TypeDefinitionHandle> Core(MetadataReader reader) |
| | 0 | 369 | | { |
| | 0 | 370 | | for (int rid = 1; rid <= reader.EventMapTable.NumberOfRows; rid++) |
| | 0 | 371 | | { |
| | 0 | 372 | | yield return reader.EventMapTable.GetParentType(rid); |
| | 0 | 373 | | } |
| | 0 | 374 | | } |
| | 0 | 375 | | } |
| | | 376 | | |
| | | 377 | | /// <summary> |
| | | 378 | | /// Given a type handle and a raw type kind found in a signature blob determines whether the target type is a va |
| | | 379 | | /// </summary> |
| | | 380 | | public static SignatureTypeKind ResolveSignatureTypeKind(this MetadataReader reader, EntityHandle typeHandle, by |
| | 0 | 381 | | { |
| | 0 | 382 | | if (reader is null) |
| | 0 | 383 | | { |
| | 0 | 384 | | Throw.ArgumentNull(nameof(reader)); |
| | | 385 | | } |
| | | 386 | | |
| | 0 | 387 | | var typeKind = (SignatureTypeKind)rawTypeKind; |
| | | 388 | | |
| | 0 | 389 | | switch (typeKind) |
| | | 390 | | { |
| | | 391 | | case SignatureTypeKind.Unknown: |
| | 0 | 392 | | return SignatureTypeKind.Unknown; |
| | | 393 | | |
| | | 394 | | case SignatureTypeKind.Class: |
| | | 395 | | case SignatureTypeKind.ValueType: |
| | 0 | 396 | | break; |
| | | 397 | | |
| | | 398 | | default: |
| | | 399 | | // If read from metadata by the decoder the value would have been checked already. |
| | | 400 | | // So it is the callers error to pass in an invalid value, not bad metadata. |
| | 0 | 401 | | throw new ArgumentOutOfRangeException(nameof(rawTypeKind)); |
| | | 402 | | } |
| | | 403 | | |
| | 0 | 404 | | switch (typeHandle.Kind) |
| | | 405 | | { |
| | | 406 | | case HandleKind.TypeDefinition: |
| | | 407 | | // WinRT projections don't apply to TypeDefs |
| | 0 | 408 | | return typeKind; |
| | | 409 | | |
| | | 410 | | case HandleKind.TypeReference: |
| | 0 | 411 | | var treatment = reader.GetTypeReference((TypeReferenceHandle)typeHandle).SignatureTreatment; |
| | 0 | 412 | | return treatment switch |
| | 0 | 413 | | { |
| | 0 | 414 | | TypeRefSignatureTreatment.ProjectedToClass => SignatureTypeKind.Class, |
| | 0 | 415 | | TypeRefSignatureTreatment.ProjectedToValueType => SignatureTypeKind.ValueType, |
| | 0 | 416 | | TypeRefSignatureTreatment.None => typeKind, |
| | 0 | 417 | | _ => throw ExceptionUtilities.UnexpectedValue(treatment), |
| | 0 | 418 | | }; |
| | | 419 | | case HandleKind.TypeSpecification: |
| | | 420 | | // TODO: https://github.com/dotnet/runtime/issues/17146 |
| | | 421 | | // We need more work here in differentiating case because instantiations can project class |
| | | 422 | | // to value type as in IReference<T> -> Nullable<T>. Unblocking Roslyn work where the differentiatio |
| | | 423 | | // feature is not used. Note that the use-case of custom-mods will not hit this because there is no |
| | | 424 | | // CLASS | VALUETYPE before the modifier token and so it always comes in unresolved. |
| | 0 | 425 | | return SignatureTypeKind.Unknown; |
| | | 426 | | |
| | | 427 | | default: |
| | 0 | 428 | | throw new ArgumentOutOfRangeException(nameof(typeHandle), SR.Format(SR.UnexpectedHandleKind, typeHan |
| | | 429 | | } |
| | 0 | 430 | | } |
| | | 431 | | } |
| | | 432 | | } |
| | | 433 | | |