mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-04-21 06:02:07 +00:00
Replace GetServiceInstance with fully source-generated version
This commit is contained in:
parent
1a55a553ea
commit
19de0d0db6
4 changed files with 43 additions and 44 deletions
|
|
@ -1,19 +1,29 @@
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.Generators
|
namespace Ryujinx.HLE.Generators
|
||||||
{
|
{
|
||||||
[Generator]
|
[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 string FullName { get; init; }
|
||||||
public required bool HasOneParamCtor { get; init; }
|
public required IReadOnlyList<(string ServiceName, string ParameterValue)> Instances { get; init; }
|
||||||
public required bool HasTwoParamCtor { get; init; }
|
|
||||||
public required string SecondParamTypeFullName { 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)
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
|
|
@ -23,17 +33,18 @@ namespace Ryujinx.HLE.Generators
|
||||||
transform: (ctx, _) =>
|
transform: (ctx, _) =>
|
||||||
{
|
{
|
||||||
var target = (INamedTypeSymbol)ctx.TargetSymbol;
|
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
|
return new ServiceData
|
||||||
{
|
{
|
||||||
FullName = target.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
FullName = target.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
||||||
HasOneParamCtor = target.Constructors.Any(ctor => ctor.Parameters.Length == 1),
|
Instances = instances.ToList(),
|
||||||
HasTwoParamCtor = twoParamCtor != null,
|
|
||||||
SecondParamTypeFullName = twoParamCtor?.Parameters[1].Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
.Where(data => data.HasOneParamCtor || data.HasTwoParamCtor);
|
|
||||||
|
|
||||||
context.RegisterSourceOutput(pipeline.Collect(),
|
context.RegisterSourceOutput(pipeline.Collect(),
|
||||||
(ctx, data) =>
|
(ctx, data) =>
|
||||||
|
|
@ -45,25 +56,29 @@ namespace Ryujinx.HLE.Generators
|
||||||
generator.EnterScope("namespace Ryujinx.HLE.HOS.Services.Sm");
|
generator.EnterScope("namespace Ryujinx.HLE.HOS.Services.Sm");
|
||||||
generator.EnterScope("partial class IUserInterface");
|
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}))");
|
foreach (var instance in serviceImpl.Instances)
|
||||||
if (service.HasTwoParamCtor)
|
|
||||||
{
|
{
|
||||||
generator.EnterScope("if (parameter != null)");
|
if (instance.ParameterValue == null)
|
||||||
generator.AppendLine($"return new {service.FullName}(context, ({service.SecondParamTypeFullName})parameter);");
|
{
|
||||||
generator.LeaveScope();
|
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();
|
||||||
|
|
||||||
generator.LeaveScope();
|
generator.LeaveScope();
|
||||||
|
|
@ -3,6 +3,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||||
[Service("acc:aa", AccountServiceFlag.BaasAccessTokenAccessor)] // Max Sessions: 4
|
[Service("acc:aa", AccountServiceFlag.BaasAccessTokenAccessor)] // Max Sessions: 4
|
||||||
class IBaasAccessTokenAccessor : IpcService
|
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
|
namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
abstract class IpcService
|
abstract partial class IpcService
|
||||||
{
|
{
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, MethodInfo> CmifCommands { get; }
|
public IReadOnlyDictionary<int, MethodInfo> CmifCommands { get; }
|
||||||
public IReadOnlyDictionary<int, MethodInfo> TipcCommands { get; }
|
public IReadOnlyDictionary<int, MethodInfo> TipcCommands { get; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,13 @@ using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
using Ryujinx.Horizon.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Sm
|
namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
{
|
{
|
||||||
partial class IUserInterface : IpcService
|
partial class IUserInterface : IpcService
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Type> _services;
|
|
||||||
|
|
||||||
private readonly SmRegistry _registry;
|
private readonly SmRegistry _registry;
|
||||||
private readonly ServerBase _commonServer;
|
private readonly ServerBase _commonServer;
|
||||||
|
|
||||||
|
|
@ -27,14 +22,6 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
_registry = registry;
|
_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)]
|
[CommandCmif(0)]
|
||||||
[CommandTipc(0)] // 12.0.0+
|
[CommandTipc(0)] // 12.0.0+
|
||||||
// Initialize(pid, u64 reserved)
|
// Initialize(pid, u64 reserved)
|
||||||
|
|
@ -91,12 +78,8 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
}
|
}
|
||||||
else
|
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.TrySetServer(_commonServer);
|
||||||
service.Server.AddSessionObj(session.ServerSession, service);
|
service.Server.AddSessionObj(session.ServerSession, service);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue