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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
[release/8.0] Make src gen for property setters consistent with reflection by github-actions[bot] · Pull Request #92167 · dotnet/runtime · GitHub
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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [release/8.0] Make src gen for property setters consistent with reflection by github-actions[bot] · Pull Request #92167 · dotnet/runtime · GitHub
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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [release/8.0] Make src gen for property setters consistent with reflection by github-actions[bot] · Pull Request #92167 · dotnet/runtime · GitHub
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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' [release/8.0] Make src gen for property setters consistent with reflection by github-actions[bot] · Pull Request #92167 · dotnet/runtime · GitHub
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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [release/8.0] Make src gen for property setters consistent with reflection by github-actions[bot] · Pull Request #92167 · dotnet/runtime · GitHub
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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); [release/8.0] Make src gen for property setters consistent with reflection by github-actions[bot] · Pull Request #92167 · dotnet/runtime · GitHub
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 numberDiff line numberDiff line change
Expand Up@@ -148,7 +148,7 @@ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParam
EmitCheckForNullArgument_WithBlankLine(Identifier.instance, voidReturn: true);
_writer.WriteLine($$"""
var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.instance}};
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
{{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, defaultValueIfNotFound: false, {{binderOptionsArg}});
""");
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,7 @@ private void EmitGetCoreMethod()
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -110,7 +111,7 @@ private void EmitGetCoreMethod()
{
if (complexType.CanInstantiate)
{
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.instance, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.CallSetter);
_writer.WriteLine($"return {Identifier.instance};");
}
else if (type is ObjectSpec { InitExceptionMessage: string exMsg })
Expand DownExpand Up@@ -173,6 +174,7 @@ private void EmitGetValueCoreMethod()
Expression.sectionPath,
writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

EmitEndBlock();
Expand DownExpand Up@@ -207,7 +209,7 @@ private void EmitBindCoreMainMethod()

EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
_writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.instance};");
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
EmitBindingLogic(type, Identifier.temp, Identifier.configuration, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"return;");
EmitEndBlock();
}
Expand DownExpand Up@@ -235,7 +237,7 @@ private void EmitBindCoreMethods()
private void EmitBindCoreMethod(ComplexTypeSpec type)
{
string objParameterExpression = $"ref {type.DisplayString} {Identifier.instance}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, bool defaultValueIfNotFound, {Identifier.BinderOptions}? {Identifier.binderOptions})");

ComplexTypeSpec effectiveType = (ComplexTypeSpec)type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
Expand DownExpand Up@@ -334,8 +336,6 @@ private void EmitInitializeMethod(ObjectSpec type)
void EmitBindImplForMember(MemberSpec member)
{
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;

string parsedMemberDeclarationLhs = $"{memberType.DisplayString} {member.Name}";
string configKeyName = member.ConfigurationKeyName;
string parsedMemberAssignmentLhsExpr;
Expand All@@ -344,7 +344,7 @@ void EmitBindImplForMember(MemberSpec member)
{
case ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue }:
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
string condition = $@"if ({Identifier.configuration}[""{configKeyName}""] is not {parsedMemberDeclarationLhs})";
EmitThrowBlock(condition);
Expand DownExpand Up@@ -377,11 +377,12 @@ void EmitBindImplForMember(MemberSpec member)
member,
parsedMemberAssignmentLhsExpr,
sectionPathExpr: GetSectionPathFromConfigurationExpression(configKeyName),
canSet: true);
canSet: true,
InitializationKind.None);

