Skip to content

Commit 1ae391e

Browse files
committed
Fix OpenGenericInterceptors not working with FromAction/FromFunc
1 parent e091188 commit 1ae391e

File tree

5 files changed

+38
-28
lines changed

5 files changed

+38
-28
lines changed

ClosedGenericInterceptor.cs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ private string GetSourceText()
4747
_ = sb.Append(reference.InterceptorAttributeSourceText).Append($"{Constants.NewLineIndent2}");
4848
}
4949
var method = InterceptsMethod;
50-
var typeParameters = GetTypeParameters(method.ContainingInterface.Arity, method.Arity);
50+
var typeParameters = Constants.InterceptorTypeParameters[method.ContainingInterface.Arity];
51+
typeParameters = typeParameters.Length != 0 ?
52+
$"<{typeParameters}>" :
53+
typeParameters;
5154
_ = sb.Append
5255
(
5356
$@"[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -84,16 +87,5 @@ public static {method.ContainingInterface.FullName} {method.Name}{typeParameters
8487
}
8588
return sb.ToString();
8689
}
87-
internal static string GetTypeParameters(int interfaceArity, int methodArity)
88-
{
89-
if (interfaceArity == 0)
90-
{
91-
return string.Empty;
92-
}
93-
int arity = interfaceArity + methodArity;
94-
return arity == 1 ?
95-
"<X>" :
96-
$"<{string.Join(", ", Enumerable.Range(1, arity).Select(x => $"X{x}"))}>";
97-
}
9890
}
9991
}

Constants.Actions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Monkeymoto.NativeGenericDelegates
1+
using System.Linq;
2+
3+
namespace Monkeymoto.NativeGenericDelegates
24
{
35
internal static partial class Constants
46
{

Constants.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ internal static partial class Constants
153153
private const string TypeParameters_T1_T15 = $"{TypeParameters_T1_T14}, T15";
154154
private const string TypeParameters_T1_T16 = $"{TypeParameters_T1_T15}, T16";
155155

156+
public static readonly string[] InterceptorTypeParameters =
157+
[
158+
.. TypeParameters.Select(static x => x.Replace('T', 'X')),
159+
$"{TypeParameters_T1_T16.Replace('T', 'X')}, X17"
160+
];
161+
156162
private static readonly string[] QualifiedTypeParameters =
157163
[.. TypeParameters.Select(x => x.Replace("T", "in T"))];
158164
}

MethodDescriptor.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal sealed class MethodDescriptor : IEquatable<MethodDescriptor>
1313
public string FirstParameterName { get; }
1414
public string FirstParameterType { get; }
1515
public string FullName { get; }
16+
public string InterceptorParameters { get; }
1617
public bool IsFromFunctionPointer { get; }
1718
public string Name { get; }
1819
public string Parameters { get; }
@@ -54,8 +55,9 @@ IMethodSymbol methodSymbol
5455
Arity = methodSymbol.Arity;
5556
ContainingInterface = containingInterface;
5657
FullName = GetFullName(methodSymbol);
58+
InterceptorParameters = GetParameters(getInterceptorParameters: true);
5759
Name = methodSymbol.Name;
58-
Parameters = GetParameters();
60+
Parameters = GetParameters(getInterceptorParameters: false);
5961
hashCode = Hash.Combine(Arity, ContainingInterface, Name);
6062
}
6163

@@ -65,16 +67,22 @@ public bool Equals(MethodDescriptor? other) =>
6567
(Name == other.Name);
6668
public override int GetHashCode() => hashCode;
6769

