namespace WoofWare.PawPrint
open System.Reflection
open System.Reflection.Metadata
///
/// Represents the implementation details of an exported type.
/// This discriminated union indicates whether the type is forwarded to another assembly
/// or references another exported type.
///
type ExportedTypeData =
///
/// Indicates the type is forwarded to another assembly.
/// Type forwarders are used to redirect type references to implementations in other assemblies.
///
| ForwardsTo of AssemblyReferenceHandle
///
/// Indicates the type references another exported type within the assembly.
/// This is often used for nested types.
///
| NonForwarded of ExportedTypeHandle
///
/// Represents a type exported from an assembly.
/// Exported types are types that are defined in one module but made visible
/// at the assembly level, or types that are forwarded to another assembly.
///
type ExportedType =
{
///
/// The metadata token handle that uniquely identifies this exported type.
///
Handle : ExportedTypeHandle
///
/// The name of the exported type.
///
Name : string
///
/// The namespace containing the exported type, if any.
/// None if the type is not in a namespace.
///
Namespace : string option
///
/// The metadata handle for the namespace definition containing this type.
///
NamespaceDefn : NamespaceDefinitionHandle
///
/// The type attributes (visibility, inheritance characteristics, etc.) for this exported type.
///
TypeAttrs : TypeAttributes
///
/// The implementation details of this exported type, indicating whether it forwards
/// to another assembly or references another exported type.
///
Data : ExportedTypeData
}
[]
module ExportedType =
let make
(getString : StringHandle -> string)
(handle : ExportedTypeHandle)
(ty : System.Reflection.Metadata.ExportedType)
: ExportedType
=
let name = getString ty.Name
let ns = getString ty.Namespace
let impl = MetadataToken.ofEntityHandle ty.Implementation
let nsDef = ty.NamespaceDefinition
let data =
if ty.IsForwarder then
match impl with
| MetadataToken.AssemblyReference e -> ExportedTypeData.ForwardsTo e
| _ -> failwith $"Expected forwarder type to have an assembly reference: {impl}"
else
match impl with
| MetadataToken.ExportedType impl -> ExportedTypeData.NonForwarded impl
| _ -> failwith $"Expected ExportedType implementation but got {impl}"
{
Handle = handle
Name = name
Namespace = if nsDef.IsNil then None else Some ns
NamespaceDefn = nsDef
TypeAttrs = ty.Attributes
Data = data
}