if (canBindToMember)
{
if (errorOnFailedBinding)
if (member is ParameterSpec parameter && parameter.ErrorOnFailedBinding)
{
// Add exception logic for parameter ctors; must be present in configuration object.
EmitThrowBlock(condition: "else");
Expand DownExpand Up@@ -633,7 +634,7 @@ private void EmitPopulationImplForArray(EnumerableSpec type)

// Create list and bind elements.
string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
EmitBindingLogic(typeToInstantiate, tempIdentifier, Identifier.configuration, InitializationKind.Declaration, ValueDefaulting.None);

// Resize array and add binded elements.
_writer.WriteLine($$"""
Expand DownExpand Up@@ -661,6 +662,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
Expression.sectionPath,
(parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand All@@ -671,7 +673,7 @@ private void EmitPopulationImplForEnumerableWithAdd(EnumerableSpec type)
break;
case ComplexTypeSpec { CanInstantiate: true } complexType:
{
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration);
EmitBindingLogic(complexType, Identifier.value, Identifier.section, InitializationKind.Declaration, ValueDefaulting.None);
_writer.WriteLine($"{addExpr}({Identifier.value});");
}
break;
Expand All@@ -696,6 +698,7 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type)
Expression.sectionPath,
Emit_BindAndAddLogic_ForElement,
checkForNullSectionValue: false,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);

void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expand All@@ -710,6 +713,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
Expression.sectionPath,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull: false,
useIncrementalStringValueIdentifier: false);
}
break;
Expand DownExpand Up@@ -746,7 +750,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
EmitObjectInit(complexElementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
EmitEndBlock();

EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None);
EmitBindingLogic(complexElementType, Identifier.element, Identifier.section, InitializationKind.None, ValueDefaulting.None);
_writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}
break;
Expand DownExpand Up@@ -774,7 +778,8 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
canSet: property.CanSet);
canSet: property.CanSet,
InitializationKind.Declaration);
}
}
}
Expand All@@ -783,9 +788,11 @@ private bool EmitBindImplForMember(
MemberSpec member,
string memberAccessExpr,
string sectionPathExpr,
bool canSet)
bool canSet,
InitializationKind initializationKind)
{
TypeSpec effectiveMemberType = member.Type.EffectiveType;

string sectionParseExpr = GetSectionFromConfigurationExpression(member.ConfigurationKeyName);

switch (effectiveMemberType)
Expand All@@ -794,19 +801,20 @@ private bool EmitBindImplForMember(
{
if (canSet)
{
bool checkForNullSectionValue = member is ParameterSpec
? true
: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;

string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
bool useDefaultValueIfSectionValueIsNull =
initializationKind == InitializationKind.Declaration &&
member is PropertySpec &&
member.Type.IsValueType &&
member.Type.SpecKind is not TypeSpecKind.Nullable;

EmitBlankLineIfRequired();
EmitBindingLogic(
stringParsableType,
$@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
sectionPathExpr,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
checkForNullSectionValue,
writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"),
checkForNullSectionValue: true,
useDefaultValueIfSectionValueIsNull,
useIncrementalStringValueIdentifier: true);
}

Expand DownExpand Up@@ -906,14 +914,17 @@ private void EmitBindingLogicForComplexMember(
targetObjAccessExpr,
configArgExpr,
initKind,
writeOnSuccess);
ValueDefaulting.None,
writeOnSuccess
);
}

private void EmitBindingLogic(
ComplexTypeSpec type,
string memberAccessExpr,
string configArgExpr,
InitializationKind initKind,
ValueDefaulting valueDefaulting,
Action<string>? writeOnSuccess = null)
{
if (!type.HasBindableMembers)
Expand DownExpand Up@@ -952,7 +963,7 @@ private void EmitBindingLogic(

void EmitBindingLogic(string instanceToBindExpr, InitializationKind initKind)
{
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, {Identifier.binderOptions});";
string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {instanceToBindExpr}, defaultValueIfNotFound: {FormatDefaultValueIfNotFound()}, {Identifier.binderOptions});";

if (type.CanInstantiate)
{
Expand DownExpand Up@@ -984,6 +995,8 @@ void EmitBindCoreCall()
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(instanceToBindExpr);
}

string FormatDefaultValueIfNotFound() => valueDefaulting == ValueDefaulting.CallSetter ? "true" : "false";
}
}

Expand All@@ -993,6 +1006,7 @@ private void EmitBindingLogic(
string sectionPathExpr,
Action<string>? writeOnSuccess,
bool checkForNullSectionValue,
bool useDefaultValueIfSectionValueIsNull,
bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Expand All@@ -1018,6 +1032,14 @@ private void EmitBindingLogic(
EmitEndBlock();
}

if (useDefaultValueIfSectionValueIsNull)
{
parsedValueExpr = $"default";
EmitStartBlock($"else if (defaultValueIfNotFound)");
InvokeWriteOnSuccess();
EmitEndBlock();
}

void InvokeWriteOnSuccess() => writeOnSuccess?.Invoke(parsedValueExpr);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,23 @@ private enum InitializationKind
Declaration = 3,
}

/// <summary>
/// The type of defaulting for a property if it does not have a config entry.
/// This should only be applied for "Get" cases, not "Bind" and is also conditioned
/// on the source generated for a particular property as to whether it uses this value.
/// Note this is different than "InitializationKind.Declaration" since it only applied to
/// complex types and not arrays\enumerables.
/// </summary>
private enum ValueDefaulting
{
None = 0,

/// <summary>
/// Call the setter with the default value for the property's Type.
/// </summary>
CallSetter = 1,
}

private static class Expression
{
public const string configurationGetSection = "configuration.GetSection";
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,6 @@ public MemberSpec(ISymbol member)
}

public string Name { get; }
public bool ErrorOnFailedBinding { get; protected set; }
public string DefaultValueExpr { get; protected set; }

public required TypeSpec Type { get; init; }
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,8 @@ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
}
}

public bool ErrorOnFailedBinding { get; private set; }

public RefKind RefKind { get; }

public override bool CanGet => false;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,7 +54,7 @@ internal enum StringParsableTypeKind
None = 0,

/// <summary>
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
/// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and typeof(object).
/// </summary>
AssignFromSectionValue = 1,
Enum = 2,
Expand Down
Loading