Skip to content

Commit 57877ec

Browse files
committed
Extend BindableProperty source gen to handle partial property initializers
1 parent 4ed306b commit 57877ec

File tree

7 files changed

+277
-94
lines changed

7 files changed

+277
-94
lines changed

src/CommunityToolkit.Maui.SourceGenerators.Internal.UnitTests/BindablePropertyAttributeSourceGeneratorTests/CommonUsageTests.cs

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ public partial class {{defaultTestClassName}}
3838
/// Backing BindableProperty for the <see cref = "Text"/> property.
3939
/// </summary>
4040
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
41-
public partial string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
41+
bool __initializingText = false;
42+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
4243
}
4344
""";
4445

@@ -79,7 +80,8 @@ public partial class {{defaultTestClassName}}
7980
/// Backing BindableProperty for the <see cref = "Text"/> property.
8081
/// </summary>
8182
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), (string)"Hello", Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
82-
public partial string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
83+
bool __initializingText = false;
84+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
8385
}
8486
""";
8587

@@ -120,7 +122,8 @@ public partial class {{defaultTestClassName}}
120122
/// Backing BindableProperty for the <see cref = "Text"/> property.
121123
/// </summary>
122124
public new static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
123-
public new partial string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
125+
bool __initializingText = false;
126+
public new partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
124127
}
125128
""";
126129

@@ -161,7 +164,8 @@ public partial class {{defaultTestClassName}}
161164
/// Backing BindableProperty for the <see cref = "Text"/> property.
162165
/// </summary>
163166
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
164-
public partial string? Text { get => (string? )GetValue(TextProperty); set => SetValue(TextProperty, value); }
167+
bool __initializingText = false;
168+
public partial string? Text { get => __initializingText ? field : (string? )GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
165169
}
166170
""";
167171

@@ -205,13 +209,15 @@ public partial class {{defaultTestClassName}}
205209
/// Backing BindableProperty for the <see cref = "Text"/> property.
206210
/// </summary>
207211
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
208-
public partial string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
212+
bool __initializingText = false;
213+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
209214
210215
/// <summary>
211216
/// Backing BindableProperty for the <see cref = "Number"/> property.
212217
/// </summary>
213218
public static readonly global::Microsoft.Maui.Controls.BindableProperty NumberProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Number", typeof(int), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
214-
public partial int Number { get => (int)GetValue(NumberProperty); set => SetValue(NumberProperty, value); }
219+
bool __initializingNumber = false;
220+
public partial int Number { get => __initializingNumber ? field : (int)GetValue(NumberProperty); set => SetValue(NumberProperty, field = value); }
215221
}
216222
""";
217223

@@ -265,7 +271,8 @@ public partial class {{defaultTestClassName}}
265271
/// Backing BindableProperty for the <see cref = "Value"/> property.
266272
/// </summary>
267273
public static readonly global::Microsoft.Maui.Controls.BindableProperty ValueProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Value", typeof(int), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), (int)42, (Microsoft.Maui.Controls.BindingMode)1, ValidateValue, OnPropertyChanged, OnPropertyChanging, CoerceValue, CreateDefaultValue);
268-
public partial int Value { get => (int)GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
274+
bool __initializingValue = false;
275+
public partial int Value { get => __initializingValue ? field : (int)GetValue(ValueProperty); set => SetValue(ValueProperty, field = value); }
269276
}
270277
""";
271278

@@ -306,7 +313,8 @@ internal partial class TestView
306313
/// Backing BindableProperty for the <see cref = "Text"/> property.
307314
/// </summary>
308315
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
309-
public partial string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
316+
bool __initializingText = false;
317+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
310318
}
311319
""";
312320

@@ -386,7 +394,8 @@ public partial class {{defaultTestClassName}}
386394
/// Backing BindableProperty for the <see cref = "Text"/> property.
387395
/// </summary>
388396
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof(TestNamespace.TestView), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
389-
public partial string Text { get => (string)GetValue(TextProperty); internal set => SetValue(TextProperty, value); }
397+
bool __initializingText = false;
398+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); internal set => SetValue(TextProperty, field = value); }
390399
}
391400
""";
392401

@@ -428,7 +437,8 @@ public partial class {{defaultTestClassName}}
428437
/// </summary>
429438
static readonly global::Microsoft.Maui.Controls.BindablePropertyKey textPropertyKey = global::Microsoft.Maui.Controls.BindableProperty.CreateReadOnly("Text", typeof(string), typeof(TestNamespace.TestView), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
430439
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = textPropertyKey.BindableProperty;
431-
public partial string Text { get => (string)GetValue(TextProperty); private protected set => SetValue(textPropertyKey, value); }
440+
bool __initializingText = false;
441+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); private protected set => SetValue(textPropertyKey, field = value); }
432442
}
433443
""";
434444

@@ -469,7 +479,8 @@ public partial class {{defaultTestClassName}}
469479
/// Backing BindableProperty for the <see cref = "Text"/> property.
470480
/// </summary>
471481
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof(TestNamespace.TestView), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
472-
public partial string Text { get => (string)GetValue(TextProperty); protected internal set => SetValue(TextProperty, value); }
482+
bool __initializingText = false;
483+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); protected internal set => SetValue(TextProperty, field = value); }
473484
}
474485
""";
475486

