Skip to content

Commit

Permalink
Move non-scoped enums nested in classes to their parents
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
  • Loading branch information
ddobrev committed Mar 6, 2019
1 parent 9cad946 commit fcb35e5
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 19 deletions.
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

0 comments on commit fcb35e5

Please sign in to comment.