Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Cpp2IL.Core.Tests/CsFileUtilsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Cpp2IL.Core.Utils;

namespace Cpp2IL.Core.Tests;

public class CsFileUtilsTests
{
[Test]
public void TypesShouldHaveCorrectKeywords()
{
var appContext = TestGameLoader.LoadSimple2019Game();
var mscorlib = appContext.SystemTypes.SystemObjectType.DeclaringAssembly;

using (Assert.EnterMultipleScope())
{
Assert.That(CsFileUtils.GetKeyWordsForType(appContext.SystemTypes.SystemObjectType), Is.EqualTo("public class"));
Assert.That(CsFileUtils.GetKeyWordsForType(appContext.SystemTypes.SystemInt32Type), Is.EqualTo("public struct"));
Assert.That(CsFileUtils.GetKeyWordsForType(mscorlib.GetTypeByFullName("System.Array")!), Is.EqualTo("public abstract class"));
Assert.That(CsFileUtils.GetKeyWordsForType(mscorlib.GetTypeByFullName("System.EmptyArray`1")!), Is.EqualTo("internal static class"));
Assert.That(CsFileUtils.GetKeyWordsForType(mscorlib.GetTypeByFullName("System.IDisposable")!), Is.EqualTo("public interface"));
}
}
}
42 changes: 42 additions & 0 deletions Cpp2IL.Core/Model/Contexts/EventAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,50 @@ public TypeAnalysisContext EventType
set => OverrideEventType = value;
}

public MethodAttributes Visibility
{
get
{
// Determine the most permissive visibility among the adder, remover, and invoker
var adderVisibility = Adder?.Visibility ?? MethodAttributes.PrivateScope;
var removerVisibility = Remover?.Visibility ?? MethodAttributes.PrivateScope;
var invokerVisibility = Invoker?.Visibility ?? MethodAttributes.PrivateScope;

// public
if (adderVisibility == MethodAttributes.Public || removerVisibility == MethodAttributes.Public || invokerVisibility == MethodAttributes.Public)
return MethodAttributes.Public;

// protected internal
if (adderVisibility == MethodAttributes.FamORAssem || removerVisibility == MethodAttributes.FamORAssem || invokerVisibility == MethodAttributes.FamORAssem)
return MethodAttributes.FamORAssem;

// internal
if (adderVisibility == MethodAttributes.Assembly || removerVisibility == MethodAttributes.Assembly || invokerVisibility == MethodAttributes.Assembly)
return MethodAttributes.Assembly;

// protected
if (adderVisibility == MethodAttributes.Family || removerVisibility == MethodAttributes.Family || invokerVisibility == MethodAttributes.Family)
return MethodAttributes.Family;

// private protected
if (adderVisibility == MethodAttributes.FamANDAssem || removerVisibility == MethodAttributes.FamANDAssem || invokerVisibility == MethodAttributes.FamANDAssem)
return MethodAttributes.FamANDAssem;

// private
return MethodAttributes.Private;
}
}

public virtual bool IsStatic => Definition?.IsStatic ?? throw new($"Subclasses must override {nameof(IsStatic)}.");

public bool IsAbstract => Adder?.IsAbstract ?? Remover?.IsAbstract ?? Invoker?.IsAbstract ?? false;

public bool IsVirtual => Adder?.IsVirtual ?? Remover?.IsVirtual ?? Invoker?.IsVirtual ?? false;

public bool IsNewSlot => Adder?.IsNewSlot ?? Remover?.IsNewSlot ?? Invoker?.IsNewSlot ?? false;

public bool IsFinal => Adder?.IsFinal ?? Remover?.IsFinal ?? Invoker?.IsFinal ?? false;

public EventAnalysisContext(Il2CppEventDefinition definition, TypeAnalysisContext parent) : base(definition.token, parent.AppContext)
{
Definition = definition;
Expand Down
2 changes: 2 additions & 0 deletions Cpp2IL.Core/Model/Contexts/MethodAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public class MethodAnalysisContext : HasGenericParameters, IMethodInfoProvider

public bool IsNewSlot => (Attributes & MethodAttributes.NewSlot) != 0;

public bool IsFinal => (Attributes & MethodAttributes.Final) != 0;

protected override int CustomAttributeIndex => Definition?.customAttributeIndex ?? throw new("Subclasses of MethodAnalysisContext should override CustomAttributeIndex if they have custom attributes");

public override AssemblyAnalysisContext CustomAttributeAssembly => DeclaringType?.DeclaringAssembly ?? throw new("Subclasses of MethodAnalysisContext should override CustomAttributeAssembly if they have custom attributes");
Expand Down
41 changes: 41 additions & 0 deletions Cpp2IL.Core/Model/Contexts/PropertyAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ public class PropertyAnalysisContext : HasCustomAttributesAndName, IPropertyInfo

public virtual bool IsStatic => Definition?.IsStatic ?? throw new($"Subclasses must override {nameof(IsStatic)}.");

public bool IsAbstract => Getter?.IsAbstract ?? Setter?.IsAbstract ?? false;

public bool IsVirtual => Getter?.IsVirtual ?? Setter?.IsVirtual ?? false;

public bool IsNewSlot => Getter?.IsNewSlot ?? Setter?.IsNewSlot ?? false;

public bool IsFinal => Getter?.IsFinal ?? Setter?.IsFinal ?? false;

public virtual PropertyAttributes DefaultAttributes => (PropertyAttributes?)Definition?.attrs ?? throw new($"Subclasses must override {nameof(DefaultAttributes)}.");

public PropertyAttributes? OverrideAttributes { get; set; }
Expand All @@ -43,6 +51,39 @@ public TypeAnalysisContext PropertyType
set => OverridePropertyType = value;
}

public MethodAttributes Visibility
{
get
{
// Determine the most permissive visibility among the getter and setter
var getterVisibility = Getter?.Visibility ?? MethodAttributes.PrivateScope;
var setterVisibility = Setter?.Visibility ?? MethodAttributes.PrivateScope;

// public
if (getterVisibility == MethodAttributes.Public || setterVisibility == MethodAttributes.Public)
return MethodAttributes.Public;

// protected internal
if (getterVisibility == MethodAttributes.FamORAssem || setterVisibility == MethodAttributes.FamORAssem)
return MethodAttributes.FamORAssem;

// internal
if (getterVisibility == MethodAttributes.Assembly || setterVisibility == MethodAttributes.Assembly)
return MethodAttributes.Assembly;

// protected
if (getterVisibility == MethodAttributes.Family || setterVisibility == MethodAttributes.Family)
return MethodAttributes.Family;

// private protected
if (getterVisibility == MethodAttributes.FamANDAssem || setterVisibility == MethodAttributes.FamANDAssem)
return MethodAttributes.FamANDAssem;

// private
return MethodAttributes.Private;
}
}

public PropertyAnalysisContext(Il2CppPropertyDefinition definition, TypeAnalysisContext parent) : base(definition.token, parent.AppContext)
{
DeclaringType = parent;
Expand Down
1 change: 1 addition & 0 deletions Cpp2IL.Core/Model/Contexts/TypeAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ public TypeAttributes Visibility
public bool IsAbstract => (Attributes & TypeAttributes.Abstract) != default;
public bool IsSealed => (Attributes & TypeAttributes.Sealed) != default;
public bool IsStatic => IsAbstract && IsSealed;
public bool IsDelegate => BaseType is not ReferencedTypeAnalysisContext and { Namespace: "System", Name: "MulticastDelegate" };

/// <summary>
/// Returns the namespace of this type expressed as a folder hierarchy, with each sub-namespace becoming a sub-directory.
Expand Down
Loading
Loading