Test with generated hooks

This commit is contained in:
max
2024-09-08 20:58:13 +02:00
parent bd76fc1b25
commit 09089c35b9
9 changed files with 214 additions and 3 deletions

View File

@ -0,0 +1,91 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Nerfed.Runtime.Generator
{
[Generator]
public class HookSourceGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
// Ensure the syntax receiver is not null and is of the expected type
if (context.SyntaxReceiver is not HookSyntaxReceiver syntaxReceiver)
return;
// Check if we have collected any hook methods
List<MethodDeclarationSyntax> hookMethods = syntaxReceiver.HookMethods;
if (hookMethods == null || !hookMethods.Any())
return;
StringBuilder codeBuilder = new StringBuilder();
codeBuilder.AppendLine("using System;");
codeBuilder.AppendLine("");
codeBuilder.AppendLine("namespace Nerfed.Runtime.Generator;");
codeBuilder.AppendLine("");
codeBuilder.AppendLine($"// Generated by {typeof(HookSourceGenerator)}");
codeBuilder.AppendLine("public static class Hook");
codeBuilder.AppendLine("{");
codeBuilder.AppendLine(" public static void InvokeHooks()");
codeBuilder.AppendLine(" {");
foreach (MethodDeclarationSyntax method in hookMethods)
{
SemanticModel model = context.Compilation.GetSemanticModel(method.SyntaxTree);
if (model.GetDeclaredSymbol(method) is not IMethodSymbol methodSymbol)
{
continue;
}
if (methodSymbol.DeclaredAccessibility != Accessibility.Public || !methodSymbol.IsStatic)
{
continue;
}
codeBuilder.AppendLine($" {methodSymbol.ContainingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.{methodSymbol.Name}();");
}
codeBuilder.AppendLine(" }");
codeBuilder.AppendLine("}");
// Add the generated code to the compilation
context.AddSource("Hook.g.cs", codeBuilder.ToString());
}
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new HookSyntaxReceiver());
}
public class HookSyntaxReceiver : ISyntaxReceiver
{
public List<MethodDeclarationSyntax> HookMethods { get; } = new List<MethodDeclarationSyntax>();
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
// Check if the node is a method declaration
if (syntaxNode is MethodDeclarationSyntax methodDeclaration)
{
// Ensure the method declaration has attribute lists
if (methodDeclaration.AttributeLists.Count == 0)
return;
// Check if the method has the Hook attribute
bool hasHookAttribute = methodDeclaration.AttributeLists
.SelectMany(attrList => attrList.Attributes)
.Any(attr => attr.Name.ToString() == "Hook");
if (hasHookAttribute)
{
HookMethods.Add(methodDeclaration);
}
}
}
}
}
}

View File

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<Configurations>Debug;Test;Release</Configurations>
<Platforms>x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0"/>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DefineConstants>TRACE;LOG_INFO;PROFILING</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Test|x64' ">
<DefineConstants>TRACE;LOG_ERROR;PROFILING</DefineConstants>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<DefineConstants>TRACE;LOG_ERROR</DefineConstants>
<Optimize>true</Optimize>
</PropertyGroup>
</Project>