13 Commits
Author SHA1 Message Date
ds5678 e871881517 Update project version to 1.2.0
Bump the version number in the project properties from 1.1.6 to 1.2.0.
2025-09-08 14:30:19 -07:00
ds5678 c1eceeda51 AsmResolver 6 beta 4
Resolves #2
2025-09-08 14:25:12 -07:00
ds5678 44996e27ff Update NuGet packages in project files
Updated several NuGet packages in `AssetRipper.CIL.Tests.csproj`:
- Microsoft.NET.Test.Sdk: 17.13.0 -> 17.14.1
- NUnit: 4.3.2 -> 4.4.0
- NUnit.Analyzers: 4.6.0 -> 4.10.0
- NUnit3TestAdapter: 5.0.0 -> 5.1.0

Also updated `System.Runtime.CompilerServices.Unsafe` in `AssetRipper.CIL.csproj` from version 6.1.1 to 6.1.2.
2025-09-08 14:20:20 -07:00
ds5678 0039dc95b3 Use IsAccessibleFromType when searching for a base constructor
* Related: #2
2025-04-08 15:06:57 -07:00
ds5678 0953640bf1 Add ReplaceMethodBodyWithThrowNull method
Introduces a new method `ReplaceMethodBodyWithThrowNull` in the `MethodDefinitionExtensions` class. This method modifies the body of a managed method to throw a `null` exception, with appropriate XML documentation. It includes checks to ensure the method is managed and has a body before making changes.
2025-03-23 20:20:02 -07:00
ds5678 c1e8657d67 Ensure references are imported 2025-03-21 19:23:54 -07:00
ds5678 09db4f64ae Bump version to 1.1.6 2025-03-20 23:03:22 -07:00
ds5678 0af62d2590 Support generating enums 2025-03-20 23:01:02 -07:00
ds5678 cc71118bfb Update package versions in project files
- Bump `coverlet.collector` to version `6.0.4`
- Bump `Microsoft.NET.Test.Sdk` to version `17.13.0`
- Bump `NUnit3TestAdapter` to version `5.0.0`
- Bump `AsmResolver.DotNet` to version `6.0.0-beta.3`
2025-03-20 22:01:39 -07:00
ds5678 21d8f70781 Add more extensions 2025-03-20 22:00:07 -07:00
ds5678 75a48b3ce0 Do not attempt to initialize fixed buffers 2025-03-20 21:11:29 -07:00
ds5678 c164acde5f Bump version 2025-01-23 14:28:47 -08:00
ds5678 8935137a6f Expand type check to include PointerTypeSignature
Modified conditions in CilInstructionCollectionExtensions.cs to check for both ByReferenceTypeSignature and PointerTypeSignature. This ensures null references are added and stored for both types.
2025-01-23 14:27:38 -08:00
16 changed files with 470 additions and 30 deletions

