Source code generator for enum types
What's Changed
- Implement source code generator for enum by @MichalBrylka in #16
Full Changelog: 2.8.2...2.9.1
Code generator for enum types
With this feature it is enough to annotate enum with 2 attributes:
[Auto.AutoEnumTransformer(
//1. optionally pass parser settings
CaseInsensitive = true, AllowParsingNumerics = true,
//2. TransformerClassName can be left blank. In that case the name of enum is used with "Transformer" suffix
TransformerClassName = "MonthCodeGenTransformer",
//3. optionally pass namespace to generate the transformer class within. If not provided the namespace of the enum will be used
TransformerClassNamespace = "ABC"
)]
//4. decorate enum with TransformerAttribute that points to automatically generated transformer
[Transformer(typeof(ABC.MonthCodeGenTransformer))]
public enum Month : byte
{
None = 0,
January = 1, February = 2, March = 3,
April = 4, May = 5, June = 6,
July = 7, August = 8, September = 9,
October = 10, November = 11, December = 12
}
This in turn generates the following parser using best practices (some lines are ommited for brevity):
Source code for generated parser
public sealed class MonthCodeGenTransformer : TransformerBase<Nemesis.TextParsers.CodeGen.Sample.Month>
{
public override string Format(Nemesis.TextParsers.CodeGen.Sample.Month element) => element switch
{
Nemesis.TextParsers.CodeGen.Sample.Month.None => nameof(Nemesis.TextParsers.CodeGen.Sample.Month.None),
Nemesis.TextParsers.CodeGen.Sample.Month.January => nameof(Nemesis.TextParsers.CodeGen.Sample.Month.January),
// ...
Nemesis.TextParsers.CodeGen.Sample.Month.December => nameof(Nemesis.TextParsers.CodeGen.Sample.Month.December),
_ => element.ToString("G"),
};
protected override Nemesis.TextParsers.CodeGen.Sample.Month ParseCore(in ReadOnlySpan<char> input) =>
input.IsWhiteSpace() ? default : (Nemesis.TextParsers.CodeGen.Sample.Month)ParseElement(input);
private static byte ParseElement(ReadOnlySpan<char> input)
{
if (input.IsEmpty || input.IsWhiteSpace()) return default;
input = input.Trim();
if (IsNumeric(input) && byte.TryParse(input
#if NETFRAMEWORK
.ToString() //legacy frameworks do not support parsing from ReadOnlySpan<char>
#endif
, out var number))
return number;
else
return ParseName(input);
static bool IsNumeric(ReadOnlySpan<char> input) =>
input.Length > 0 && input[0] is var first &&
(char.IsDigit(first) || first is '-' or '+');
}
private static byte ParseName(ReadOnlySpan<char> input)
{
if (IsEqual(input, nameof(Nemesis.TextParsers.CodeGen.Sample.Month.None)))
return (byte)Nemesis.TextParsers.CodeGen.Sample.Month.None;
else if (IsEqual(input, nameof(Nemesis.TextParsers.CodeGen.Sample.Month.January)))
return (byte)Nemesis.TextParsers.CodeGen.Sample.Month.January;
else if (IsEqual(input, nameof(Nemesis.TextParsers.CodeGen.Sample.Month.February)))
return (byte)Nemesis.TextParsers.CodeGen.Sample.Month.February;
// ...
else if (IsEqual(input, nameof(Nemesis.TextParsers.CodeGen.Sample.Month.December)))
return (byte)Nemesis.TextParsers.CodeGen.Sample.Month.December;
else throw new FormatException(@$"Enum of type 'Nemesis.TextParsers.CodeGen.Sample.Month' cannot be parsed from '{input.ToString()}'.
Valid values are: [None or January or February or March or April or May or June or July or August or September or October or November or December] or number within byte range.
Ignore case option on.");
static bool IsEqual(ReadOnlySpan<char> input, string label) =>
MemoryExtensions.Equals(input, label.AsSpan(), StringComparison.OrdinalIgnoreCase);
}
}