68-
private string GetParameters()
70+
private string GetParameters(bool getInterceptorParameters)
6971
{
7072
var marshalReturnAsParam = !ContainingInterface.IsAction ?
7173
$"MarshalAsAttribute marshalReturnAs,{Constants.NewLineIndent3}" :
7274
string.Empty;
7375
var marshalParamsAsParam = ContainingInterface.InvokeParameterCount != 0 ?
7476
$"MarshalAsAttribute[] marshalParamsAs,{Constants.NewLineIndent3}" :
7577
string.Empty;
78+
var firstParameterType = FirstParameterType;
79+
if (getInterceptorParameters && !IsFromFunctionPointer && (ContainingInterface.Arity > 0))
80+
{
81+
var typeParameters = Constants.InterceptorTypeParameters[ContainingInterface.Arity];
82+
firstParameterType = $"{ContainingInterface.Category}<{typeParameters}>";
83+
}
7684
return
77-
$"{FirstParameterType} {FirstParameterName},{Constants.NewLineIndent3}{marshalReturnAsParam}" +
85+
$"{firstParameterType} {FirstParameterName},{Constants.NewLineIndent3}{marshalReturnAsParam}" +
7886
$"{marshalParamsAsParam}CallingConvention callingConvention";
7987
}
8088
}

OpenGenericInterceptors.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,14 @@ private string GetSourceText()
4444
{
4545
Debug.Assert(attributes.ContainsKey(kv.Key));
4646
var first = kv.Value.First();
47-
var interfaceTypeParameters =
48-
ClosedGenericInterceptor.GetTypeParameters(first.Method.ContainingInterface.Arity, 0);
49-
var interfaceName = $"{first.Method.ContainingInterface.Name}{interfaceTypeParameters}";
47+
var typeParameters = Constants.InterceptorTypeParameters[first.Method.ContainingInterface.Arity];
48+
typeParameters = typeParameters.Length != 0 ?
49+
$"<{typeParameters}>" :
50+
typeParameters;
51+
var interfaceName = $"{first.Method.ContainingInterface.Name}{typeParameters}";
5052
var methodHash = kv.Key.GetHashCode();
5153
var methodName = first.Method.Name;
52-
var parameters = first.Method.Parameters;
53-
var typeParameters = ClosedGenericInterceptor.GetTypeParameters
54-
(
55-
first.Method.ContainingInterface.Arity,
56-
first.Method.Arity
57-
);
54+
var parameters = first.Method.InterceptorParameters;
5855
_ = sb.AppendLine().Append(" ").AppendLine
5956
(
6057
$@"file static class NativeGenericDelegates_{(methodHash < 0 ? $"S{-methodHash}" : $"U{methodHash}")}
@@ -75,7 +72,8 @@ public static {interfaceName} {methodName}{typeParameters}
7572
);
7673
for (int i = 0; i < kv.Value.Count; ++i)
7774
{
78-
var typeArguments = kv.Value[i].Method.ContainingInterface.TypeArguments;
75+
var method = kv.Value[i].Method;
76+
var typeArguments = method.ContainingInterface.TypeArguments;
7977
if (typeArguments.Count == 1)
8078
{
8179
_ = sb.Append($" if (typeof(X) == typeof({typeArguments[0]}))");
@@ -94,19 +92,23 @@ public static {interfaceName} {methodName}{typeParameters}
9492
_ = sb.Append(" )");
9593
}
9694
_ = sb.Append(Constants.NewLineIndent3);
95+
var firstParam = method.FirstParameterName;
96+
if (!method.IsFromFunctionPointer)
97+
{
98+
firstParam = $"({method.ContainingInterface.Category}{method.ContainingInterface.TypeArgumentList})(object){firstParam}";
99+
}
97100
if (kv.Value[i].Marshalling.StaticCallingConvention is not null)
98101
{
99102
_ = sb.AppendLine
100103
(
101104
$@"{{
102-
return ({interfaceName})(object)(new {kv.Value[i].ClassName}({kv.Value[i].Method.FirstParameterName}));
105+
return ({interfaceName})(object)(new {kv.Value[i].ClassName}({firstParam}));
103106
}}"
104107
);
105108
}
106109
else
107110
{
108111
var className = kv.Value[i].ClassName;
109-
var firstParam = kv.Value[i].Method.FirstParameterName;
110112
_ = sb.AppendLine
111113
(
112114
$@"{{

0 commit comments

Comments
 (0)