From 587373a20dce89e3f7f78f7aa9a819731890f624 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Mon, 28 Jul 2025 21:31:46 -0300 Subject: [PATCH 1/8] SG update --- ...indablePropertyAttributeSourceGenerator.cs | 86 +++++++++++++------ .../Helpers/AttributeExtensions.cs | 9 +- 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index a494eacdf2..a2dcc16c0d 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Text; using CommunityToolkit.Maui.SourceGenerators.Helpers; @@ -26,10 +27,10 @@ public class BindablePropertyAttributeSourceGenerator : IIncrementalGenerator #nullable enable namespace CommunityToolkit.Maui; - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] sealed partial class BindablePropertyAttribute : Attribute { - public string PropertyName { get; } = string.Empty; + public string? PropertyName { get; } public Type? DeclaringType { get; set; } public object? DefaultValue { get; set; } public string DefaultBindingMode { get; set; } = string.Empty; @@ -43,30 +44,67 @@ public BindablePropertyAttribute(string propertyName) { PropertyName = propertyName; } + + public BindablePropertyAttribute() + { + } } """; public void Initialize(IncrementalGeneratorInitializationContext context) { + +#if DEBUG + + if (!Debugger.IsAttached) + { + // To debug this SG, unccoment the line below and rebuild the SourceGenerator project. + + //Debugger.Launch(); + } +#endif + context.RegisterPostInitializationOutput(ctx => ctx.AddSource("BindablePropertyAttribute.g.cs", SourceText.From(bpAttribute, Encoding.UTF8))); var provider = context.SyntaxProvider.ForAttributeWithMetadataName("CommunityToolkit.Maui.BindablePropertyAttribute`1", SyntaxPredicate, SemanticTransform) .Where(static x => x.ClassInformation != default || !x.BindableProperties.IsEmpty) - .Collect() - .SelectMany(static (types, _) => types); + .Collect(); - context.RegisterSourceOutput(provider, Execute); + context.RegisterSourceOutput(provider, ExecuteAllValues); } - static void Execute(SourceProductionContext context, SemanticValues semanticValues) + static void ExecuteAllValues(SourceProductionContext context, ImmutableArray semanticValues) { - var source = GenerateSource(semanticValues); - SourceStringService.FormatText(ref source); - context.AddSource($"{semanticValues.ClassInformation.ClassName}.g.cs", SourceText.From(source, Encoding.UTF8)); + var groupedValues = semanticValues + .GroupBy(sv => (sv.ClassInformation.ClassName, sv.ClassInformation.ContainingNamespace)) + .ToDictionary(d => d.Key, d => d.ToArray()); + + foreach (var kvp in groupedValues) + { + var (className, containingNamespace) = kvp.Key; + var values = kvp.Value; + + if (values.Length is 0 || string.IsNullOrEmpty(className) || string.IsNullOrEmpty(containingNamespace)) + { + continue; + } + + var bindableProperties = values.SelectMany(x => x.BindableProperties).ToImmutableArray(); + + var classAccessibility = values[0].ClassInformation.DeclaredAccessibility; + + var combinedClassInfo = new ClassInformation(className, classAccessibility, containingNamespace); + var combinedValues = new SemanticValues(combinedClassInfo, bindableProperties); + + var source = GenerateSource(combinedValues); + SourceStringService.FormatText(ref source); + context.AddSource($"{className}.g.cs", SourceText.From(source, Encoding.UTF8)); + } } + static string GenerateSource(SemanticValues value) { var sb = new StringBuilder( @@ -124,17 +162,12 @@ static void GenerateBindableProperty(StringBuilder sb, BindablePropertyModel inf static void GenerateProperty(StringBuilder sb, BindablePropertyModel info) { - /* - /// - */ - sb.AppendLine("/// "); - - //public string Text + //public partial string Text //{ // get => (string)GetValue(TextProperty); // set => SetValue(TextProperty, value); //} - sb.AppendLine($"public {info.ReturnType} {info.PropertyName}") + sb.AppendLine($"public partial {info.ReturnType} {info.PropertyName}") .AppendLine("{") .Append("get => (") .Append(info.ReturnType) @@ -148,30 +181,33 @@ static void GenerateProperty(StringBuilder sb, BindablePropertyModel info) static SemanticValues SemanticTransform(GeneratorAttributeSyntaxContext context, CancellationToken cancellationToken) { - var classDeclarationSyntax = Unsafe.As(context.TargetNode); + var propertyDeclarationSyntax = Unsafe.As(context.TargetNode); var semanticModel = context.SemanticModel; - var classSymbol = (ITypeSymbol?)semanticModel.GetDeclaredSymbol(classDeclarationSyntax, cancellationToken); + var propertySymbol = (IPropertySymbol?)semanticModel.GetDeclaredSymbol(propertyDeclarationSyntax, cancellationToken); - if (classSymbol is null) + if (propertySymbol is null) { return emptySemanticValues; } - var classInfo = new ClassInformation(classSymbol.Name, classSymbol.DeclaredAccessibility.ToString().ToLower(), classSymbol.ContainingNamespace.ToDisplayString()); + var @namespace = propertySymbol.ContainingNamespace.ToDisplayString(); + var className = propertySymbol.ContainingType.Name; + var classAccessibility = propertySymbol.ContainingSymbol.DeclaredAccessibility.ToString().ToLower(); + var propertyInfo = new ClassInformation(className, classAccessibility, @namespace); var bindablePropertyModels = new List(context.Attributes.Length); for (var index = 0; index < context.Attributes.Length; index++) { var attributeData = context.Attributes[index]; - bindablePropertyModels.Add(GetAttributeValues(attributeData, classSymbol?.ToString() ?? string.Empty)); + bindablePropertyModels.Add(GetAttributeValues(attributeData, propertySymbol.ToString() ?? string.Empty, propertySymbol.Name)); } - return new(classInfo, bindablePropertyModels.ToImmutableArray()); + return new(propertyInfo, bindablePropertyModels.ToImmutableArray()); } - static BindablePropertyModel GetAttributeValues(in AttributeData attributeData, in string declaringTypeString) + static BindablePropertyModel GetAttributeValues(in AttributeData attributeData, in string declaringTypeString, in string defaultName) { if (attributeData.AttributeClass is null) { @@ -186,7 +222,7 @@ static BindablePropertyModel GetAttributeValues(in AttributeData attributeData, var declaringType = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.DeclaringType), declaringTypeString); var propertyChangedMethodName = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.PropertyChangedMethodName)); var propertyChangingMethodName = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.PropertyChangingMethodName)); - var propertyName = attributeData.GetConstructorArgumentsAttributeValueByNameAsString(); + var propertyName = attributeData.GetConstructorArgumentsAttributeValueByNameAsString(defaultName); var validateValueMethodName = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.ValidateValueMethodName)); return new BindablePropertyModel @@ -205,5 +241,5 @@ static BindablePropertyModel GetAttributeValues(in AttributeData attributeData, } static bool SyntaxPredicate(SyntaxNode node, CancellationToken cancellationToken) => - node is ClassDeclarationSyntax { AttributeLists.Count: > 0 }; + node is PropertyDeclarationSyntax { AttributeLists.Count: > 0 }; } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/Helpers/AttributeExtensions.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/Helpers/AttributeExtensions.cs index d2fb797b30..e9d0c66167 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/Helpers/AttributeExtensions.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/Helpers/AttributeExtensions.cs @@ -17,11 +17,16 @@ public static string GetNamedArgumentsAttributeValueByNameAsString(this Attribut return data.Value is null ? placeholder : data.Value.ToString(); } - public static string GetConstructorArgumentsAttributeValueByNameAsString(this AttributeData attribute) + public static string GetConstructorArgumentsAttributeValueByNameAsString(this AttributeData attribute, string placeholder) { + if (attribute.ConstructorArguments.Length is 0) + { + return placeholder; + } + var data = attribute.ConstructorArguments[0]; - return data.Value is null ? throw new InvalidOperationException() : data.Value.ToString(); + return data.Value is null ? placeholder : data.Value.ToString(); } } \ No newline at end of file From 6c52a3862386783746849025d544485eb826cbaa Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Mon, 28 Jul 2025 21:33:52 -0300 Subject: [PATCH 2/8] update control --- ...indablePropertyAttributeSourceGenerator.cs | 7 +--- .../Views/Expander/Expander.shared.cs | 37 ++++++++++++++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index a2dcc16c0d..78c340e9ae 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -198,11 +198,8 @@ static SemanticValues SemanticTransform(GeneratorAttributeSyntaxContext context, var bindablePropertyModels = new List(context.Attributes.Length); - for (var index = 0; index < context.Attributes.Length; index++) - { - var attributeData = context.Attributes[index]; - bindablePropertyModels.Add(GetAttributeValues(attributeData, propertySymbol.ToString() ?? string.Empty, propertySymbol.Name)); - } + var attributeData = context.Attributes[0]; + bindablePropertyModels.Add(GetAttributeValues(attributeData, propertySymbol.ToString() ?? string.Empty, propertySymbol.Name)); return new(propertyInfo, bindablePropertyModels.ToImmutableArray()); } diff --git a/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs b/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs index cad239f1e3..52b1c30f6f 100644 --- a/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs @@ -6,16 +6,41 @@ namespace CommunityToolkit.Maui.Views; /// -[BindableProperty("Header", PropertyChangedMethodName = nameof(OnHeaderPropertyChanged))] -[BindableProperty("Content", PropertyChangedMethodName = nameof(OnContentPropertyChanged))] -[BindableProperty("IsExpanded", PropertyChangedMethodName = nameof(OnIsExpandedPropertyChanged))] -[BindableProperty("CommandParameter")] -[BindableProperty("Command")] [ContentProperty(nameof(Content))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] [RequiresUnreferencedCode("Calls Microsoft.Maui.Controls.Binding.Binding(String, BindingMode, IValueConverter, Object, String, Object)")] public partial class Expander : ContentView, IExpander { + /// + /// Gets or sets the command to execute when the expander is expanded or collapsed. + /// + [BindableProperty()] + public partial ICommand Command { get; set; } + + /// + /// Gets or sets the parameter to pass to the property. + /// + [BindableProperty()] + public partial object CommandParameter { get; set; } + + /// + /// Gets or sets a value indicating whether the expander is expanded. + /// + [BindableProperty(PropertyChangedMethodName = nameof(OnIsExpandedPropertyChanged))] + public partial bool IsExpanded { get; set; } + + /// + /// Gets or sets the content to be expanded or collapsed. + /// + [BindableProperty(PropertyChangedMethodName = nameof(OnContentPropertyChanged))] + public new partial IView Content { get; set; } + + /// + /// Gets or sets the header view of the expander. + /// + [BindableProperty(PropertyChangedMethodName = nameof(OnHeaderPropertyChanged))] + public partial IView Header { get; set; } + /// /// Backing BindableProperty for the property. /// @@ -43,7 +68,7 @@ public Expander() } /// - /// Triggered when the value of changes + /// Triggered when the value of changes. /// public event EventHandler ExpandedChanged { From 94f1ef262db375d35ea0b92809605ed90418b5be Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Mon, 28 Jul 2025 18:40:59 -0700 Subject: [PATCH 3/8] Update BindablePropertyAttributeSourceGenerator.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../BindablePropertyAttributeSourceGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index 78c340e9ae..8c6184e7f5 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -58,7 +58,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (!Debugger.IsAttached) { - // To debug this SG, unccoment the line below and rebuild the SourceGenerator project. + // To debug this SG, uncomment the line below and rebuild the SourceGenerator project. //Debugger.Launch(); } From 9168ab1a67ee42886e5cbaaf0836ab8e23eb69ec Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Mon, 28 Jul 2025 23:15:32 -0300 Subject: [PATCH 4/8] remove new keyword --- src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs b/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs index 52b1c30f6f..213dd83384 100644 --- a/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs @@ -33,7 +33,7 @@ public partial class Expander : ContentView, IExpander /// Gets or sets the content to be expanded or collapsed. /// [BindableProperty(PropertyChangedMethodName = nameof(OnContentPropertyChanged))] - public new partial IView Content { get; set; } + public partial IView Content { get; set; } /// /// Gets or sets the header view of the expander. From 644c60b487828b8fab0f281e77a091c15e1d93d4 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Mon, 28 Jul 2025 23:34:20 -0300 Subject: [PATCH 5/8] fix property type --- .../BindablePropertyAttributeSourceGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index 8c6184e7f5..32fc2238a5 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -199,7 +199,7 @@ static SemanticValues SemanticTransform(GeneratorAttributeSyntaxContext context, var bindablePropertyModels = new List(context.Attributes.Length); var attributeData = context.Attributes[0]; - bindablePropertyModels.Add(GetAttributeValues(attributeData, propertySymbol.ToString() ?? string.Empty, propertySymbol.Name)); + bindablePropertyModels.Add(GetAttributeValues(attributeData, propertySymbol.Type.ToDisplayString(), propertySymbol.Name)); return new(propertyInfo, bindablePropertyModels.ToImmutableArray()); } From 987ff0053d13de39092c90a08057d42e145c7da9 Mon Sep 17 00:00:00 2001 From: Pedro Jesus Date: Sat, 9 Aug 2025 20:43:47 -0300 Subject: [PATCH 6/8] code review --- .../BindablePropertyAttributeSourceGenerator.cs | 12 ++++++------ .../Views/Expander/Expander.shared.cs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index 32fc2238a5..0cdfb1d44a 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -28,7 +28,7 @@ public class BindablePropertyAttributeSourceGenerator : IIncrementalGenerator namespace CommunityToolkit.Maui; [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] - sealed partial class BindablePropertyAttribute : Attribute + sealed partial class BindablePropertyAttribute : Attribute { public string? PropertyName { get; } public Type? DeclaringType { get; set; } @@ -66,7 +66,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterPostInitializationOutput(ctx => ctx.AddSource("BindablePropertyAttribute.g.cs", SourceText.From(bpAttribute, Encoding.UTF8))); - var provider = context.SyntaxProvider.ForAttributeWithMetadataName("CommunityToolkit.Maui.BindablePropertyAttribute`1", + var provider = context.SyntaxProvider.ForAttributeWithMetadataName("CommunityToolkit.Maui.BindablePropertyAttribute", SyntaxPredicate, SemanticTransform) .Where(static x => x.ClassInformation != default || !x.BindableProperties.IsEmpty) .Collect(); @@ -193,25 +193,25 @@ static SemanticValues SemanticTransform(GeneratorAttributeSyntaxContext context, var @namespace = propertySymbol.ContainingNamespace.ToDisplayString(); var className = propertySymbol.ContainingType.Name; var classAccessibility = propertySymbol.ContainingSymbol.DeclaredAccessibility.ToString().ToLower(); + var returnType = propertySymbol.Type; var propertyInfo = new ClassInformation(className, classAccessibility, @namespace); var bindablePropertyModels = new List(context.Attributes.Length); var attributeData = context.Attributes[0]; - bindablePropertyModels.Add(GetAttributeValues(attributeData, propertySymbol.Type.ToDisplayString(), propertySymbol.Name)); + bindablePropertyModels.Add(CreateBindablePropertyModel(attributeData, propertySymbol.Type.ToDisplayString(), propertySymbol.Name, returnType)); return new(propertyInfo, bindablePropertyModels.ToImmutableArray()); } - static BindablePropertyModel GetAttributeValues(in AttributeData attributeData, in string declaringTypeString, in string defaultName) + static BindablePropertyModel CreateBindablePropertyModel(in AttributeData attributeData, in string declaringTypeString, in string defaultName, in ITypeSymbol returnType) { if (attributeData.AttributeClass is null) { throw new ArgumentException($"{nameof(attributeData.AttributeClass)} Cannot Be Null", nameof(attributeData.AttributeClass)); } - var bpType = attributeData.AttributeClass.TypeArguments[0]; var defaultValue = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.DefaultValue)); var coerceValueMethodName = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.CoerceValueMethodName)); var defaultBindingMode = attributeData.GetNamedArgumentsAttributeValueByNameAsString(nameof(BindablePropertyModel.DefaultBindingMode), "BindingMode.OneWay"); @@ -232,7 +232,7 @@ static BindablePropertyModel GetAttributeValues(in AttributeData attributeData, PropertyChangedMethodName = propertyChangedMethodName, PropertyChangingMethodName = propertyChangingMethodName, PropertyName = propertyName, - ReturnType = bpType, + ReturnType = returnType, ValidateValueMethodName = validateValueMethodName }; } diff --git a/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs b/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs index 213dd83384..d9221b1e95 100644 --- a/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs @@ -14,31 +14,31 @@ public partial class Expander : ContentView, IExpander /// /// Gets or sets the command to execute when the expander is expanded or collapsed. /// - [BindableProperty()] + [BindableProperty] public partial ICommand Command { get; set; } /// /// Gets or sets the parameter to pass to the property. /// - [BindableProperty()] + [BindableProperty] public partial object CommandParameter { get; set; } /// /// Gets or sets a value indicating whether the expander is expanded. /// - [BindableProperty(PropertyChangedMethodName = nameof(OnIsExpandedPropertyChanged))] + [BindableProperty(PropertyChangedMethodName = nameof(OnIsExpandedPropertyChanged))] public partial bool IsExpanded { get; set; } /// /// Gets or sets the content to be expanded or collapsed. /// - [BindableProperty(PropertyChangedMethodName = nameof(OnContentPropertyChanged))] + [BindableProperty(PropertyChangedMethodName = nameof(OnContentPropertyChanged))] public partial IView Content { get; set; } /// /// Gets or sets the header view of the expander. /// - [BindableProperty(PropertyChangedMethodName = nameof(OnHeaderPropertyChanged))] + [BindableProperty(PropertyChangedMethodName = nameof(OnHeaderPropertyChanged))] public partial IView Header { get; set; } /// From 868fd323c30751fd89b06fa5841372823924b968 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Thu, 28 Aug 2025 12:19:38 -0700 Subject: [PATCH 7/8] Use static anonymous methods, ExcludeFromCodeCoverage --- ...indablePropertyAttributeSourceGenerator.cs | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index 0cdfb1d44a..aad8769b88 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -22,11 +22,15 @@ public class BindablePropertyAttributeSourceGenerator : IIncrementalGenerator const string bpAttribute = /* language=C#-test */ //lang=csharp - """ + $$""" + // + // See: CommunityToolkit.Maui.SourceGenerators.Internal.BindablePropertyAttributeSourceGenerator + #pragma warning disable #nullable enable namespace CommunityToolkit.Maui; + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] sealed partial class BindablePropertyAttribute : Attribute { @@ -64,7 +68,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) } #endif - context.RegisterPostInitializationOutput(ctx => ctx.AddSource("BindablePropertyAttribute.g.cs", SourceText.From(bpAttribute, Encoding.UTF8))); + context.RegisterPostInitializationOutput(static ctx => ctx.AddSource("BindablePropertyAttribute.g.cs", SourceText.From(bpAttribute, Encoding.UTF8))); var provider = context.SyntaxProvider.ForAttributeWithMetadataName("CommunityToolkit.Maui.BindablePropertyAttribute", SyntaxPredicate, SemanticTransform) @@ -78,20 +82,20 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static void ExecuteAllValues(SourceProductionContext context, ImmutableArray semanticValues) { var groupedValues = semanticValues - .GroupBy(sv => (sv.ClassInformation.ClassName, sv.ClassInformation.ContainingNamespace)) - .ToDictionary(d => d.Key, d => d.ToArray()); + .GroupBy(static sv => (sv.ClassInformation.ClassName, sv.ClassInformation.ContainingNamespace)) + .ToDictionary(static d => d.Key, static d => d.ToArray()); - foreach (var kvp in groupedValues) + foreach (var keyValuePair in groupedValues) { - var (className, containingNamespace) = kvp.Key; - var values = kvp.Value; + var (className, containingNamespace) = keyValuePair.Key; + var values = keyValuePair.Value; if (values.Length is 0 || string.IsNullOrEmpty(className) || string.IsNullOrEmpty(containingNamespace)) { continue; } - var bindableProperties = values.SelectMany(x => x.BindableProperties).ToImmutableArray(); + var bindableProperties = values.SelectMany(static x => x.BindableProperties).ToImmutableArray(); var classAccessibility = values[0].ClassInformation.DeclaredAccessibility; @@ -162,11 +166,15 @@ static void GenerateBindableProperty(StringBuilder sb, BindablePropertyModel inf static void GenerateProperty(StringBuilder sb, BindablePropertyModel info) { - //public partial string Text - //{ - // get => (string)GetValue(TextProperty); - // set => SetValue(TextProperty, value); - //} + // The code below creates the following Property: + // + // public partial string Text + // { + // get => (string)GetValue(TextProperty); + // set => SetValue(TextProperty, value); + // } + // + sb.AppendLine($"public partial {info.ReturnType} {info.PropertyName}") .AppendLine("{") .Append("get => (") From 83bc060e60d5387a6e0c7560f819252ebabe57ce Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Thu, 28 Aug 2025 12:20:06 -0700 Subject: [PATCH 8/8] `dotnet format` --- .../BindablePropertyAttributeSourceGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs index aad8769b88..21cd6b6513 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs +++ b/src/CommunityToolkit.Maui.SourceGenerators.Internal/BindablePropertyAttributeSourceGenerator.cs @@ -174,7 +174,7 @@ static void GenerateProperty(StringBuilder sb, BindablePropertyModel info) // set => SetValue(TextProperty, value); // } // - + sb.AppendLine($"public partial {info.ReturnType} {info.PropertyName}") .AppendLine("{") .Append("get => (")