From 9fdd36101a6a1d9da4ebd5cbb038330a84e62273 Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Fri, 28 Feb 2025 13:42:46 +0000 Subject: [PATCH] Feature: `InitializeComponentAttribute` Fixes #62 Add `InitializeComponentAttribute` feature to the project. * **Attribute Class**: Add `InitializeComponentAttribute` class in `src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.cs`. - Define `InitializeComponentAttribute` partial class in `Riverside.Extensions.WinUI` namespace. - Mark the class with `[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly)]`. - Add a constructor to the class. * **Source Generator**: Add source generator for `InitializeComponentAttribute` in `src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.SourceGenerator.cs`. - Define `InitializeComponentGenerator` partial class in `Riverside.Extensions.WinUI` namespace. - Implement `ISourceGenerator` interface. - Implement `Initialize` method. - Implement `Execute` method to generate the constructor with `this.InitializeComponent()` for classes with `InitializeComponentAttribute`. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/RiversideValley/Toolkit/issues/62?shareId=XXXX-XXXX-XXXX-XXXX). --- ...alizeComponentAttribute.SourceGenerator.cs | 50 +++++++++++++++++++ .../InitializeComponentAttribute.cs | 12 +++++ 2 files changed, 62 insertions(+) create mode 100644 src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.SourceGenerator.cs create mode 100644 src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.cs diff --git a/src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.SourceGenerator.cs b/src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.SourceGenerator.cs new file mode 100644 index 0000000..ea583b6 --- /dev/null +++ b/src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.SourceGenerator.cs @@ -0,0 +1,50 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Riverside.Extensions.WinUI +{ + [Generator] + public partial class InitializeComponentGenerator : ISourceGenerator + { + public void Initialize(GeneratorInitializationContext context) + { + // No initialization required for this source generator + } + + public void Execute(GeneratorExecutionContext context) + { + // Find all classes with the InitializeComponentAttribute + var classesWithAttribute = context.Compilation.SyntaxTrees + .SelectMany(syntaxTree => syntaxTree.GetRoot().DescendantNodes()) + .OfType() + .Where(classDeclaration => classDeclaration.AttributeLists + .SelectMany(attributeList => attributeList.Attributes) + .Any(attribute => attribute.Name.ToString() == "InitializeComponent")); + + foreach (var classDeclaration in classesWithAttribute) + { + var namespaceDeclaration = classDeclaration.Ancestors().OfType().FirstOrDefault(); + var namespaceName = namespaceDeclaration?.Name.ToString() ?? "GlobalNamespace"; + var className = classDeclaration.Identifier.Text; + + var source = $@" +namespace {namespaceName} +{{ + public partial class {className} + {{ + public {className}() + {{ + this.InitializeComponent(); + }} + }} +}}"; + context.AddSource($"{className}_InitializeComponent.g.cs", SourceText.From(source, Encoding.UTF8)); + } + } + } +} diff --git a/src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.cs b/src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.cs new file mode 100644 index 0000000..e49085f --- /dev/null +++ b/src/core/Riverside.Extensions.WinUI/InitializeComponentAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace Riverside.Extensions.WinUI +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly)] + public partial class InitializeComponentAttribute : Attribute + { + public InitializeComponentAttribute() + { + } + } +}