diff --git a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/CSharpGeneratorTests.cs b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/CSharpGeneratorTests.cs index 6a3b966..66dd579 100644 --- a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/CSharpGeneratorTests.cs +++ b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/CSharpGeneratorTests.cs @@ -333,7 +333,7 @@ public async Task should_generate_enums() }); code.ShouldContain("public enum Foo : short"); - code.ShouldContain("Default = 0,"); + code.ShouldContain("Default,"); code.ShouldContain("Bar = -2,"); code.ShouldContain("Baz = Bar"); code.ShouldContain("[EnumAttr]"); diff --git a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/ParsedContractsTests.cs b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/ParsedContractsTests.cs index ca53919..386e896 100644 --- a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/ParsedContractsTests.cs +++ b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/ParsedContractsTests.cs @@ -590,7 +590,9 @@ enum Counter ); var enumDef = msg.Enums.ExpectedSingle(); - enumDef.Members.Select(m => m.CSharpValue).ShouldEqual([ + + enumDef.UseInferredValues.ShouldBeTrue(); + enumDef.Members.Select(m => m.InferredValueAsCSharpString).ShouldEqual([ "0", "1", "2", diff --git a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_enums.verified.cs b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_enums.verified.cs index 47921b3..a38b8c2 100644 --- a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_enums.verified.cs +++ b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_enums.verified.cs @@ -13,7 +13,7 @@ [EnumAttr] public enum Foo : short { - Default = 0, + Default, [Description("Beer!")] Bar = -2, diff --git a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_internal_enums.verified.cs b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_internal_enums.verified.cs index e48dad7..1fe9ca2 100644 --- a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_internal_enums.verified.cs +++ b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_internal_enums.verified.cs @@ -12,5 +12,5 @@ [System.CodeDom.Compiler.GeneratedCode("Abc.Zebus.MessageDsl", "1.2.3.4")] internal enum Foo { - Default = 0 + Default } diff --git a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_simple_enums.verified.cs b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_simple_enums.verified.cs index d463caf..c119dcb 100644 --- a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_simple_enums.verified.cs +++ b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_generate_simple_enums.verified.cs @@ -13,7 +13,7 @@ [EnumAttr] public enum Foo { - Default = 0, + Default, Bar = -2, - Baz = -1 + Baz } diff --git a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_handle_custom_contract_attribute_on_enums.verified.cs b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_handle_custom_contract_attribute_on_enums.verified.cs index efb6c6b..a3a3819 100644 --- a/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_handle_custom_contract_attribute_on_enums.verified.cs +++ b/src/Abc.Zebus.MessageDsl.Tests/MessageDsl/Snapshots/CSharpGeneratorTests.should_handle_custom_contract_attribute_on_enums.verified.cs @@ -12,5 +12,5 @@ [ProtoContract(EnumPassthru = true)] public enum Foo { - Default = 0 + Default } diff --git a/src/Abc.Zebus.MessageDsl/Analysis/AstProcessor.cs b/src/Abc.Zebus.MessageDsl/Analysis/AstProcessor.cs index 876a8c6..423fca4 100644 --- a/src/Abc.Zebus.MessageDsl/Analysis/AstProcessor.cs +++ b/src/Abc.Zebus.MessageDsl/Analysis/AstProcessor.cs @@ -89,71 +89,49 @@ private static void ResolveTags(MessageDefinition message) private static void ResolveEnumValues(EnumDefinition enumDef) { - ResolveCSharpValues(); - ResolveProtoValues(); + var lastValue = (string?)null; + var lastValueAsNumber = (long?)null; + var lastValueIsParsed = false; + var lastOffset = 0L; - void ResolveCSharpValues() - { - var lastValue = (string?)null; - var lastValueAsNumber = (long?)null; - var lastValueIsParsed = false; - var lastOffset = 0L; + enumDef.UseInferredValues = enumDef.Members.Any(i => i.IsDiscarded); - foreach (var member in enumDef.Members) + foreach (var member in enumDef.Members) + { + if (!string.IsNullOrEmpty(member.Value)) { - if (!string.IsNullOrEmpty(member.Value)) - { - lastValue = member.CSharpValue = member.Value; - lastValueAsNumber = null; - lastValueIsParsed = false; - lastOffset = 0; - } - else if (lastValue is null) + lastValue = member.InferredValueAsCSharpString = member.Value; + lastValueAsNumber = null; + lastValueIsParsed = false; + lastOffset = 0; + } + else if (lastValue is null) + { + lastValue = member.InferredValueAsCSharpString = "0"; + lastValueAsNumber = 0; + lastValueIsParsed = true; + lastOffset = 0; + } + else + { + if (lastValueAsNumber is null && !lastValueIsParsed) { - lastValue = member.CSharpValue = "0"; - lastValueAsNumber = 0; + if (long.TryParse(lastValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var lastValueParsed)) + lastValueAsNumber = lastValueParsed; + else if (lastValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && long.TryParse(lastValue.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out lastValueParsed)) + lastValueAsNumber = lastValueParsed; + lastValueIsParsed = true; - lastOffset = 0; } - else - { - if (lastValueAsNumber is null && !lastValueIsParsed) - { - if (long.TryParse(lastValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var lastValueParsed)) - lastValueAsNumber = lastValueParsed; - else if (lastValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && long.TryParse(lastValue.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out lastValueParsed)) - lastValueAsNumber = lastValueParsed; - - lastValueIsParsed = true; - } - ++lastOffset; + ++lastOffset; - member.CSharpValue = lastValueAsNumber is { } lastBaseValue - ? checked(lastBaseValue + lastOffset).ToString(CultureInfo.InvariantCulture) - : $"({lastValue}) + {lastOffset}"; - } + member.InferredValueAsCSharpString = lastValueAsNumber is { } lastBaseValue + ? checked(lastBaseValue + lastOffset).ToString(CultureInfo.InvariantCulture) + : $"({lastValue}) + {lastOffset}"; } - } - - void ResolveProtoValues() - { - if (!enumDef.Options.Proto) - return; - if (enumDef.UnderlyingType.NetType != "int") - return; - - var nextValue = (int?)0; - - foreach (var member in enumDef.Members) - { - member.ProtoValue = string.IsNullOrEmpty(member.Value) - ? nextValue - : enumDef.GetValidUnderlyingValue(member.Value) as int?; - - nextValue = member.ProtoValue + 1; - } + member.InferredValueAsNumber = enumDef.GetValidUnderlyingValue(member.InferredValueAsCSharpString); } } diff --git a/src/Abc.Zebus.MessageDsl/Ast/EnumDefinition.cs b/src/Abc.Zebus.MessageDsl/Ast/EnumDefinition.cs index 490da9c..7147ede 100644 --- a/src/Abc.Zebus.MessageDsl/Ast/EnumDefinition.cs +++ b/src/Abc.Zebus.MessageDsl/Ast/EnumDefinition.cs @@ -15,6 +15,8 @@ public class EnumDefinition : AstNode, IMemberNode public AttributeSet Attributes { get; } = new(); public IList Members { get; } = new List(); + internal bool UseInferredValues { get; set; } + public MemberOptions Options { get => _options ??= new MemberOptions(); diff --git a/src/Abc.Zebus.MessageDsl/Ast/EnumMemberDefinition.cs b/src/Abc.Zebus.MessageDsl/Ast/EnumMemberDefinition.cs index 6f21bd4..d834530 100644 --- a/src/Abc.Zebus.MessageDsl/Ast/EnumMemberDefinition.cs +++ b/src/Abc.Zebus.MessageDsl/Ast/EnumMemberDefinition.cs @@ -6,8 +6,8 @@ public class EnumMemberDefinition : AstNode, INamedNode public string? Value { get; set; } public AttributeSet Attributes { get; } = new(); - internal string? CSharpValue { get; set; } - internal int? ProtoValue { get; set; } + internal string? InferredValueAsCSharpString { get; set; } + internal object? InferredValueAsNumber { get; set; } internal bool IsDiscarded { get; set; } public override string ToString() diff --git a/src/Abc.Zebus.MessageDsl/Generator/CSharpGenerator.cs b/src/Abc.Zebus.MessageDsl/Generator/CSharpGenerator.cs index 803202d..0e9c6f6 100644 --- a/src/Abc.Zebus.MessageDsl/Generator/CSharpGenerator.cs +++ b/src/Abc.Zebus.MessageDsl/Generator/CSharpGenerator.cs @@ -152,10 +152,10 @@ private void WriteEnum(EnumDefinition enumDef) Writer.Write(Identifier(member.Name)); - if (!string.IsNullOrEmpty(member.CSharpValue)) - Writer.Write(" = {0}", member.CSharpValue); - else if (!string.IsNullOrEmpty(member.Value)) + if (!string.IsNullOrEmpty(member.Value)) Writer.Write(" = {0}", member.Value); + else if (enumDef.UseInferredValues && !string.IsNullOrEmpty(member.InferredValueAsCSharpString)) + Writer.Write(" = {0}", member.InferredValueAsCSharpString); if (member != lastMember) { diff --git a/src/Abc.Zebus.MessageDsl/Generator/ProtoGenerator.cs b/src/Abc.Zebus.MessageDsl/Generator/ProtoGenerator.cs index d9bc28d..fde4512 100644 --- a/src/Abc.Zebus.MessageDsl/Generator/ProtoGenerator.cs +++ b/src/Abc.Zebus.MessageDsl/Generator/ProtoGenerator.cs @@ -69,11 +69,11 @@ private void WriteEnum(EnumDefinition enumDef) using (Block()) { - if (enumDef.Members.Where(i => i.ProtoValue != null).GroupBy(i => i.ProtoValue.GetValueOrDefault()).Any(g => g.Count() > 1)) + if (enumDef.Members.Where(i => i.InferredValueAsNumber != null).GroupBy(i => i.InferredValueAsNumber).Any(g => g.Count() > 1)) Writer.WriteLine("option allow_alias = true;"); foreach (var member in enumDef.Members) - Writer.WriteLine("{0} = {1};", member.Name, member.ProtoValue ?? (object)"TODO"); + Writer.WriteLine("{0} = {1};", member.Name, member.InferredValueAsNumber ?? "TODO"); } }