Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update binder gen emitted-interceptor nullability to match framework impl #91180

Merged
merged 1 commit into from
Aug 28, 2023
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 @@ -96,19 +96,19 @@ private void EmitBindCoreCall(
EmitBindCoreCall(memberAccessExpr, initKind);
}

void EmitBindCoreCall(string objExpression, InitializationKind initKind)
void EmitBindCoreCall(string instanceExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {objExpression}, {Identifier.binderOptions});";
EmitObjectInit(objExpression, initKind);
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceExpr}, {Identifier.binderOptions});";
EmitObjectInit(instanceExpr, initKind);
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(objExpression);
writeOnSuccess?.Invoke(instanceExpr);
}

void EmitObjectInit(string objExpression, InitializationKind initKind)
void EmitObjectInit(string instanceExpr, InitializationKind initKind)
{
if (initKind is not InitializationKind.None)
{
this.EmitObjectInit(type, objExpression, initKind, configArgExpr);
this.EmitObjectInit(type, instanceExpr, initKind, configArgExpr);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using SourceGenerators;

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
Expand Down Expand Up @@ -101,13 +100,13 @@ private void EmitBindMethods_ConfigurationBinder()
return;
}

string objParamExpr = $"object? {Identifier.obj}";
string instanceParamExpr = $"object? {Identifier.instance}";

if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance))
{
EmitMethods(
MethodsToGen_ConfigurationBinder.Bind_instance,
additionalParams: objParamExpr,
additionalParams: instanceParamExpr,
configExpression: Identifier.configuration,
configureOptions: false);
}
Expand All @@ -116,7 +115,7 @@ private void EmitBindMethods_ConfigurationBinder()
{
EmitMethods(
MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions,
additionalParams: $"{objParamExpr}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}",
additionalParams: $"{instanceParamExpr}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}",
configExpression: Identifier.configuration,
configureOptions: true);
}
Expand All @@ -125,7 +124,7 @@ private void EmitBindMethods_ConfigurationBinder()
{
EmitMethods(
MethodsToGen_ConfigurationBinder.Bind_key_instance,
additionalParams: $"string {Identifier.key}, {objParamExpr}",
additionalParams: $"string {Identifier.key}, {instanceParamExpr}",
configExpression: $"{Expression.configurationGetSection}({Identifier.key})",
configureOptions: false);
}
Expand All @@ -141,17 +140,17 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitInterceptsLocationAnnotations(interceptorInfoList);
EmitStartBlock($"public static void {Identifier.Bind}_{type.DisplayString.ToIdentifierSubstring()}(this {Identifier.IConfiguration} {Identifier.configuration}, {additionalParams})");

if (!EmitInitException(type) && type.NeedsMemberBinding)
if (type.NeedsMemberBinding)
{
string binderOptionsArg = configureOptions ? $"{Identifier.GetBinderOptions}({Identifier.configureOptions})" : $"{Identifier.binderOptions}: null";

EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
if (!type.IsValueType)
{
EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
}
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.obj}};
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
""");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ private void EmitGetCoreMethod()
}
else if (!EmitInitException(effectiveType))
{
EmitBindCoreCall(effectiveType, Identifier.obj, Identifier.configuration, InitializationKind.Declaration);
_writer.WriteLine($"return {Identifier.obj};");
EmitBindCoreCall(effectiveType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
_writer.WriteLine($"return {Identifier.instance};");
}

EmitEndBlock();
Expand Down Expand Up @@ -168,9 +168,8 @@ private void EmitBindCoreMainMethod()
}

EmitBlankLineIfRequired();
EmitStartBlock($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}({Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
EmitStartBlock($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}({Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.instance}, Type {Identifier.type}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
EmitIConfigurationHasValueOrChildrenCheck(voidReturn: true);
_writer.WriteLine($"{Identifier.BinderOptions}? {Identifier.binderOptions} = {Identifier.GetBinderOptions}({Identifier.configureOptions});");
_writer.WriteLine();
Expand All @@ -184,7 +183,7 @@ private void EmitBindCoreMainMethod()
EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
if (!EmitInitException(effectiveType))
{
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.obj};");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindCoreCall(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
_writer.WriteLine($"return;");
}
Expand Down Expand Up @@ -213,9 +212,7 @@ private void EmitBindCoreMethods()

private void EmitBindCoreMethod(TypeSpec type)
{
Debug.Assert(type.CanInitialize);

string objParameterExpression = $"ref {type.DisplayString} {Identifier.obj}";
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");

TypeSpec effectiveType = type.EffectiveType;
Expand Down Expand Up @@ -618,15 +615,15 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Resize array and add binded elements.
_writer.WriteLine($$"""
{{Identifier.Int32}} {{Identifier.originalCount}} = {{Identifier.obj}}.{{Identifier.Length}};
{{Identifier.Array}}.{{Identifier.Resize}}(ref {{Identifier.obj}}, {{Identifier.originalCount}} + {{tempIdentifier}}.{{Identifier.Count}});
{{tempIdentifier}}.{{Identifier.CopyTo}}({{Identifier.obj}}, {{Identifier.originalCount}});
{{Identifier.Int32}} {{Identifier.originalCount}} = {{Identifier.instance}}.{{Identifier.Length}};
{{Identifier.Array}}.{{Identifier.Resize}}(ref {{Identifier.instance}}, {{Identifier.originalCount}} + {{tempIdentifier}}.{{Identifier.Count}});
{{tempIdentifier}}.{{Identifier.CopyTo}}({{Identifier.instance}}, {{Identifier.originalCount}});
""");
}

private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
{
EmitCollectionCastIfRequired(type, out string objIdentifier);
EmitCollectionCastIfRequired(type, out string instanceIdentifier);

Emit_Foreach_Section_In_ConfigChildren_StartBlock();

Expand All @@ -638,22 +635,22 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
stringParsableType,
Expression.sectionValue,
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{objIdentifier}.{Identifier.Add}({parsedValueExpr});"),
(parsedValueExpr) => _writer.WriteLine($"{instanceIdentifier}.{Identifier.Add}({parsedValueExpr});"),
checkForNullSectionValue: true,
useIncrementalStringValueIdentifier: false);
}
else
{
EmitBindCoreCall(elementType, Identifier.value, Identifier.section, InitializationKind.Declaration);
_writer.WriteLine($"{objIdentifier}.{Identifier.Add}({Identifier.value});");
_writer.WriteLine($"{instanceIdentifier}.{Identifier.Add}({Identifier.value});");
}

EmitEndBlock();
}

private void EmitBindCoreImplForDictionary(DictionarySpec type)
{
EmitCollectionCastIfRequired(type, out string objIdentifier);
EmitCollectionCastIfRequired(type, out string instanceIdentifier);

Emit_Foreach_Section_In_ConfigChildren_StartBlock();

Expand All @@ -677,7 +674,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
stringParsableElementType,
Expression.sectionValue,
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{objIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useIncrementalStringValueIdentifier: false);
}
Expand All @@ -696,7 +693,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
string expressionForElementIsNotNull = $"{Identifier.element} is not null";
string elementTypeDisplayString = elementType.DisplayString + (elementType.IsValueType ? string.Empty : "?");

string expressionForElementExists = $"{objIdentifier}.{Identifier.TryGetValue}({parsedKeyExpr}, out {elementTypeDisplayString} {Identifier.element})";
string expressionForElementExists = $"{instanceIdentifier}.{Identifier.TryGetValue}({parsedKeyExpr}, out {elementTypeDisplayString} {Identifier.element})";
string conditionToUseExistingElement = expressionForElementExists;

// If key already exists, bind to existing element instance if not null (for ref types).
Expand Down Expand Up @@ -727,7 +724,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
}

EmitBindCoreCall(elementType, Identifier.element, Identifier.section, InitializationKind.None);
_writer.WriteLine($"{objIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
}

Expand All @@ -747,7 +744,7 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
bool noSetter_And_IsReadonly = !property.CanSet && property.Type is CollectionSpec { InitializationStrategy: InitializationStrategy.ParameterizedConstructor };
if (property.ShouldBind() && !noSetter_And_IsReadonly)
{
string containingTypeRef = property.IsStatic ? type.DisplayString : Identifier.obj;
string containingTypeRef = property.IsStatic ? type.DisplayString : Identifier.instance;
EmitBindImplForMember(
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
Expand Down Expand Up @@ -883,14 +880,14 @@ private void EmitBindCoreCallForMember(
writeOnSuccess);
}

private void EmitCollectionCastIfRequired(CollectionSpec type, out string objIdentifier)
private void EmitCollectionCastIfRequired(CollectionSpec type, out string instanceIdentifier)
{
objIdentifier = Identifier.obj;
instanceIdentifier = Identifier.instance;
if (type.PopulationStrategy is CollectionPopulationStrategy.Cast_Then_Add)
{
objIdentifier = Identifier.temp;
instanceIdentifier = Identifier.temp;
_writer.WriteLine($$"""
if ({{Identifier.obj}} is not {{type.PopulationCastType!.DisplayString}} {{objIdentifier}})
if ({{Identifier.instance}} is not {{type.PopulationCastType!.DisplayString}} {{instanceIdentifier}})
{
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ private static class TypeDisplayString
private static class Identifier
{
public const string binderOptions = nameof(binderOptions);
public const string config = nameof(config);
public const string configureBinder = nameof(configureBinder);
public const string configureOptions = nameof(configureOptions);
public const string configuration = nameof(configuration);
public const string configSectionPath = nameof(configSectionPath);
Expand All @@ -55,7 +57,7 @@ private static class Identifier
public const string getPath = nameof(getPath);
public const string key = nameof(key);
public const string name = nameof(name);
public const string obj = nameof(obj);
public const string instance = nameof(instance);
public const string optionsBuilder = nameof(optionsBuilder);
public const string originalCount = nameof(originalCount);
public const string section = nameof(section);
Expand Down Expand Up @@ -211,12 +213,16 @@ private void EmitBlankLineIfRequired()
_emitBlankLineBeforeNextStatement = true;
}

private void EmitCheckForNullArgument_WithBlankLine(string paramName)
private void EmitCheckForNullArgument_WithBlankLine(string paramName, bool voidReturn = false)
{
string returnExpr = voidReturn
? "return"
: $"throw new ArgumentNullException(nameof({paramName}))";

_writer.WriteLine($$"""
if ({{paramName}} is null)
{
throw new ArgumentNullException(nameof({{paramName}}));
{{returnExpr}};
}
""");

Expand Down
Loading