Skip to content

Commit 3a59507

Browse files
authored
Fix Config Source Gen to avoid compilation error missing System.Collections.Generic namespace (#121364)
Fixes #118630 The configuration source generator can produce code that references collection types such as HashSet<T> without including the System.Collections.Generic namespace. This results in a compilation error. More users have started encountering this issue when using project templates like webapiaot and disabling ImplicitUsings.
1 parent 2e85cbd commit 3a59507

File tree

47 files changed

+264
-227
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+264
-227
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ private static class Expression
5353
private static class TypeDisplayString
5454
{
5555
public const string NullableActionOfBinderOptions = "Action<BinderOptions>?";
56-
public const string OptionsBuilderOfTOptions = $"OptionsBuilder<{Identifier.TOptions}>";
57-
public const string HashSetOfString = "HashSet<string>";
58-
public const string LazyHashSetOfString = "Lazy<HashSet<string>>";
59-
public const string ListOfString = "List<string>";
56+
public const string OptionsBuilderOfTOptions = $"global::Microsoft.Extensions.Options.OptionsBuilder<{Identifier.TOptions}>";
57+
public const string HashSetOfString = "global::System.Collections.Generic.HashSet<string>";
58+
public const string LazyHashSetOfString = "Lazy<global::System.Collections.Generic.HashSet<string>>";
59+
public const string ListOfString = "global::System.Collections.Generic.List<string>";
6060
}
6161

6262
private static class Identifier

src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/TypeIndex.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,12 @@ public static string GetPopulationCastTypeDisplayString(CollectionWithCtorInitSp
8585

8686
public static string GetGenericTypeDisplayString(CollectionWithCtorInitSpec type, Enum genericProxyTypeName)
8787
{
88-
string proxyTypeNameStr = genericProxyTypeName.ToString();
88+
string typeFNQ = type.TypeRef.FullyQualifiedName;
89+
int genericIndex = typeFNQ.IndexOf('<');
90+
91+
// To get the namespace.
92+
int lastDotIndex = genericIndex > 0 ? typeFNQ.LastIndexOf('.', genericIndex) : -1;
93+
string proxyTypeNameStr = lastDotIndex >= 0 ? $"{typeFNQ.Substring(0, lastDotIndex + 1)}{genericProxyTypeName}" : genericProxyTypeName.ToString();
8994
string elementTypeFQN = type.ElementTypeRef.FullyQualifiedName;
9095

9196
if (type is EnumerableSpec)

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
9090
#endregion IConfiguration extensions.
9191

9292
#region Core binding extensions.
93-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
93+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
9494

9595
public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List<int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
9696
{
@@ -212,17 +212,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
212212

213213

214214
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
215-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
215+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
216216
{
217217
if (binderOptions?.ErrorOnUnknownConfiguration is true)
218218
{
219-
List<string>? temp = null;
219+
global::System.Collections.Generic.List<string>? temp = null;
220220

221221
foreach (IConfigurationSection section in configuration.GetChildren())
222222
{
223223
if (!keys.Value.Contains(section.Key))
224224
{
225-
(temp ??= new List<string>()).Add($"'{section.Key}'");
225+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
226226
}
227227
}
228228

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
5454
#endregion IConfiguration extensions.
5555

5656
#region Core binding extensions.
57-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
57+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
5858

5959
public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List<int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
6060
{
@@ -176,17 +176,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
176176

177177

178178
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
179-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
179+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
180180
{
181181
if (binderOptions?.ErrorOnUnknownConfiguration is true)
182182
{
183-
List<string>? temp = null;
183+
global::System.Collections.Generic.List<string>? temp = null;
184184

185185
foreach (IConfigurationSection section in configuration.GetChildren())
186186
{
187187
if (!keys.Value.Contains(section.Key))
188188
{
189-
(temp ??= new List<string>()).Add($"'{section.Key}'");
189+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
190190
}
191191
}
192192

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
5454
#endregion IConfiguration extensions.
5555

5656
#region Core binding extensions.
57-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
57+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
5858

5959
public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List<int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
6060
{
@@ -176,17 +176,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
176176

177177

178178
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
179-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
179+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
180180
{
181181
if (binderOptions?.ErrorOnUnknownConfiguration is true)
182182
{
183-
List<string>? temp = null;
183+
global::System.Collections.Generic.List<string>? temp = null;
184184

185185
foreach (IConfigurationSection section in configuration.GetChildren())
186186
{
187187
if (!keys.Value.Contains(section.Key))
188188
{
189-
(temp ??= new List<string>()).Add($"'{section.Key}'");
189+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
190190
}
191191
}
192192

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
5454
#endregion IConfiguration extensions.
5555

5656
#region Core binding extensions.
57-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
57+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
5858

5959
public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List<int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
6060
{
@@ -176,17 +176,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
176176

177177

178178
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
179-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
179+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
180180
{
181181
if (binderOptions?.ErrorOnUnknownConfiguration is true)
182182
{
183-
List<string>? temp = null;
183+
global::System.Collections.Generic.List<string>? temp = null;
184184

185185
foreach (IConfigurationSection section in configuration.GetChildren())
186186
{
187187
if (!keys.Value.Contains(section.Key))
188188
{
189-
(temp ??= new List<string>()).Add($"'{section.Key}'");
189+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
190190
}
191191
}
192192

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get.generated.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
5252
#endregion IConfiguration extensions.
5353

5454
#region Core binding extensions.
55-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
56-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
55+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
56+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
5757

5858
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
5959
{
@@ -234,17 +234,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
234234

235235

236236
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
237-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
237+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
238238
{
239239
if (binderOptions?.ErrorOnUnknownConfiguration is true)
240240
{
241-
List<string>? temp = null;
241+
global::System.Collections.Generic.List<string>? temp = null;
242242

243243
foreach (IConfigurationSection section in configuration.GetChildren())
244244
{
245245
if (!keys.Value.Contains(section.Key))
246246
{
247-
(temp ??= new List<string>()).Add($"'{section.Key}'");
247+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
248248
}
249249
}
250250

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
4040
#endregion IConfiguration extensions.
4141

4242
#region Core binding extensions.
43-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
43+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
4444

4545
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
4646
{
@@ -198,17 +198,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
198198

199199

200200
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
201-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
201+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
202202
{
203203
if (binderOptions?.ErrorOnUnknownConfiguration is true)
204204
{
205-
List<string>? temp = null;
205+
global::System.Collections.Generic.List<string>? temp = null;
206206

207207
foreach (IConfigurationSection section in configuration.GetChildren())
208208
{
209209
if (!keys.Value.Contains(section.Key))
210210
{
211-
(temp ??= new List<string>()).Add($"'{section.Key}'");
211+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
212212
}
213213
}
214214

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
4040
#endregion IConfiguration extensions.
4141

4242
#region Core binding extensions.
43-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
43+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
4444

4545
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
4646
{
@@ -198,17 +198,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
198198

199199

200200
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
201-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
201+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
202202
{
203203
if (binderOptions?.ErrorOnUnknownConfiguration is true)
204204
{
205-
List<string>? temp = null;
205+
global::System.Collections.Generic.List<string>? temp = null;
206206

207207
foreach (IConfigurationSection section in configuration.GetChildren())
208208
{
209209
if (!keys.Value.Contains(section.Key))
210210
{
211-
(temp ??= new List<string>()).Add($"'{section.Key}'");
211+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
212212
}
213213
}
214214

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf.generated.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
4040
#endregion IConfiguration extensions.
4141

4242
#region Core binding extensions.
43-
private readonly static Lazy<HashSet<string>> s_configKeys_Program__MyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
43+
private readonly static Lazy<global::System.Collections.Generic.HashSet<string>> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
4444

4545
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
4646
{
@@ -97,17 +97,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
9797

9898

9999
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
100-
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
100+
public static void ValidateConfigurationKeys(Type type, Lazy<global::System.Collections.Generic.HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
101101
{
102102
if (binderOptions?.ErrorOnUnknownConfiguration is true)
103103
{
104-
List<string>? temp = null;
104+
global::System.Collections.Generic.List<string>? temp = null;
105105

106106
foreach (IConfigurationSection section in configuration.GetChildren())
107107
{
108108
if (!keys.Value.Contains(section.Key))
109109
{
110-
(temp ??= new List<string>()).Add($"'{section.Key}'");
110+
(temp ??= new global::System.Collections.Generic.List<string>()).Add($"'{section.Key}'");
111111
}
112112
}
113113

0 commit comments

Comments
 (0)