Skip to content

Commit

Permalink
Update binder gen emitted-interceptor nullability to match framework …
Browse files Browse the repository at this point in the history
…impl (dotnet#91180)
  • Loading branch information
layomia committed Aug 30, 2023
1 parent 41b2c8f commit 8e14319
Show file tree
Hide file tree
Showing 34 changed files with 699 additions and 608 deletions.
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

0 comments on commit 8e14319

Please sign in to comment.