Source generator

Eduardo Gomez 3,651 Reputation points
2025-06-08T21:28:58.7333333+00:00

Hello

I have a Class library, with a class

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

using System.Text;

namespace FontAliasGenerator {

    // Step 1: Mark this class as an incremental source generator
    [Generator]
    public class FontAliasGenerator : IIncrementalGenerator {
        // Step 2: Initialize the generator and set up an incremental syntax provider pipeline
        public void Initialize(IncrementalGeneratorInitializationContext context) {

            var syntaxProvider = context.SyntaxProvider
                .CreateSyntaxProvider((node, _) => IsMauiProgram(node), // Step 3: Identify MauiProgram class
                    (ctx, _) => ctx.SemanticModel.Compilation) // Step 4: Extract Compilation object
                .Where(comp => comp is not null);

            // Step 5: Register the source output, generating code from extracted compilation data
            context.RegisterSourceOutput(syntaxProvider, GenerateCode);
        }

        // Step 6: Function to determine if a node belongs to MauiProgram.cs
        private bool IsMauiProgram(SyntaxNode node) {
            return node is CompilationUnitSyntax root &&
                   root.DescendantNodes().OfType<ClassDeclarationSyntax>()
                       .Any(c => c.Identifier.Text == "MauiProgram");
        }

        // Step 7: Main source generation logic—extract font aliases and add generated code
        private void GenerateCode(SourceProductionContext context, Compilation compilation) {

            context.ReportDiagnostic(Diagnostic.Create(
     new DiagnosticDescriptor(
         "FONT001",
         "Debug",
         "Source Generator is executing!",
         "SourceGenerator",
         DiagnosticSeverity.Info,
         true),
     Location.None));



            var fontAliases = ExtractFontAliases(compilation);
            context.AddSource("FontAliases.g.cs", GenerateFontAliasEnum(fontAliases));
        }

        // Step 8: Extract font alias names from AddFont method calls
        private List<string> ExtractFontAliases(Compilation compilation) {
            var fontAliases = new List<string>();

            // Step 9: Iterate over syntax trees to find MauiProgram.cs
            foreach(var syntaxTree in compilation.SyntaxTrees) {
                var root = syntaxTree.GetRoot();

                foreach(var invocation in root.DescendantNodes().OfType<InvocationExpressionSyntax>()) {
                    if(!invocation.Expression.ToString().Contains("AddFont")) {
                        continue; // Step 10: Filter only AddFont method calls
                    }

                    var arguments = invocation.ArgumentList.Arguments;
                    if(arguments.Count < 2) {
                        continue; // Step 11: Ensure we have both font file and alias
                    }

                    var semanticModel = compilation.GetSemanticModel(syntaxTree);
                    var aliasExpr = arguments[1].Expression;
                    var constValue = semanticModel.GetConstantValue(aliasExpr);

                    if(constValue.HasValue && constValue.Value is string alias) {
                        fontAliases.Add(alias); // Step 12: Extract and store alias
                    }
                }
            }

            return fontAliases;
        }

        // Step 13: Generate Enum for font aliases
        private string GenerateFontAliasEnum(List<string> fontAliases) {
            var sb = new StringBuilder();
            sb.AppendLine("namespace WindowsPhoneTile.Enums");
            sb.AppendLine("{");
            sb.AppendLine("    public enum FontAliases");
            sb.AppendLine("    {");

            foreach(var alias in fontAliases.Distinct()) {
                var safeName = Sanitize(alias); // Step 14: Clean up alias names for enums
                sb.AppendLine($"        {safeName},");
            }

            sb.AppendLine("    }");
            sb.AppendLine("}");
            return sb.ToString();
        }

        // Step 15: Function to sanitize alias names for enum compatibility
        private string Sanitize(string alias) {
            var sanitized = new string([.. alias.Where(char.IsLetterOrDigit)]);
            return string.IsNullOrEmpty(sanitized) ? "_" : char.IsLetter(sanitized[0]) ? sanitized : "_" + sanitized;
        }
    }
}

that search for my MauiProgram in my Maui app, and generates an Enum in my Enum folder with all my font alias

this is my structure

User's image

but every time I build it doesn't generate anything.

I also put

using FontAliasGenerator;

in my maui program

and inmy csproj file

<ItemGroup>
	<ProjectReference Include="..\FontAliasGenerator\FontAliasGenerator.csproj"
					  OutputItemType="Analyzer"
					  ReferenceOutputAssembly="true" />
</ItemGroup>
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
4,148 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.