Skip to content

Commit

Permalink
Merge pull request #120 from dotnet-campus/t/walterlv/collection-inte…
Browse files Browse the repository at this point in the history
…rface

使 IPC 对象支持传输集合接口类型
  • Loading branch information
lindexi authored Feb 10, 2023
2 parents f4d6378 + 8d89f2e commit 064e9e3
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ namespace dotnetCampus.Ipc.CodeAnalysis.Utils;
/// </summary>
internal static class IpcSemanticAttributeHelper
{
/// <summary>
/// 如果类型是 IPC 类型,则返回 true;否则返回 false。
/// <para>IPC 类型为标记了 <see cref="IpcPublicAttribute"/> 或 <see cref="IpcShapeAttribute"/> 的类型。</para>
/// </summary>
/// <param name="type">要检查的类型。</param>
/// <returns></returns>
internal static bool GetIsIpcType(this ITypeSymbol type)
{
return type.GetIsDefined<IpcPublicAttribute>() || type.GetIsDefined<IpcShapeAttribute>();
}

/// <summary>
/// 检查此类型上标记的 <see cref="IpcPublicAttribute"/> 并将其转换为传入 IPC 代理的类型。
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ internal static class SemanticAttributeHelper
throw new NotSupportedException($"尚不支持读取 {typeof(T).Name} 类型的特性。");
}

/// <summary>
/// 检查此成员是否已定义了 <typeparamref name="TAttribute"/> 类型的特性。
/// </summary>
/// <typeparam name="TAttribute">要检查的类型。</typeparam>
/// <param name="symbol">要查找特性的语义符号。</param>
/// <returns>如果定义了 <typeparamref name="TAttribute"/>,则返回 true;否则返回 false。</returns>
internal static bool GetIsDefined<TAttribute>(this ISymbol symbol)
{
return symbol.GetAttributes().FirstOrDefault(x => string.Equals(
x.AttributeClass?.ToString(),
typeof(TAttribute).FullName,
StringComparison.Ordinal)) is { } ipcMethodAttribute;
}

/// <summary>
/// 检查此成员的 <paramref name="attributeTypeName"/> 类型特性的 <paramref name="namedArgumentName"/> 名字的参数的值。
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,9 @@ private string GenerateGarmArguments(SourceTextBuilder builder, ImmutableArray<I
{
return string.Join(
", ",
parameters.Select(x => x.Type.TypeKind == TypeKind.Interface
parameters.Select(x => x.Type.GetIsIpcType()
? $"new Garm<{builder.SimplifyNameByAddUsing(x.Type)}>({x.Name}, typeof({x.Type.Name}))"
: $"{x.Name}"));
: $"new Garm<{builder.SimplifyNameByAddUsing(x.Type)}>({x.Name})"));
}

/// <summary>
Expand Down Expand Up @@ -296,7 +296,7 @@ private string GenerateGarmArguments(SourceTextBuilder builder, ImmutableArray<I
/// <returns>方法实参列表字符串。</returns>
private string GenerateGarmReturn(SourceTextBuilder builder, ITypeSymbol @return, string value)
{
return @return.TypeKind == TypeKind.Interface
return @return.GetIsIpcType()
? $"new Garm<{builder.SimplifyNameByAddUsing(@return)}>({value}, typeof({@return.Name}))"
: $"new Garm<{builder.SimplifyNameByAddUsing(@return)}>({value})";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ public string GenerateJointMatch(SourceTextBuilder builder, string real)
/// <returns></returns>
private string GenerateGarmArgument(SourceTextBuilder builder, ITypeSymbol parameterType, string argumentName)
{
return parameterType.TypeKind == TypeKind.Interface
return parameterType.GetIsIpcType()
? $"new Garm<{builder.SimplifyNameByAddUsing(parameterType)}>({argumentName}, typeof({parameterType.Name}))"
: argumentName;
: $"new Garm<{builder.SimplifyNameByAddUsing(parameterType)}>({argumentName})";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -56,6 +58,12 @@ public INestedFakeIpcArgumentOrReturn NestedIpcProperty
set => _nestedIpcObject = value;
}

public List<string>? ListProperty { get; set; } = new List<string>() { "List1", "List2" };

public IList<string>? CollectionProperty { get; set; } = new List<string>() { "Collection1", "Collection2" };

public string[]? ArrayProperty { get; set; } = new string[] { "Array1", "Array2" };

public void WaitsVoidMethod()
{
Thread.Sleep(100);
Expand Down Expand Up @@ -136,6 +144,24 @@ public async Task<string> MethodThatCannotBeCompiled_MustSetOtherAttributes()
return "xxx";
}

public async Task<List<string>> MethodWithListParametersAndListReturn(List<string> a, List<string> b)
{
await Task.Delay(1);
return a.Concat(b).ToList();
}

public async Task<IList<string>> MethodWithCollectionParametersAndCollectionReturn(IList<string> a, IList<string> b)
{
await Task.Delay(1);
return a.Concat(b).ToList();
}

public async Task<string[]> MethodWithArrayParametersAndArrayReturn(string[] a, string[] b)
{
await Task.Delay(1);
return a.Concat(b).ToArray();
}

public void MethodWithStructParameters(BindingFlags flags)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;

Expand All @@ -19,6 +20,12 @@ internal interface IFakeIpcObject : IFakeIpcObjectBase

IntPtr? NullableIntPtrProperty { get; }

List<string>? ListProperty { get; set; }

IList<string>? CollectionProperty { get; set; }

string[]? ArrayProperty { get; set; }

INestedFakeIpcArgumentOrReturn NestedIpcProperty { get; set; }

[IpcMethod(WaitsVoid = true)]
Expand Down Expand Up @@ -62,6 +69,12 @@ internal interface IFakeIpcObject : IFakeIpcObjectBase
[IpcMethod(DefaultReturn = "default1")]
Task<string> MethodThatCannotBeCompiled_MustSetOtherAttributes();

Task<List<string>> MethodWithListParametersAndListReturn(List<string> a, List<string> b);

Task<IList<string>> MethodWithCollectionParametersAndCollectionReturn(IList<string> a, IList<string> b);

Task<string[]> MethodWithArrayParametersAndArrayReturn(string[] a, string[] b);

void MethodWithStructParameters(BindingFlags flags);

bool MethodWithStructReturn();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
Expand All @@ -13,6 +15,7 @@

using Microsoft.VisualStudio.TestTools.UnitTesting;

using MSTest.Extensions.AssertExtensions;
using MSTest.Extensions.Contracts;

namespace dotnetCampus.Ipc.Tests.CompilerServices.GeneratedProxies
Expand Down Expand Up @@ -291,6 +294,88 @@ public void IpcParametersAndReturnsTests()
});
}

