mirror of https://github.com/mono/CppSharp.git
Browse Source
* Rename `CheckFlagEnumsPass` to `CheckEnumsPass` * Fix invalid enum base types being generated in C# source * Add enum base type validation testspull/1909/head
8 changed files with 113 additions and 62 deletions
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
using CppSharp.AST; |
||||
using CppSharp.Extensions; |
||||
|
||||
namespace CppSharp.Passes |
||||
{ |
||||
/// <summary>
|
||||
/// Validates enumerations and checks if any should be treated as a collection
|
||||
/// of flags (and annotate them with the .NET [Flags] when generated).
|
||||
/// </summary>
|
||||
public class CheckEnumsPass : TranslationUnitPass |
||||
{ |
||||
public CheckEnumsPass() |
||||
=> VisitOptions.ResetFlags(VisitFlags.NamespaceEnums); |
||||
|
||||
private static bool IsFlagEnum(Enumeration @enum) |
||||
{ |
||||
// If the enumeration only has power of two values, assume it's
|
||||
// a flags enum.
|
||||
|
||||
var isFlags = true; |
||||
var hasBigRange = false; |
||||
|
||||
foreach (var item in @enum.Items) |
||||
{ |
||||
var value = item.Value; |
||||
|
||||
if (value >= 4) |
||||
hasBigRange = true; |
||||
|
||||
if (value <= 1 || value.IsPowerOfTwo()) |
||||
continue; |
||||
|
||||
isFlags = false; |
||||
} |
||||
|
||||
// Only apply this heuristic if there are enough values to have a
|
||||
// reasonable chance that it really is a bitfield.
|
||||
|
||||
return isFlags && hasBigRange; |
||||
} |
||||
|
||||
private bool IsValidEnumBaseType(Enumeration @enum) |
||||
{ |
||||
if (Options.IsCSharpGenerator) |
||||
return @enum.BuiltinType.Type.IsIntegerType(); |
||||
|
||||
return @enum.BuiltinType.Type.IsIntegerType() || @enum.BuiltinType.Type == PrimitiveType.Bool; |
||||
} |
||||
|
||||
public override bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
if (!base.VisitEnumDecl(@enum)) |
||||
return false; |
||||
|
||||
if (!IsValidEnumBaseType(@enum)) |
||||
{ |
||||
if (@enum.BuiltinType.Type == PrimitiveType.Bool) |
||||
{ |
||||
@enum.BuiltinType = new BuiltinType(PrimitiveType.UChar); |
||||
} |
||||
else |
||||
{ |
||||
Diagnostics.Warning( |
||||
"The enum `{0}` has a base type of `{1}`, which is currently not supported. The base type will be ignored.", |
||||
@enum, @enum.BuiltinType); |
||||
@enum.BuiltinType = new BuiltinType(PrimitiveType.Int); |
||||
} |
||||
} |
||||
|
||||
if (IsFlagEnum(@enum)) |
||||
@enum.Modifiers |= Enumeration.EnumModifiers.Flags; |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
} |
@ -1,52 +0,0 @@
@@ -1,52 +0,0 @@
|
||||
using CppSharp.AST; |
||||
|
||||
namespace CppSharp.Passes |
||||
{ |
||||
/// <summary>
|
||||
/// Checks for enumerations that should be treated as a collection
|
||||
/// of flags (and annotated with the .NET [Flags] when generated).
|
||||
/// </summary>
|
||||
public class CheckFlagEnumsPass : TranslationUnitPass |
||||
{ |
||||
public CheckFlagEnumsPass() |
||||
=> VisitOptions.ResetFlags(VisitFlags.NamespaceEnums); |
||||
|
||||
private static bool IsFlagEnum(Enumeration @enum) |
||||
{ |
||||
// If the enumeration only has power of two values, assume it's
|
||||
// a flags enum.
|
||||
|
||||
var isFlags = true; |
||||
var hasBigRange = false; |
||||
|
||||
foreach (var item in @enum.Items) |
||||
{ |
||||
var value = item.Value; |
||||
|
||||
if (value >= 4) |
||||
hasBigRange = true; |
||||
|
||||
if (value <= 1 || value.IsPowerOfTwo()) |
||||
continue; |
||||
|
||||
isFlags = false; |
||||
} |
||||
|
||||
// Only apply this heuristic if there are enough values to have a
|
||||
// reasonable chance that it really is a bitfield.
|
||||
|
||||
return isFlags && hasBigRange; |
||||
} |
||||
|
||||
public override bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
if (IsFlagEnum(@enum)) |
||||
{ |
||||
@enum.Modifiers |= Enumeration.EnumModifiers.Flags; |
||||
return true; |
||||
} |
||||
|
||||
return base.VisitEnumDecl(@enum); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue