Skip to content

Commit 0f222cd

Browse files
committed
Implement proper parsing for primitives in config binding gen
1 parent dddf223 commit 0f222cd

20 files changed

+1064
-380
lines changed

src/libraries/Microsoft.Extensions.Configuration.Binder/gen/CollectionSpec.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,18 @@ public CollectionSpec(ITypeSymbol type) : base(type)
2222
public CollectionSpec? ConcreteType { get; init; }
2323
}
2424

25+
internal sealed record ArraySpec : CollectionSpec
26+
{
27+
public ArraySpec(ITypeSymbol type) : base(type) { }
28+
29+
public override TypeSpecKind SpecKind => TypeSpecKind.Array;
30+
}
31+
2532
internal sealed record EnumerableSpec : CollectionSpec
2633
{
2734
public EnumerableSpec(ITypeSymbol type) : base(type) { }
2835

29-
public override TypeSpecKind SpecKind { get; init; } = TypeSpecKind.Enumerable;
36+
public override TypeSpecKind SpecKind => TypeSpecKind.Enumerable;
3037
}
3138

3239
internal sealed record DictionarySpec : CollectionSpec
@@ -35,6 +42,6 @@ public DictionarySpec(INamedTypeSymbol type) : base(type) { }
3542

3643
public override TypeSpecKind SpecKind => TypeSpecKind.Dictionary;
3744

38-
public required TypeSpec KeyType { get; init; }
45+
public required ParsableFromStringTypeSpec KeyType { get; init; }
3946
}
4047
}

src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingSourceGenerator.Emitter.cs

Lines changed: 202 additions & 119 deletions
Large diffs are not rendered by default.

src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingSourceGenerator.Helpers.cs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,32 @@ public sealed partial class ConfigurationBindingSourceGenerator
3434
defaultSeverity: DiagnosticSeverity.Error,
3535
isEnabledByDefault: true);
3636

37-
// Unlike sourcegen warnings, exception messages should not be localized so we keep them in source.
37+
// Runtime exception messages; not localized so we keep them in source.
3838
private static class ExceptionMessages
3939
{
4040
public const string TypeNotSupported = "Unable to bind to type '{0}': '{1}'";
41+
public const string FailedBinding = "Failed to convert configuration value at '{0}' to type '{1}'.";
42+
}
43+
44+
private static class NotSupportedReason
45+
{
46+
public const string AbstractOrInterfaceNotSupported = "Abstract or interface types are not supported";
47+
public const string NeedPublicParameterlessConstructor = "Only objects with public parameterless ctors are supported";
48+
public const string CollectionNotSupported = "The collection type is not supported";
49+
public const string DictionaryKeyNotSupported = "The dictionary key type is not supported";
50+
public const string ElementTypeNotSupported = "The collection element type is not supported";
51+
public const string MultiDimArraysNotSupported = "Multidimensional arrays are not supported.";
52+
public const string NullableUnderlyingTypeNotSupported = "Nullable underlying type is not supported";
53+
public const string TypeNotDetectedAsInput = "Generator parser did not detect the type as input";
54+
public const string TypeNotSupported = "The type is not supported";
4155
}
4256

4357
private static class Identifier
4458
{
4559
public const string configuration = nameof(configuration);
4660
public const string element = nameof(element);
4761
public const string enumValue = nameof(enumValue);
62+
public const string exception = nameof(exception);
4863
public const string key = nameof(key);
4964
public const string obj = nameof(obj);
5065
public const string originalCount = nameof(originalCount);
@@ -64,10 +79,15 @@ private static class Identifier
6479
public const string CopyTo = nameof(CopyTo);
6580
public const string ContainsKey = nameof(ContainsKey);
6681
public const string Count = nameof(Count);
82+
public const string CultureInfo = nameof(CultureInfo);
83+
public const string CultureNotFoundException = nameof(CultureNotFoundException);
6784
public const string Enum = nameof(Enum);
85+
public const string Exception = nameof(Exception);
86+
public const string Float = nameof(Float);
6887
public const string GeneratedConfigurationBinder = nameof(GeneratedConfigurationBinder);
6988
public const string Get = nameof(Get);
7089
public const string GetChildren = nameof(GetChildren);
90+
public const string GetCultureInfoByIetfLanguageTag = nameof(GetCultureInfoByIetfLanguageTag);
7191
public const string GetSection = nameof(GetSection);
7292
public const string HasChildren = nameof(HasChildren);
7393
public const string HasValueOrChildren = nameof(HasValueOrChildren);
@@ -76,42 +96,49 @@ private static class Identifier
7696
public const string IConfiguration = nameof(IConfiguration);
7797
public const string IConfigurationSection = nameof(IConfigurationSection);
7898
public const string Int32 = "int";
99+
public const string Integer = nameof(Integer);
100+
public const string InvalidOperationException = nameof(InvalidOperationException);
101+
public const string InvariantCulture = nameof(InvariantCulture);
79102
public const string Length = nameof(Length);
103+
public const string NumberStyles = nameof(NumberStyles);
80104
public const string Parse = nameof(Parse);
105+
public const string Path = nameof(Path);
106+
public const string RelativeOrAbsolute = nameof(RelativeOrAbsolute);
81107
public const string Resize = nameof(Resize);
108+
public const string TryCreate = nameof(TryCreate);
82109
public const string TryGetValue = nameof(TryGetValue);
83110
public const string TryParse = nameof(TryParse);
111+
public const string Uri = nameof(Uri);
112+
public const string UriKind = nameof(UriKind);
84113
public const string Value = nameof(Value);
85114
}
86115

87-
private static class NotSupportedReason
88-
{
89-
public const string AbstractOrInterfaceNotSupported = "Abstract or interface types are not supported";
90-
public const string NeedPublicParameterlessConstructor = "Only objects with public parameterless ctors are supported";
91-
public const string CollectionNotSupported = "The collection type is not supported";
92-
public const string DictionaryKeyNotSupported = "The dictionary key type is not supported";
93-
public const string ElementTypeNotSupported = "The collection element type is not supported";
94-
public const string MultiDimArraysNotSupported = "Multidimensional arrays are not supported.";
95-
public const string NullableUnderlyingTypeNotSupported = "Nullable underlying type is not supported";
96-
public const string TypeNotDetectedAsInput = "Generator parser did not detect the type as input";
97-
public const string TypeNotSupported = "The type is not supported";
98-
}
99-
100116
private static class TypeFullName
101117
{
102118
public const string ConfigurationKeyNameAttribute = "Microsoft.Extensions.Configuration.ConfigurationKeyNameAttribute";
119+
public const string CultureInfo = "System.Globalization.CultureInfo";
120+
public const string DateOnly = "System.DateOnly";
121+
public const string DateTimeOffset = "System.DateTimeOffset";
103122
public const string Dictionary = "System.Collections.Generic.Dictionary`2";
104123
public const string GenericIDictionary = "System.Collections.Generic.IDictionary`2";
124+
public const string Guid = "System.Guid";
125+
public const string Half = "System.Half";
105126
public const string HashSet = "System.Collections.Generic.HashSet`1";
106127
public const string IConfiguration = "Microsoft.Extensions.Configuration.IConfiguration";
107128
public const string IConfigurationSection = "Microsoft.Extensions.Configuration.IConfigurationSection";
108129
public const string IDictionary = "System.Collections.Generic.IDictionary";
130+
public const string Int128 = "System.Int128";
109131
public const string ISet = "System.Collections.Generic.ISet`1";
110132
public const string IServiceCollection = "Microsoft.Extensions.DependencyInjection.IServiceCollection";
111133
public const string List = "System.Collections.Generic.List`1";
134+
public const string TimeOnly = "System.TimeOnly";
135+
public const string TimeSpan = "System.TimeSpan";
136+
public const string UInt128 = "System.UInt128";
137+
public const string Uri = "System.Uri";
138+
public const string Version = "System.Version";
112139
}
113140

114-
private static bool TypesAreEqual(ITypeSymbol first, ITypeSymbol second)
141+
private static bool TypesAreEqual(ITypeSymbol first, ITypeSymbol? second)
115142
=> first.Equals(second, SymbolEqualityComparer.Default);
116143
}
117144
}

0 commit comments

Comments
 (0)