[ContractTestCase]
public void IpcCollectionTests()
{
"IPC 代理生成:集合(列表)属性".Test(async () =>
{
// 准备。
var (peer, proxy) = await CreateIpcPairAsync(nameof(FakeIpcObject.ListProperty));

// 安放。
var result = proxy.ListProperty;

// 植物。
CollectionAssert.AreEqual(new string[] { "List1", "List2" }, result);
});

"IPC 代理生成:集合(接口)属性".Test(async () =>
{
// 准备。
var (peer, proxy) = await CreateIpcPairAsync(nameof(FakeIpcObject.CollectionProperty));

// 安放。
var result = proxy.CollectionProperty;

// 植物。
CollectionAssert.AreEqual(new string[] { "Collection1", "Collection2" }, (ICollection?) result);
});

"IPC 代理生成:集合(数组)属性".Test(async () =>
{
// 准备。
var (peer, proxy) = await CreateIpcPairAsync(nameof(FakeIpcObject.ArrayProperty));

// 安放。
var result = proxy.ArrayProperty;

// 植物。
CollectionAssert.AreEqual(new string[] { "Array1", "Array2" }, result);
});

"IPC 代理生成:集合(列表)异步方法".Test(async () =>
{
// 准备。
var (peer, proxy) = await CreateIpcPairAsync(nameof(FakeIpcObject.MethodWithListParametersAndListReturn));

// 安放。
var result = await proxy.MethodWithListParametersAndListReturn(
new List<string> { "a", "b" },
new List<string> { "c", "d" });

// 植物。
CollectionAssert.AreEqual(new string[] { "a", "b", "c", "d" }, result);
});

"IPC 代理生成:集合(接口)异步方法".Test(async () =>
{
// 准备。
var (peer, proxy) = await CreateIpcPairAsync(nameof(FakeIpcObject.MethodWithCollectionParametersAndCollectionReturn));

// 安放。
var result = await proxy.MethodWithCollectionParametersAndCollectionReturn(
new List<string> { "a", "b" },
new List<string> { "c", "d" });

// 植物。
CollectionAssert.AreEqual(new string[] { "a", "b", "c", "d" }, (ICollection) result);
});

"IPC 代理生成:集合(数组)异步方法".Test(async () =>
{
// 准备。
var (peer, proxy) = await CreateIpcPairAsync(nameof(FakeIpcObject.MethodWithArrayParametersAndArrayReturn));

// 安放。
var result = await proxy.MethodWithArrayParametersAndArrayReturn(
new string[] { "a", "b" },
new string[] { "c", "d" });

// 植物。
CollectionAssert.AreEqual(new string[] { "a", "b", "c", "d" }, result);
});
}

[ContractTestCase]
public void IpcMethodExceptionTests()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using dotnetCampus.Ipc.Tests.CompilerServices;
using dotnetCampus.Ipc.Tests.CompilerServices.Fake;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

Expand Down Expand Up @@ -32,6 +34,15 @@ internal class NotGeneratedTestOnlyFakeIpcObjectIpcShape : IFakeIpcObject
[IpcProperty]
INestedFakeIpcArgumentOrReturn IFakeIpcObject.NestedIpcProperty { get; set; }

[IpcProperty]
public List<string> ListProperty { get; set; }

[IpcProperty]
public IList<string> CollectionProperty { get; set; }

[IpcProperty]
public string[] ArrayProperty { get; set; }

[IpcMethod]
void IFakeIpcObject.WaitsVoidMethod()
{
Expand Down Expand Up @@ -110,6 +121,21 @@ Task<string> IFakeIpcObject.MethodThatCannotBeCompiled_MustSetOtherAttributes()
throw null;
}

public Task<List<string>> MethodWithListParametersAndListReturn(List<string> a, List<string> b)
{
throw null;
}

public Task<IList<string>> MethodWithCollectionParametersAndCollectionReturn(IList<string> a, IList<string> b)
{
throw null;
}

public Task<string[]> MethodWithArrayParametersAndArrayReturn(string[] a, string[] b)
{
throw null;
}

[IpcMethod]
void IFakeIpcObject.MethodWithStructParameters(BindingFlags flags)
{
Expand Down

0 comments on commit 064e9e3

Please sign in to comment.