mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-03-11 17:11:06 +00:00
Replace GetServiceInstance with fully source-generated version
This commit is contained in:
@@ -1,19 +1,29 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.HLE.Generators
|
||||
{
|
||||
[Generator]
|
||||
public sealed class IpcServiceGenerator : IIncrementalGenerator
|
||||
public sealed class UserServiceGenerator : IIncrementalGenerator
|
||||
{
|
||||
private sealed record ServiceData
|
||||
private sealed class ServiceData : IEquatable<ServiceData>
|
||||
{
|
||||
public required string FullName { get; init; }
|
||||
public required bool HasOneParamCtor { get; init; }
|
||||
public required bool HasTwoParamCtor { get; init; }
|
||||
public required string SecondParamTypeFullName { get; init; }
|
||||
public required IReadOnlyList<(string ServiceName, string ParameterValue)> Instances { get; init; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
=> obj is ServiceData data && Equals(data);
|
||||
|
||||
public bool Equals(ServiceData other)
|
||||
{
|
||||
return this.FullName == other.FullName && this.Instances.SequenceEqual(other.Instances);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => FullName.GetHashCode();
|
||||
}
|
||||
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
@@ -23,17 +33,18 @@ namespace Ryujinx.HLE.Generators
|
||||
transform: (ctx, _) =>
|
||||
{
|
||||
var target = (INamedTypeSymbol)ctx.TargetSymbol;
|
||||
var twoParamCtor = target.Constructors.FirstOrDefault(ctor => ctor.Parameters.Length == 2);
|
||||
var instances = ctx.Attributes.Select(attr =>
|
||||
{
|
||||
string param = attr.ConstructorArguments is [_, { IsNull: false } arg] ? arg.ToCSharpString() : null;
|
||||
return ((string)attr.ConstructorArguments[0].Value, param);
|
||||
});
|
||||
return new ServiceData
|
||||
{
|
||||
FullName = target.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
||||
HasOneParamCtor = target.Constructors.Any(ctor => ctor.Parameters.Length == 1),
|
||||
HasTwoParamCtor = twoParamCtor != null,
|
||||
SecondParamTypeFullName = twoParamCtor?.Parameters[1].Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
||||
Instances = instances.ToList(),
|
||||
};
|
||||
}
|
||||
)
|
||||
.Where(data => data.HasOneParamCtor || data.HasTwoParamCtor);
|
||||
);
|
||||
|
||||
context.RegisterSourceOutput(pipeline.Collect(),
|
||||
(ctx, data) =>
|
||||
@@ -45,25 +56,29 @@ namespace Ryujinx.HLE.Generators
|
||||
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)");
|
||||
generator.EnterScope("public IpcService? GetServiceInstance(string name, ServiceCtx context)");
|
||||
|
||||
generator.EnterScope("return name switch");
|
||||
|
||||
foreach (var service in data)
|
||||
foreach (var serviceImpl in data)
|
||||
{
|
||||
generator.EnterScope($"if (type == typeof({service.FullName}))");
|
||||
if (service.HasTwoParamCtor)
|
||||
foreach (var instance in serviceImpl.Instances)
|
||||
{
|
||||
generator.EnterScope("if (parameter != null)");
|
||||
generator.AppendLine($"return new {service.FullName}(context, ({service.SecondParamTypeFullName})parameter);");
|
||||
generator.LeaveScope();
|
||||
if (instance.ParameterValue == null)
|
||||
{
|
||||
generator.AppendLine($"\"{instance.ServiceName}\" => new {serviceImpl.FullName}(context),");
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.AppendLine($"\"{instance.ServiceName}\" => new {serviceImpl.FullName}(context, {instance.ParameterValue}),");
|
||||
}
|
||||
}
|
||||
if (service.HasOneParamCtor)
|
||||
{
|
||||
generator.AppendLine($"return new {service.FullName}(context);");
|
||||
}
|
||||
generator.LeaveScope();
|
||||
}
|
||||
|
||||
generator.AppendLine("return null;");
|
||||
generator.AppendLine("_ => null,");
|
||||
|
||||
generator.LeaveScope(";");
|
||||
|
||||
generator.LeaveScope();
|
||||
|
||||
generator.LeaveScope();
|
||||
@@ -3,6 +3,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
[Service("acc:aa", AccountServiceFlag.BaasAccessTokenAccessor)] // Max Sessions: 4
|
||||
class IBaasAccessTokenAccessor : IpcService
|
||||
{
|
||||
public IBaasAccessTokenAccessor(ServiceCtx context) { }
|
||||
public IBaasAccessTokenAccessor(ServiceCtx context, AccountServiceFlag serviceFlag) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ using System.Reflection;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services
|
||||
{
|
||||
abstract class IpcService
|
||||
abstract partial class IpcService
|
||||
{
|
||||
|
||||
public IReadOnlyDictionary<int, MethodInfo> CmifCommands { get; }
|
||||
public IReadOnlyDictionary<int, MethodInfo> TipcCommands { get; }
|
||||
|
||||
|
||||
@@ -4,18 +4,13 @@ using Ryujinx.HLE.HOS.Kernel;
|
||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Sm
|
||||
{
|
||||
partial class IUserInterface : IpcService
|
||||
{
|
||||
private static readonly Dictionary<string, Type> _services;
|
||||
|
||||
private readonly SmRegistry _registry;
|
||||
private readonly ServerBase _commonServer;
|
||||
|
||||
@@ -27,14 +22,6 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||
_registry = registry;
|
||||
}
|
||||
|
||||
static IUserInterface()
|
||||
{
|
||||
_services = typeof(IUserInterface).Assembly.GetTypes()
|
||||
.SelectMany(type => type.GetCustomAttributes(typeof(ServiceAttribute), true)
|
||||
.Select(service => (((ServiceAttribute)service).Name, type)))
|
||||
.ToDictionary(service => service.Name, service => service.type);
|
||||
}
|
||||
|
||||
[CommandCmif(0)]
|
||||
[CommandTipc(0)] // 12.0.0+
|
||||
// Initialize(pid, u64 reserved)
|
||||
@@ -91,12 +78,8 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_services.TryGetValue(name, out Type type))
|
||||
if (GetServiceInstance(name, context) is { } service)
|
||||
{
|
||||
ServiceAttribute serviceAttribute = type.GetCustomAttributes<ServiceAttribute>().First(service => service.Name == name);
|
||||
|
||||
IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter);
|
||||
|
||||
service.TrySetServer(_commonServer);
|
||||
service.Server.AddSessionObj(session.ServerSession, service);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user