Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move non-scoped enums nested in classes to their parents #1187

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
8 changes: 5 additions & 3 deletions src/AST/Declaration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,15 @@ public virtual string LogicalOriginalName
public string GetQualifiedName(Func<Declaration, string> getName,
Func<Declaration, DeclarationContext> getNamespace)
{
if (Namespace == null)
DeclarationContext declarationContext = getNamespace(this);

if (declarationContext == null)
return getName(this);

if (Namespace.IsRoot)
if (declarationContext.IsRoot)
return getName(this);

var namespaces = GatherNamespaces(getNamespace(this));
var namespaces = GatherNamespaces(declarationContext);

var names = namespaces.Select(getName).ToList();
names.Add(getName(this));
Expand Down
1 change: 1 addition & 0 deletions src/Generator/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ public void SetupPasses(ILibrary library)
TranslationUnitPasses.AddPass(new FindSymbolsPass());
TranslationUnitPasses.AddPass(new CheckMacroPass());
TranslationUnitPasses.AddPass(new CheckStaticClass());
TranslationUnitPasses.AddPass(new MoveNonScopedNestedEnumsToParentPass());
TranslationUnitPasses.AddPass(new MoveOperatorToClassPass());
TranslationUnitPasses.AddPass(new MoveFunctionToClassPass());
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
Expand Down
56 changes: 56 additions & 0 deletions src/Generator/Passes/MoveNonScopedNestedEnumsToParentPass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using CppSharp.AST;
using System.Collections.Generic;
using System.Linq;

namespace CppSharp.Passes
{
/// <summary>
/// This pass moves old-style (non-scoped) enumerations nested in classes
/// to the parents of those classes.
/// </summary>
/// <remarks>
/// Such enums are presumably written this way because C++ before 11
/// could not scope enums and nesting was the only way to do so
/// in order to prevent conflicts. But target languages don't have
/// this limitation so we can generate a more sensible API.
/// </remarks>
public class MoveNonScopedNestedEnumsToParentPass : TranslationUnitPass
{
public override bool VisitASTContext(ASTContext context)
{
bool result = base.VisitASTContext(context);

foreach (var movableEnum in movableEnums)
{
DeclarationContext declarationContext = movableEnum.Namespace;
declarationContext.Declarations.Remove(movableEnum);
declarationContext.Namespace.Declarations.Add(movableEnum);
movableEnum.Namespace = declarationContext.Namespace;
}

return result;
}

public override bool VisitEnumDecl(Enumeration @enum)
{
if (!base.VisitEnumDecl(@enum))
return false;

if (string.IsNullOrEmpty(@enum.Name) ||
!(@enum.Namespace is Class) ||
@enum.Access != AccessSpecifier.Public ||
@enum.IsScoped)
return false;

if (@enum.Namespace.Namespace.Declarations.Union(movableEnums).Any(
e => e.Name == @enum.Name))
return false;

movableEnums.Add(@enum);

return true;
}

private readonly List<Enumeration> movableEnums = new List<Enumeration>();
}
}
18 changes: 9 additions & 9 deletions tests/CSharp/CSharp.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ public void TestUncompilableCode()
new HasCtorWithMappedToEnum<TestFlag>(TestFlag.Flag1).Dispose();
using (var testOverrideFromSecondaryBase = new TestOverrideFromSecondaryBase())
{
testOverrideFromSecondaryBase.function();
testOverrideFromSecondaryBase.Function();
var ok = false;
testOverrideFromSecondaryBase.function(ref ok);
var property = testOverrideFromSecondaryBase.property;
testOverrideFromSecondaryBase.Function(ref ok);
var property = testOverrideFromSecondaryBase.Property;
testOverrideFromSecondaryBase.VirtualMember();
}
using (var foo = new Foo())
Expand Down Expand Up @@ -670,12 +670,12 @@ public void TestEnumProperty()
{
using (var proprietor = new Proprietor())
{
Assert.That(proprietor.Items, Is.EqualTo(Bar.Items.Item1));
proprietor.Items = Bar.Items.Item2;
Assert.That(proprietor.Items, Is.EqualTo(Bar.Items.Item2));
Assert.That(proprietor.ItemsByValue, Is.EqualTo(Bar.Items.Item1));
proprietor.ItemsByValue = Bar.Items.Item2;
Assert.That(proprietor.ItemsByValue, Is.EqualTo(Bar.Items.Item2));
Assert.That(proprietor.Items, Is.EqualTo(Items.Item1));
proprietor.Items = Items.Item2;
Assert.That(proprietor.Items, Is.EqualTo(Items.Item2));
Assert.That(proprietor.ItemsByValue, Is.EqualTo(Items.Item1));
proprietor.ItemsByValue = Items.Item2;
Assert.That(proprietor.ItemsByValue, Is.EqualTo(Items.Item2));
}
}

Expand Down
15 changes: 9 additions & 6 deletions tests/Common/Common.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ public unsafe void TestCodeGeneration()
Assert.That(changedAccessOfInheritedProperty.Property, Is.EqualTo(2));
}
Foo.NestedAbstract a;
var renamedEmptyEnum = Foo.RenamedEmptyEnum.EmptyEnum1;
var renamedEmptyEnum = RenamedEmptyEnum.EmptyEnum1;
using (var foo = new Foo())
{
Bar bar = foo;
Assert.IsTrue(Bar.Item.Item1 == bar);
Assert.IsTrue(Item.Item1 == bar);

using (var hasOverloadsWithDifferentPointerKindsToSameType =
new HasOverloadsWithDifferentPointerKindsToSameType())
Expand Down Expand Up @@ -101,7 +101,7 @@ public void TestHello()

var bar = new Bar { A = 4, B = 7 };
Assert.That(hello.AddBar(bar), Is.EqualTo(11));
Assert.That(bar.RetItem1(), Is.EqualTo(Bar.Item.Item1));
Assert.That(bar.RetItem1(), Is.EqualTo(Item.Item1));

var retFoo = hello.RetFoo(7, 2.0f);
Assert.That(retFoo.A, Is.EqualTo(7));
Expand Down Expand Up @@ -245,7 +245,7 @@ public void TestLeftShiftOperator()
{
var foo2 = new Foo2 { C = 2 };
Foo2 result = foo2 << 3;
foo2.TestKeywordParam(IntPtr.Zero, Bar.Item.Item1, 1);
foo2.TestKeywordParam(IntPtr.Zero, Item.Item1, 1);
Assert.That(result.C, Is.EqualTo(16));
}

Expand Down Expand Up @@ -501,8 +501,11 @@ public void TestProperties()
prop.VirtualSetterReturnsBoolean = 45;
Assert.That(prop.VirtualSetterReturnsBoolean, Is.EqualTo(45));

Assert.That(prop.nestedEnum(), Is.EqualTo(5));
Assert.That(prop.nestedEnum(55), Is.EqualTo(55));
Assert.That(prop.NestedEnum(), Is.EqualTo(5));
Assert.That(prop.NestedEnum(55), Is.EqualTo(55));

Assert.That(prop.nestedScopedEnum(10), Is.EqualTo(10));
Assert.That(prop.nestedScopedEnum(65), Is.EqualTo(65));
}
}

Expand Down
10 changes: 10 additions & 0 deletions tests/Common/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,16 @@ int TestProperties::nestedEnum(int i)
return i;
}

int TestProperties::nestedScopedEnum()
{
return 10;
}

int TestProperties::nestedScopedEnum(int i)
{
return i;
}

HasOverridenSetter::HasOverridenSetter()
{
}
Expand Down
11 changes: 10 additions & 1 deletion tests/Common/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,13 @@ DLL_API int Function()
struct DLL_API TestProperties
{
public:
enum class NestedEnum
enum NestedEnum
{
Value1,
Value2
};

enum class NestedScopedEnum
{
Value1,
Value2
Expand Down Expand Up @@ -609,6 +615,9 @@ struct DLL_API TestProperties

int nestedEnum();
int nestedEnum(int i);

int nestedScopedEnum();
int nestedScopedEnum(int i);
private:
int FieldValue;
double _refToPrimitiveInSetter;
Expand Down