Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ private void EmitBindLogicFromString(
{
parsedValueExpr = stringValueToParse_Expr;
}
else if (typeKind is StringParsableTypeKind.Enum)
{
parsedValueExpr = $"ParseEnum<{type.MinimalDisplayString}>({stringValueToParse_Expr}, () => {sectionPathExpr})";
}
else
{
string helperMethodDisplayString = GetHelperMethodDisplayString(type.ParseMethodName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,24 @@ private void EmitHelperMethods()
_emitBlankLineBeforeNextStatement = true;
}

bool enumTypeExists = false;

foreach (ParsableFromStringSpec type in _sourceGenSpec.PrimitivesForHelperGen)
{
EmitBlankLineIfRequired();
EmitPrimitiveParseMethod(type);

if (type.StringParsableTypeKind == StringParsableTypeKind.Enum)
Copy link
Contributor

@layomia layomia Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the parser should not include enum types in the PrimitivesForHelperGen list. The emitter should have minimal/no post-processing of the input data. The SourceGenerationSpec could have a boolean property indicating whether an enum was part of the input graph.

{
if (!enumTypeExists)
{
EmitEnumParseMethod();
enumTypeExists = true;
}
}
else
{
EmitPrimitiveParseMethod(type);
}
}
}

Expand Down Expand Up @@ -518,6 +532,30 @@ private void EmitGetBinderOptionsHelper()
""");
}

private void EmitEnumParseMethod()
{
string innerExceptionTypeDisplayString = _useFullyQualifiedNames ? "global::System.Exception" : "Exception";
string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof(T)}}");

_writer.WriteLine($$"""
public static T ParseEnum<T>(string value, Func<string?> getPath) where T : struct
{
try
{
#if NETFRAMEWORK || NETSTANDARD2_0
return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
#else
return Enum.Parse<T>(value, ignoreCase: true);
#endif
}
catch ({{innerExceptionTypeDisplayString}} {{Identifier.exception}})
{
throw new {{GetInvalidOperationDisplayName()}}($"{{exceptionArg1}}", {{Identifier.exception}});
}
}
""");
}

private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
{
string innerExceptionTypeDisplayString;
Expand Down Expand Up @@ -546,10 +584,7 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
switch (typeKind)
{
case StringParsableTypeKind.Enum:
{
parsedValueExpr = $"({typeDisplayString}){Identifier.Enum}.{Identifier.Parse}(typeof({typeDisplayString}), {Identifier.value}, ignoreCase: true)";
}
break;
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should never fall into this case based on other diffs above.

case StringParsableTypeKind.ByteArray:
{
parsedValueExpr = $"Convert.FromBase64String({Identifier.value})";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration

if (configuration["Prop27"] is string value22)
{
obj.Prop27 = ParseDayOfWeek(value22, () => configuration.GetSection("Prop27").Path);
obj.Prop27 = ParseEnum<DayOfWeek>(value22, () => configuration.GetSection("Prop27").Path);
}

if (configuration["Prop7"] is string value23)
Expand Down Expand Up @@ -430,15 +430,19 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}

public static DayOfWeek ParseDayOfWeek(string value, Func<string?> getPath)
public static T ParseEnum<T>(string value, Func<string?> getPath) where T : struct
{
try
{
return (DayOfWeek)Enum.Parse(typeof(DayOfWeek), value, ignoreCase: true);
#if NETFRAMEWORK || NETSTANDARD2_0
return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
#else
return Enum.Parse<T>(value, ignoreCase: true);
#endif
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(DayOfWeek)}'.", exception);
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(T)}'.", exception);
}
}

Expand Down