@@ -511,7 +522,8 @@ public partial class {{defaultTestClassName}}
511522
/// </summary>
512523
static readonly global::Microsoft.Maui.Controls.BindablePropertyKey textPropertyKey = global::Microsoft.Maui.Controls.BindableProperty.CreateReadOnly("Text", typeof(string), typeof(TestNamespace.TestView), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
513524
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = textPropertyKey.BindableProperty;
514-
public partial string Text { get => (string)GetValue(TextProperty); protected set => SetValue(textPropertyKey, value); }
525+
bool __initializingText = false;
526+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); protected set => SetValue(textPropertyKey, field = value); }
515527
}
516528
""";
517529

@@ -553,7 +565,8 @@ public partial class {{defaultTestClassName}}
553565
/// </summary>
554566
static readonly global::Microsoft.Maui.Controls.BindablePropertyKey textPropertyKey = global::Microsoft.Maui.Controls.BindableProperty.CreateReadOnly("Text", typeof(string), typeof(TestNamespace.TestView), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
555567
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = textPropertyKey.BindableProperty;
556-
public partial string Text { get => (string)GetValue(TextProperty); private set => SetValue(textPropertyKey, value); }
568+
bool __initializingText = false;
569+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); private set => SetValue(textPropertyKey, field = value); }
557570
}
558571
""";
559572

@@ -595,7 +608,8 @@ public partial class {{defaultTestClassName}}
595608
/// </summary>
596609
static readonly global::Microsoft.Maui.Controls.BindablePropertyKey textPropertyKey = global::Microsoft.Maui.Controls.BindableProperty.CreateReadOnly("Text", typeof(string), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
597610
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = textPropertyKey.BindableProperty;
598-
public partial string Text { get => (string)GetValue(TextProperty); }
611+
bool __initializingText = false;
612+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); }
599613
}
600614
""";
601615

@@ -640,16 +654,69 @@ public partial class {{defaultTestClassName}}
640654
/// Backing BindableProperty for the <see cref = "Position"/> property.
641655
/// </summary>
642656
public static readonly global::Microsoft.Maui.Controls.BindableProperty PositionProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Position", typeof(System.TimeSpan), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), global::System.TimeSpan.Zero, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
643-
public partial System.TimeSpan Position { get => (System.TimeSpan)GetValue(PositionProperty); set => SetValue(PositionProperty, value); }
657+
bool __initializingPosition = false;
658+
public partial System.TimeSpan Position { get => __initializingPosition ? field : (System.TimeSpan)GetValue(PositionProperty); set => SetValue(PositionProperty, field = value); }
644659
645660
/// <summary>
646661
/// Backing BindableProperty for the <see cref = "CustomDuration"/> property.
647662
/// </summary>
648663
public static readonly global::Microsoft.Maui.Controls.BindableProperty CustomDurationProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("CustomDuration", typeof(System.TimeSpan), typeof({{defaultTestNamespace}}.{{defaultTestClassName}}), new global::System.TimeSpan(900000000), Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
649-
public partial System.TimeSpan CustomDuration { get => (System.TimeSpan)GetValue(CustomDurationProperty); set => SetValue(CustomDurationProperty, value); }
664+
bool __initializingCustomDuration = false;
665+
public partial System.TimeSpan CustomDuration { get => __initializingCustomDuration ? field : (System.TimeSpan)GetValue(CustomDurationProperty); set => SetValue(CustomDurationProperty, field = value); }
650666
}
651667
""";
652668

653669
await VerifySourceGeneratorAsync(source, expectedGenerated);
654670
}
671+
672+
[Fact]
673+
public async Task GenerateBindableProperty_WithInitializers_GeneratesCorrectCode()
674+
{
675+
const string source =
676+
/* language=C#-test */
677+
//lang=csharp
678+
$$"""
679+
using CommunityToolkit.Maui;
680+
using Microsoft.Maui.Controls;
681+
682+
namespace {{defaultTestNamespace}};
683+
684+
public partial class {{defaultTestClassName}} : View
685+
{
686+
[BindablePropertyAttribute]
687+
public partial string Text { get; set; } = "Initial Value";
688+
}
689+
""";
690+
691+
const string expectedGenerated =
692+
/* language=C#-test */
693+
//lang=csharp
694+
$$"""
695+
// <auto-generated>
696+
// See: CommunityToolkit.Maui.SourceGenerators.Internal.BindablePropertyAttributeSourceGenerator
697+
#pragma warning disable
698+
#nullable enable
699+
namespace {{defaultTestNamespace}};
700+
public partial class {{defaultTestClassName}}
701+
{
702+
/// <summary>
703+
/// Backing BindableProperty for the <see cref = "Text"/> property.
704+
/// </summary>
705+
public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Text", typeof(string), typeof(TestNamespace.TestView), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, __createDefaultText);
706+
bool __initializingText = false;
707+
public partial string Text { get => __initializingText ? field : (string)GetValue(TextProperty); set => SetValue(TextProperty, field = value); }
708+
709+
static object __createDefaultText(Microsoft.Maui.Controls.BindableObject bindable)
710+
{
711+
((TestView)bindable).__initializingText = true;
712+
var defaultValue = ((TestView)bindable).Text;
713+
((TestView)bindable).__initializingText = false;
714+
return defaultValue;
715+
}
716+
}
717+
""";
718+
719+
await VerifySourceGeneratorAsync(source, expectedGenerated);
720+
}
721+
655722
}

0 commit comments

Comments
 (0)