Skip to content

Commit

Permalink
Interpret discards in enums and always emit explicit values
Browse files Browse the repository at this point in the history
  • Loading branch information
ltrzesniewski committed May 9, 2024
1 parent b3f0037 commit 90f457e
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ public async Task should_generate_enums()
});

code.ShouldContain("public enum Foo : short");
code.ShouldContain("Default,");
code.ShouldContain("Default = 0,");
code.ShouldContain("Bar = -2,");
code.ShouldContain("Baz = Bar");
code.ShouldContain("[EnumAttr]");
Expand Down
53 changes: 53 additions & 0 deletions src/Abc.Zebus.MessageDsl.Tests/MessageDsl/ParsedContractsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,59 @@ public enum Metrics
enumDef.Members.ExpectedSingle(i => i.Name == "Test").Value.ShouldEqual("Lifetime | (Latency)");
}

[Test]
public void should_compute_enum_member_values()
{
var msg = ParseValid(
"""
enum Counter
{
Zero,
One,
Two,
_,
_,
Five,
Six,
Seven,
Eight = 2 << 2,
Nine,
Ten,
Eleven,
_,
AnotherOne = One,
AnotherTwo,
AnotherThree,
_,
Twenty = 0x14,
TwentyOne,
TwentyTwo,
_
}
"""
);

var enumDef = msg.Enums.ExpectedSingle();
enumDef.Members.Select(m => m.CSharpValue).ShouldEqual([
"0",
"1",
"2",
"5",
"6",
"7",
"2 << 2",
"(2 << 2) + 1",
"(2 << 2) + 2",
"(2 << 2) + 3",
"One",
"(One) + 1",
"(One) + 2",
"0x14",
"21",
"22"
]);
}

[Test]
public void should_handle_double_angled_brackets()
{
Expand Down
74 changes: 63 additions & 11 deletions src/Abc.Zebus.MessageDsl/Analysis/AstProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using Abc.Zebus.MessageDsl.Ast;

Expand Down Expand Up @@ -87,21 +89,71 @@ private static void ResolveTags(MessageDefinition message)

private static void ResolveEnumValues(EnumDefinition enumDef)
{
if (!enumDef.Options.Proto)
return;
ResolveCSharpValues();
ResolveProtoValues();

if (enumDef.UnderlyingType.NetType != "int")
return;
void ResolveCSharpValues()
{
var lastValue = (string?)null;
var lastValueAsNumber = (long?)null;
var lastValueIsParsed = false;
var lastOffset = 0L;

foreach (var member in enumDef.Members)
{
if (!string.IsNullOrEmpty(member.Value))
{
lastValue = member.CSharpValue = member.Value;
lastValueAsNumber = null;
lastValueIsParsed = false;
lastOffset = 0;
}
else if (lastValue is null)
{
lastValue = member.CSharpValue = "0";
lastValueAsNumber = 0;
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;

var nextValue = (int?)0;
lastValueIsParsed = true;
}

foreach (var member in enumDef.Members)
++lastOffset;

member.CSharpValue = lastValueAsNumber is { } lastBaseValue
? checked(lastBaseValue + lastOffset).ToString(CultureInfo.InvariantCulture)
: $"({lastValue}) + {lastOffset}";
}
}
}

void ResolveProtoValues()
{
member.ProtoValue = string.IsNullOrEmpty(member.Value)
? nextValue
: enumDef.GetValidUnderlyingValue(member.Value) as int?;
if (!enumDef.Options.Proto)
return;

nextValue = member.ProtoValue + 1;
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;
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Abc.Zebus.MessageDsl/Ast/EnumMemberDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ public class EnumMemberDefinition : AstNode, INamedNode
public string Name { get; set; } = string.Empty;
public string? Value { get; set; }
public AttributeSet Attributes { get; } = new();

internal string? CSharpValue { get; set; }
internal int? ProtoValue { get; set; }
internal bool IsDiscarded { get; set; }

Expand Down
4 changes: 3 additions & 1 deletion src/Abc.Zebus.MessageDsl/Generator/CSharpGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ private void WriteEnum(EnumDefinition enumDef)

Writer.Write(Identifier(member.Name));

if (!string.IsNullOrEmpty(member.Value))
if (!string.IsNullOrEmpty(member.CSharpValue))
Writer.Write(" = {0}", member.CSharpValue);
else if (!string.IsNullOrEmpty(member.Value))
Writer.Write(" = {0}", member.Value);

if (member != lastMember)
Expand Down

0 comments on commit 90f457e

Please sign in to comment.