mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-29 16:39:15 +00:00
Convert HLE.Generators to IIncrementalSourceGenerator
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
|
||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
||||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
||||||
|
<PackageVersion Include="PolySharp" Version="1.15.0" />
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
@@ -59,4 +60,4 @@
|
|||||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
<PackageVersion Include="System.Management" Version="9.0.2" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -6,73 +6,73 @@ using System.Linq;
|
|||||||
namespace Ryujinx.HLE.Generators
|
namespace Ryujinx.HLE.Generators
|
||||||
{
|
{
|
||||||
[Generator]
|
[Generator]
|
||||||
public class IpcServiceGenerator : ISourceGenerator
|
public sealed class IpcServiceGenerator : IIncrementalGenerator
|
||||||
{
|
{
|
||||||
public void Execute(GeneratorExecutionContext context)
|
private sealed record ServiceData
|
||||||
{
|
{
|
||||||
ServiceSyntaxReceiver syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver;
|
public required string FullName { get; init; }
|
||||||
CodeGenerator generator = new();
|
public required bool HasOneParamCtor { get; init; }
|
||||||
|
public required bool HasTwoParamCtor { get; init; }
|
||||||
generator.AppendLine("#nullable enable");
|
public required string SecondParamTypeFullName { get; init; }
|
||||||
generator.AppendLine("using System;");
|
}
|
||||||
generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm");
|
|
||||||
generator.EnterScope($"partial class IUserInterface");
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
|
{
|
||||||
generator.EnterScope($"public IpcService? GetServiceInstance(Type type, ServiceCtx context, object? parameter = null)");
|
var pipeline = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.ServiceAttribute",
|
||||||
foreach (ClassDeclarationSyntax className in syntaxReceiver.Types)
|
predicate: (node, _) => node is ClassDeclarationSyntax decl && !decl.Modifiers.Any(SyntaxKind.AbstractKeyword) && !decl.Modifiers.Any(SyntaxKind.PrivateKeyword),
|
||||||
{
|
transform: (ctx, _) =>
|
||||||
if (className.Modifiers.Any(SyntaxKind.AbstractKeyword) || className.Modifiers.Any(SyntaxKind.PrivateKeyword) || !className.AttributeLists.Any(x => x.Attributes.Any(y => y.ToString().StartsWith("Service"))))
|
|
||||||
continue;
|
|
||||||
string name = GetFullName(className, context).Replace("global::", string.Empty);
|
|
||||||
if (!name.StartsWith("Ryujinx.HLE.HOS.Services"))
|
|
||||||
continue;
|
|
||||||
ConstructorDeclarationSyntax[] constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax).ToArray();
|
|
||||||
|
|
||||||
if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (constructors.Where(x => x.ParameterList.Parameters.Count >= 1).FirstOrDefault().ParameterList.Parameters[0].Type.ToString() == "ServiceCtx")
|
|
||||||
{
|
{
|
||||||
generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))");
|
var target = (INamedTypeSymbol)ctx.TargetSymbol;
|
||||||
if (constructors.Any(x => x.ParameterList.Parameters.Count == 2))
|
var twoParamCtor = target.Constructors.FirstOrDefault(ctor => ctor.Parameters.Length == 2);
|
||||||
|
return new ServiceData
|
||||||
{
|
{
|
||||||
TypeSyntax type = constructors.Where(x => x.ParameterList.Parameters.Count == 2).FirstOrDefault().ParameterList.Parameters[1].Type;
|
FullName = target.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
||||||
SemanticModel model = context.Compilation.GetSemanticModel(type.SyntaxTree);
|
HasOneParamCtor = target.Constructors.Any(ctor => ctor.Parameters.Length == 1),
|
||||||
INamedTypeSymbol typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol;
|
HasTwoParamCtor = twoParamCtor != null,
|
||||||
string fullName = typeSymbol.ToString();
|
SecondParamTypeFullName = twoParamCtor?.Parameters[1].Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
||||||
generator.EnterScope("if (parameter != null)");
|
};
|
||||||
generator.AppendLine($"return new {GetFullName(className, context)}(context, ({fullName})parameter);");
|
}
|
||||||
|
)
|
||||||
|
.Where(data => data.HasOneParamCtor || data.HasTwoParamCtor);
|
||||||
|
|
||||||
|
context.RegisterSourceOutput(pipeline.Collect(),
|
||||||
|
(ctx, data) =>
|
||||||
|
{
|
||||||
|
var generator = new CodeGenerator();
|
||||||
|
|
||||||
|
generator.AppendLine("#nullable enable");
|
||||||
|
generator.AppendLine("using System;");
|
||||||
|
generator.EnterScope("namespace Ryujinx.HLE.HOS.Services.Sm");
|
||||||
|
generator.EnterScope("partial class IUserInterface");
|
||||||
|
|
||||||
|
generator.EnterScope("public IpcService? GetServiceInstance(Type type, ServiceCtx context, object? parameter = null)");
|
||||||
|
|
||||||
|
foreach (var service in data)
|
||||||
|
{
|
||||||
|
generator.EnterScope($"if (type == typeof({service.FullName}))");
|
||||||
|
if (service.HasTwoParamCtor)
|
||||||
|
{
|
||||||
|
generator.EnterScope("if (parameter != null)");
|
||||||
|
generator.AppendLine($"return new {service.FullName}(context, ({service.SecondParamTypeFullName})parameter);");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
if (service.HasOneParamCtor)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"return new {service.FullName}(context);");
|
||||||
|
}
|
||||||
generator.LeaveScope();
|
generator.LeaveScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constructors.Any(x => x.ParameterList.Parameters.Count == 1))
|
generator.AppendLine("return null;");
|
||||||
{
|
generator.LeaveScope();
|
||||||
generator.AppendLine($"return new {GetFullName(className, context)}(context);");
|
|
||||||
}
|
|
||||||
|
|
||||||
generator.LeaveScope();
|
generator.LeaveScope();
|
||||||
}
|
generator.LeaveScope();
|
||||||
}
|
|
||||||
|
generator.AppendLine("#nullable disable");
|
||||||
generator.AppendLine("return null;");
|
|
||||||
generator.LeaveScope();
|
ctx.AddSource("IUserInterface.g.cs", generator.ToString());
|
||||||
|
});
|
||||||
generator.LeaveScope();
|
|
||||||
generator.LeaveScope();
|
|
||||||
generator.AppendLine("#nullable disable");
|
|
||||||
context.AddSource($"IUserInterface.g.cs", generator.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetFullName(ClassDeclarationSyntax syntaxNode, GeneratorExecutionContext context)
|
|
||||||
{
|
|
||||||
INamedTypeSymbol typeSymbol = context.Compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
|
|
||||||
|
|
||||||
return typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize(GeneratorInitializationContext context)
|
|
||||||
{
|
|
||||||
context.RegisterForSyntaxNotifications(() => new ServiceSyntaxReceiver());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
|
||||||
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
|
|
||||||
<IsRoslynComponent>true</IsRoslynComponent>
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -15,6 +13,10 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||||
|
<PackageReference Include="PolySharp">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.Generators
|
|
||||||
{
|
|
||||||
internal class ServiceSyntaxReceiver : ISyntaxReceiver
|
|
||||||
{
|
|
||||||
public HashSet<ClassDeclarationSyntax> Types = [];
|
|
||||||
|
|
||||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
|
||||||
{
|
|
||||||
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
|
|
||||||
{
|
|
||||||
if (classDeclaration.BaseList == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Types.Add(classDeclaration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user