No files matched your search

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.3">
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit.Analyzers" Version="4.6.0">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="NUnit" Version="4.4.0" />
<PackageReference Include="NUnit.Analyzers" Version="4.10.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="NUnit3TestAdapter" Version="5.1.0" />
</ItemGroup>
<ItemGroup>
+1 -1
View File
@@ -94,7 +94,7 @@ public class LoadIndirectTests
private static void AssertCorrectLoadIndirect(TypeSignature typeToLoad, CilCode expectedOpCode)
{
MethodDefinition method = new MethodDefinition("Test", MethodAttributes.Public | MethodAttributes.Static, null);
method.CilMethodBody = new(method);
method.CilMethodBody = new();
CilInstructionCollection instructions = method.CilMethodBody.Instructions;
instructions.AddLoadIndirect(typeToLoad);
Assert.That(instructions, Has.Count.EqualTo(1));
+1 -1
View File
@@ -94,7 +94,7 @@ public class StoreIndirectTests
private static void AssertCorrectStoreIndirect(TypeSignature typeToStore, CilCode expectedOpCode)
{
MethodDefinition method = new MethodDefinition("Test", MethodAttributes.Public | MethodAttributes.Static, null);
method.CilMethodBody = new(method);
method.CilMethodBody = new();
CilInstructionCollection instructions = method.CilMethodBody.Instructions;
instructions.AddStoreIndirect(typeToStore);
Assert.That(instructions, Has.Count.EqualTo(1));
+2 -1
View File
@@ -15,8 +15,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AsmResolver.DotNet" Version="6.0.0-beta.1" />
<PackageReference Include="AsmResolver.DotNet" Version="6.0.0-beta.4" />
<PackageReference Include="PolySharp" Version="1.15.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
</ItemGroup>
<ItemGroup>
@@ -22,7 +22,7 @@ public static class CilInstructionCollectionExtensions
{
instructions.AddDefaultPrimitiveValue(corLibTypeSignature);
}
else if (type is ByReferenceTypeSignature)
else if (type is ByReferenceTypeSignature or PointerTypeSignature)
{
instructions.AddNullRef();
}
@@ -43,7 +43,7 @@ public static class CilInstructionCollectionExtensions
{
instructions.InitializeDefaultPrimitiveValue(corLibTypeSignature, localVariable);
}
else if (type is ByReferenceTypeSignature)
else if (type is ByReferenceTypeSignature or PointerTypeSignature)
{
instructions.AddNullRef();
instructions.Add(CilOpCodes.Stloc, localVariable);
@@ -0,0 +1,83 @@
using AsmResolver.DotNet.Signatures;
namespace AssetRipper.CIL;
internal static class CorLibTypeFactoryExtensions
{
public static CorLibTypeSignature? FromType(this CorLibTypeFactory factory, Type type)
{
if (type == typeof(bool))
{
return factory.Boolean;
}
if (type == typeof(char))
{
return factory.Char;
}
if (type == typeof(byte))
{
return factory.Byte;
}
if (type == typeof(sbyte))
{
return factory.SByte;
}
if (type == typeof(short))
{
return factory.Int16;
}
if (type == typeof(ushort))
{
return factory.UInt16;
}
if (type == typeof(int))
{
return factory.Int32;
}
if (type == typeof(uint))
{
return factory.UInt32;
}
if (type == typeof(long))
{
return factory.Int64;
}
if (type == typeof(ulong))
{
return factory.UInt64;
}
if (type == typeof(float))
{
return factory.Single;
}
if (type == typeof(double))
{
return factory.Double;
}
if (type == typeof(string))
{
return factory.String;
}
if (type == typeof(IntPtr))
{
return factory.IntPtr;
}
if (type == typeof(UIntPtr))
{
return factory.UIntPtr;
}
if (type == typeof(object))
{
return factory.Object;
}
if (type == typeof(void))
{
return factory.Void;
}
if (type == typeof(TypedReference))
{
return factory.TypedReference;
}
return null;
}
}
@@ -0,0 +1,15 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
namespace AssetRipper.CIL;
public static class CustomAttributeExtensions
{
public static CustomAttributeArgument AddFixedArgument(this CustomAttribute attribute, TypeSignature paramType, object paramValue)
{
attribute.Signature ??= new();
CustomAttributeArgument argument = new(paramType, paramValue);
attribute.Signature.FixedArguments.Add(argument);
return argument;
}
}
@@ -57,4 +57,9 @@ public static class FieldDefinitionExtensions
return false;
}
}
public static bool IsFixedBuffer(this FieldDefinition field)
{
return field.HasCustomAttribute("System.Runtime.CompilerServices", "FixedBufferAttribute");
}
}
@@ -0,0 +1,87 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
using System.Runtime.CompilerServices;
namespace AssetRipper.CIL;
public static class IHasCustomAttributeExtensions
{
public static CustomAttribute AddCustomAttribute(this IHasCustomAttribute _this, IMethodDefOrRef constructor)
{
if (constructor is ICustomAttributeType usableConstructor)
{
CustomAttribute attribute = new(usableConstructor);
_this.CustomAttributes.Add(attribute);
return attribute;
}
else
{
throw new ArgumentException("Constructor is not ICustomAttributeType", nameof(constructor));
}
}
public static CustomAttribute AddCustomAttribute(this IHasCustomAttribute _this, IMethodDefOrRef constructor, TypeSignature paramType, object paramValue)
{
CustomAttribute attribute = _this.AddCustomAttribute(constructor);
attribute.AddFixedArgument(paramType, paramValue);
return attribute;
}
internal static ModuleDefinition GetModule(this IHasCustomAttribute _this)
{
return (_this as IModuleProvider)?.ContextModule ?? throw new ArgumentException("Entity does not have a module", nameof(_this));
}
public static CustomAttribute AddFlagsAttribute(this IHasCustomAttribute _this)
{
ModuleDefinition module = _this.GetModule();
if (module.TryGetTopLevelType("System", nameof(FlagsAttribute), out TypeDefinition? flagsType))
{
return _this.AddCustomAttribute(flagsType.GetDefaultConstructor());
}
else
{
TypeReference flagsTypeRef = new(module.CorLibTypeFactory.CorLibScope, "System", nameof(FlagsAttribute));
MemberReference constructor = new(flagsTypeRef, ".ctor", MethodSignature.CreateInstance(module.CorLibTypeFactory.Void));
return _this.AddCustomAttribute(module.DefaultImporter.ImportMethod(constructor));
}
}
/// <summary>
/// Applies the <see cref="CompilerGeneratedAttribute"/>
/// </summary>
/// <param name="_this">The entity on which to apply the attribute</param>
/// <returns>The resulting custom attribute</returns>
public static CustomAttribute AddCompilerGeneratedAttribute(this IHasCustomAttribute _this)
{
ModuleDefinition module = _this.GetModule();
if (module.TryGetTopLevelType("System.Runtime.CompilerServices", nameof(CompilerGeneratedAttribute), out TypeDefinition? compilerGeneratedType))
{
return _this.AddCustomAttribute(compilerGeneratedType.GetDefaultConstructor());
}
else
{
AssemblyReference compilerServicesAssembly = GetOrAddReferenceToSystemRuntimeCompilerServices(module);
TypeReference compilerGeneratedTypeRef = new(compilerServicesAssembly, "System.Runtime.CompilerServices", nameof(CompilerGeneratedAttribute));
MemberReference constructor = new(compilerGeneratedTypeRef, ".ctor", MethodSignature.CreateInstance(module.CorLibTypeFactory.Void));
return _this.AddCustomAttribute(module.DefaultImporter.ImportMethod(constructor));
}
static AssemblyReference GetOrAddReferenceToSystemRuntimeCompilerServices(ModuleDefinition module)
{
AssemblyReference? compilerServicesAssembly = module.AssemblyReferences.FirstOrDefault(a => a.Name == "System.Runtime.CompilerServices");
if (compilerServicesAssembly is null)
{
Version version = module.CorLibTypeFactory.CorLibScope.GetAssembly()?.Version ?? new Version(0, 0, 0, 0);
compilerServicesAssembly = new("System.Runtime.CompilerServices", version);
module.AssemblyReferences.Add(compilerServicesAssembly);
}
return compilerServicesAssembly;
}
}
}
@@ -11,7 +11,7 @@ public sealed class SwitchRemover : ICilManipulator
{
public void Execute(CilManipulationContext context)
{
ModuleDefinition? module = context.Instructions.Owner.Owner.Module;
ModuleDefinition? module = context.Instructions.Owner.Owner?.DeclaringModule;
if (module is null)
{
return;
@@ -1,6 +1,8 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Code.Cil;
using AsmResolver.DotNet.Collections;
using AsmResolver.DotNet.Signatures;
using AsmResolver.PE.DotNet.Cil;
using AsmResolver.PE.DotNet.Metadata.Tables;
using System.Diagnostics.CodeAnalysis;
@@ -23,6 +25,25 @@ public static class MethodDefinitionExtensions
MethodStubber.FillMethodBodyWithStub(methodDefinition);
}
/// <summary>
/// Replaces the method body with: <code>throw null;</code>
/// </summary>
/// <remarks>
/// If the method is not managed or should not have a body, this method does nothing.
/// </remarks>
/// <param name="methodDefinition">The method to modify.</param>
public static void ReplaceMethodBodyWithThrowNull(this MethodDefinition methodDefinition)
{
if (!methodDefinition.IsManagedMethodWithBody())
{
return;
}
methodDefinition.CilMethodBody = new();
CilInstructionCollection methodInstructions = methodDefinition.CilMethodBody.Instructions;
methodInstructions.Add(CilOpCodes.Ldnull);
methodInstructions.Add(CilOpCodes.Throw);
}
public static bool IsInstance(this MethodDefinition methodDefinition)
{
return !methodDefinition.IsStatic;
+8 -15
View File
@@ -16,7 +16,7 @@ internal static class MethodStubber
return;
}
methodDefinition.CilMethodBody = new(methodDefinition);
methodDefinition.CilMethodBody = new();
CilInstructionCollection methodInstructions = methodDefinition.CilMethodBody.Instructions;
if (methodDefinition.IsAutoPropertyGetMethod(out FieldDefinition? backingField))
@@ -55,7 +55,7 @@ internal static class MethodStubber
TypeDefinition declaringType = methodDefinition.DeclaringType!;
foreach (FieldDefinition field in declaringType.Fields)
{
if (field.IsStatic || field.Signature is null)
if (field.IsStatic || field.Signature is null || field.IsFixedBuffer())
{
continue;
}
@@ -131,13 +131,13 @@ internal static class MethodStubber
return null;
}
MethodDefinition? baseConstructor = GetFirstCompatibleConstructor(methodDefinition.DeclaringType, baseTypeResolved);
if (baseConstructor is null || methodDefinition.DeclaringType.Module is null)
if (baseConstructor is null || methodDefinition.DeclaringType.DeclaringModule is null)
{
return null;
}
else
{
return methodDefinition.DeclaringType.Module.DefaultImporter.ImportMethod(baseConstructor);
return methodDefinition.DeclaringType.DeclaringModule.DefaultImporter.ImportMethod(baseConstructor);
}
}
else if (baseType is TypeSpecification baseTypeSpec)
@@ -153,11 +153,11 @@ internal static class MethodStubber
return null;
}
MethodDefinition? baseConstructor = GetFirstCompatibleConstructor(methodDefinition.DeclaringType, baseTypeResolved);
if (baseConstructor is null || methodDefinition.DeclaringType.Module is null)
if (baseConstructor is null || methodDefinition.DeclaringType.DeclaringModule is null)
{
return null;
}
IMethodDefOrRef baseConstructorImported = methodDefinition.DeclaringType.Module.DefaultImporter.ImportMethod(baseConstructor);
IMethodDefOrRef baseConstructorImported = methodDefinition.DeclaringType.DeclaringModule.DefaultImporter.ImportMethod(baseConstructor);
return new MemberReference(baseType, baseConstructorImported.Name, baseConstructorImported.Signature);
}
@@ -165,14 +165,7 @@ internal static class MethodStubber
static MethodDefinition? GetFirstCompatibleConstructor(TypeDefinition declaringType, TypeDefinition baseType)
{
if (declaringType.Module == baseType.Module)
{
return baseType.Methods.FirstOrDefault(m => m.IsInstanceConstructor() && !m.IsPrivate);
}
else
{
return baseType.Methods.FirstOrDefault(m => m.IsInstanceConstructor() && (m.IsFamily || m.IsPublic));
}
return baseType.Methods.FirstOrDefault(m => m.IsInstanceConstructor() && m.IsAccessibleFromType(declaringType));
}
}
@@ -190,7 +183,7 @@ internal static class MethodStubber
}
TypeSignature[] typeArguments = Enumerable.Range(0, field.DeclaringType.GenericParameters.Count)
.Select(i => new GenericParameterSignature(field.Module, GenericParameterType.Type, i))
.Select(i => new GenericParameterSignature(field.DeclaringModule, GenericParameterType.Type, i))
.ToArray();
return new MemberReference(field.DeclaringType.MakeGenericInstanceType(typeArguments).ToTypeDefOrRef(), field.Name, field.Signature);
@@ -0,0 +1,94 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
using AsmResolver.PE.DotNet.Metadata.Tables;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace AssetRipper.CIL;
public static class ModuleDefinitionExtensions
{
public static bool TryGetTopLevelType(this ModuleDefinition module, string? @namespace, string? name, [NotNullWhen(true)] out TypeDefinition? type)
{
type = module.TopLevelTypes.FirstOrDefault(t => t.Namespace == @namespace && t.Name == name);
return type != null;
}
public static bool HasTopLevelType(this ModuleDefinition module, string? @namespace, string? name)
{
return module.TryGetTopLevelType(@namespace, name, out _);
}
public static TypeDefinition AddEmptyEnum(this ModuleDefinition module, string? @namespace, string? name, Visibility visibility, ElementType underlyingType)
{
CorLibTypeSignature underlyingTypeSignature = module.CorLibTypeFactory.FromElementType(underlyingType)
?? throw new ArgumentOutOfRangeException(nameof(underlyingType), underlyingType, null);
TypeReference baseType = new(module.CorLibTypeFactory.CorLibScope, "System", "Enum");
TypeDefinition type = new(@namespace, name, visibility.ToTypeAttributes() | TypeAttributes.Sealed, module.DefaultImporter.ImportType(baseType));
module.TopLevelTypes.Add(type);
AddEnumValue(type, underlyingTypeSignature);
return type;
static void AddEnumValue(TypeDefinition type, TypeSignature underlyingType)
{
FieldSignature fieldSignature = new FieldSignature(underlyingType);
FieldDefinition fieldDef = new FieldDefinition("value__", FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RuntimeSpecialName, fieldSignature);
type.Fields.Add(fieldDef);
}
}
public static TypeDefinition AddExistingEnum<T>(this ModuleDefinition module) where T : struct, Enum
{
Type underlyingType = Enum.GetUnderlyingType(typeof(T));
bool isSigned = underlyingType == typeof(sbyte) || underlyingType == typeof(short) || underlyingType == typeof(int) || underlyingType == typeof(long);
CorLibTypeSignature underlyingTypeSignature = module.CorLibTypeFactory.FromType(underlyingType)
?? throw new InvalidOperationException($"Failed to get underlying type for {typeof(T)}");
TypeDefinition type = module.AddEmptyEnum(typeof(T).Namespace, typeof(T).Name, VisibilityExtensions.GetVisibility(typeof(T)), underlyingTypeSignature.ElementType);
foreach (T value in GetValues())
{
type.AddEnumField(value.ToString(), ToInt64(value));
}
if (typeof(T).CustomAttributes.Any(a => a.AttributeType is { Namespace: "System", Name: nameof(FlagsAttribute) }))
{
type.AddFlagsAttribute();
}
return type;
static IEnumerable<T> GetValues()
{
#if NETSTANDARD
return Enum.GetValues(typeof(T)).Cast<T>();
#else
return Enum.GetValues<T>();
#endif
}
long ToInt64(T value)
{
if (Unsafe.SizeOf<T>() == sizeof(long))
{
return Unsafe.As<T, long>(ref value);
}
else if (Unsafe.SizeOf<T>() == sizeof(int))
{
return isSigned ? Unsafe.As<T, int>(ref value) : Unsafe.As<T, uint>(ref value);
}
else if (Unsafe.SizeOf<T>() == sizeof(short))
{
return isSigned ? Unsafe.As<T, short>(ref value) : Unsafe.As<T, ushort>(ref value);
}
else if (Unsafe.SizeOf<T>() == sizeof(byte))
{
return isSigned ? Unsafe.As<T, sbyte>(ref value) : Unsafe.As<T, byte>(ref value);
}
else
{
throw new NotSupportedException($"Unsupported enum underlying type {typeof(T)}");
}
}
}
}
+59 -1
View File
@@ -7,6 +7,33 @@ namespace AssetRipper.CIL;
public static class TypeDefinitionExtensions
{
public static FieldDefinition AddField(this TypeDefinition type, string fieldName, TypeSignature fieldType, bool isStatic = false, Visibility visibility = Visibility.Public)
{
FieldAttributes fieldAttributes = visibility.ToFieldAttributes() | (isStatic ? FieldAttributes.Static : default);
FieldDefinition field = new FieldDefinition(fieldName, fieldAttributes, fieldType);
type.Fields.Add(field);
return field;
}
public static FieldDefinition AddConstantField(
this TypeDefinition type,
TypeSignature fieldType,
string fieldName,
Constant constant,
Visibility visibility = Visibility.Public)
{
FieldDefinition field = new FieldDefinition(
fieldName,
FieldAttributes.Static |
FieldAttributes.Literal |
FieldAttributes.HasDefault |
visibility.ToFieldAttributes(),
new FieldSignature(fieldType));
field.Constant = constant;
type.Fields.Add(field);
return field;
}
public static MethodDefinition AddMethod(this TypeDefinition type, string methodName, MethodAttributes methodAttributes, TypeSignature returnType)
{
MethodDefinition method = CreateMethod(methodName, methodAttributes, returnType);
@@ -14,6 +41,32 @@ public static class TypeDefinitionExtensions
return method;
}
public static MethodDefinition AddConstructor(this TypeDefinition type, Visibility visibility = Visibility.Public)
{
MethodAttributes methodAttributes = visibility.ToMethodAttributes() | MethodAttributes.SpecialName | MethodAttributes.RuntimeSpecialName;
return type.AddMethod(".ctor", methodAttributes, type.DeclaringModule!.CorLibTypeFactory.Void);
}
public static FieldDefinition AddEnumField(this TypeDefinition type, string name, long value)
{
TypeSignature underlyingType = type.GetEnumUnderlyingType() ?? throw new ArgumentException("Type is not an enum", nameof(type));
return type.AddConstantField(type.ToTypeSignature(), name, FromValue(value, underlyingType.ElementType));
static Constant FromValue(long value, ElementType elementType) => elementType switch
{
ElementType.I1 => Constant.FromValue((sbyte)value),
ElementType.U1 => Constant.FromValue((byte)value),
ElementType.I2 => Constant.FromValue((short)value),
ElementType.U2 => Constant.FromValue((ushort)value),
ElementType.I4 => Constant.FromValue((int)value),
ElementType.U4 => Constant.FromValue((uint)value),
ElementType.I8 => Constant.FromValue(value),
ElementType.U8 => Constant.FromValue(unchecked((ulong)value)),
_ => throw new ArgumentOutOfRangeException(nameof(elementType)),
};
}
private static MethodDefinition CreateMethod(string methodName, MethodAttributes methodAttributes, TypeSignature returnType)
{
bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
@@ -22,11 +75,16 @@ public static class TypeDefinitionExtensions
: MethodSignature.CreateInstance(returnType);
MethodDefinition result = new MethodDefinition(methodName, methodAttributes, methodSignature);
result.CilMethodBody = new CilMethodBody(result);
result.CilMethodBody = new CilMethodBody();
return result;
}
public static MethodDefinition GetDefaultConstructor(this TypeDefinition type)
{
return type.Methods.First(m => m.IsInstanceConstructor() && m.Parameters.Count == 0);
}
public static bool IsStaticClass(this TypeDefinition type)
{
return type.IsSealed && type.IsAbstract;
+84
View File
@@ -0,0 +1,84 @@
using AsmResolver.PE.DotNet.Metadata.Tables;
namespace AssetRipper.CIL;
public enum Visibility
{
Public,
Protected,
Internal,
ProtectedInternal,
Private,
PrivateProtected
}
public static class VisibilityExtensions
{
public static MethodAttributes ToMethodAttributes(this Visibility visibility) => visibility switch
{
Visibility.Public => MethodAttributes.Public,
Visibility.Protected => MethodAttributes.Family,
Visibility.Internal => MethodAttributes.Assembly,
Visibility.ProtectedInternal => MethodAttributes.FamilyOrAssembly,
Visibility.Private => MethodAttributes.Private,
Visibility.PrivateProtected => MethodAttributes.FamilyAndAssembly,
_ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, null),
};
public static FieldAttributes ToFieldAttributes(this Visibility visibility) => visibility switch
{
Visibility.Public => FieldAttributes.Public,
Visibility.Protected => FieldAttributes.Family,
Visibility.Internal => FieldAttributes.Assembly,
Visibility.ProtectedInternal => FieldAttributes.FamilyOrAssembly,
Visibility.Private => FieldAttributes.Private,
Visibility.PrivateProtected => FieldAttributes.FamilyAndAssembly,
_ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, null),
};
public static TypeAttributes ToTypeAttributes(this Visibility visibility, bool nested = false) => nested
? visibility switch
{
Visibility.Public => TypeAttributes.NestedPublic,
Visibility.Protected => TypeAttributes.NestedFamily,
Visibility.Internal => TypeAttributes.NestedAssembly,
Visibility.ProtectedInternal => TypeAttributes.NestedFamilyOrAssembly,
Visibility.Private => TypeAttributes.NestedPrivate,
Visibility.PrivateProtected => TypeAttributes.NestedFamilyAndAssembly,
_ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, null),
}
: visibility switch
{
Visibility.Public => TypeAttributes.Public,
Visibility.Internal => TypeAttributes.NotPublic,
_ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, null),
};
internal static Visibility GetVisibility(Type type)
{
if (type.IsPublic || type.IsNestedPublic)
{
return Visibility.Public;
}
if (type.IsNestedFamily)
{
return Visibility.Protected;
}
if (type.IsNotPublic || type.IsNestedAssembly)
{
return Visibility.Internal;
}
if (type.IsNestedFamORAssem)
{
return Visibility.ProtectedInternal;
}
if (type.IsNestedPrivate)
{
return Visibility.Private;
}
if (type.IsNestedFamANDAssem)
{
return Visibility.PrivateProtected;
}
throw new ArgumentException($"Unknown visibility for type {type}", nameof(type));
}
}
+2 -3
View File
@@ -2,13 +2,12 @@
<PropertyGroup>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<IsAotCompatible>true</IsAotCompatible>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<PolySharpIncludeRuntimeSupportedAttributes>true</PolySharpIncludeRuntimeSupportedAttributes>
<Version>1.1.4</Version>
<Version>1.2.0</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<Copyright>Copyright (c) 2024 ds5678</Copyright>
<Copyright>Copyright (c) 2025 ds5678</Copyright>
<Authors>ds5678</Authors>
<Company>AssetRipper</Company>
<PackageLicenseExpression>MIT</PackageLicenseExpression>