Migrate `BizHawk.SrcGen.*` to `IIncrementalGenerator`

This commit is contained in:
YoshiRulz 2025-05-16 18:02:04 +10:00
parent 7c8c2c0a4b
commit 3df637ab84
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
7 changed files with 45 additions and 38 deletions

View File

@ -7,9 +7,9 @@ using System.Text;
using BizHawk.Analyzers;
[Generator]
public sealed class ReflectionCacheGenerator : ISourceGenerator
public sealed class ReflectionCacheGenerator : IIncrementalGenerator
{
private sealed class ReflectionCacheGenSyntaxReceiver : ISyntaxReceiver
private sealed class NamespaceInferrer
{
/// <remarks>
/// I may have just added RNG to the build process...
@ -35,9 +35,9 @@ public sealed class ReflectionCacheGenerator : ISourceGenerator
return ns[ns.Length - 1] == '.' ? ns.Substring(0, ns.Length - 1) : ns; // trim trailing '.' (can't use BizHawk.Common from Source Generators)
}
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
public void AddSample(NamespaceDeclarationSyntax syn)
{
if (_namespace != null || syntaxNode is not NamespaceDeclarationSyntax syn) return;
if (_namespace is not null) return;
var newNS = syn.Name.ToMetadataNameStr();
if (!newNS.StartsWith("BizHawk.", StringComparison.Ordinal)) return;
_namespaces.Add(newNS);
@ -45,13 +45,24 @@ public sealed class ReflectionCacheGenerator : ISourceGenerator
}
}
public void Initialize(GeneratorInitializationContext context)
=> context.RegisterForSyntaxNotifications(() => new ReflectionCacheGenSyntaxReceiver());
public void Execute(GeneratorExecutionContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var nSpace = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (syntaxNode, _) => syntaxNode is NamespaceDeclarationSyntax,
transform: static (ctx, _) => (NamespaceDeclarationSyntax) ctx.Node)
.Collect()
.Select((nsSyns, _) =>
{
NamespaceInferrer shim = new();
foreach (var syn in nsSyns) shim.AddSample(syn);
return shim.Namespace;
});
context.RegisterSourceOutput(nSpace, Execute);
}
public void Execute(SourceProductionContext context, string nSpace)
{
if (context.SyntaxReceiver is not ReflectionCacheGenSyntaxReceiver receiver) return;
var nSpace = receiver.Namespace;
var src = $@"#nullable enable
using System;

View File

@ -3,4 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<Import Project="../AnalyzersCommon.props" />
<PropertyGroup>
<NoWarn>$(NoWarn);SA1135</NoWarn> <!-- the Analyzer for SA1135 chokes on the tuple alias syntax -->
</PropertyGroup>
</Project>

View File

@ -1,31 +1,24 @@
namespace BizHawk.SrcGen.SettingsUtil;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using BizHawk.Analyzers;
using TestType = (ClassDeclarationSyntax CDS, SemanticModel SemanticModel);
[Generator]
public class DefaultSetterGenerator : ISourceGenerator
public class DefaultSetterGenerator : IIncrementalGenerator
{
public class SyntaxReceiver : ISyntaxContextReceiver
public void Initialize(IncrementalGeneratorInitializationContext context)
{
public readonly List<(ClassDeclarationSyntax CDS, SemanticModel SemanticModel)> ClassDeclarations = new();
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
{
if (context.Node is ClassDeclarationSyntax cds)
{
ClassDeclarations.Add((cds, context.SemanticModel));
}
}
var classDecls = context.SyntaxProvider.CreateSyntaxProvider(
predicate: static (syntaxNode, _) => syntaxNode is ClassDeclarationSyntax,
transform: static (ctx, _) => ((ClassDeclarationSyntax) ctx.Node, ctx.SemanticModel));
context.RegisterSourceOutput(context.CompilationProvider.Combine(classDecls.Collect()), Execute);
}
public void Initialize(GeneratorInitializationContext context)
=> context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
private static void CreateDefaultSetter(StringBuilder source, INamespaceOrTypeSymbol symbol)
{
var props = symbol
@ -78,13 +71,12 @@ public class DefaultSetterGenerator : ISourceGenerator
");
}
public void Execute(GeneratorExecutionContext context)
public void Execute(
SourceProductionContext context,
(Compilation Compilation, ImmutableArray<TestType> ClassDeclarations) value)
{
if (context.SyntaxContextReceiver is not SyntaxReceiver syntaxReceiver)
{
return;
}
var consumerAttrSym = context.Compilation.GetTypeByMetadataName("BizHawk.Emulation.Common.CoreSettingsAttribute");
var (compilation, classDeclarations) = value;
var consumerAttrSym = compilation.GetTypeByMetadataName("BizHawk.Emulation.Common.CoreSettingsAttribute");
if (consumerAttrSym is null) return;
// Generated source code
@ -94,7 +86,7 @@ namespace BizHawk.Emulation.Cores
public static partial class SettingsUtil
{");
foreach (var (cds, semanticModel) in syntaxReceiver.ClassDeclarations
foreach (var (cds, semanticModel) in classDeclarations
.Where(tuple => tuple.CDS.AttributeLists.Matching(
consumerAttrSym,
tuple.SemanticModel,

View File

@ -5,11 +5,10 @@ using System.IO;
using System.Linq;
[Generator]
public class VersionInfoGenerator : ISourceGenerator
public class VersionInfoGenerator : IIncrementalGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
}
public void Initialize(IncrementalGeneratorInitializationContext context)
=> context.RegisterSourceOutput(context.CompilationProvider, Execute);
private static string? ExecuteGitWithArguments(string arguments)
{
@ -38,12 +37,14 @@ public class VersionInfoGenerator : ISourceGenerator
#endif
}
public void Execute(GeneratorExecutionContext context)
public void Execute(SourceProductionContext context, Compilation compilation)
{
// Finds the current project directory in order to pass to git commands.
// This is written in a way to (hopefully) work both for build and IDE analyzers
// FIXME: This should probably be done in a better way, but I haven't found any
string projectDir = Path.GetDirectoryName(context.Compilation.SyntaxTrees.First(x => x.HasCompilationUnitRoot && x.FilePath.Contains("BizHawk.Common")).FilePath)!;
var projectDir = Path.GetDirectoryName(compilation.SyntaxTrees
.First(static x => x.HasCompilationUnitRoot && x.FilePath.Contains("BizHawk.Common"))
.FilePath)!;
var rev = ExecuteGitWithArguments($"-C {projectDir} rev-list HEAD --count") ?? string.Empty;
var branch = ExecuteGitWithArguments($"-C {projectDir} rev-parse --abbrev-ref HEAD") ?? "master";