obfuz/Plugins/dnlib/DotNet/FullNameFactory.cs

2247 lines
77 KiB
C#
Raw Normal View History

2025-04-08 20:31:44 +08:00
// dnlib: See LICENSE.txt for more info
using System.Collections.Generic;
using System.Text;
namespace dnlib.DotNet {
/// <summary>
/// Helps <see cref="FullNameFactory"/> create a name
/// </summary>
public interface IFullNameFactoryHelper {
/// <summary>
/// Checks whether the assembly name should be included when printing
/// the full type name. The assembly name isn't required in custom attributes
/// when the type already exists in the same module as the CA, or if the type
/// exists in mscorlib.
/// </summary>
/// <param name="type">The type (<c>TypeDef</c>, <c>TypeRef</c> or <c>ExportedType</c>)
/// or <c>null</c></param>
/// <returns><c>true</c> if the assembly name must be included, <c>false</c> otherwise</returns>
bool MustUseAssemblyName(IType type);
}
/// <summary>
/// Creates type names, method names, etc.
/// </summary>
public struct FullNameFactory {
const uint MaxArrayRank = 100;
const uint MaxMethodGenParamCount = 200;
const string RECURSION_ERROR_RESULT_STRING = "<<<INFRECURSION>>>";
const string NULLVALUE = "<<<NULL>>>";
readonly StringBuilder sb;
readonly bool isReflection;
readonly IFullNameFactoryHelper helper;
GenericArguments genericArguments;
RecursionCounter recursionCounter;
/// <summary>
/// Checks whether the assembly name should be included when printing the full name.
/// See <see cref="IFullNameFactoryHelper.MustUseAssemblyName"/> for more info.
/// </summary>
/// <param name="module">Owner module</param>
/// <param name="type">The type (<c>TypeDef</c>, <c>TypeRef</c> or <c>ExportedType</c>)
/// or <c>null</c></param>
/// <returns><c>true</c> if the assembly name must be included, <c>false</c> otherwise</returns>
public static bool MustUseAssemblyName(ModuleDef module, IType type) => MustUseAssemblyName(module, type, true);
/// <summary>
/// Checks whether the assembly name should be included when printing the full name.
/// See <see cref="IFullNameFactoryHelper.MustUseAssemblyName"/> for more info.
/// </summary>
/// <param name="module">Owner module</param>
/// <param name="type">The type (<c>TypeDef</c>, <c>TypeRef</c> or <c>ExportedType</c>)
/// or <c>null</c></param>
/// <param name="allowCorlib">If false, don't add an assembly name if it's a type in <paramref name="module"/>,
/// if true, don't add an assembly name if it's a type in <paramref name="module"/> or the corlib.</param>
/// <returns><c>true</c> if the assembly name must be included, <c>false</c> otherwise</returns>
public static bool MustUseAssemblyName(ModuleDef module, IType type, bool allowCorlib) {
if (type is TypeDef td)
return td.Module != module;
var tr = type as TypeRef;
if (tr is null)
return true;
if (tr.ResolutionScope == AssemblyRef.CurrentAssembly)
return false;
if (allowCorlib) {
if (!tr.DefinitionAssembly.IsCorLib())
return true;
// If it's present in this module, but it's a corlib type, then we will need the
// assembly name.
return module.Find(tr) is not null;
}
else
return true;
}
/// <summary>
/// Returns the full name of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string FullName(IType type, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) =>
FullNameSB(type, isReflection, helper, sb).ToString();
/// <summary>
/// Returns the full name of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder FullNameSB(IType type, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) {
if (type is TypeDef td)
return FullNameSB(td, isReflection, helper, sb);
if (type is TypeRef tr)
return FullNameSB(tr, isReflection, helper, sb);
if (type is TypeSpec ts)
return FullNameSB(ts, isReflection, helper, sb);
if (type is TypeSig sig)
return FullNameSB(sig, isReflection, helper, null, null, sb);
if (type is ExportedType et)
return FullNameSB(et, isReflection, helper, sb);
return sb ?? new StringBuilder();
}
/// <summary>
/// Returns the name of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string Name(IType type, bool isReflection, StringBuilder sb) =>
NameSB(type, isReflection, sb).ToString();
/// <summary>
/// Returns the name of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder NameSB(IType type, bool isReflection, StringBuilder sb) {
if (type is TypeDef td)
return NameSB(td, isReflection, sb);
if (type is TypeRef tr)
return NameSB(tr, isReflection, sb);
if (type is TypeSpec ts)
return NameSB(ts, isReflection, sb);
if (type is TypeSig sig)
return NameSB(sig, isReflection, sb);
if (type is ExportedType et)
return NameSB(et, isReflection, sb);
return sb ?? new StringBuilder();
}
/// <summary>
/// Returns the namespace of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string Namespace(IType type, bool isReflection, StringBuilder sb) =>
NamespaceSB(type, isReflection, sb).ToString();
/// <summary>
/// Returns the namespace of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder NamespaceSB(IType type, bool isReflection, StringBuilder sb) {
if (type is TypeDef td)
return NamespaceSB(td, isReflection, sb);
if (type is TypeRef tr)
return NamespaceSB(tr, isReflection, sb);
if (type is TypeSpec ts)
return NamespaceSB(ts, isReflection, sb);
if (type is TypeSig sig)
return NamespaceSB(sig, isReflection, sb);
if (type is ExportedType et)
return NamespaceSB(et, isReflection, sb);
return sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly qualified full name of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>IType</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static string AssemblyQualifiedName(IType type, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
AssemblyQualifiedNameSB(type, helper, sb).ToString();
/// <summary>
/// Returns the assembly qualified full name of a <see cref="IType"/>
/// </summary>
/// <param name="type">The <c>IType</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static StringBuilder AssemblyQualifiedNameSB(IType type, IFullNameFactoryHelper helper, StringBuilder sb) {
if (type is TypeDef td)
return AssemblyQualifiedNameSB(td, helper, sb);
if (type is TypeRef tr)
return AssemblyQualifiedNameSB(tr, helper, sb);
if (type is TypeSpec ts)
return AssemblyQualifiedNameSB(ts, helper, sb);
if (type is TypeSig sig)
return AssemblyQualifiedNameSB(sig, helper, sb);
if (type is ExportedType et)
return AssemblyQualifiedNameSB(et, helper, sb);
return sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a property
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of property</param>
/// <param name="propertySig">Property signature</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Property full name</returns>
public static string PropertyFullName(string declaringType, UTF8String name, CallingConventionSig propertySig, IList<TypeSig> typeGenArgs = null, StringBuilder sb = null) =>
PropertyFullNameSB(declaringType, name, propertySig, typeGenArgs, sb).ToString();
/// <summary>
/// Returns the full name of a property
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of property</param>
/// <param name="propertySig">Property signature</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Property full name</returns>
public static StringBuilder PropertyFullNameSB(string declaringType, UTF8String name, CallingConventionSig propertySig, IList<TypeSig> typeGenArgs, StringBuilder sb) {
var fnc = new FullNameFactory(false, null, sb);
if (typeGenArgs is not null) {
fnc.genericArguments = new GenericArguments();
fnc.genericArguments.PushTypeArgs(typeGenArgs);
}
fnc.CreatePropertyFullName(declaringType, name, propertySig);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a property
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of property</param>
/// <param name="typeDefOrRef">Event type</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Property full name</returns>
public static string EventFullName(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef, IList<TypeSig> typeGenArgs = null, StringBuilder sb = null) =>
EventFullNameSB(declaringType, name, typeDefOrRef, typeGenArgs, sb).ToString();
/// <summary>
/// Returns the full name of a property
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of property</param>
/// <param name="typeDefOrRef">Event type</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Property full name</returns>
public static StringBuilder EventFullNameSB(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef, IList<TypeSig> typeGenArgs, StringBuilder sb) {
var fnc = new FullNameFactory(false, null, sb);
if (typeGenArgs is not null) {
fnc.genericArguments = new GenericArguments();
fnc.genericArguments.PushTypeArgs(typeGenArgs);
}
fnc.CreateEventFullName(declaringType, name, typeDefOrRef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a field
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of field</param>
/// <param name="fieldSig">Field signature</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Field full name</returns>
public static string FieldFullName(string declaringType, string name, FieldSig fieldSig, IList<TypeSig> typeGenArgs = null, StringBuilder sb = null) =>
FieldFullNameSB(declaringType, name, fieldSig, typeGenArgs, sb).ToString();
/// <summary>
/// Returns the full name of a field
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of field</param>
/// <param name="fieldSig">Field signature</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Field full name</returns>
public static StringBuilder FieldFullNameSB(string declaringType, string name, FieldSig fieldSig, IList<TypeSig> typeGenArgs, StringBuilder sb) {
var fnc = new FullNameFactory(false, null, sb);
if (typeGenArgs is not null) {
fnc.genericArguments = new GenericArguments();
fnc.genericArguments.PushTypeArgs(typeGenArgs);
}
fnc.CreateFieldFullName(declaringType, name, fieldSig);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a method
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of method or <c>null</c> if none</param>
/// <param name="methodSig">Method signature</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="methodGenArgs">Method generic arguments or <c>null</c> if none</param>
/// <param name="gppMethod">Generic parameter owner method or <c>null</c></param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Method full name</returns>
public static string MethodFullName(string declaringType, string name, MethodSig methodSig, IList<TypeSig> typeGenArgs = null, IList<TypeSig> methodGenArgs = null, MethodDef gppMethod = null, StringBuilder sb = null) =>
MethodFullNameSB(declaringType, name, methodSig, typeGenArgs, methodGenArgs, gppMethod, sb).ToString();
/// <summary>
/// Returns the full name of a method
/// </summary>
/// <param name="declaringType">Declaring type full name or <c>null</c> if none</param>
/// <param name="name">Name of method or <c>null</c> if none</param>
/// <param name="methodSig">Method signature</param>
/// <param name="typeGenArgs">Type generic arguments or <c>null</c> if none</param>
/// <param name="methodGenArgs">Method generic arguments or <c>null</c> if none</param>
/// <param name="gppMethod">Generic parameter owner method or <c>null</c></param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Method full name</returns>
public static StringBuilder MethodFullNameSB(string declaringType, string name, MethodSig methodSig, IList<TypeSig> typeGenArgs, IList<TypeSig> methodGenArgs, MethodDef gppMethod, StringBuilder sb) {
var fnc = new FullNameFactory(false, null, sb);
if (typeGenArgs is not null || methodGenArgs is not null)
fnc.genericArguments = new GenericArguments();
if (typeGenArgs is not null)
fnc.genericArguments.PushTypeArgs(typeGenArgs);
if (methodGenArgs is not null)
fnc.genericArguments.PushMethodArgs(methodGenArgs);
fnc.CreateMethodFullName(declaringType, name, methodSig, gppMethod);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a property sig
/// </summary>
/// <param name="sig">Property sig</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Property sig full name</returns>
public static string MethodBaseSigFullName(MethodBaseSig sig, StringBuilder sb = null) =>
MethodBaseSigFullNameSB(sig, sb).ToString();
/// <summary>
/// Returns the full name of a property sig
/// </summary>
/// <param name="sig">Property sig</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Property sig full name</returns>
public static StringBuilder MethodBaseSigFullNameSB(MethodBaseSig sig, StringBuilder sb) {
var fnc = new FullNameFactory(false, null, sb);
fnc.CreateMethodFullName(null, null, sig, null);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a sig
/// </summary>
/// <param name="declType">Declaring type or null</param>
/// <param name="name">Name or null</param>
/// <param name="sig">Method sig</param>
/// <param name="gppMethod">Owner method or null</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Sig full name</returns>
public static string MethodBaseSigFullName(string declType, string name, MethodBaseSig sig, MethodDef gppMethod, StringBuilder sb = null) =>
MethodBaseSigFullNameSB(declType, name, sig, gppMethod, sb).ToString();
/// <summary>
/// Returns the full name of a sig
/// </summary>
/// <param name="declType">Declaring type or null</param>
/// <param name="name">Name or null</param>
/// <param name="sig">Method sig</param>
/// <param name="gppMethod">Owner method or null</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>Sig full name</returns>
public static StringBuilder MethodBaseSigFullNameSB(string declType, string name, MethodBaseSig sig, MethodDef gppMethod, StringBuilder sb) {
var fnc = new FullNameFactory(false, null, sb);
fnc.CreateMethodFullName(declType, name, sig, gppMethod);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the namespace of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static string Namespace(TypeRef typeRef, bool isReflection, StringBuilder sb = null) =>
NamespaceSB(typeRef, isReflection, sb).ToString();
/// <summary>
/// Returns the namespace of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static StringBuilder NamespaceSB(TypeRef typeRef, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateNamespace(typeRef, true);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the name of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static string Name(TypeRef typeRef, bool isReflection, StringBuilder sb = null) =>
NameSB(typeRef, isReflection, sb).ToString();
/// <summary>
/// Returns the name of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static StringBuilder NameSB(TypeRef typeRef, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateName(typeRef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string FullName(TypeRef typeRef, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
FullNameSB(typeRef, isReflection, helper, sb).ToString();
/// <summary>
/// Returns the full name of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder FullNameSB(TypeRef typeRef, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, helper, sb);
fnc.CreateFullName(typeRef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static string AssemblyQualifiedName(TypeRef typeRef, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
AssemblyQualifiedNameSB(typeRef, helper, sb).ToString();
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeRef"/>
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static StringBuilder AssemblyQualifiedNameSB(TypeRef typeRef, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(true, helper, sb);
fnc.CreateAssemblyQualifiedName(typeRef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly where this type is defined
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <returns>A <see cref="IAssembly"/> or <c>null</c> if none found</returns>
public static IAssembly DefinitionAssembly(TypeRef typeRef) =>
new FullNameFactory().GetDefinitionAssembly(typeRef);
/// <summary>
/// Gets the scope
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <returns>The <see cref="IScope"/> or <c>null</c> if none found</returns>
public static IScope Scope(TypeRef typeRef) =>
new FullNameFactory().GetScope(typeRef);
/// <summary>
/// Returns the owner module. The type was created from metadata in this module.
/// </summary>
/// <param name="typeRef">The <c>TypeRef</c></param>
/// <returns>A <see cref="ModuleDef"/> or <c>null</c> if none found</returns>
public static ModuleDef OwnerModule(TypeRef typeRef) =>
new FullNameFactory().GetOwnerModule(typeRef);
/// <summary>
/// Returns the namespace of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static string Namespace(TypeDef typeDef, bool isReflection, StringBuilder sb = null) =>
NamespaceSB(typeDef, isReflection, sb).ToString();
/// <summary>
/// Returns the namespace of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static StringBuilder NamespaceSB(TypeDef typeDef, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateNamespace(typeDef, true);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the name of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static string Name(TypeDef typeDef, bool isReflection, StringBuilder sb = null) =>
NameSB(typeDef, isReflection, sb).ToString();
/// <summary>
/// Returns the name of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static StringBuilder NameSB(TypeDef typeDef, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateName(typeDef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string FullName(TypeDef typeDef, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
FullNameSB(typeDef, isReflection, helper, sb).ToString();
/// <summary>
/// Returns the full name of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder FullNameSB(TypeDef typeDef, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, helper, sb);
fnc.CreateFullName(typeDef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static string AssemblyQualifiedName(TypeDef typeDef, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
AssemblyQualifiedNameSB(typeDef, helper, sb).ToString();
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeDef"/>
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static StringBuilder AssemblyQualifiedNameSB(TypeDef typeDef, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(true, helper, sb);
fnc.CreateAssemblyQualifiedName(typeDef);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly where this type is defined
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <returns>A <see cref="IAssembly"/> or <c>null</c> if none found</returns>
public static IAssembly DefinitionAssembly(TypeDef typeDef) =>
new FullNameFactory().GetDefinitionAssembly(typeDef);
/// <summary>
/// Returns the owner module. The type was created from metadata in this module.
/// </summary>
/// <param name="typeDef">The <c>TypeDef</c></param>
/// <returns>A <see cref="ModuleDef"/> or <c>null</c> if none found</returns>
public static ModuleDef OwnerModule(TypeDef typeDef) =>
new FullNameFactory().GetOwnerModule(typeDef);
/// <summary>
/// Returns the namespace of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static string Namespace(TypeSpec typeSpec, bool isReflection, StringBuilder sb = null) =>
NamespaceSB(typeSpec, isReflection, sb).ToString();
/// <summary>
/// Returns the namespace of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static StringBuilder NamespaceSB(TypeSpec typeSpec, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateNamespace(typeSpec, true);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the name of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static string Name(TypeSpec typeSpec, bool isReflection, StringBuilder sb = null) =>
NameSB(typeSpec, isReflection, sb).ToString();
/// <summary>
/// Returns the name of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static StringBuilder NameSB(TypeSpec typeSpec, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateName(typeSpec);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string FullName(TypeSpec typeSpec, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
FullNameSB(typeSpec, isReflection, helper, sb).ToString();
/// <summary>
/// Returns the full name of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder FullNameSB(TypeSpec typeSpec, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, helper, sb);
fnc.CreateFullName(typeSpec);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static string AssemblyQualifiedName(TypeSpec typeSpec, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
AssemblyQualifiedNameSB(typeSpec, helper, sb).ToString();
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeSpec"/>
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static StringBuilder AssemblyQualifiedNameSB(TypeSpec typeSpec, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(true, helper, sb);
fnc.CreateAssemblyQualifiedName(typeSpec);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly where this type is defined
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <returns>A <see cref="IAssembly"/> or <c>null</c> if none found</returns>
public static IAssembly DefinitionAssembly(TypeSpec typeSpec) =>
new FullNameFactory().GetDefinitionAssembly(typeSpec);
/// <summary>
/// Gets the scope type
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <returns>The scope type or <c>null</c> if none found</returns>
public static ITypeDefOrRef ScopeType(TypeSpec typeSpec) =>
new FullNameFactory().GetScopeType(typeSpec);
/// <summary>
/// Gets the scope
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <returns>The <see cref="IScope"/> or <c>null</c> if none found</returns>
public static IScope Scope(TypeSpec typeSpec) =>
new FullNameFactory().GetScope(typeSpec);
/// <summary>
/// Returns the owner module. The type was created from metadata in this module.
/// </summary>
/// <param name="typeSpec">The <c>TypeSpec</c></param>
/// <returns>A <see cref="ModuleDef"/> or <c>null</c> if none found</returns>
public static ModuleDef OwnerModule(TypeSpec typeSpec) =>
new FullNameFactory().GetOwnerModule(typeSpec);
/// <summary>
/// Returns the namespace of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The type sig</param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static string Namespace(TypeSig typeSig, bool isReflection, StringBuilder sb = null) =>
NamespaceSB(typeSig, isReflection, sb).ToString();
/// <summary>
/// Returns the namespace of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The type sig</param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static StringBuilder NamespaceSB(TypeSig typeSig, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateNamespace(typeSig, true);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the name of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The type sig</param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static string Name(TypeSig typeSig, bool isReflection, StringBuilder sb = null) =>
NameSB(typeSig, isReflection, sb).ToString();
/// <summary>
/// Returns the name of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The type sig</param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static StringBuilder NameSB(TypeSig typeSig, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateName(typeSig);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The type sig</param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="typeGenArgs">Type generic args or <c>null</c> if none</param>
/// <param name="methodGenArgs">Method generic args or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string FullName(TypeSig typeSig, bool isReflection, IFullNameFactoryHelper helper = null, IList<TypeSig> typeGenArgs = null, IList<TypeSig> methodGenArgs = null, StringBuilder sb = null) =>
FullNameSB(typeSig, isReflection, helper, typeGenArgs, methodGenArgs, sb).ToString();
/// <summary>
/// Returns the full name of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The type sig</param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="typeGenArgs">Type generic args or <c>null</c> if none</param>
/// <param name="methodGenArgs">Method generic args or <c>null</c> if none</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder FullNameSB(TypeSig typeSig, bool isReflection, IFullNameFactoryHelper helper, IList<TypeSig> typeGenArgs, IList<TypeSig> methodGenArgs, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, helper, sb);
if (typeGenArgs is not null || methodGenArgs is not null)
fnc.genericArguments = new GenericArguments();
if (typeGenArgs is not null)
fnc.genericArguments.PushTypeArgs(typeGenArgs);
if (methodGenArgs is not null)
fnc.genericArguments.PushMethodArgs(methodGenArgs);
fnc.CreateFullName(typeSig);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The <c>TypeSig</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static string AssemblyQualifiedName(TypeSig typeSig, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
AssemblyQualifiedNameSB(typeSig, helper, sb).ToString();
/// <summary>
/// Returns the assembly qualified full name of a <see cref="TypeSig"/>
/// </summary>
/// <param name="typeSig">The <c>TypeSig</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static StringBuilder AssemblyQualifiedNameSB(TypeSig typeSig, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(true, helper, sb);
fnc.CreateAssemblyQualifiedName(typeSig);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly where this type is defined
/// </summary>
/// <param name="typeSig">The <c>TypeSig</c></param>
/// <returns>A <see cref="IAssembly"/> or <c>null</c> if none found</returns>
public static IAssembly DefinitionAssembly(TypeSig typeSig) =>
new FullNameFactory().GetDefinitionAssembly(typeSig);
/// <summary>
/// Gets the scope
/// </summary>
/// <param name="typeSig">The <c>TypeSig</c></param>
/// <returns>The <see cref="IScope"/> or <c>null</c> if none found</returns>
public static IScope Scope(TypeSig typeSig) =>
new FullNameFactory().GetScope(typeSig);
/// <summary>
/// Gets the scope type
/// </summary>
/// <param name="typeSig">The <c>TypeSig</c></param>
/// <returns>The scope type or <c>null</c> if none found</returns>
public static ITypeDefOrRef ScopeType(TypeSig typeSig) =>
new FullNameFactory().GetScopeType(typeSig);
/// <summary>
/// Returns the owner module. The type was created from metadata in this module.
/// </summary>
/// <param name="typeSig">The <c>TypeSig</c></param>
/// <returns>A <see cref="ModuleDef"/> or <c>null</c> if none found</returns>
public static ModuleDef OwnerModule(TypeSig typeSig) =>
new FullNameFactory().GetOwnerModule(typeSig);
/// <summary>
/// Returns the namespace of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static string Namespace(ExportedType exportedType, bool isReflection, StringBuilder sb = null) =>
NamespaceSB(exportedType, isReflection, sb).ToString();
/// <summary>
/// Returns the namespace of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The namespace</returns>
public static StringBuilder NamespaceSB(ExportedType exportedType, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateNamespace(exportedType, true);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the name of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static string Name(ExportedType exportedType, bool isReflection, StringBuilder sb = null) =>
NameSB(exportedType, isReflection, sb).ToString();
/// <summary>
/// Returns the name of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The name</returns>
public static StringBuilder NameSB(ExportedType exportedType, bool isReflection, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, null, sb);
fnc.CreateName(exportedType);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the full name of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static string FullName(ExportedType exportedType, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
FullNameSB(exportedType, isReflection, helper, sb).ToString();
/// <summary>
/// Returns the full name of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="isReflection">Set if output should be compatible with reflection</param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full name</returns>
public static StringBuilder FullNameSB(ExportedType exportedType, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(isReflection, helper, sb);
fnc.CreateFullName(exportedType);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly qualified full name of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static string AssemblyQualifiedName(ExportedType exportedType, IFullNameFactoryHelper helper = null, StringBuilder sb = null) =>
AssemblyQualifiedNameSB(exportedType, helper, sb).ToString();
/// <summary>
/// Returns the assembly qualified full name of a <see cref="ExportedType"/>
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <param name="helper">Helps print the name</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The assembly qualified full name</returns>
public static StringBuilder AssemblyQualifiedNameSB(ExportedType exportedType, IFullNameFactoryHelper helper, StringBuilder sb) {
var fnc = new FullNameFactory(true, helper, sb);
fnc.CreateAssemblyQualifiedName(exportedType);
return fnc.sb ?? new StringBuilder();
}
/// <summary>
/// Returns the assembly where this type is defined
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <returns>A <see cref="IAssembly"/> or <c>null</c> if none found</returns>
public static IAssembly DefinitionAssembly(ExportedType exportedType) =>
new FullNameFactory().GetDefinitionAssembly(exportedType);
/// <summary>
/// Gets the scope type
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <returns>The scope type or <c>null</c> if none found</returns>
public static ITypeDefOrRef ScopeType(ExportedType exportedType) =>
new FullNameFactory().GetScopeType(exportedType);
/// <summary>
/// Gets the scope
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <returns>The <see cref="IScope"/> or <c>null</c> if none found</returns>
public static IScope Scope(ExportedType exportedType) =>
new FullNameFactory().GetScope(exportedType);
/// <summary>
/// Returns the owner module. The type was created from metadata in this module.
/// </summary>
/// <param name="exportedType">The <c>ExportedType</c></param>
/// <returns>A <see cref="ModuleDef"/> or <c>null</c> if none found</returns>
public static ModuleDef OwnerModule(ExportedType exportedType) =>
new FullNameFactory().GetOwnerModule(exportedType);
/// <summary>
/// Returns the full assembly name of a <see cref="IAssembly"/>
/// </summary>
/// <param name="assembly">The <c>IAssembly</c></param>
/// <param name="withToken"><c>true</c> to use public key token in name even if a public key is available</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full assembly name</returns>
public static string AssemblyFullName(IAssembly assembly, bool withToken, StringBuilder sb = null) =>
AssemblyFullNameSB(assembly, withToken, sb).ToString();
/// <summary>
/// Returns the full assembly name of a <see cref="IAssembly"/>
/// </summary>
/// <param name="assembly">The <c>IAssembly</c></param>
/// <param name="withToken"><c>true</c> to use public key token in name even if a public key is available</param>
/// <param name="sb">String builder to use or null</param>
/// <returns>The full assembly name</returns>
public static StringBuilder AssemblyFullNameSB(IAssembly assembly, bool withToken, StringBuilder sb = null) {
var fnc = new FullNameFactory(false, null, sb);
fnc.CreateAssemblyFullName(assembly, withToken);
return fnc.sb ?? new StringBuilder();
}
string Result => sb?.ToString();
FullNameFactory(bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) {
this.sb = sb ?? new StringBuilder();
this.isReflection = isReflection;
this.helper = helper;
genericArguments = null;
recursionCounter = new RecursionCounter();
}
bool MustUseAssemblyName(IType type) {
if (helper is null)
return true;
return helper.MustUseAssemblyName(GetDefinitionType(type));
}
IType GetDefinitionType(IType type) {
if (!recursionCounter.Increment())
return type;
if (type is TypeSpec ts)
type = ts.TypeSig;
if (type is TypeSig sig) {
GenericInstSig gis;
if (sig is TypeDefOrRefSig tdr)
type = GetDefinitionType(tdr.TypeDefOrRef);
else if ((gis = sig as GenericInstSig) is not null)
type = GetDefinitionType(gis.GenericType);
else
type = GetDefinitionType(sig.Next);
}
recursionCounter.Decrement();
return type;
}
void CreateFullName(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef)
CreateFullName((TypeRef)typeDefOrRef);
else if (typeDefOrRef is TypeDef)
CreateFullName((TypeDef)typeDefOrRef);
else if (typeDefOrRef is TypeSpec)
CreateFullName((TypeSpec)typeDefOrRef);
else
sb.Append(NULLVALUE);
}
void CreateNamespace(ITypeDefOrRef typeDefOrRef, bool onlyNamespace) {
if (typeDefOrRef is TypeRef)
CreateNamespace((TypeRef)typeDefOrRef, onlyNamespace);
else if (typeDefOrRef is TypeDef)
CreateNamespace((TypeDef)typeDefOrRef, onlyNamespace);
else if (typeDefOrRef is TypeSpec)
CreateNamespace((TypeSpec)typeDefOrRef, onlyNamespace);
else
sb.Append(NULLVALUE);
}
void CreateName(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef)
CreateName((TypeRef)typeDefOrRef);
else if (typeDefOrRef is TypeDef)
CreateName((TypeDef)typeDefOrRef);
else if (typeDefOrRef is TypeSpec)
CreateName((TypeSpec)typeDefOrRef);
else
sb.Append(NULLVALUE);
}
void CreateAssemblyQualifiedName(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef)
CreateAssemblyQualifiedName((TypeRef)typeDefOrRef);
else if (typeDefOrRef is TypeDef)
CreateAssemblyQualifiedName((TypeDef)typeDefOrRef);
else if (typeDefOrRef is TypeSpec)
CreateAssemblyQualifiedName((TypeSpec)typeDefOrRef);
else
sb.Append(NULLVALUE);
}
void CreateAssemblyQualifiedName(TypeRef typeRef) {
if (typeRef is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
CreateFullName(typeRef);
if (MustUseAssemblyName(typeRef)) {
sb.Append(", ");
CreateAssemblyFullName(GetDefinitionAssembly(typeRef), true);
}
recursionCounter.Decrement();
}
void CreateFullName(TypeRef typeRef) {
if (typeRef is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
if (typeRef.ResolutionScope is TypeRef declaringTypeRef) {
CreateFullName(declaringTypeRef);
AddNestedTypeSeparator();
}
if (AddNamespace(typeRef.Namespace, false))
sb.Append('.');
AddName(typeRef.Name);
recursionCounter.Decrement();
}
void CreateNamespace(TypeRef typeRef, bool onlyNamespace) {
if (typeRef is null) {
sb.Append(NULLVALUE);
return;
}
AddNamespace(typeRef.Namespace, onlyNamespace);
}
void CreateName(TypeRef typeRef) {
if (typeRef is null) {
sb.Append(NULLVALUE);
return;
}
AddName(typeRef.Name);
}
void CreateAssemblyQualifiedName(TypeDef typeDef) {
if (typeDef is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
CreateFullName(typeDef);
if (MustUseAssemblyName(typeDef)) {
sb.Append(", ");
CreateAssemblyFullName(GetDefinitionAssembly(typeDef), true);
}
recursionCounter.Decrement();
}
void CreateFullName(TypeDef typeDef) {
if (typeDef is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
var declaringTypeDef = typeDef.DeclaringType;
if (declaringTypeDef is not null) {
CreateFullName(declaringTypeDef);
AddNestedTypeSeparator();
}
if (AddNamespace(typeDef.Namespace, false))
sb.Append('.');
AddName(typeDef.Name);
recursionCounter.Decrement();
}
void CreateNamespace(TypeDef typeDef, bool onlyNamespace) {
if (typeDef is null) {
sb.Append(NULLVALUE);
return;
}
AddNamespace(typeDef.Namespace, onlyNamespace);
}
void CreateName(TypeDef typeDef) {
if (typeDef is null) {
sb.Append(NULLVALUE);
return;
}
AddName(typeDef.Name);
}
void CreateAssemblyQualifiedName(TypeSpec typeSpec) {
if (typeSpec is null) {
sb.Append(NULLVALUE);
return;
}
CreateAssemblyQualifiedName(typeSpec.TypeSig);
}
void CreateFullName(TypeSpec typeSpec) {
if (typeSpec is null) {
sb.Append(NULLVALUE);
return;
}
CreateFullName(typeSpec.TypeSig);
}
void CreateNamespace(TypeSpec typeSpec, bool onlyNamespace) {
if (typeSpec is null) {
sb.Append(NULLVALUE);
return;
}
CreateNamespace(typeSpec.TypeSig, onlyNamespace);
}
void CreateName(TypeSpec typeSpec) {
if (typeSpec is null) {
sb.Append(NULLVALUE);
return;
}
CreateName(typeSpec.TypeSig);
}
void CreateAssemblyQualifiedName(TypeSig typeSig) {
if (typeSig is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
CreateFullName(typeSig);
if (MustUseAssemblyName(typeSig)) {
sb.Append(", ");
CreateAssemblyFullName(GetDefinitionAssembly(typeSig), true);
}
recursionCounter.Decrement();
}
void CreateFullName(TypeSig typeSig) => CreateTypeSigName(typeSig, TYPESIG_NAMESPACE | TYPESIG_NAME);
void CreateNamespace(TypeSig typeSig, bool onlyNamespace) => CreateTypeSigName(typeSig, TYPESIG_NAMESPACE | (onlyNamespace ? TYPESIG_ONLY_NAMESPACE : 0));
void CreateName(TypeSig typeSig) => CreateTypeSigName(typeSig, TYPESIG_NAME);
TypeSig ReplaceGenericArg(TypeSig typeSig) {
if (genericArguments is null)
return typeSig;
var newTypeSig = genericArguments.Resolve(typeSig);
if (newTypeSig != typeSig)
genericArguments = null;
return newTypeSig;
}
const int TYPESIG_NAMESPACE = 1;
const int TYPESIG_NAME = 2;
const int TYPESIG_ONLY_NAMESPACE = 4;
void CreateTypeSigName(TypeSig typeSig, int flags) {
if (typeSig is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
var old = genericArguments;
typeSig = ReplaceGenericArg(typeSig);
bool createNamespace = (flags & TYPESIG_NAMESPACE) != 0;
bool createName = (flags & TYPESIG_NAME) != 0;
switch (typeSig.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
case ElementType.ValueType:
case ElementType.Class:
if (createNamespace && createName)
CreateFullName(((TypeDefOrRefSig)typeSig).TypeDefOrRef);
else if (createNamespace)
CreateNamespace(((TypeDefOrRefSig)typeSig).TypeDefOrRef, (flags & TYPESIG_ONLY_NAMESPACE) != 0);
else if (createName)
CreateName(((TypeDefOrRefSig)typeSig).TypeDefOrRef);
break;
case ElementType.Ptr:
CreateTypeSigName(typeSig.Next, flags);
if (createName)
sb.Append('*');
break;
case ElementType.ByRef:
CreateTypeSigName(typeSig.Next, flags);
if (createName)
sb.Append('&');
break;
case ElementType.Array:
CreateTypeSigName(typeSig.Next, flags);
if (createName) {
var arraySig = (ArraySig)typeSig;
sb.Append('[');
uint rank = arraySig.Rank;
if (rank > MaxArrayRank)
rank = MaxArrayRank;
if (rank == 0)
sb.Append("<RANK0>"); // Not allowed
else if (rank == 1)
sb.Append('*');
else for (int i = 0; i < (int)rank; i++) {
if (i != 0)
sb.Append(',');
if (!isReflection) {
const int NO_LOWER = int.MinValue;
const uint NO_SIZE = uint.MaxValue;
int lower = i < arraySig.LowerBounds.Count ? arraySig.LowerBounds[i] : NO_LOWER;
uint size = i < arraySig.Sizes.Count ? arraySig.Sizes[i] : NO_SIZE;
if (lower != NO_LOWER) {
sb.Append(lower);
sb.Append("..");
if (size != NO_SIZE)
sb.Append(lower + (int)size - 1);
else
sb.Append('.');
}
}
}
sb.Append(']');
}
break;
case ElementType.SZArray:
CreateTypeSigName(typeSig.Next, flags);
if (createName)
sb.Append("[]");
break;
case ElementType.CModReqd:
CreateTypeSigName(typeSig.Next, flags);
if (!isReflection && createName) {
sb.Append(" modreq(");
if (createNamespace)
CreateFullName(((ModifierSig)typeSig).Modifier);
else
CreateName(((ModifierSig)typeSig).Modifier);
sb.Append(")");
}
break;
case ElementType.CModOpt:
CreateTypeSigName(typeSig.Next, flags);
if (!isReflection && createName) {
sb.Append(" modopt(");
if (createNamespace)
CreateFullName(((ModifierSig)typeSig).Modifier);
else
CreateName(((ModifierSig)typeSig).Modifier);
sb.Append(")");
}
break;
case ElementType.Pinned:
CreateTypeSigName(typeSig.Next, flags);
break;
case ElementType.ValueArray:
CreateTypeSigName(typeSig.Next, flags);
if (createName) {
var valueArraySig = (ValueArraySig)typeSig;
sb.Append(" ValueArray(");
sb.Append(valueArraySig.Size);
sb.Append(')');
}
break;
case ElementType.Module:
CreateTypeSigName(typeSig.Next, flags);
if (createName) {
var moduleSig = (ModuleSig)typeSig;
sb.Append(" Module(");
sb.Append(moduleSig.Index);
sb.Append(')');
}
break;
case ElementType.GenericInst:
var genericInstSig = (GenericInstSig)typeSig;
var typeGenArgs = genericInstSig.GenericArguments;
CreateTypeSigName(genericInstSig.GenericType, flags);
if (createNamespace && createName) {
if (isReflection) {
sb.Append('[');
int i = -1;
int count = typeGenArgs.Count;
for (int j = 0; j < count; j++) {
var genArg = typeGenArgs[j];
i++;
if (i != 0)
sb.Append(',');
bool mustWriteAssembly = MustUseAssemblyName(genArg);
if (mustWriteAssembly)
sb.Append('[');
CreateFullName(genArg);
if (mustWriteAssembly) {
sb.Append(", ");
CreateAssemblyFullName(GetDefinitionAssembly(genArg), true, true);
sb.Append(']');
}
}
sb.Append(']');
}
else {
sb.Append('<');
int i = -1;
int count = typeGenArgs.Count;
for (int j = 0; j < count; j++) {
var genArg = typeGenArgs[j];
i++;
if (i != 0)
sb.Append(',');
CreateFullName(genArg);
}
sb.Append('>');
}
}
break;
case ElementType.Var:
case ElementType.MVar:
if (createName) {
var gs = (GenericSig)typeSig;
var gp = gs.GenericParam;
if (gp is null || !AddName(gp.Name)) {
sb.Append(gs.IsMethodVar ? "!!" : "!");
sb.Append(gs.Number);
}
}
break;
case ElementType.FnPtr:
if (createName) {
if (isReflection)
sb.Append("(fnptr)");
else
CreateMethodFullName(null, null, ((FnPtrSig)typeSig).MethodSig, null);
}
break;
case ElementType.Sentinel:
break;
case ElementType.End:
case ElementType.R:
case ElementType.Internal:
default:
break;
}
genericArguments = old;
recursionCounter.Decrement();
}
void CreateAssemblyQualifiedName(ExportedType exportedType) {
if (exportedType is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
CreateFullName(exportedType);
if (MustUseAssemblyName(exportedType)) {
sb.Append(", ");
CreateAssemblyFullName(GetDefinitionAssembly(exportedType), true);
}
recursionCounter.Decrement();
}
void CreateFullName(ExportedType exportedType) {
if (exportedType is null) {
sb.Append(NULLVALUE);
return;
}
if (!recursionCounter.Increment()) {
sb.Append(RECURSION_ERROR_RESULT_STRING);
return;
}
if (exportedType.Implementation is ExportedType declaringExportedType) {
CreateFullName(declaringExportedType);
AddNestedTypeSeparator();
}
if (AddNamespace(exportedType.TypeNamespace, false))
sb.Append('.');
AddName(exportedType.TypeName);
recursionCounter.Decrement();
}
void CreateNamespace(ExportedType exportedType, bool onlyNamespace) {
if (exportedType is null) {
sb.Append(NULLVALUE);
return;
}
AddNamespace(exportedType.TypeNamespace, onlyNamespace);
}
void CreateName(ExportedType exportedType) {
if (exportedType is null) {
sb.Append(NULLVALUE);
return;
}
AddName(exportedType.TypeName);
}
static string EscapeAssemblyName(UTF8String asmSimpleName) =>
EscapeAssemblyName(UTF8String.ToSystemString(asmSimpleName));
static string EscapeAssemblyName(string asmSimpleName) {
if (asmSimpleName.IndexOf(']') < 0)
return asmSimpleName;
var sb = new StringBuilder(asmSimpleName.Length);
foreach (var c in asmSimpleName) {
if (c == ']')
sb.Append('\\');
sb.Append(c);
}
return sb.ToString();
}
void AddNestedTypeSeparator() {
if (isReflection)
sb.Append('+');
else
sb.Append('/');
}
bool AddNamespace(UTF8String @namespace, bool onlyNamespace) {
if (UTF8String.IsNullOrEmpty(@namespace))
return false;
// If it's reflection and only namespace (instead of full name), it's not escaped
if (onlyNamespace && isReflection)
sb.Append(@namespace.String);
else
AddIdentifier(@namespace.String);
return true;
}
bool AddName(UTF8String name) {
if (UTF8String.IsNullOrEmpty(name))
return false;
AddIdentifier(name.String);
return true;
}
void CreateAssemblyFullName(IAssembly assembly, bool useToken, bool escapeClosingBracket = false) {
if (assembly is null) {
sb.Append(NULLVALUE);
return;
}
foreach (var c in UTF8String.ToSystemStringOrEmpty(assembly.Name)) {
if (c == ',' || c == '=' || (escapeClosingBracket && c == ']'))
sb.Append('\\');
sb.Append(c);
}
if (assembly.Version is not null) {
sb.Append(", Version=");
sb.Append(Utils.CreateVersionWithNoUndefinedValues(assembly.Version));
}
if (assembly.Culture is not null) {
sb.Append(", Culture=");
if (UTF8String.IsNullOrEmpty(assembly.Culture))
sb.Append("neutral");
else
sb.Append(escapeClosingBracket ? EscapeAssemblyName(assembly.Culture) : assembly.Culture.String);
}
var publicKey = assembly.PublicKeyOrToken;
if (useToken)
publicKey = PublicKeyBase.ToPublicKeyToken(publicKey);
sb.Append(", ");
sb.Append(publicKey is null || publicKey is PublicKeyToken ? "PublicKeyToken=" : "PublicKey=");
sb.Append(publicKey is null ? "null" : publicKey.ToString());
if (assembly.IsRetargetable)
sb.Append(", Retargetable=Yes");
if (assembly.IsContentTypeWindowsRuntime)
sb.Append(", ContentType=WindowsRuntime");
}
void AddIdentifier(string id) {
if (isReflection) {
// Periods are not escaped by Reflection, even if they're part of a type name.
foreach (var c in id) {
switch (c) {
case ',':
case '+':
case '&':
case '*':
case '[':
case ']':
case '\\':
sb.Append('\\');
break;
}
sb.Append(c);
}
}
else
sb.Append(id);
}
IAssembly GetDefinitionAssembly(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef tr)
return GetDefinitionAssembly(tr);
if (typeDefOrRef is TypeDef td)
return GetDefinitionAssembly(td);
if (typeDefOrRef is TypeSpec ts)
return GetDefinitionAssembly(ts);
return null;
}
IScope GetScope(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef tr)
return GetScope(tr);
if (typeDefOrRef is TypeDef td)
return td.Scope;
if (typeDefOrRef is TypeSpec ts)
return GetScope(ts);
return null;
}
ITypeDefOrRef GetScopeType(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef tr)
return tr;
if (typeDefOrRef is TypeDef td)
return td;
if (typeDefOrRef is TypeSpec ts)
return GetScopeType(ts);
return null;
}
ModuleDef GetOwnerModule(ITypeDefOrRef typeDefOrRef) {
if (typeDefOrRef is TypeRef tr)
return GetOwnerModule(tr);
if (typeDefOrRef is TypeDef td)
return GetOwnerModule(td);
if (typeDefOrRef is TypeSpec ts)
return GetOwnerModule(ts);
return null;
}
IAssembly GetDefinitionAssembly(TypeRef typeRef) {
if (typeRef is null)
return null;
if (!recursionCounter.Increment())
return null;
IAssembly result;
var scope = typeRef.ResolutionScope;
if (scope is null)
result = null; //TODO: Check ownerModule's ExportedType table
else if (scope is TypeRef)
result = GetDefinitionAssembly((TypeRef)scope);
else if (scope is AssemblyRef)
result = (AssemblyRef)scope;
else if (scope is ModuleRef) {
var ownerModule = GetOwnerModule(typeRef);
result = ownerModule?.Assembly;
}
else if (scope is ModuleDef)
result = ((ModuleDef)scope).Assembly;
else
result = null; // Should never be reached
recursionCounter.Decrement();
return result;
}
IScope GetScope(TypeRef typeRef) {
if (typeRef is null)
return null;
if (!recursionCounter.Increment())
return null;
IScope result;
TypeRef tr;
AssemblyRef asmRef;
ModuleRef modRef;
ModuleDef modDef;
var scope = typeRef.ResolutionScope;
if (scope is null)
result = null; //TODO: Check ownerModule's ExportedType table
else if ((tr = scope as TypeRef) is not null)
result = GetScope(tr);
else if ((asmRef = scope as AssemblyRef) is not null)
result = asmRef;
else if ((modRef = scope as ModuleRef) is not null)
result = modRef;
else if ((modDef = scope as ModuleDef) is not null)
result = modDef;
else
result = null; // Should never be reached
recursionCounter.Decrement();
return result;
}
ModuleDef GetOwnerModule(TypeRef typeRef) {
if (typeRef is null)
return null;
return typeRef.Module;
}
IAssembly GetDefinitionAssembly(TypeDef typeDef) => GetOwnerModule(typeDef)?.Assembly;
ModuleDef GetOwnerModule(TypeDef typeDef) {
if (typeDef is null)
return null;
ModuleDef result = null;
for (int i = recursionCounter.Counter; i < RecursionCounter.MAX_RECURSION_COUNT; i++) {
var declaringType = typeDef.DeclaringType;
if (declaringType is null) {
result = typeDef.Module2;
break;
}
typeDef = declaringType;
}
return result;
}
IAssembly GetDefinitionAssembly(TypeSpec typeSpec) {
if (typeSpec is null)
return null;
return GetDefinitionAssembly(typeSpec.TypeSig);
}
IScope GetScope(TypeSpec typeSpec) {
if (typeSpec is null)
return null;
return GetScope(typeSpec.TypeSig);
}
ITypeDefOrRef GetScopeType(TypeSpec typeSpec) {
if (typeSpec is null)
return null;
return GetScopeType(typeSpec.TypeSig);
}
ModuleDef GetOwnerModule(TypeSpec typeSpec) {
if (typeSpec is null)
return null;
return GetOwnerModule(typeSpec.TypeSig);
}
IAssembly GetDefinitionAssembly(TypeSig typeSig) {
if (typeSig is null)
return null;
if (!recursionCounter.Increment())
return null;
IAssembly result;
var old = genericArguments;
typeSig = ReplaceGenericArg(typeSig);
switch (typeSig.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
case ElementType.ValueType:
case ElementType.Class:
result = GetDefinitionAssembly(((TypeDefOrRefSig)typeSig).TypeDefOrRef);
break;
case ElementType.Ptr:
case ElementType.ByRef:
case ElementType.Array:
case ElementType.SZArray:
case ElementType.CModReqd:
case ElementType.CModOpt:
case ElementType.Pinned:
case ElementType.ValueArray:
case ElementType.Module:
result = GetDefinitionAssembly(typeSig.Next);
break;
case ElementType.GenericInst:
var genericInstSig = (GenericInstSig)typeSig;
var genericType = genericInstSig.GenericType;
result = GetDefinitionAssembly(genericType?.TypeDefOrRef);
break;
case ElementType.Var:
case ElementType.MVar:
case ElementType.FnPtr:
case ElementType.Sentinel:
case ElementType.End:
case ElementType.R:
case ElementType.Internal:
default:
result = null;
break;
}
genericArguments = old;
recursionCounter.Decrement();
return result;
}
ITypeDefOrRef GetScopeType(TypeSig typeSig) {
if (typeSig is null)
return null;
if (!recursionCounter.Increment())
return null;
ITypeDefOrRef result;
var old = genericArguments;
typeSig = ReplaceGenericArg(typeSig);
switch (typeSig.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
case ElementType.ValueType:
case ElementType.Class:
result = GetScopeType(((TypeDefOrRefSig)typeSig).TypeDefOrRef);
break;
case ElementType.Ptr:
case ElementType.ByRef:
case ElementType.Array:
case ElementType.SZArray:
case ElementType.CModReqd:
case ElementType.CModOpt:
case ElementType.Pinned:
case ElementType.ValueArray:
case ElementType.Module:
result = GetScopeType(typeSig.Next);
break;
case ElementType.GenericInst:
result = GetScopeType(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef);
break;
case ElementType.Var:
case ElementType.MVar:
case ElementType.FnPtr:
case ElementType.Sentinel:
case ElementType.End:
case ElementType.R:
case ElementType.Internal:
default:
result = null;
break;
}
genericArguments = old;
recursionCounter.Decrement();
return result;
}
IScope GetScope(TypeSig typeSig) {
if (typeSig is null)
return null;
if (!recursionCounter.Increment())
return null;
IScope result;
var old = genericArguments;
typeSig = ReplaceGenericArg(typeSig);
switch (typeSig.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
case ElementType.ValueType:
case ElementType.Class:
result = GetScope(((TypeDefOrRefSig)typeSig).TypeDefOrRef);
break;
case ElementType.Ptr:
case ElementType.ByRef:
case ElementType.Array:
case ElementType.SZArray:
case ElementType.CModReqd:
case ElementType.CModOpt:
case ElementType.Pinned:
case ElementType.ValueArray:
case ElementType.Module:
result = GetScope(typeSig.Next);
break;
case ElementType.GenericInst:
result = GetScope(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef);
break;
case ElementType.Var:
case ElementType.MVar:
case ElementType.FnPtr:
case ElementType.Sentinel:
case ElementType.End:
case ElementType.R:
case ElementType.Internal:
default:
result = null;
break;
}
genericArguments = old;
recursionCounter.Decrement();
return result;
}
ModuleDef GetOwnerModule(TypeSig typeSig) {
if (typeSig is null)
return null;
if (!recursionCounter.Increment())
return null;
ModuleDef result;
var old = genericArguments;
typeSig = ReplaceGenericArg(typeSig);
switch (typeSig.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
case ElementType.ValueType:
case ElementType.Class:
result = GetOwnerModule(((TypeDefOrRefSig)typeSig).TypeDefOrRef);
break;
case ElementType.Ptr:
case ElementType.ByRef:
case ElementType.Array:
case ElementType.SZArray:
case ElementType.CModReqd:
case ElementType.CModOpt:
case ElementType.Pinned:
case ElementType.ValueArray:
case ElementType.Module:
result = GetOwnerModule(typeSig.Next);
break;
case ElementType.GenericInst:
result = GetOwnerModule(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef);
break;
case ElementType.Var:
case ElementType.MVar:
case ElementType.FnPtr:
case ElementType.Sentinel:
case ElementType.End:
case ElementType.R:
case ElementType.Internal:
default:
result = null;
break;
}
genericArguments = old;
recursionCounter.Decrement();
return result;
}
IAssembly GetDefinitionAssembly(ExportedType exportedType) {
if (exportedType is null)
return null;
if (!recursionCounter.Increment())
return null;
IAssembly result;
AssemblyRef asmRef;
var scope = exportedType.Implementation;
if (scope is ExportedType et)
result = GetDefinitionAssembly(et);
else if ((asmRef = scope as AssemblyRef) is not null)
result = asmRef;
else if (scope is FileDef) {
var ownerModule = GetOwnerModule(exportedType);
result = ownerModule?.Assembly;
}
else
result = null;
recursionCounter.Decrement();
return result;
}
ITypeDefOrRef GetScopeType(ExportedType exportedType) => null;
IScope GetScope(ExportedType exportedType) {
if (exportedType is null)
return null;
if (!recursionCounter.Increment())
return null;
IScope result;
AssemblyRef asmRef;
FileDef file;
var scope = exportedType.Implementation;
if (scope is ExportedType et)
result = GetScope(et);
else if ((asmRef = scope as AssemblyRef) is not null)
result = asmRef;
else if ((file = scope as FileDef) is not null) {
var ownerModule = GetOwnerModule(exportedType);
//TODO: Not all modules' names are equal to the name in FileDef.Name
var modRef = new ModuleRefUser(ownerModule, file.Name);
if (ownerModule is not null)
ownerModule.UpdateRowId(modRef);
result = modRef;
}
else
result = null;
recursionCounter.Decrement();
return result;
}
ModuleDef GetOwnerModule(ExportedType exportedType) {
if (exportedType is null)
return null;
return exportedType.Module;
}
void CreateFieldFullName(string declaringType, string name, FieldSig fieldSig) {
CreateFullName(fieldSig?.Type);
sb.Append(' ');
if (declaringType is not null) {
sb.Append(declaringType);
sb.Append("::");
}
if (name is not null)
sb.Append(name);
}
void CreateMethodFullName(string declaringType, string name, MethodBaseSig methodSig, MethodDef gppMethod) {
if (methodSig is null) {
sb.Append(NULLVALUE);
return;
}
CreateFullName(methodSig.RetType);
sb.Append(' ');
if (declaringType is not null) {
sb.Append(declaringType);
sb.Append("::");
}
if (name is not null)
sb.Append(name);
if (methodSig.Generic) {
sb.Append('<');
uint genParamCount = methodSig.GenParamCount;
if (genParamCount > MaxMethodGenParamCount)
genParamCount = MaxMethodGenParamCount;
for (uint i = 0; i < genParamCount; i++) {
if (i != 0)
sb.Append(',');
CreateFullName(new GenericMVar(i, gppMethod));
}
sb.Append('>');
}
sb.Append('(');
int count = PrintMethodArgList(methodSig.Params, false, false);
PrintMethodArgList(methodSig.ParamsAfterSentinel, count > 0, true);
sb.Append(')');
}
int PrintMethodArgList(IList<TypeSig> args, bool hasPrintedArgs, bool isAfterSentinel) {
if (args is null)
return 0;
if (isAfterSentinel) {
if (hasPrintedArgs)
sb.Append(',');
sb.Append("...");
hasPrintedArgs = true;
}
int count = 0;
int argsCount = args.Count;
for (int i = 0; i < argsCount; i++) {
var arg = args[i];
count++;
if (hasPrintedArgs)
sb.Append(',');
CreateFullName(arg);
hasPrintedArgs = true;
}
return count;
}
void CreatePropertyFullName(string declaringType, UTF8String name, CallingConventionSig propertySig) =>
CreateMethodFullName(declaringType, UTF8String.ToSystemString(name), propertySig as MethodBaseSig, null);
void CreateEventFullName(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef) {
CreateFullName(typeDefOrRef);
sb.Append(' ');
if (declaringType is not null) {
sb.Append(declaringType);
sb.Append("::");
}
if (!UTF8String.IsNull(name))
sb.Append(UTF8String.ToSystemString(name));
}
/// <inheritdoc/>
public override string ToString() => Result;
}
}