Hello Eduardo Gomez!
I see that you are trying to implement the source generator that inspects user code and generate new C# source files. Based on my review, here are a few issues I noticed:
- Wrong return type: In your code:
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);
The (ctx, _) => ctx.SemanticModel.Compilation) return the wrong type. By returning the whole compilation, you’re not actually triggering anything useful. Since compilation is already available via context.CompilationProvider, you don’t need this implementation at all.
The "transformer" is supposed to take the syntax node that passed the filter and transform it into a smaller, more relevant piece of data. Instead, it throws away the node and returns the entire Compilation object.
- The source output is never triggered: Since your pipeline is filtering for
MauiProgramincorrectly and your provider returnsCompilationinstead of syntax nodes, the pipeline doesn’t produce anything, which causes the generator to remain silent.
Solutions
- Update your code:
The correct approach for an incremental generator would be to filter on the type of node you are interested in (e.g., a ClassDeclarationSyntax) and then use the semantic model to check if it has the properties you need.
Update your Initialize function to match the filter and return type
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var addFontCalls =
context.SyntaxProvider.CreateSyntaxProvider(
static (node, _) => node is InvocationExpressionSyntax ies &&
ies.Expression is MemberAccessExpressionSyntax ma &&
ma.Name.Identifier.Text == "AddFont",
static (ctx, _) => (InvocationExpressionSyntax)ctx.Node)
.Collect();
var compilationAndCalls = context.CompilationProvider.Combine(addFontCalls);
context.RegisterSourceOutput(compilationAndCalls, Generate);
}
Update the rest of the function parameters accordingly.
private static void GenerateCode(SourceProductionContext spc, (Compilation compilation, ImmutableArray<InvocationExpressionSyntax> invocations) pair)
{
var (compilation, invocations) = pair;
var aliases = ExtractFontAliases(compilation, invocations);
spc.ReportDiagnostic(Diagnostic.Create(
FontDiagnosticDescriptor,
Location.None,
aliases.Count));
var source = GenerateFontAliasEnum(aliases);
spc.AddSource("FontAliases.g.cs", source);
}
private static List<string> ExtractFontAliases(Compilation compilation, IReadOnlyList<InvocationExpressionSyntax> invocations)
{
var list = new List<string>();
foreach (var invocation in invocations)
{
var args = invocation.ArgumentList.Arguments;
if (args.Count < 2) continue;
var semanticModel = compilation.GetSemanticModel(invocation.SyntaxTree);
var aliasExpr = args[1].Expression;
var constValue = semanticModel.GetConstantValue(aliasExpr);
if (constValue.HasValue && constValue.Value is string s && !string.IsNullOrWhiteSpace(s))
{
list.Add(s);
}
}
return list;
}
- Check your class library configuration
- Source generator must use .NET standard 2.0, other version won't work, see here
Here is the example configuration for your Class Library:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.14.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" PrivateAssets="all" />
</ItemGroup>
</Project>
- Ensure
ReferenceOutputAssemblyset tofalse:
Since the source generator is in compiler runtime, you don't want to reference the library at the runtime, here is the correct one:
<ItemGroup>
<ProjectReference Include="..\FontAliasGenerator\FontAliasGenerator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
After update, make sure you:
- Do a
CleanandRebuildproject/solution. - After finish building, Look inside your MAUI project and check for
Dependencies>AnyPlatform>Analyzer>WndowsPhoneTile, yourFontAliases.g.csshould appear.
If you're looking for a well-documented example, the MVVM Toolkit provides source generators you can check out here.
I hope this helps! Let me know if you stuck any!
References: