using System; using System.Collections.Generic; using System.Text; using Mono.Cecil; namespace zzzUnity.Burst.CodeGen { /// /// Provides some Cecil Extensions. /// #if BURST_COMPILER_SHARED public #else internal #endif static class CecilExtensions { public static void BuildAssemblyQualifiedName(this TypeReference type, StringBuilder builder) { if (type == null) throw new ArgumentNullException(nameof(type)); TypeReference elementType; type.BuildReflectionFullName(builder, out elementType, assemblyQualified: true); if (!(elementType is GenericParameter)) { // Recover assembly reference from scope first (e.g for types imported), otherwise from Module.Assembly var assemblyReference = elementType.Scope as AssemblyNameReference ?? elementType.Module.Assembly?.Name; builder.Append(", ").Append(assemblyReference); } } public static void BuildReflectionFullName(this TypeReference type, StringBuilder builder, bool assemblyQualified) { BuildReflectionFullName(type, builder, out _, assemblyQualified); } public static void BuildReflectionFullName(this TypeReference type, StringBuilder builder, out TypeReference elementType, bool assemblyQualified) { if (type == null) throw new ArgumentNullException(nameof(type)); if (type is PointerType pointerType) { pointerType.ElementType.BuildReflectionFullName(builder, out elementType, assemblyQualified); builder.Append("*"); } else if (type is PinnedType pinnedType) { pinnedType.ElementType.BuildReflectionFullName(builder, out elementType, assemblyQualified); builder.Append(" pinned"); } else if (type is ByReferenceType byReferenceType) { byReferenceType.ElementType.BuildReflectionFullName(builder, out elementType, assemblyQualified); builder.Append("&"); } else if (type is ArrayType arrayType) { arrayType.ElementType.BuildReflectionFullName(builder, out elementType, assemblyQualified); builder.Append("[]"); } else if (type is GenericParameter genericParameter) { elementType = type; builder.Append(genericParameter.Type == GenericParameterType.Method ? "!!" : "!"); builder.Append(genericParameter.Position); } else { elementType = type; var types = new List(); var declaringType = type; while (declaringType != null) { types.Add(declaringType); declaringType = declaringType.DeclaringType; } var baseType = types[types.Count - 1]; if (!string.IsNullOrEmpty(baseType.Namespace)) { builder.Append(baseType.Namespace); builder.Append("."); } builder.Append(baseType.Name); for (int i = types.Count - 2; i >= 0; i--) { var nestedType = types[i]; builder.Append("+").Append(nestedType.Name); } if (elementType is GenericInstanceType genericInstanceType && genericInstanceType.HasGenericArguments) { builder.Append("["); for (var i = 0; i < genericInstanceType.GenericArguments.Count; i++) { var genericArgument = genericInstanceType.GenericArguments[i]; if (i > 0) { builder.Append(","); } if (assemblyQualified) { builder.Append("["); genericArgument.BuildAssemblyQualifiedName(builder); builder.Append("]"); } else { genericArgument.BuildReflectionFullName(builder, out var _, assemblyQualified: true); } } builder.Append("]"); } } } } }