add csharpier

This commit is contained in:
Adam Hathcock
2024-05-21 16:34:46 +01:00
parent 1734d5162a
commit e341772cbc
110 changed files with 1096 additions and 656 deletions
+12
View File
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "0.28.2",
"commands": [
"dotnet-csharpier"
]
}
}
}
@@ -10,6 +10,7 @@ namespace ProxyInterfaceConsumer
[SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
public event EventHandler<EventArgs> MyEvent = null!;
public int Weird { get; set; }
public int Weird2()
{
return 0;
@@ -3,11 +3,7 @@ using System.Net.Http;
namespace ProxyInterfaceConsumer.Http;
[ProxyInterfaceGenerator.Proxy(typeof(HttpClient), true)]
public partial interface IHttpClient : IHttpMessageInvoker
{
}
public partial interface IHttpClient : IHttpMessageInvoker { }
[ProxyInterfaceGenerator.Proxy(typeof(HttpMessageInvoker))]
public partial interface IHttpMessageInvoker
{
}
public partial interface IHttpMessageInvoker { }
@@ -13,94 +13,210 @@ namespace ProxyInterfaceConsumer.Http;
public static class IHttpClientExtensions
{
#region PostAsJsonAsync
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, TValue value, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default)
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
TValue value,
JsonSerializerOptions? options = null,
CancellationToken cancellationToken = default
)
{
return client._Instance.PostAsJsonAsync(requestUri, value, options, cancellationToken);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(this IHttpClient client, Uri? requestUri, TValue value, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default)
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(
this IHttpClient client,
Uri? requestUri,
TValue value,
JsonSerializerOptions? options = null,
CancellationToken cancellationToken = default
)
{
return client._Instance.PostAsJsonAsync(requestUri, value, options, cancellationToken);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, TValue value, CancellationToken cancellationToken)
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
TValue value,
CancellationToken cancellationToken
)
{
return client._Instance.PostAsJsonAsync(requestUri, value, options: null, cancellationToken);
return client._Instance.PostAsJsonAsync(
requestUri,
value,
options: null,
cancellationToken
);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(this IHttpClient client, Uri? requestUri, TValue value, CancellationToken cancellationToken)
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(
this IHttpClient client,
Uri? requestUri,
TValue value,
CancellationToken cancellationToken
)
{
return client._Instance.PostAsJsonAsync(requestUri, value, options: null, cancellationToken);
return client._Instance.PostAsJsonAsync(
requestUri,
value,
options: null,
cancellationToken
);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, TValue value, JsonTypeInfo<TValue> jsonTypeInfo, CancellationToken cancellationToken = default)
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
TValue value,
JsonTypeInfo<TValue> jsonTypeInfo,
CancellationToken cancellationToken = default
)
{
return client._Instance.PostAsJsonAsync(requestUri, value, jsonTypeInfo, cancellationToken);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(this IHttpClient client, Uri? requestUri, TValue value, JsonTypeInfo<TValue> jsonTypeInfo, CancellationToken cancellationToken = default)
public static Task<HttpResponseMessage> PostAsJsonAsync<TValue>(
this IHttpClient client,
Uri? requestUri,
TValue value,
JsonTypeInfo<TValue> jsonTypeInfo,
CancellationToken cancellationToken = default
)
{
return client._Instance.PostAsJsonAsync(requestUri, value, jsonTypeInfo, cancellationToken);
}
#endregion
#region GetFromJsonAsync
public static Task<object?> GetFromJsonAsync(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, Type type, JsonSerializerOptions? options, CancellationToken cancellationToken = default)
public static Task<object?> GetFromJsonAsync(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
Type type,
JsonSerializerOptions? options,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, type, options, cancellationToken);
}
public static Task<object?> GetFromJsonAsync(this IHttpClient client, Uri? requestUri, Type type, JsonSerializerOptions? options, CancellationToken cancellationToken = default)
public static Task<object?> GetFromJsonAsync(
this IHttpClient client,
Uri? requestUri,
Type type,
JsonSerializerOptions? options,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, type, options, cancellationToken);
}
public static Task<TValue?> GetFromJsonAsync<TValue>(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, JsonSerializerOptions? options, CancellationToken cancellationToken = default)
public static Task<TValue?> GetFromJsonAsync<TValue>(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
JsonSerializerOptions? options,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync<TValue>(requestUri, options, cancellationToken);
}
public static Task<TValue?> GetFromJsonAsync<TValue>(this IHttpClient client, Uri? requestUri, JsonSerializerOptions? options, CancellationToken cancellationToken = default)
public static Task<TValue?> GetFromJsonAsync<TValue>(
this IHttpClient client,
Uri? requestUri,
JsonSerializerOptions? options,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync<TValue>(requestUri, options, cancellationToken);
}
public static Task<object?> GetFromJsonAsync(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, Type type, JsonSerializerContext context, CancellationToken cancellationToken = default)
public static Task<object?> GetFromJsonAsync(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
Type type,
JsonSerializerContext context,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, type, context, cancellationToken);
}
public static Task<object?> GetFromJsonAsync(this IHttpClient client, Uri? requestUri, Type type, JsonSerializerContext context, CancellationToken cancellationToken = default)
public static Task<object?> GetFromJsonAsync(
this IHttpClient client,
Uri? requestUri,
Type type,
JsonSerializerContext context,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, type, context, cancellationToken);
}
public static Task<TValue?> GetFromJsonAsync<TValue>(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, JsonTypeInfo<TValue> jsonTypeInfo, CancellationToken cancellationToken = default)
public static Task<TValue?> GetFromJsonAsync<TValue>(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
JsonTypeInfo<TValue> jsonTypeInfo,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, jsonTypeInfo, cancellationToken);
}
public static Task<TValue?> GetFromJsonAsync<TValue>(this IHttpClient client, Uri? requestUri, JsonTypeInfo<TValue> jsonTypeInfo, CancellationToken cancellationToken = default)
public static Task<TValue?> GetFromJsonAsync<TValue>(
this IHttpClient client,
Uri? requestUri,
JsonTypeInfo<TValue> jsonTypeInfo,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, jsonTypeInfo, cancellationToken);
}
public static Task<object?> GetFromJsonAsync(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, Type type, CancellationToken cancellationToken = default)
public static Task<object?> GetFromJsonAsync(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
Type type,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, type, options: null, cancellationToken);
return client._Instance.GetFromJsonAsync(
requestUri,
type,
options: null,
cancellationToken
);
}
public static Task<object?> GetFromJsonAsync(this IHttpClient client, Uri? requestUri, Type type, CancellationToken cancellationToken = default)
public static Task<object?> GetFromJsonAsync(
this IHttpClient client,
Uri? requestUri,
Type type,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync(requestUri, type, options: null, cancellationToken);
return client._Instance.GetFromJsonAsync(
requestUri,
type,
options: null,
cancellationToken
);
}
public static Task<TValue?> GetFromJsonAsync<TValue>(this IHttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, CancellationToken cancellationToken = default)
public static Task<TValue?> GetFromJsonAsync<TValue>(
this IHttpClient client,
[StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync<TValue>(requestUri, cancellationToken);
}
public static Task<TValue?> GetFromJsonAsync<TValue>(this IHttpClient client, Uri? requestUri, CancellationToken cancellationToken = default)
public static Task<TValue?> GetFromJsonAsync<TValue>(
this IHttpClient client,
Uri? requestUri,
CancellationToken cancellationToken = default
)
{
return client._Instance.GetFromJsonAsync<TValue>(requestUri, cancellationToken);
}
@@ -1,7 +1,5 @@
namespace ProxyInterfaceConsumer
{
// [ProxyInterfaceGenerator.Proxy(typeof(Microsoft.CodeAnalysis.GeneratorExecutionContext))]
public partial interface IGeneratorExecutionContext
{
}
public partial interface IGeneratorExecutionContext { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceConsumer
{
public interface IMyInterface
{
}
public interface IMyInterface { }
}
@@ -3,7 +3,5 @@ using ProxyInterfaceGenerator;
namespace ProxyInterfaceConsumer
{
[Proxy(typeof(ProxyInterfaceConsumer.Person), ProxyClassAccessibility.Internal)]
public partial interface IPerson
{
}
public partial interface IPerson { }
}
@@ -2,6 +2,5 @@ namespace ProxyInterfaceConsumer
{
[ProxyInterfaceGenerator.Proxy(typeof(ProxyInterfaceConsumer.PersonT<>))]
public partial interface IPersonT //<T> where T : struct
{
}
{ }
}
@@ -3,7 +3,5 @@ namespace ProxyInterfaceConsumer
[ProxyInterfaceGenerator.Proxy(typeof(ProxyInterfaceConsumer.PersonTT<,>))]
public partial interface IPersonTT<T1, T2>
where T1 : struct
where T2 : class, new()
{
}
where T2 : class, new() { }
}
+7 -11
View File
@@ -25,8 +25,10 @@ namespace ProxyInterfaceConsumer
[SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
public List<Address> AddressesList { get; set; } = null!;
public Dictionary<string, Address> AddressesDict { get; set; } = new Dictionary<string, Address>();
public Dictionary<Address, Address> AddressesDict2 { get; set; } = new Dictionary<Address, Address>();
public Dictionary<string, Address> AddressesDict { get; set; } =
new Dictionary<string, Address>();
public Dictionary<Address, Address> AddressesDict2 { get; set; } =
new Dictionary<Address, Address>();
public E E { get; set; }
@@ -55,9 +57,7 @@ namespace ProxyInterfaceConsumer
return $"Hello {name} !";
}
public void AddWithParams(params string[] values)
{
}
public void AddWithParams(params string[] values) { }
public Address AddAddress(Address a)
{
@@ -66,9 +66,7 @@ namespace ProxyInterfaceConsumer
return a;
}
public void AddAddresses(params Address[] addresses)
{
}
public void AddAddresses(params Address[] addresses) { }
public void In_Out_Ref1(in int a, out int b, ref int c)
{
@@ -83,9 +81,7 @@ namespace ProxyInterfaceConsumer
// return 404;
//}
public void Void()
{
}
public void Void() { }
public Task Method1Async()
{
@@ -1,6 +1,7 @@
namespace ProxyInterfaceConsumer
{
public class PersonT<T> where T : struct
public class PersonT<T>
where T : struct
{
public T TVal { get; set; }
@@ -8,8 +8,6 @@ namespace ProxyInterfaceConsumer
public T2 TVal2 { get; set; }
public void Call(int x, T1 t1, T2 t2)
{
}
public void Call(int x, T1 t1, T2 t2) { }
}
}
+8 -14
View File
@@ -11,10 +11,7 @@ namespace ProxyInterfaceConsumer;
public class Program
{
private static JsonSerializerOptions JsonSerializerOptions = new ()
{
WriteIndented = true
};
private static JsonSerializerOptions JsonSerializerOptions = new() { WriteIndented = true };
public static async Task Main()
{
@@ -24,7 +21,10 @@ public class Program
var result = await ph.GetAsync("https://www.google.nl");
var todo = await ph.GetFromJsonAsync<Todo>("https://jsonplaceholder.typicode.com/todos/1");
var postResult = await h.PostAsJsonAsync<Todo>("https://jsonplaceholder.typicode.com/todos", new Todo { Id = 123 });
var postResult = await h.PostAsJsonAsync<Todo>(
"https://jsonplaceholder.typicode.com/todos",
new Todo { Id = 123 }
);
var t = new TestProxy(new Test());
@@ -41,9 +41,7 @@ public class Program
var ap = new AddressProxy(new Address { HouseNumber = 42 });
ap.HouseNumber = -1;
ap.MyEvent += delegate (object x, EventArgs a)
{
};
ap.MyEvent += delegate(object x, EventArgs a) { };
IPerson p = new PersonProxy(new Person());
p.Name = "test";
@@ -93,11 +91,7 @@ public sealed class Clazz
}
[ProxyInterfaceGenerator.Proxy(typeof(Test))]
public partial interface ITest
{
}
public partial interface ITest { }
[ProxyInterfaceGenerator.Proxy(typeof(Clazz))]
public partial interface IClazz
{
}
public partial interface IClazz { }
@@ -4,6 +4,4 @@ using Akka.Remote;
[ProxyInterfaceGenerator.Proxy(typeof(AddressUid))]
// ReSharper disable once CheckNamespace
public partial interface IAddressUid
{
}
public partial interface IAddressUid { }
@@ -3,7 +3,5 @@ using Akka.Actor;
namespace ProxyInterfaceConsumerForAkka.Interfaces
{
[ProxyInterfaceGenerator.Proxy(typeof(LocalActorRefProvider))]
public partial interface ILocalActorRefProvider
{
}
public partial interface ILocalActorRefProvider { }
}
@@ -11,9 +11,15 @@ namespace ProxyInterfaceConsumerForPnP.Interfaces;
[SuppressMessage("ReSharper", "InconsistentNaming")]
public partial class ClientContextProxy
{
public Task ExecuteQueryRetryAsync(Interfaces.IClientRuntimeContext clientContext, int retryCount = 10, string? userAgent = null)
public Task ExecuteQueryRetryAsync(
Interfaces.IClientRuntimeContext clientContext,
int retryCount = 10,
string? userAgent = null
)
{
ClientRuntimeContext clientObject_ = Mapster.TypeAdapter.Adapt<ClientRuntimeContext>(clientContext);
ClientRuntimeContext clientObject_ = Mapster.TypeAdapter.Adapt<ClientRuntimeContext>(
clientContext
);
return clientObject_.ExecuteQueryRetryAsync(retryCount, userAgent);
}
@@ -25,17 +31,24 @@ public partial class ClientContextProxy
_Instance.Load<T>(clientObject_, retrievals_);
}
public void Load<TSource, TTarget>(Interfaces.IClientObject clientObject, params Expression<Func<TSource, object>>[] retrievals)
public void Load<TSource, TTarget>(
Interfaces.IClientObject clientObject,
params Expression<Func<TSource, object>>[] retrievals
)
where TSource : Interfaces.IClientObject
where TTarget : ClientObject
{
TTarget clientObject_ = Mapster.TypeAdapter.Adapt<TTarget>(clientObject);
Expression<Func<TTarget, object>>[] retrievals_ = retrievals.Select(MapExpression<TSource, TTarget>).ToArray();
Expression<Func<TTarget, object>>[] retrievals_ = retrievals
.Select(MapExpression<TSource, TTarget>)
.ToArray();
_Instance.Load(clientObject_, retrievals_);
}
private static Expression<Func<TTarget, object>> MapExpression<TSource, TTarget>(Expression<Func<TSource, object>> expression)
private static Expression<Func<TTarget, object>> MapExpression<TSource, TTarget>(
Expression<Func<TSource, object>> expression
)
where TSource : Interfaces.IClientObject
where TTarget : ClientObject
{
@@ -45,20 +58,28 @@ public partial class ClientContextProxy
switch (expression.Body)
{
case MemberExpression memberExpression:
memberAccessExpression = Expression.PropertyOrField(parameterExpression, memberExpression.Member.Name);
memberAccessExpression = Expression.PropertyOrField(
parameterExpression,
memberExpression.Member.Name
);
break;
case UnaryExpression unaryExpression:
var expressionOperand = (MemberExpression)unaryExpression.Operand;
memberAccessExpression = Expression.PropertyOrField(parameterExpression, expressionOperand.Member.Name);
memberAccessExpression = Expression.PropertyOrField(
parameterExpression,
expressionOperand.Member.Name
);
memberAccessExpression = Expression.Convert(memberAccessExpression, typeof(object));
break;
default:
throw new NotSupportedException();
}
return Expression.Lambda<Func<TTarget, object>>(memberAccessExpression, parameterExpression);
return Expression.Lambda<Func<TTarget, object>>(
memberAccessExpression,
parameterExpression
);
}
}
@@ -6,9 +6,15 @@ namespace ProxyInterfaceConsumerForPnP.Implementations;
public static class ClientRuntimeContextExtensions
{
public static Task ExecuteQueryRetryAsync(this IClientRuntimeContext clientContext, int retryCount = 10, string? userAgent = null)
public static Task ExecuteQueryRetryAsync(
this IClientRuntimeContext clientContext,
int retryCount = 10,
string? userAgent = null
)
{
ClientRuntimeContext clientObject_ = Mapster.TypeAdapter.Adapt<ClientRuntimeContext>(clientContext);
ClientRuntimeContext clientObject_ = Mapster.TypeAdapter.Adapt<ClientRuntimeContext>(
clientContext
);
return clientObject_.ExecuteQueryRetryAsync(retryCount, userAgent);
}
}
@@ -7,7 +7,10 @@ namespace ProxyInterfaceConsumerForPnP.Interfaces
[ProxyInterfaceGenerator.Proxy(typeof(ClientContext))]
public partial interface IClientContext : IClientRuntimeContext
{
void Load<TSource, TTarget>(IClientObject clientObject, params Expression<Func<TSource, object>>[] retrievals)
void Load<TSource, TTarget>(
IClientObject clientObject,
params Expression<Func<TSource, object>>[] retrievals
)
where TSource : IClientObject
where TTarget : ClientObject;
}
@@ -1,7 +1,5 @@
namespace ProxyInterfaceConsumerForPnP.Interfaces
{
[ProxyInterfaceGenerator.Proxy(typeof(Microsoft.SharePoint.Client.ClientObject))]
public partial interface IClientObject
{
}
public partial interface IClientObject { }
}
@@ -1,8 +1,5 @@
namespace ProxyInterfaceConsumerForPnP.Interfaces
{
[ProxyInterfaceGenerator.Proxy(typeof(Microsoft.SharePoint.Client.ClientRuntimeContext))]
public partial interface IClientRuntimeContext
{
}
public partial interface IClientRuntimeContext { }
}
@@ -1,7 +1,5 @@
namespace ProxyInterfaceConsumerForPnP.Interfaces
{
[ProxyInterfaceGenerator.Proxy(typeof(Microsoft.SharePoint.Client.User))]
public partial interface IUser
{
}
public partial interface IUser { }
}
@@ -1,7 +1,5 @@
namespace ProxyInterfaceConsumerForPnP.Interfaces
{
[ProxyInterfaceGenerator.Proxy(typeof(Microsoft.SharePoint.Client.Web))]
public partial interface IWeb: ISecurableObject
{
}
public partial interface IWeb : ISecurableObject { }
}
@@ -18,9 +18,12 @@ public class Program
"15b347bf-90a2-4c16-aa76-5a3263476b59",
"Test.pfx",
Environment.GetEnvironmentVariable("Test.pfx_PWD"),
"s7gb6.onmicrosoft.com");
"s7gb6.onmicrosoft.com"
);
using var clientContext = await authManager.GetContextAsync("https://s7gb6.sharepoint.com/sites/Test");
using var clientContext = await authManager.GetContextAsync(
"https://s7gb6.sharepoint.com/sites/Test"
);
clientContext.Load(clientContext.Web, p => p.Title);
await clientContext.ExecuteQueryRetryAsync();
@@ -28,7 +31,12 @@ public class Program
IClientContext cp = new ClientContextProxy(clientContext);
cp.Load<ProxyInterfaceConsumerForPnP.Interfaces.IWeb, Web>(cp.Web, w => w.Lists, w => w.Language, w => w.Author);
cp.Load<ProxyInterfaceConsumerForPnP.Interfaces.IWeb, Web>(
cp.Web,
w => w.Lists,
w => w.Language,
w => w.Author
);
await cp.ExecuteQueryRetryAsync();
@@ -1,7 +1,5 @@
namespace ProxyInterfaceConsumer
{
[ProxyInterfaceGenerator.Proxy(typeof(ProxyInterfaceConsumer.Address))]
public partial interface IAddress
{
}
public partial interface IAddress { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceConsumer
{
public interface IMyInterface
{
}
public interface IMyInterface { }
}
@@ -3,7 +3,5 @@ using ProxyInterfaceGenerator;
namespace ProxyInterfaceConsumer
{
[Proxy(typeof(Person), ProxyClassAccessibility.Internal)]
public partial interface IPerson
{
}
public partial interface IPerson { }
}
@@ -25,8 +25,10 @@ namespace ProxyInterfaceConsumer
[SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
public List<Address> AddressesLIst { get; set; } = null!;
public Dictionary<string, Address> AddressesDict { get; set; } = new Dictionary<string, Address>();
public Dictionary<Address, Address> AddressesDict2 { get; set; } = new Dictionary<Address, Address>();
public Dictionary<string, Address> AddressesDict { get; set; } =
new Dictionary<string, Address>();
public Dictionary<Address, Address> AddressesDict2 { get; set; } =
new Dictionary<Address, Address>();
public E E { get; set; }
@@ -38,9 +40,7 @@ namespace ProxyInterfaceConsumer
return s + @string;
}
public void AddWithParams(params string[] values)
{
}
public void AddWithParams(params string[] values) { }
public Address AddAddress(Address a)
{
@@ -49,9 +49,7 @@ namespace ProxyInterfaceConsumer
return a;
}
public void AddAddresses(params Address[] addresses)
{
}
public void AddAddresses(params Address[] addresses) { }
public void In_Out_Ref1(in int a, out int b, ref int c)
{
@@ -64,9 +62,7 @@ namespace ProxyInterfaceConsumer
return 404;
}
public void Void()
{
}
public void Void() { }
public Task Method1Async()
{
@@ -5,10 +5,7 @@ namespace ProxyInterfaceConsumer
{
class Program
{
private static JsonSerializerOptions JsonSerializerOptions = new ()
{
WriteIndented = true
};
private static JsonSerializerOptions JsonSerializerOptions = new() { WriteIndented = true };
static void Main(string[] args)
{
@@ -5,7 +5,9 @@ namespace Speckle.ProxyGenerator.Extensions;
internal static class MethodSymbolExtensions
{
public static string GetMethodNameWithOptionalTypeParameters(this IMethodSymbol method) =>
!method.IsGenericMethod ? method.Name : $"{method.Name}<{string.Join(", ", method.TypeParameters.Select(tp => tp.Name))}>";
!method.IsGenericMethod
? method.Name
: $"{method.Name}<{string.Join(", ", method.TypeParameters.Select(tp => tp.Name))}>";
//public static string GetWhereStatement(this IMethodSymbol method) =>
// !method.IsGenericMethod ? string.Empty : string.Join("", method.TypeParameters.Select(tp => tp.GetWhereConstraints()));
@@ -41,22 +41,34 @@ internal static class NamedTypeSymbolExtensions
/// </summary>
public static string ResolveProxyClassName(this INamedTypeSymbol namedTypeSymbol)
{
return !namedTypeSymbol.IsGenericType ?
$"{namedTypeSymbol.Name}Proxy" :
$"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
return !namedTypeSymbol.IsGenericType
? $"{namedTypeSymbol.Name}Proxy"
: $"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
}
public static List<INamedTypeSymbol> ResolveImplementedInterfaces(this INamedTypeSymbol symbol, bool proxyBaseClasses)
public static List<INamedTypeSymbol> ResolveImplementedInterfaces(
this INamedTypeSymbol symbol,
bool proxyBaseClasses
)
{
// Members implemented by us or base classes should go here.
var publicMembers = symbol.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public).ToList();
var publicMembers = symbol
.GetMembers()
.Where(m => m.DeclaredAccessibility == Accessibility.Public)
.ToList();
// Direct interfaces, recursive interfaces or base class interfaces should go here.
var interfaces = new List<INamedTypeSymbol>(symbol.Interfaces);
var baseType = symbol.BaseType;
while (proxyBaseClasses && baseType != null && baseType.SpecialType != SpecialType.System_Object)
while (
proxyBaseClasses
&& baseType != null
&& baseType.SpecialType != SpecialType.System_Object
)
{
publicMembers.AddRange(baseType.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public));
publicMembers.AddRange(
baseType.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public)
);
interfaces.AddRange(baseType.Interfaces);
baseType = baseType.BaseType;
}
@@ -66,7 +78,10 @@ internal static class NamedTypeSymbolExtensions
foreach (var @interface in interfaces)
{
var isRealized = true;
var allMembers = @interface.AllInterfaces.Aggregate(@interface.GetMembers(), (xs, x) => xs.AddRange(x.GetMembers()));
var allMembers = @interface.AllInterfaces.Aggregate(
@interface.GetMembers(),
(xs, x) => xs.AddRange(x.GetMembers())
);
foreach (var member in allMembers)
{
var implementation = symbol.FindImplementationForInterfaceMember(member);
@@ -24,7 +24,8 @@ internal static class ParameterSymbolExtensions
};
}
public static string GetParamsPrefix(this IParameterSymbol ps) => ps.IsParams ? "params " : string.Empty;
public static string GetParamsPrefix(this IParameterSymbol ps) =>
ps.IsParams ? "params " : string.Empty;
public static string GetDefaultValue(this IParameterSymbol ps)
{
@@ -44,7 +45,8 @@ internal static class ParameterSymbolExtensions
else
{
defaultValue = ps.Type.IsReferenceType
? ParameterValueNull : // The parameter is a ReferenceType, so use "null".
? ParameterValueNull
: // The parameter is a ReferenceType, so use "null".
$"default({ps.Type})"; // The parameter is not a ReferenceType, so use "default(T)".
}
}
@@ -8,7 +8,10 @@ internal static class PropertySymbolExtensions
{
public static TypeEnum GetTypeEnum(this IPropertySymbol p) => p.Type.GetTypeEnum();
public static (string PropertyType, string? PropertyName, string GetSet)? ToPropertyDetails(this IPropertySymbol property, string? overrideType = null)
public static (string PropertyType, string? PropertyName, string GetSet)? ToPropertyDetails(
this IPropertySymbol property,
string? overrideType = null
)
{
var getIsPublic = property.GetMethod.IsPublic();
var setIsPublic = property.SetMethod.IsPublic();
@@ -21,8 +24,12 @@ internal static class PropertySymbolExtensions
var get = getIsPublic ? "get; " : string.Empty;
var set = setIsPublic ? "set; " : string.Empty;
var type = !string.IsNullOrEmpty(overrideType) ? overrideType
: BaseGenerator.FixType(property.Type.ToFullyQualifiedDisplayString(), property.NullableAnnotation);
var type = !string.IsNullOrEmpty(overrideType)
? overrideType
: BaseGenerator.FixType(
property.Type.ToFullyQualifiedDisplayString(),
property.NullableAnnotation
);
return (type!, property.GetSanitizedName(), $"{{ {get}{set}}}");
}
@@ -17,7 +17,13 @@ internal static class SymbolExtensions
{
return symbol
.GetAttributes()
.Where(a => a.AttributeClass.IsPublic() && !ExcludedAttributes.Contains(a.AttributeClass?.ToString(), StringComparer.OrdinalIgnoreCase))
.Where(a =>
a.AttributeClass.IsPublic()
&& !ExcludedAttributes.Contains(
a.AttributeClass?.ToString(),
StringComparer.OrdinalIgnoreCase
)
)
.Select(a => $"[{a}]")
.ToArray();
}
@@ -53,7 +59,10 @@ internal static class SymbolExtensions
sb.Insert(0, '.');
}
sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
sb.Insert(
0,
s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)
);
s = s.ContainingSymbol;
}
@@ -64,7 +73,8 @@ internal static class SymbolExtensions
symbol.IsKeywordOrReserved() ? $"@{symbol.Name}" : symbol.Name;
public static bool IsKeywordOrReserved(this ISymbol symbol) =>
SyntaxFacts.GetKeywordKind(symbol.Name) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(symbol.Name) != SyntaxKind.None;
SyntaxFacts.GetKeywordKind(symbol.Name) != SyntaxKind.None
|| SyntaxFacts.GetContextualKeywordKind(symbol.Name) != SyntaxKind.None;
public static bool IsPublic(this ISymbol? symbol) =>
symbol is { DeclaredAccessibility: Accessibility.Public };
@@ -7,7 +7,11 @@ namespace Speckle.ProxyGenerator.Extensions;
internal static class SyntaxNodeExtensions
{
// https://stackoverflow.com/questions/20458457/getting-class-fullname-including-namespace-from-roslyn-classdeclarationsyntax
public static bool TryGetParentSyntax<T>(this SyntaxNode? syntaxNode, [NotNullWhen(true)] out T? result) where T : SyntaxNode
public static bool TryGetParentSyntax<T>(
this SyntaxNode? syntaxNode,
[NotNullWhen(true)] out T? result
)
where T : SyntaxNode
{
result = null;
@@ -57,9 +61,11 @@ internal static class SyntaxNodeExtensions
// Keep moving "out" of nested classes etc until we get to a namespace
// or until we run out of parents
while (potentialNamespaceParent != null &&
potentialNamespaceParent is not NamespaceDeclarationSyntax
&& potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
while (
potentialNamespaceParent != null
&& potentialNamespaceParent is not NamespaceDeclarationSyntax
&& potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax
)
{
potentialNamespaceParent = potentialNamespaceParent.Parent;
}
@@ -21,7 +21,8 @@ internal static class TypeSymbolExtensions
}
public static bool IsString(this ITypeSymbol ts) =>
ts.ToString().ToLowerInvariant() == "string" || ts.ToString().ToLowerInvariant() == "string?";
ts.ToString().ToLowerInvariant() == "string"
|| ts.ToString().ToLowerInvariant() == "string?";
public static string ToFullyQualifiedDisplayString(this ITypeSymbol property) =>
property.ToDisplayString(NullableFlowState.None, SymbolDisplayFormat.FullyQualifiedFormat);
@@ -30,7 +30,10 @@ internal abstract class BaseGenerator
return GetReplacedTypeAsString(property.Type, out isReplaced);
}
protected bool TryFindProxyDataByTypeName(string type, [NotNullWhen(true)] out ProxyData? proxyData)
protected bool TryFindProxyDataByTypeName(
string type,
[NotNullWhen(true)] out ProxyData? proxyData
)
{
proxyData = Context.Candidates.Values.FirstOrDefault(x => x.FullQualifiedTypeName == type);
return proxyData != null;
@@ -55,16 +58,23 @@ internal abstract class BaseGenerator
return string.Concat(list);
}
protected string ResolveInterfaceNameWithOptionalTypeConstraints(INamedTypeSymbol namedTypeSymbol, string interfaceName)
protected string ResolveInterfaceNameWithOptionalTypeConstraints(
INamedTypeSymbol namedTypeSymbol,
string interfaceName
)
{
if (!namedTypeSymbol.IsGenericType)
{
return interfaceName;
}
var str = new StringBuilder($"{interfaceName}<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>");
var str = new StringBuilder(
$"{interfaceName}<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>"
);
foreach (var typeParameterSymbol in namedTypeSymbol.TypeArguments.OfType<ITypeParameterSymbol>())
foreach (
var typeParameterSymbol in namedTypeSymbol.TypeArguments.OfType<ITypeParameterSymbol>()
)
{
if (TryGetWhereConstraints(typeParameterSymbol, false, out var constraint))
{
@@ -78,7 +88,11 @@ internal abstract class BaseGenerator
/// <summary>
/// https://www.codeproject.com/Articles/871704/Roslyn-Code-Analysis-in-Easy-Samples-Part-2
/// </summary>
public bool TryGetWhereConstraints(ITypeParameterSymbol typeParameterSymbol, bool replaceIt, [NotNullWhen(true)] out ConstraintInfo? constraint)
public bool TryGetWhereConstraints(
ITypeParameterSymbol typeParameterSymbol,
bool replaceIt,
[NotNullWhen(true)] out ConstraintInfo? constraint
)
{
var constraints = new List<string>();
if (typeParameterSymbol.HasReferenceTypeConstraint)
@@ -91,7 +105,9 @@ internal abstract class BaseGenerator
constraints.Add("struct");
}
foreach (var namedTypeSymbol in typeParameterSymbol.ConstraintTypes.OfType<INamedTypeSymbol>())
foreach (
var namedTypeSymbol in typeParameterSymbol.ConstraintTypes.OfType<INamedTypeSymbol>()
)
{
if (replaceIt)
{
@@ -123,17 +139,20 @@ internal abstract class BaseGenerator
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included,
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions:
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
SymbolDisplayMiscellaneousOptions.UseSpecialTypes |
SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers
| SymbolDisplayMiscellaneousOptions.UseSpecialTypes
| SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier
);
protected string GetReplacedTypeAsString(ITypeSymbol typeSymbol, out bool isReplaced)
{
isReplaced = false;
var typeSymbolAsString = typeSymbol.ToFullyQualifiedDisplayString();
var nullableTypeSymbolAsString = typeSymbol.ToDisplayString(NullableFlowState.None, NullableDisplayFormat);
var nullableTypeSymbolAsString = typeSymbol.ToDisplayString(
NullableFlowState.None,
NullableDisplayFormat
);
if (TryFindProxyDataByTypeName(typeSymbolAsString, out var existing))
{
@@ -171,17 +190,28 @@ internal abstract class BaseGenerator
if (!Context.ReplacedTypes.ContainsKey(typeArgumentAsString))
{
Context.ReplacedTypes.Add(typeArgumentAsString, existingTypeArgument.FullInterfaceName);
Context.ReplacedTypes.Add(
typeArgumentAsString,
existingTypeArgument.FullInterfaceName
);
}
propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, existingTypeArgument.FullInterfaceName);
propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(
typeArgumentAsString,
existingTypeArgument.FullInterfaceName
);
}
}
return FixType(propertyTypeAsStringToBeModified, typeSymbol.NullableAnnotation);
}
protected bool TryGetNamedTypeSymbolByFullName(TypeKind kind, string name, IEnumerable<string> usings, [NotNullWhen(true)] out ClassSymbol? classSymbol)
protected bool TryGetNamedTypeSymbolByFullName(
TypeKind kind,
string name,
IEnumerable<string> usings,
[NotNullWhen(true)] out ClassSymbol? classSymbol
)
{
classSymbol = default;
const string globalPrefix = "global::";
@@ -195,16 +225,26 @@ internal abstract class BaseGenerator
if (symbol is not null && symbol.TypeKind == kind)
{
classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
classSymbol = new ClassSymbol(
symbol,
symbol.GetBaseTypes(),
symbol.AllInterfaces.ToList()
);
return true;
}
foreach (var @using in usings)
{
symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(
$"{@using}.{name}"
);
if (symbol is not null && symbol.TypeKind == kind)
{
classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
classSymbol = new ClassSymbol(
symbol,
symbol.GetBaseTypes(),
symbol.AllInterfaces.ToList()
);
return true;
}
}
@@ -212,7 +252,10 @@ internal abstract class BaseGenerator
return false;
}
protected IReadOnlyList<string> GetMethodParameters(ImmutableArray<IParameterSymbol> parameterSymbols, bool includeType)
protected IReadOnlyList<string> GetMethodParameters(
ImmutableArray<IParameterSymbol> parameterSymbols,
bool includeType
)
{
var methodParameters = new List<string>();
foreach (var parameterSymbol in parameterSymbols)
@@ -226,7 +269,10 @@ internal abstract class BaseGenerator
}
else
{
type = FixType(parameterSymbol.Type.ToFullyQualifiedDisplayString(), parameterSymbol.NullableAnnotation);
type = FixType(
parameterSymbol.Type.ToFullyQualifiedDisplayString(),
parameterSymbol.NullableAnnotation
);
}
}
@@ -236,12 +282,17 @@ internal abstract class BaseGenerator
return methodParameters;
}
protected IReadOnlyList<ProxyData> GetExtendsProxyData(ProxyData proxyData, ClassSymbol targetClassSymbol)
protected IReadOnlyList<ProxyData> GetExtendsProxyData(
ProxyData proxyData,
ClassSymbol targetClassSymbol
)
{
var extendsProxyClasses = new List<ProxyData>();
foreach (var baseType in targetClassSymbol.BaseTypes)
{
var candidate = Context.Candidates.Values.FirstOrDefault(ci => ci.FullQualifiedTypeName == baseType.ToFullyQualifiedDisplayString());
var candidate = Context.Candidates.Values.FirstOrDefault(ci =>
ci.FullQualifiedTypeName == baseType.ToFullyQualifiedDisplayString()
);
if (candidate is not null)
{
extendsProxyClasses.Add(candidate);
@@ -253,7 +304,10 @@ internal abstract class BaseGenerator
internal static string FixType(string type, NullableAnnotation nullableAnnotation)
{
if (nullableAnnotation == NullableAnnotation.Annotated && !type.EndsWith("?", StringComparison.Ordinal))
if (
nullableAnnotation == NullableAnnotation.Annotated
&& !type.EndsWith("?", StringComparison.Ordinal)
)
{
return $"{type}?";
}
@@ -8,7 +8,9 @@ internal class ExtraFilesGenerator : IFileGenerator
public FileData GenerateFile()
{
return new FileData($"{Name}", $@"//----------------------------------------------------------------------------------------
return new FileData(
$"{Name}",
$@"//----------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
//
@@ -61,6 +63,7 @@ namespace ProxyInterfaceGenerator
Internal = 1
}}
}}");
}}"
);
}
}
@@ -11,11 +11,11 @@ namespace Speckle.ProxyGenerator.FileGenerators;
internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
{
private IReadOnlyCollection<INamedTypeSymbol> _implementedInterfaces = new List<INamedTypeSymbol>();
private IReadOnlyCollection<INamedTypeSymbol> _implementedInterfaces =
new List<INamedTypeSymbol>();
public PartialInterfacesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
{
}
public PartialInterfacesGenerator(Context context, bool supportsNullable)
: base(context, supportsNullable) { }
public IEnumerable<FileData> GenerateFiles()
{
@@ -28,21 +28,42 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
}
}
private bool TryGenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
private bool TryGenerateFile(
InterfaceDeclarationSyntax ci,
ProxyData pd,
[NotNullWhen(true)] out FileData? fileData
)
{
fileData = default;
if (!TryGetNamedTypeSymbolByFullName(TypeKind.Interface, ci.Identifier.ToString(), pd.Usings, out var sourceInterfaceSymbol))
if (
!TryGetNamedTypeSymbolByFullName(
TypeKind.Interface,
ci.Identifier.ToString(),
pd.Usings,
out var sourceInterfaceSymbol
)
)
{
return false;
}
if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol))
if (
!TryGetNamedTypeSymbolByFullName(
TypeKind.Class,
pd.FullMetadataTypeName,
pd.Usings,
out var targetClassSymbol
)
)
{
return false;
}
var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(targetClassSymbol.Symbol, pd.ShortInterfaceName);
var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(
targetClassSymbol.Symbol,
pd.ShortInterfaceName
);
fileData = new FileData(
$"{sourceInterfaceSymbol.Symbol.GetFullMetadataName()}.g.cs",
@@ -56,12 +77,19 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
string ns,
ClassSymbol classSymbol,
string interfaceName,
ProxyData proxyData)
ProxyData proxyData
)
{
var extendsProxyClasses = GetExtendsProxyData(proxyData, classSymbol);
_implementedInterfaces = classSymbol.Symbol.ResolveImplementedInterfaces(proxyData.ProxyBaseClasses);
var implementedInterfacesNames = _implementedInterfaces.Select(i => i.ToFullyQualifiedDisplayString()).ToArray();
var implements = implementedInterfacesNames.Any() ? $" : {string.Join(", ", implementedInterfacesNames)}" : string.Empty;
_implementedInterfaces = classSymbol.Symbol.ResolveImplementedInterfaces(
proxyData.ProxyBaseClasses
);
var implementedInterfacesNames = _implementedInterfaces
.Select(i => i.ToFullyQualifiedDisplayString())
.ToArray();
var implements = implementedInterfacesNames.Any()
? $" : {string.Join(", ", implementedInterfacesNames)}"
: string.Empty;
var @new = extendsProxyClasses.Any() ? "new " : string.Empty;
var (namespaceStart, namespaceEnd) = NamespaceBuilder.Build(ns);
var events = GenerateEvents(classSymbol, proxyData);
@@ -93,12 +121,16 @@ methods}
{SupportsNullable.IIf("#nullable restore")}";
}
private Func<T, bool> InterfaceFilter<T>() where T : ISymbol
private Func<T, bool> InterfaceFilter<T>()
where T : ISymbol
{
var hashSet = new HashSet<string>();
foreach (var @interface in _implementedInterfaces)
{
var members = @interface.AllInterfaces.Aggregate(@interface.GetMembers(), (xs, x) => xs.AddRange(x.GetMembers()));
var members = @interface.AllInterfaces.Aggregate(
@interface.GetMembers(),
(xs, x) => xs.AddRange(x.GetMembers())
);
foreach (var member in members)
{
hashSet.Add(member.Name);
@@ -113,11 +145,19 @@ methods}
{
var str = new StringBuilder();
foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyData, InterfaceFilter<IPropertySymbol>()))
foreach (
var property in MemberHelper.GetPublicProperties(
targetClassSymbol,
proxyData,
InterfaceFilter<IPropertySymbol>()
)
)
{
var type = GetPropertyType(property, out var isReplaced);
var getterSetter = isReplaced ? property.ToPropertyDetails(type) : property.ToPropertyDetails();
var getterSetter = isReplaced
? property.ToPropertyDetails(type)
: property.ToPropertyDetails();
if (getterSetter is null)
{
continue;
@@ -136,7 +176,9 @@ methods}
str.AppendLine($" {attribute}");
}
str.AppendLine($" {getterSetter.Value.PropertyType} {propertyName} {getterSetter.Value.GetSet}");
str.AppendLine(
$" {getterSetter.Value.PropertyType} {propertyName} {getterSetter.Value.GetSet}"
);
str.AppendLine();
}
return str.ToString();
@@ -145,7 +187,13 @@ methods}
private string GenerateMethods(ClassSymbol targetClassSymbol, ProxyData proxyData)
{
var str = new StringBuilder();
foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol, proxyData, InterfaceFilter<IMethodSymbol>()))
foreach (
var method in MemberHelper.GetPublicMethods(
targetClassSymbol,
proxyData,
InterfaceFilter<IMethodSymbol>()
)
)
{
var methodParameters = GetMethodParameters(method.Parameters, true);
var whereStatement = GetWhereStatementFromMethod(method);
@@ -155,7 +203,9 @@ methods}
str.AppendLine($" {attribute}");
}
str.AppendLine($" {GetReplacedTypeAsString(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement};");
str.AppendLine(
$" {GetReplacedTypeAsString(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement};"
);
str.AppendLine();
}
@@ -165,10 +215,19 @@ methods}
private string GenerateEvents(ClassSymbol targetClassSymbol, ProxyData proxyData)
{
var str = new StringBuilder();
foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyData, InterfaceFilter<IMethodSymbol>()))
foreach (
var @event in MemberHelper.GetPublicEvents(
targetClassSymbol,
proxyData,
InterfaceFilter<IMethodSymbol>()
)
)
{
var ps = @event.First().Parameters.First();
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
var type =
ps.GetTypeEnum() == TypeEnum.Complex
? GetParameterType(ps, out _)
: ps.Type.ToString();
foreach (var attribute in ps.GetAttributesAsList())
{
@@ -19,13 +19,20 @@ internal partial class ProxyClassesGenerator
foreach (var replacedType in Context.ReplacedTypes)
{
TryFindProxyDataByTypeName(replacedType.Key, out var fullTypeName);
var classNameProxy = $"{fullTypeName!.NamespaceDot}{fullTypeName.ShortMetadataName}Proxy";
var classNameProxy =
$"{fullTypeName!.NamespaceDot}{fullTypeName.ShortMetadataName}Proxy";
var instance = $"instance{(replacedType.Key + replacedType.Value).GetDeterministicHashCodeAsString()}";
var proxy = $"proxy{(replacedType.Value + replacedType.Key).GetDeterministicHashCodeAsString()}";
var instance =
$"instance{(replacedType.Key + replacedType.Value).GetDeterministicHashCodeAsString()}";
var proxy =
$"proxy{(replacedType.Value + replacedType.Key).GetDeterministicHashCodeAsString()}";
str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>().ConstructUsing({instance} => new {classNameProxy}({instance}));");
str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>().ConstructUsing({proxy} => (({classNameProxy}) {proxy})._Instance);");
str.AppendLine(
$" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>().ConstructUsing({instance} => new {classNameProxy}({instance}));"
);
str.AppendLine(
$" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>().ConstructUsing({proxy} => (({classNameProxy}) {proxy})._Instance);"
);
str.AppendLine();
}
str.AppendLine(" }).CreateMapper();");
@@ -12,13 +12,20 @@ internal partial class ProxyClassesGenerator
foreach (var replacedType in Context.ReplacedTypes)
{
TryFindProxyDataByTypeName(replacedType.Key, out var fullTypeName);
var classNameProxy = $"global::{fullTypeName!.NamespaceDot}{fullTypeName!.ShortMetadataName}Proxy";
var classNameProxy =
$"global::{fullTypeName!.NamespaceDot}{fullTypeName!.ShortMetadataName}Proxy";
var instance = $"instance{(replacedType.Key + replacedType.Value).GetDeterministicHashCodeAsString()}";
var proxy = $"proxy{(replacedType.Value + replacedType.Key).GetDeterministicHashCodeAsString()}";
var instance =
$"instance{(replacedType.Key + replacedType.Value).GetDeterministicHashCodeAsString()}";
var proxy =
$"proxy{(replacedType.Value + replacedType.Key).GetDeterministicHashCodeAsString()}";
str.AppendLine($" Mapster.TypeAdapterConfig<{replacedType.Key}, {replacedType.Value}>.NewConfig().ConstructUsing({instance} => new {classNameProxy}({instance}));");
str.AppendLine($" Mapster.TypeAdapterConfig<{replacedType.Value}, {replacedType.Key}>.NewConfig().MapWith({proxy} => (({classNameProxy}) {proxy})._Instance);");
str.AppendLine(
$" Mapster.TypeAdapterConfig<{replacedType.Key}, {replacedType.Value}>.NewConfig().ConstructUsing({instance} => new {classNameProxy}({instance}));"
);
str.AppendLine(
$" Mapster.TypeAdapterConfig<{replacedType.Value}, {replacedType.Key}>.NewConfig().MapWith({proxy} => (({classNameProxy}) {proxy})._Instance);"
);
str.AppendLine();
}
@@ -12,9 +12,8 @@ namespace Speckle.ProxyGenerator.FileGenerators;
internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
{
public ProxyClassesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
{
}
public ProxyClassesGenerator(Context context, bool supportsNullable)
: base(context, supportsNullable) { }
public IEnumerable<FileData> GenerateFiles()
{
@@ -27,17 +26,31 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
}
}
[SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1024:Compare symbols correctly", Justification = "<Pending>")]
[SuppressMessage(
"MicrosoftCodeAnalysisCorrectness",
"RS1024:Compare symbols correctly",
Justification = "<Pending>"
)]
private bool TryGenerateFile(ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
{
fileData = default;
if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol))
if (
!TryGetNamedTypeSymbolByFullName(
TypeKind.Class,
pd.FullMetadataTypeName,
pd.Usings,
out var targetClassSymbol
)
)
{
return false;
}
var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(targetClassSymbol.Symbol, pd.FullInterfaceName);
var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(
targetClassSymbol.Symbol,
pd.FullInterfaceName
);
var className = targetClassSymbol.Symbol.ResolveProxyClassName();
var constructorName = $"{targetClassSymbol.Symbol.Name}Proxy";
@@ -45,7 +58,14 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
fileData = new FileData(
$"{targetClassSymbol.Symbol.GetFullMetadataName()}Proxy.g.cs",
CreateProxyClassCode(pd, targetClassSymbol, extendsProxyClasses, interfaceName, className, constructorName)
CreateProxyClassCode(
pd,
targetClassSymbol,
extendsProxyClasses,
interfaceName,
className,
constructorName
)
);
return true;
@@ -57,7 +77,8 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
IReadOnlyList<ProxyData> extendsProxyClasses,
string interfaceName,
string className,
string constructorName)
string constructorName
)
{
var firstExtends = extendsProxyClasses.FirstOrDefault();
var extends = string.Empty;
@@ -71,8 +92,10 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
extends = $"global::{firstExtends.NamespaceDot}{firstExtends.ShortMetadataName}Proxy, ";
@base = " : base(instance)";
@new = "new ";
instanceBaseDefinition = $"public {firstExtends.FullQualifiedTypeName} _Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} {{ get; }}";
instanceBaseSetter = $"_Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} = instance;";
instanceBaseDefinition =
$"public {firstExtends.FullQualifiedTypeName} _Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} {{ get; }}";
instanceBaseSetter =
$"_Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} = instance;";
}
var @abstract = string.Empty; // targetClassSymbol.Symbol.IsAbstract ? "abstract " : string.Empty;
@@ -89,7 +112,8 @@ internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
var (namespaceStart, namespaceEnd) = NamespaceBuilder.Build(pd.Namespace);
var accessibility = pd.Accessibility == ProxyClassAccessibility.Internal ? "internal" : "public";
var accessibility =
pd.Accessibility == ProxyClassAccessibility.Internal ? "internal" : "public";
return $@"//----------------------------------------------------------------------------------------
// <auto-generated>
@@ -132,9 +156,7 @@ operators}
{
var type = GetPropertyType(property, out var isReplaced);
var instance = !property.IsStatic ?
"_Instance" :
$"{targetClassSymbol.Symbol}";
var instance = !property.IsStatic ? "_Instance" : $"{targetClassSymbol.Symbol}";
var propertyName = property.GetSanitizedName();
var instancePropertyName = $"{instance}.{propertyName}";
@@ -169,8 +191,12 @@ operators}
string set;
if (isReplaced)
{
get = getIsPublic ? $"get => Mapster.TypeAdapter.Adapt<{type}>({instancePropertyName}); " : string.Empty;
set = setIsPublic ? $"set => {instancePropertyName} = Mapster.TypeAdapter.Adapt<{property.Type}>(value); " : string.Empty;
get = getIsPublic
? $"get => Mapster.TypeAdapter.Adapt<{type}>({instancePropertyName}); "
: string.Empty;
set = setIsPublic
? $"set => {instancePropertyName} = Mapster.TypeAdapter.Adapt<{property.Type}>(value); "
: string.Empty;
}
else
{
@@ -183,7 +209,9 @@ operators}
str.AppendLine($" {attribute}");
}
str.AppendLine($" public {overrideOrVirtual}{type} {propertyName} {{ {get}{set}}}");
str.AppendLine(
$" public {overrideOrVirtual}{type} {propertyName} {{ {get}{set}}}"
);
str.AppendLine();
}
@@ -208,7 +236,9 @@ operators}
methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type));
// Do not add the '_' for a 'ref' parameter.
invokeParameters.Add($"{parameterSymbol.GetRefKindPrefix()}{parameterSymbol.GetSanitizedName()}{(!parameterSymbol.IsRef()).IIf("_")}");
invokeParameters.Add(
$"{parameterSymbol.GetRefKindPrefix()}{parameterSymbol.GetSanitizedName()}{(!parameterSymbol.IsRef()).IIf("_")}"
);
}
string overrideOrVirtual = string.Empty;
@@ -225,7 +255,10 @@ operators}
overrideOrVirtual = "virtual ";
}
string returnTypeAsString = GetReplacedTypeAsString(method.ReturnType, out var returnIsReplaced);
string returnTypeAsString = GetReplacedTypeAsString(
method.ReturnType,
out var returnIsReplaced
);
var whereStatement = GetWhereStatementFromMethod(method);
@@ -234,12 +267,17 @@ operators}
str.AppendLine($" {attribute}");
}
str.AppendLine($" public {overrideOrVirtual}{returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement}");
str.AppendLine(
$" public {overrideOrVirtual}{returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement}"
);
str.AppendLine(@" {");
foreach (var ps in method.Parameters.Where(p => !p.IsRef()))
{
var type = FixType(ps.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), ps.Type.NullableAnnotation);
var type = FixType(
ps.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
ps.Type.NullableAnnotation
);
string normalOrMap = $" = {ps.GetSanitizedName()}";
if (ps.RefKind == RefKind.Out)
{
@@ -250,7 +288,8 @@ operators}
_ = GetParameterType(ps, out var isReplaced); // TODO : response is not used?
if (isReplaced)
{
normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()})";
normalOrMap =
$" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()})";
}
}
@@ -258,17 +297,24 @@ operators}
}
var methodName = method.GetMethodNameWithOptionalTypeParameters();
var alternateReturnVariableName = $"result_{methodName.GetDeterministicHashCodeAsString()}";
var alternateReturnVariableName =
$"result_{methodName.GetDeterministicHashCodeAsString()}";
string instance = method.IsStatic ? targetClassSymbol.Symbol.ToFullyQualifiedDisplayString() : "_Instance";
string instance = method.IsStatic
? targetClassSymbol.Symbol.ToFullyQualifiedDisplayString()
: "_Instance";
if (returnTypeAsString == "void")
{
str.AppendLine($" {instance}.{methodName}({string.Join(", ", invokeParameters)});");
str.AppendLine(
$" {instance}.{methodName}({string.Join(", ", invokeParameters)});"
);
}
else
{
str.AppendLine($" var {alternateReturnVariableName} = {instance}.{methodName}({string.Join(", ", invokeParameters)});");
str.AppendLine(
$" var {alternateReturnVariableName} = {instance}.{methodName}({string.Join(", ", invokeParameters)});"
);
}
foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
@@ -279,7 +325,8 @@ operators}
var type = GetParameterType(ps, out var isReplaced);
if (isReplaced)
{
normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)";
normalOrMap =
$" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)";
}
}
@@ -290,7 +337,9 @@ operators}
{
if (returnIsReplaced)
{
str.AppendLine($" return Mapster.TypeAdapter.Adapt<{returnTypeAsString}>({alternateReturnVariableName});");
str.AppendLine(
$" return Mapster.TypeAdapter.Adapt<{returnTypeAsString}>({alternateReturnVariableName});"
);
}
else
{
@@ -312,7 +361,10 @@ operators}
{
var name = @event.Key.GetSanitizedName();
var ps = @event.First().Parameters.First();
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
var type =
ps.GetTypeEnum() == TypeEnum.Complex
? GetParameterType(ps, out _)
: ps.Type.ToString();
foreach (var attribute in ps.GetAttributesAsList())
{
@@ -340,7 +392,9 @@ operators}
private string GenerateOperators(ClassSymbol targetClassSymbol, ProxyData proxyData)
{
var str = new StringBuilder();
foreach (var @operator in MemberHelper.GetPublicStaticOperators(targetClassSymbol, proxyData))
foreach (
var @operator in MemberHelper.GetPublicStaticOperators(targetClassSymbol, proxyData)
)
{
foreach (var attribute in @operator.GetAttributesAsList())
{
@@ -360,18 +414,26 @@ operators}
{
var returnTypeAsString = GetReplacedTypeAsString(@operator.ReturnType, out _);
str.AppendLine($" public static explicit operator {returnTypeAsString}({proxyClassName} {parameter.Name})");
str.AppendLine(
$" public static explicit operator {returnTypeAsString}({proxyClassName} {parameter.Name})"
);
str.AppendLine(@" {");
str.AppendLine($" return ({returnTypeAsString}) {parameter.Name}._Instance;");
str.AppendLine(
$" return ({returnTypeAsString}) {parameter.Name}._Instance;"
);
str.AppendLine(@" }");
}
else
{
var returnTypeAsString = GetReplacedTypeAsString(parameter.Type, out _);
str.AppendLine($" public static implicit operator {proxyClassName}({returnTypeAsString} {parameter.Name})");
str.AppendLine(
$" public static implicit operator {proxyClassName}({returnTypeAsString} {parameter.Name})"
);
str.AppendLine(@" {");
str.AppendLine($" return new {proxyClassName}(({targetClassSymbol.Symbol.Name}) {parameter.Name});");
str.AppendLine(
$" return new {proxyClassName}(({targetClassSymbol.Symbol.Name}) {parameter.Name});"
);
str.AppendLine(@" }");
}
@@ -2,10 +2,17 @@ using Microsoft.CodeAnalysis;
namespace Speckle.ProxyGenerator.Models;
internal record ClassSymbol(INamedTypeSymbol Symbol, List<INamedTypeSymbol> BaseTypes, List<INamedTypeSymbol> Interfaces)
internal record ClassSymbol(
INamedTypeSymbol Symbol,
List<INamedTypeSymbol> BaseTypes,
List<INamedTypeSymbol> Interfaces
)
{
public override string ToString()
{
return Symbol.ToDisplayString(NullableFlowState.None, SymbolDisplayFormat.FullyQualifiedFormat);
return Symbol.ToDisplayString(
NullableFlowState.None,
SymbolDisplayFormat.FullyQualifiedFormat
);
}
}
+15 -7
View File
@@ -25,7 +25,8 @@ internal class ProxyData
public ProxyClassAccessibility Accessibility { get; }
public string[] MembersToIgnore { get; }
public ProxyData(string @namespace,
public ProxyData(
string @namespace,
string namespaceDot,
string shortInterfaceName,
string fullInterfaceName,
@@ -34,15 +35,22 @@ internal class ProxyData
string fullMetadataTypeName,
List<string> usings,
bool proxyBaseClasses,
ProxyClassAccessibility accessibility, string[] membersToIgnore)
ProxyClassAccessibility accessibility,
string[] membersToIgnore
)
{
Namespace = @namespace ?? throw new ArgumentNullException(nameof(@namespace));
NamespaceDot = namespaceDot ?? throw new ArgumentNullException(nameof(namespaceDot));
ShortInterfaceName = shortInterfaceName ?? throw new ArgumentNullException(nameof(shortInterfaceName));
FullInterfaceName = fullInterfaceName ?? throw new ArgumentNullException(nameof(fullInterfaceName));
FullQualifiedTypeName = fullQualifiedTypeName ?? throw new ArgumentNullException(nameof(fullQualifiedTypeName));
ShortMetadataName = shortMetadataTypeName ?? throw new ArgumentNullException(nameof(shortMetadataTypeName));
FullMetadataTypeName = fullMetadataTypeName ?? throw new ArgumentNullException(nameof(fullMetadataTypeName));
ShortInterfaceName =
shortInterfaceName ?? throw new ArgumentNullException(nameof(shortInterfaceName));
FullInterfaceName =
fullInterfaceName ?? throw new ArgumentNullException(nameof(fullInterfaceName));
FullQualifiedTypeName =
fullQualifiedTypeName ?? throw new ArgumentNullException(nameof(fullQualifiedTypeName));
ShortMetadataName =
shortMetadataTypeName ?? throw new ArgumentNullException(nameof(shortMetadataTypeName));
FullMetadataTypeName =
fullMetadataTypeName ?? throw new ArgumentNullException(nameof(fullMetadataTypeName));
Usings = usings ?? throw new ArgumentNullException(nameof(usings));
ProxyBaseClasses = proxyBaseClasses;
Accessibility = accessibility;
@@ -40,7 +40,9 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator
if (context.SyntaxContextReceiver is not ProxySyntaxReceiver receiver)
{
throw new NotSupportedException($"Only {nameof(ProxySyntaxReceiver)} is supported.");
throw new NotSupportedException(
$"Only {nameof(ProxySyntaxReceiver)} is supported."
);
}
// https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
@@ -58,7 +60,8 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator
private void GenerateError(GeneratorExecutionContext context, Exception exception)
{
var message = $"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
var message =
$"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
context.AddSource("Error.g", SourceText.From(message, Encoding.UTF8));
}
@@ -71,10 +74,17 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator
};
var attributeData = _proxyAttributeGenerator.GenerateFile();
context.GeneratorExecutionContext.AddSource(attributeData.FileName, SourceText.From(attributeData.Text, Encoding.UTF8));
context.GeneratorExecutionContext.AddSource(
attributeData.FileName,
SourceText.From(attributeData.Text, Encoding.UTF8)
);
}
private static void GeneratePartialInterfaces(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
private static void GeneratePartialInterfaces(
GeneratorExecutionContext ctx,
ProxySyntaxReceiver receiver,
bool supportsNullable
)
{
var context = new Context
{
@@ -85,11 +95,18 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator
var partialInterfacesGenerator = new PartialInterfacesGenerator(context, supportsNullable);
foreach (var (fileName, text) in partialInterfacesGenerator.GenerateFiles())
{
context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
context.GeneratorExecutionContext.AddSource(
fileName,
SourceText.From(text, Encoding.UTF8)
);
}
}
private static void GenerateProxyClasses(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
private static void GenerateProxyClasses(
GeneratorExecutionContext ctx,
ProxySyntaxReceiver receiver,
bool supportsNullable
)
{
var context = new Context
{
@@ -100,7 +117,10 @@ class ProxyInterfaceCodeGenerator : ISourceGenerator
var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable);
foreach (var (fileName, text) in proxyClassesGenerator.GenerateFiles())
{
context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
context.GeneratorExecutionContext.AddSource(
fileName,
SourceText.From(text, Encoding.UTF8)
);
}
}
}
@@ -9,7 +9,10 @@ namespace Speckle.ProxyGenerator.SyntaxReceiver;
internal static class AttributeArgumentListParser
{
public static ProxyInterfaceGeneratorAttributeArguments ParseAttributeArguments(AttributeArgumentListSyntax? argumentList, SemanticModel semanticModel)
public static ProxyInterfaceGeneratorAttributeArguments ParseAttributeArguments(
AttributeArgumentListSyntax? argumentList,
SemanticModel semanticModel
)
{
if (argumentList is null || argumentList.Arguments.Count is < 1 or > 4)
{
@@ -17,13 +20,25 @@ internal static class AttributeArgumentListParser
}
ProxyInterfaceGeneratorAttributeArguments result;
if (TryParseAsType(argumentList.Arguments[0].Expression, semanticModel, out var fullyQualifiedDisplayString, out var metadataName))
if (
TryParseAsType(
argumentList.Arguments[0].Expression,
semanticModel,
out var fullyQualifiedDisplayString,
out var metadataName
)
)
{
result = new ProxyInterfaceGeneratorAttributeArguments(fullyQualifiedDisplayString, metadataName);
result = new ProxyInterfaceGeneratorAttributeArguments(
fullyQualifiedDisplayString,
metadataName
);
}
else
{
throw new ArgumentException("The first argument from the ProxyAttribute should be a Type.");
throw new ArgumentException(
"The first argument from the ProxyAttribute should be a Type."
);
}
foreach (var argument in argumentList.Arguments.Skip(1))
@@ -61,7 +76,12 @@ internal static class AttributeArgumentListParser
return false;
}
private static bool TryParseAsType(ExpressionSyntax expressionSyntax, SemanticModel semanticModel, [NotNullWhen(true)] out string? fullyQualifiedDisplayString, [NotNullWhen(true)] out string? metadataName)
private static bool TryParseAsType(
ExpressionSyntax expressionSyntax,
SemanticModel semanticModel,
[NotNullWhen(true)] out string? fullyQualifiedDisplayString,
[NotNullWhen(true)] out string? metadataName
)
{
fullyQualifiedDisplayString = null;
metadataName = null;
@@ -83,7 +103,13 @@ internal static class AttributeArgumentListParser
where TEnum : struct
{
var enumAsString = expressionSyntax.ToString();
if (enumAsString.Length > typeof(TEnum).Name.Length && Enum.TryParse(expressionSyntax.ToString().Substring(typeof(TEnum).Name.Length + 1), out value))
if (
enumAsString.Length > typeof(TEnum).Name.Length
&& Enum.TryParse(
expressionSyntax.ToString().Substring(typeof(TEnum).Name.Length + 1),
out value
)
)
{
return true;
}
@@ -94,10 +120,15 @@ internal static class AttributeArgumentListParser
private static bool TryParseAsStringArray(ExpressionSyntax expressionSyntax, out string[] value)
{
if (expressionSyntax is ImplicitArrayCreationExpressionSyntax lmplicitArrayCreationExpressionSyntax)
if (
expressionSyntax
is ImplicitArrayCreationExpressionSyntax lmplicitArrayCreationExpressionSyntax
)
{
var strings = new List<string>();
foreach (var expression in lmplicitArrayCreationExpressionSyntax.Initializer.Expressions)
foreach (
var expression in lmplicitArrayCreationExpressionSyntax.Initializer.Expressions
)
{
if (expression.GetFirstToken().Value is string s)
{
@@ -9,26 +9,44 @@ namespace Speckle.ProxyGenerator.SyntaxReceiver;
internal class ProxySyntaxReceiver : ISyntaxContextReceiver
{
private const string GlobalPrefix = "global::";
private static readonly string[] GenerateProxyAttributes = ["ProxyInterfaceGenerator.Proxy", "Proxy"];
private static readonly string[] GenerateProxyAttributes =
[
"ProxyInterfaceGenerator.Proxy",
"Proxy"
];
private static readonly string[] Modifiers = ["public", "partial"];
public IDictionary<InterfaceDeclarationSyntax, ProxyData> CandidateInterfaces { get; } = new Dictionary<InterfaceDeclarationSyntax, ProxyData>();
public IDictionary<InterfaceDeclarationSyntax, ProxyData> CandidateInterfaces { get; } =
new Dictionary<InterfaceDeclarationSyntax, ProxyData>();
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
{
var syntaxNode = context.Node;
var semanticModel = context.SemanticModel;
if (syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax && TryGet(interfaceDeclarationSyntax, out var data, semanticModel!))
if (
syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax
&& TryGet(interfaceDeclarationSyntax, out var data, semanticModel!)
)
{
CandidateInterfaces.Add(interfaceDeclarationSyntax, data);
}
}
private static string CreateFullInterfaceName(string ns, BaseTypeDeclarationSyntax classDeclarationSyntax)
private static string CreateFullInterfaceName(
string ns,
BaseTypeDeclarationSyntax classDeclarationSyntax
)
{
return !string.IsNullOrEmpty(ns) ? $"{ns}.{classDeclarationSyntax.Identifier}" : classDeclarationSyntax.Identifier.ToString();
return !string.IsNullOrEmpty(ns)
? $"{ns}.{classDeclarationSyntax.Identifier}"
: classDeclarationSyntax.Identifier.ToString();
}
private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, [NotNullWhen(true)] out ProxyData? data, SemanticModel semanticModel)
private static bool TryGet(
InterfaceDeclarationSyntax interfaceDeclarationSyntax,
[NotNullWhen(true)] out ProxyData? data,
SemanticModel semanticModel
)
{
data = null;
@@ -38,7 +56,9 @@ internal class ProxySyntaxReceiver : ISyntaxContextReceiver
return false;
}
var attributeList = interfaceDeclarationSyntax.AttributeLists.FirstOrDefault(x => x.Attributes.Any(a => GenerateProxyAttributes.Contains(a.Name.ToString())));
var attributeList = interfaceDeclarationSyntax.AttributeLists.FirstOrDefault(x =>
x.Attributes.Any(a => GenerateProxyAttributes.Contains(a.Name.ToString()))
);
if (attributeList is null)
{
// InterfaceDeclarationSyntax should have the correct attribute
@@ -61,7 +81,10 @@ internal class ProxySyntaxReceiver : ISyntaxContextReceiver
}
}
var fluentBuilderAttributeArguments = AttributeArgumentListParser.ParseAttributeArguments(attributeList.Attributes.FirstOrDefault()?.ArgumentList, semanticModel);
var fluentBuilderAttributeArguments = AttributeArgumentListParser.ParseAttributeArguments(
attributeList.Attributes.FirstOrDefault()?.ArgumentList,
semanticModel
);
var metadataName = fluentBuilderAttributeArguments.MetadataName;
var globalNamespace = string.IsNullOrEmpty(ns) ? string.Empty : $"{GlobalPrefix}{ns}";
@@ -1,6 +1,9 @@
namespace Speckle.ProxyGenerator.Types;
internal record ProxyInterfaceGeneratorAttributeArguments(string FullyQualifiedDisplayString, string MetadataName)
internal record ProxyInterfaceGeneratorAttributeArguments(
string FullyQualifiedDisplayString,
string MetadataName
)
{
public bool ProxyBaseClasses { get; set; }
@@ -10,7 +10,8 @@ internal static class MemberHelper
public static IReadOnlyList<IPropertySymbol> GetPublicProperties(
ClassSymbol classSymbol,
ProxyData proxyData,
params Func<IPropertySymbol, bool>[] filters)
params Func<IPropertySymbol, bool>[] filters
)
{
var allFilters = new List<Func<IPropertySymbol, bool>>(filters)
{
@@ -23,43 +24,46 @@ internal static class MemberHelper
public static IReadOnlyList<IMethodSymbol> GetPublicMethods(
ClassSymbol classSymbol,
ProxyData proxyData,
Func<IMethodSymbol, bool>? filter = null)
Func<IMethodSymbol, bool>? filter = null
)
{
filter ??= _ => true;
return
GetPublicMembers(
return GetPublicMembers(
classSymbol,
proxyData,
m => m.Kind == SymbolKind.Method,
m => m.MethodKind == MethodKind.Ordinary,
m => !ExcludedMethods.Contains(m.Name),
filter)
filter
)
.ToArray();
}
public static IReadOnlyList<IMethodSymbol> GetPublicStaticOperators(
ClassSymbol classSymbol,
ProxyData proxyData,
Func<IMethodSymbol, bool>? filter = null)
Func<IMethodSymbol, bool>? filter = null
)
{
filter ??= _ => true;
return
GetPublicMembers(
return GetPublicMembers(
classSymbol,
proxyData,
m => m.Kind == SymbolKind.Method,
m => m.MethodKind == MethodKind.Conversion,
m => !ExcludedMethods.Contains(m.Name),
filter)
filter
)
.ToArray();
}
public static IReadOnlyList<IGrouping<ISymbol, IMethodSymbol>> GetPublicEvents(
ClassSymbol classSymbol,
ProxyData proxyData,
Func<IMethodSymbol, bool>? filter = null)
Func<IMethodSymbol, bool>? filter = null
)
{
filter ??= _ => true;
@@ -68,8 +72,13 @@ internal static class MemberHelper
return GetPublicMembers(
classSymbol,
proxyData,
m => m.MethodKind is MethodKind.EventAdd or MethodKind.EventRemove/* || m.MethodKind == MethodKind.EventRaise*/,
filter)
m =>
m.MethodKind
is MethodKind.EventAdd
or MethodKind.EventRemove /* || m.MethodKind == MethodKind.EventRaise*/
,
filter
)
.GroupBy(e => e.AssociatedSymbol)
.ToArray();
#pragma warning restore RS1024 // Compare symbols correctly
@@ -81,9 +90,12 @@ internal static class MemberHelper
ClassSymbol classSymbol,
ProxyData proxyData,
params Func<T, bool>[] filters
) where T : ISymbol
)
where T : ISymbol
{
var membersQuery = classSymbol.Symbol.GetMembers().OfType<T>()
var membersQuery = classSymbol
.Symbol.GetMembers()
.OfType<T>()
.Where(m => m.DeclaredAccessibility == Accessibility.Public);
var f = filters.ToList();
@@ -106,7 +118,9 @@ internal static class MemberHelper
while (baseType != null && baseType.SpecialType != SpecialType.System_Object)
{
var baseMembers = baseType.GetMembers().OfType<T>()
var baseMembers = baseType
.GetMembers()
.OfType<T>()
.Where(m => m.DeclaredAccessibility == Accessibility.Public)
.Where(x => !ownMemberNames.Contains(x.Name));
@@ -6,8 +6,7 @@ internal static class NamespaceBuilder
{
var namespaceDefined = !string.IsNullOrEmpty(ns);
return
(
return (
namespaceDefined ? $"namespace {ns}\r\n{{" : string.Empty,
namespaceDefined ? "}" : string.Empty
);
@@ -40,10 +40,7 @@ public class AkkaTests
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -54,8 +51,14 @@ public class AkkaTests
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/AkkaGenerated/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/AkkaGenerated/{fileName.fileName}"));
if (Write)
File.WriteAllText(
$"../../../Destination/AkkaGenerated/{fileName.fileName}",
builder.Text
);
builder
.Text.Should()
.Be(File.ReadAllText($"../../../Destination/AkkaGenerated/{fileName.fileName}"));
}
}
}
@@ -27,17 +27,17 @@ public class InheritedInterfaceTests
[Theory]
[InlineData(false, false)]
[InlineData(true, true)]
public void GenerateFiles_InheritedInterface_InheritFromBaseClass(bool proxyBaseClass, bool inheritBaseInterface)
public void GenerateFiles_InheritedInterface_InheritFromBaseClass(
bool proxyBaseClass,
bool inheritBaseInterface
)
{
var name = "Child";
var interfaceName = "I" + name;
var proxyName = name + "Proxy";
// Arrange
string[] fileNames = [
$"{Namespace}.{interfaceName}.g.cs",
$"{Namespace}.{proxyName}.g.cs"
];
string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"];
var path = $"./Source/Disposable/{interfaceName}.cs";
SourceFile sourceFile = CreateSourceFile(path, name, proxyBaseClass);
@@ -69,10 +69,7 @@ public class InheritedInterfaceTests
var proxyName = name + "Proxy";
// Arrange
string[] fileNames = [
$"{Namespace}.{interfaceName}.g.cs",
$"{Namespace}.{proxyName}.g.cs"
];
string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"];
var path = $"./Source/Disposable/{interfaceName}.cs";
SourceFile sourceFile = CreateSourceFile(path, name, true);
@@ -107,10 +104,7 @@ public class InheritedInterfaceTests
var proxyName = name + "Proxy";
// Arrange
string[] fileNames = [
$"{Namespace}.{interfaceName}.g.cs",
$"{Namespace}.{proxyName}.g.cs"
];
string[] fileNames = [$"{Namespace}.{interfaceName}.g.cs", $"{Namespace}.{proxyName}.g.cs"];
var interfaceIndex = 1;
var path = $"./Source/Disposable/{interfaceName}.cs";
SourceFile sourceFile = CreateSourceFile(path, name, true);
@@ -30,7 +30,6 @@ public class PnPTests
"ProxyInterfaceSourceGeneratorTests.Source.PnP.IWeb.g.cs",
"ProxyInterfaceSourceGeneratorTests.Source.PnP.IClientRuntimeContext.g.cs",
"ProxyInterfaceSourceGeneratorTests.Source.PnP.IClientContext.g.cs",
"Microsoft.SharePoint.Client.ClientObjectProxy.g.cs",
"Microsoft.SharePoint.Client.SecurableObjectProxy.g.cs",
"Microsoft.SharePoint.Client.WebProxy.g.cs",
@@ -99,14 +98,16 @@ public class PnPTests
};
// Act
var result = _sut.Execute(new[]
var result = _sut.Execute(
new[]
{
sourceFileClientObject,
sourceFileSec,
sourceFileWeb,
sourceFileClientRuntimeContext,
sourceFileClientContext
});
}
);
// Assert
result.Valid.Should().BeTrue();
@@ -117,7 +118,8 @@ public class PnPTests
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
if (Write)
File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/{fileName.fileName}"));
}
}
@@ -72,10 +72,7 @@ public class ProxyInterfaceSourceGeneratorTest
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -86,7 +83,6 @@ public class ProxyInterfaceSourceGeneratorTest
return Verify(results);
}
[Fact]
public Task GenerateFiles_ForClassWithIgnores()
{
@@ -107,17 +103,16 @@ public class ProxyInterfaceSourceGeneratorTest
Name = "ProxyInterfaceGenerator.Proxy",
ArgumentList = new[]
{
"typeof(ProxyInterfaceSourceGeneratorTests.Source.Foo2)", "false", "ProxyClassAccessibility.Public",
"typeof(ProxyInterfaceSourceGeneratorTests.Source.Foo2)",
"false",
"ProxyClassAccessibility.Public",
"new []{\"Weird\",\"NotHere\"}"
}
}
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -151,10 +146,7 @@ public class ProxyInterfaceSourceGeneratorTest
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -165,7 +157,8 @@ public class ProxyInterfaceSourceGeneratorTest
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
if (Write)
File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/{fileName.fileName}"));
}
}
@@ -193,10 +186,7 @@ public class ProxyInterfaceSourceGeneratorTest
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -207,7 +197,8 @@ public class ProxyInterfaceSourceGeneratorTest
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
if (Write)
File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/{fileName.fileName}"));
}
}
@@ -235,10 +226,7 @@ public class ProxyInterfaceSourceGeneratorTest
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -249,15 +237,13 @@ public class ProxyInterfaceSourceGeneratorTest
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
if (Write)
File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/{fileName.fileName}"));
}
var name = "stef";
var operatorTest = new OperatorTest
{
Name = name
};
var operatorTest = new OperatorTest { Name = name };
string name1 = (string)operatorTest;
name1.Should().Be(name);
@@ -273,11 +259,7 @@ public class ProxyInterfaceSourceGeneratorTest
public void GenerateFiles_When_NoNamespace_Should_GenerateCorrectFiles()
{
// Arrange
var fileNames = new[]
{
"INoNamespace.g.cs",
"NoNamespaceProxy.g.cs"
};
var fileNames = new[] { "INoNamespace.g.cs", "NoNamespaceProxy.g.cs" };
var path = "./Source/INoNamespace.cs";
var sourceFile = new SourceFile
@@ -292,10 +274,7 @@ public class ProxyInterfaceSourceGeneratorTest
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -306,7 +285,8 @@ public class ProxyInterfaceSourceGeneratorTest
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
if (Write)
File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/{fileName.fileName}"));
}
}
@@ -334,10 +314,7 @@ public class ProxyInterfaceSourceGeneratorTest
};
// Act
var result = _sut.Execute(new[]
{
sourceFile
});
var result = _sut.Execute(new[] { sourceFile });
// Assert
result.Valid.Should().BeTrue();
@@ -348,7 +325,8 @@ public class ProxyInterfaceSourceGeneratorTest
var builder = result.Files[fileName.index + 1]; // +1 means skip the attribute
builder.Path.Should().EndWith(fileName.fileName);
if (Write) File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
if (Write)
File.WriteAllText($"../../../Destination/{fileName.fileName}", builder.Text);
builder.Text.Should().Be(File.ReadAllText($"../../../Destination/{fileName.fileName}"));
}
}
@@ -359,7 +337,8 @@ public class ProxyInterfaceSourceGeneratorTest
// Arrange
var attributeFilename = "ProxyInterfaceGenerator.Extra.g.cs";
var interfaceFilename = "ProxyInterfaceSourceGeneratorTests.Source.IPersonExtends.g.cs";
var proxyClassFilename = "ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs";
var proxyClassFilename =
"ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs";
var path = "./Source/IPersonExtends.cs";
var sourceFile = new SourceFile
@@ -369,7 +348,11 @@ public class ProxyInterfaceSourceGeneratorTest
AttributeToAddToInterface = new ExtraAttribute
{
Name = "ProxyInterfaceGenerator.Proxy",
ArgumentList = new[] { "typeof(ProxyInterfaceSourceGeneratorTests.Source.PersonExtends)", "true" }
ArgumentList = new[]
{
"typeof(ProxyInterfaceSourceGeneratorTests.Source.PersonExtends)",
"true"
}
}
};
@@ -389,16 +372,24 @@ public class ProxyInterfaceSourceGeneratorTest
@interface.FilePath.Should().EndWith(interfaceFilename);
var interfaceCode = @interface.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
// Assert Proxy
var proxyClass = result.Files[2].SyntaxTree;
proxyClass.FilePath.Should().EndWith(proxyClassFilename);
var proxyCode = proxyClass.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
}
[Fact]
@@ -406,7 +397,8 @@ public class ProxyInterfaceSourceGeneratorTest
{
// Arrange
var interfaceFilename = "ProxyInterfaceSourceGeneratorTests.Source.ITestClassInternal.g.cs";
var proxyClassFilename = "ProxyInterfaceSourceGeneratorTests.Source.TestClassInternalProxy.g.cs";
var proxyClassFilename =
"ProxyInterfaceSourceGeneratorTests.Source.TestClassInternalProxy.g.cs";
var path = "./Source/ITestClassInternal.cs";
var sourceFile = new SourceFile
@@ -416,7 +408,11 @@ public class ProxyInterfaceSourceGeneratorTest
AttributeToAddToInterface = new ExtraAttribute
{
Name = "ProxyInterfaceGenerator.Proxy",
ArgumentList = new[] { "typeof(ProxyInterfaceSourceGeneratorTests.Source.TestClassInternal)", "ProxyClassAccessibility.Internal" }
ArgumentList = new[]
{
"typeof(ProxyInterfaceSourceGeneratorTests.Source.TestClassInternal)",
"ProxyClassAccessibility.Internal"
}
}
};
@@ -432,16 +428,24 @@ public class ProxyInterfaceSourceGeneratorTest
@interface.FilePath.Should().EndWith(interfaceFilename);
var interfaceCode = @interface.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
// Assert Proxy
var proxyClass = result.Files[2].SyntaxTree;
proxyClass.FilePath.Should().EndWith(proxyClassFilename);
var proxyCode = proxyClass.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
}
[Fact]
@@ -489,41 +493,56 @@ public class ProxyInterfaceSourceGeneratorTest
var attribute = result.Files[0].SyntaxTree;
attribute.FilePath.Should().EndWith(attributeFilename);
// Assert interface Human
var interfaceHuman = result.Files[1].SyntaxTree;
interfaceHuman.FilePath.Should().EndWith(interfaceHumanFilename);
var interfaceCodeHuman = interfaceHuman.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfaceHumanFilename}", interfaceCodeHuman);
interfaceCodeHuman.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceHumanFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{interfaceHumanFilename}", interfaceCodeHuman);
interfaceCodeHuman
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{interfaceHumanFilename}"));
// Assert interface Person
var interfacePerson = result.Files[2].SyntaxTree;
interfacePerson.FilePath.Should().EndWith(interfacePersonFilename);
var interfaceCodePerson = interfacePerson.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfacePersonFilename}", interfaceCodePerson);
interfaceCodePerson.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfacePersonFilename}"));
if (Write)
File.WriteAllText(
$"../../../Destination/{interfacePersonFilename}",
interfaceCodePerson
);
interfaceCodePerson
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{interfacePersonFilename}"));
// Assert Proxy Human
var proxyClassHuman = result.Files[3].SyntaxTree;
proxyClassHuman.FilePath.Should().EndWith(proxyClassHumanFilename);
var proxyCodeHuman = proxyClassHuman.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassHumanFilename}", proxyCodeHuman);
proxyCodeHuman.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassHumanFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{proxyClassHumanFilename}", proxyCodeHuman);
proxyCodeHuman
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{proxyClassHumanFilename}"));
// Assert Proxy Person
var proxyClassPerson = result.Files[4].SyntaxTree;
proxyClassPerson.FilePath.Should().EndWith(proxyClassPersonFilename);
var proxyCode = proxyClassPerson.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassPersonFilename}", proxyCode);
proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassPersonFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{proxyClassPersonFilename}", proxyCode);
proxyCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{proxyClassPersonFilename}"));
var personProxy = new PersonProxy(new Person());
@@ -538,9 +557,11 @@ public class ProxyInterfaceSourceGeneratorTest
{
// Arrange
var attributeFilename = "ProxyInterfaceGenerator.Extra.g.cs";
var interfaceIHttpClientFilename = "ProxyInterfaceSourceGeneratorTests.Source.IHttpClient.g.cs";
var interfaceIHttpClientFilename =
"ProxyInterfaceSourceGeneratorTests.Source.IHttpClient.g.cs";
var proxyClassIHttpClientFilename = "System.Net.Http.HttpClientProxy.g.cs";
var interfaceIHttpMessageInvokerFilename = "ProxyInterfaceSourceGeneratorTests.Source.IHttpMessageInvoker.g.cs";
var interfaceIHttpMessageInvokerFilename =
"ProxyInterfaceSourceGeneratorTests.Source.IHttpMessageInvoker.g.cs";
var proxyClassIHttpMessageInvokerFilename = "System.Net.Http.HttpMessageInvokerProxy.g.cs";
var pathIHttpClient = "./Source/IHttpClient.cs";
@@ -578,41 +599,69 @@ public class ProxyInterfaceSourceGeneratorTest
var attribute = result.Files[0].SyntaxTree;
attribute.FilePath.Should().EndWith(attributeFilename);
// Assert interface IHttpClient
var interfaceIHttpClient = result.Files[1].SyntaxTree;
interfaceIHttpClient.FilePath.Should().EndWith(interfaceIHttpClientFilename);
var interfaceCodeIHttpClient = interfaceIHttpClient.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfaceIHttpClientFilename}", interfaceCodeIHttpClient);
interfaceCodeIHttpClient.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceIHttpClientFilename}"));
if (Write)
File.WriteAllText(
$"../../../Destination/{interfaceIHttpClientFilename}",
interfaceCodeIHttpClient
);
interfaceCodeIHttpClient
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{interfaceIHttpClientFilename}"));
// Assert interface IHttpMessageInvoker
var interfaceIMessageInvoker = result.Files[2].SyntaxTree;
interfaceIMessageInvoker.FilePath.Should().EndWith(interfaceIHttpMessageInvokerFilename);
var interfaceCodeIMessageInvoker = interfaceIMessageInvoker.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfaceIHttpMessageInvokerFilename}", interfaceCodeIMessageInvoker);
interfaceCodeIMessageInvoker.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceIHttpMessageInvokerFilename}"));
if (Write)
File.WriteAllText(
$"../../../Destination/{interfaceIHttpMessageInvokerFilename}",
interfaceCodeIMessageInvoker
);
interfaceCodeIMessageInvoker
.Should()
.NotBeNullOrEmpty()
.And.Be(
File.ReadAllText($"../../../Destination/{interfaceIHttpMessageInvokerFilename}")
);
// Assert Proxy IHttpClient
var proxyClassIHttpClient = result.Files[3].SyntaxTree;
proxyClassIHttpClient.FilePath.Should().EndWith(proxyClassIHttpClientFilename);
var proxyCodeIHttpClient = proxyClassIHttpClient.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassIHttpClientFilename}", proxyCodeIHttpClient);
proxyCodeIHttpClient.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassIHttpClientFilename}"));
if (Write)
File.WriteAllText(
$"../../../Destination/{proxyClassIHttpClientFilename}",
proxyCodeIHttpClient
);
proxyCodeIHttpClient
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{proxyClassIHttpClientFilename}"));
// Assert Proxy IHttpMessageInvoker
var proxyClassIMessageInvoker = result.Files[4].SyntaxTree;
proxyClassIMessageInvoker.FilePath.Should().EndWith(proxyClassIHttpMessageInvokerFilename);
var proxyIMessageInvoker = proxyClassIMessageInvoker.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassIHttpMessageInvokerFilename}", proxyIMessageInvoker);
proxyIMessageInvoker.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassIHttpMessageInvokerFilename}"));
if (Write)
File.WriteAllText(
$"../../../Destination/{proxyClassIHttpMessageInvokerFilename}",
proxyIMessageInvoker
);
proxyIMessageInvoker
.Should()
.NotBeNullOrEmpty()
.And.Be(
File.ReadAllText($"../../../Destination/{proxyClassIHttpMessageInvokerFilename}")
);
}
[Fact]
@@ -623,8 +672,10 @@ public class ProxyInterfaceSourceGeneratorTest
foreach (var x in new[] { 1, 2 })
{
var attributeFilename = "ProxyInterfaceGenerator.Extra.g.cs";
var interfaceFilename = $"ProxyInterfaceSourceGeneratorTests.Namespace{x}.I{@class}.g.cs";
var proxyClassFilename = $"ProxyInterfaceSourceGeneratorTests.Namespace{x}.{@class}Proxy.g.cs";
var interfaceFilename =
$"ProxyInterfaceSourceGeneratorTests.Namespace{x}.I{@class}.g.cs";
var proxyClassFilename =
$"ProxyInterfaceSourceGeneratorTests.Namespace{x}.{@class}Proxy.g.cs";
var path = $"./Source/I{@class}{x}.cs";
var sourceFile = new SourceFile
@@ -634,7 +685,11 @@ public class ProxyInterfaceSourceGeneratorTest
AttributeToAddToInterface = new ExtraAttribute
{
Name = "ProxyInterfaceGenerator.Proxy",
ArgumentList = new[] { $"typeof(ProxyInterfaceSourceGeneratorTests.Namespace{x}.{@class})", "true" }
ArgumentList = new[]
{
$"typeof(ProxyInterfaceSourceGeneratorTests.Namespace{x}.{@class})",
"true"
}
}
};
@@ -654,18 +709,24 @@ public class ProxyInterfaceSourceGeneratorTest
@interface.FilePath.Should().EndWith(interfaceFilename);
var interfaceCode = @interface.ToString();
if (Write) File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
if (Write)
File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
// Assert Proxy
var proxyClass = result.Files[2].SyntaxTree;
proxyClass.FilePath.Should().EndWith(proxyClassFilename);
var proxyCode = proxyClass.ToString();
if (Write) File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
}
if (Write)
File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode
.Should()
.NotBeNullOrEmpty()
.And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
}
}
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.AkkaActor
{
public partial interface ILocalActorRefProvider
{
}
public partial interface ILocalActorRefProvider { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.AkkaActor
{
public partial interface ILocalActorRefProvider
{
}
public partial interface ILocalActorRefProvider { }
}
@@ -1,5 +1,3 @@
namespace ProxyInterfaceSourceGeneratorTests.Source;
public class Bar
{
}
public class Bar { }
@@ -1,7 +1,5 @@
// ReSharper disable once CheckNamespace
namespace ProxyInterfaceSourceGeneratorTests.Namespace1
{
public class ClassInNamespace
{
}
public class ClassInNamespace { }
}
@@ -1,7 +1,5 @@
// ReSharper disable once CheckNamespace
namespace ProxyInterfaceSourceGeneratorTests.Namespace2
{
public class ClassInNamespace
{
}
public class ClassInNamespace { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.Disposable
{
public class Child : Parent
{
}
public class Child : Parent { }
}
@@ -6,15 +6,8 @@ namespace ProxyInterfaceSourceGeneratorTests.Source.Disposable
event EventHandler<string>? IUpdate<string>.Update
{
add
{
throw new NotSupportedException();
}
remove
{
throw new NotSupportedException();
}
add { throw new NotSupportedException(); }
remove { throw new NotSupportedException(); }
}
void IDisposable.Dispose()
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.Disposable
{
public partial interface IChild
{
}
public partial interface IChild { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.Disposable
{
public partial interface IExplicit
{
}
public partial interface IExplicit { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.Disposable
{
public partial interface IParent
{
}
public partial interface IParent { }
}
@@ -26,7 +26,9 @@ public class Foo2
{
return new[] { new Foo2() };
}
public int Weird { get; set; }
public int Weird2()
{
return 0;
@@ -6,9 +6,6 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
public string GetterOnly => "x";
public void Dispose()
{
}
public void Dispose() { }
}
}
@@ -1,7 +1,5 @@
// ReSharper disable once CheckNamespace
namespace ProxyInterfaceSourceGeneratorTests.Namespace1
{
public partial interface IClassInNamespace
{
}
public partial interface IClassInNamespace { }
}
@@ -1,7 +1,5 @@
// ReSharper disable once CheckNamespace
namespace ProxyInterfaceSourceGeneratorTests.Namespace2
{
public partial interface IClassInNamespace
{
}
public partial interface IClassInNamespace { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IFoo
{
}
public partial interface IFoo { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IFoo2
{
}
public partial interface IFoo2 { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IGeneric
{
}
public partial interface IGeneric { }
}
@@ -1,5 +1,3 @@
namespace ProxyInterfaceSourceGeneratorTests.Source;
public partial interface IHttpClient : IHttpMessageInvoker
{
}
public partial interface IHttpClient : IHttpMessageInvoker { }
@@ -1,5 +1,3 @@
namespace ProxyInterfaceSourceGeneratorTests.Source;
public partial interface IHttpMessageInvoker
{
}
public partial interface IHttpMessageInvoker { }
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IHuman
{
}
public partial interface IHuman { }
}
@@ -1,5 +1,3 @@
namespace ProxyInterfaceSourceGeneratorTests.Source;
public partial interface IMixedVisibility
{
}
public partial interface IMixedVisibility { }
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IMyStruct
{
}
public partial interface IMyStruct { }
}
@@ -1,4 +1,2 @@
// ReSharper disable once CheckNamespace
public partial interface INoNamespace
{
}
public partial interface INoNamespace { }
@@ -1,6 +1,4 @@
// file-scoped namespace !
namespace ProxyInterfaceSourceGeneratorTests.Source;
public partial interface IOperatorTest
{
}
public partial interface IOperatorTest { }
@@ -1,6 +1,4 @@
// file-scoped namespace !
namespace ProxyInterfaceSourceGeneratorTests.Source;
public partial interface IPerson : IHuman
{
}
public partial interface IPerson : IHuman { }
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IPersonExtends
{
}
public partial interface IPersonExtends { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface ITestClassInternal
{
}
public partial interface ITestClassInternal { }
}
@@ -6,7 +6,5 @@ using System.Threading.Tasks;
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public interface IÜberGeneric
{
}
public interface IÜberGeneric { }
}
@@ -9,18 +9,12 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
// Operator : implicit
public static implicit operator OperatorTest(string name)
{
return new()
{
Name = name
};
return new() { Name = name };
}
public static implicit operator OperatorTest(int? id)
{
return new()
{
Id = id
};
return new() { Id = id };
}
// Operator : explicit
@@ -25,7 +25,11 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
public IList<Human> AddHuman(Human h)
{
return new List<Human> { h, new Human { IsAlive = true } };
return new List<Human>
{
h,
new Human { IsAlive = true }
};
}
[Display(ResourceType = typeof(PeriodicTimer))]
@@ -39,9 +43,7 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
[SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
public object @object { get; set; } = null!;
public void Void()
{
}
public void Void() { }
public string HelloWorld(string name)
{
@@ -68,9 +70,7 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
return $"Hello {ch} !";
}
public void WithParams(params string[] values)
{
}
public void WithParams(params string[] values) { }
public string Add(string s, string @string)
{
@@ -117,9 +117,12 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
return Task.FromResult((string?)"");
}
public void CreateInvokeHttpClient(int i = 5, string? appId = null, IReadOnlyDictionary<string, string>? metadata = null, CancellationToken token = default)
{
}
public void CreateInvokeHttpClient(
int i = 5,
string? appId = null,
IReadOnlyDictionary<string, string>? metadata = null,
CancellationToken token = default
) { }
public bool TryParse(string s1, [NotNullWhen(true)] params int[]? ii)
{
@@ -17,18 +17,14 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
public object @object { get; set; } = null!;
public void Void()
{
}
public void Void() { }
public string HelloWorld(string name)
{
return $"Hello {name} !";
}
public void WithParams(params string[] values)
{
}
public void WithParams(params string[] values) { }
public string Add(string s, string @string)
{
@@ -2,8 +2,5 @@ using Microsoft.SharePoint.Client;
namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
{
public partial interface IClientContext
{
}
public partial interface IClientContext { }
}
@@ -1,6 +1,4 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
{
public partial interface IClientObject
{
}
public partial interface IClientObject { }
}
@@ -1,8 +1,6 @@
namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
{
public partial interface IClientRuntimeContext
{
}
public partial interface IClientRuntimeContext { }
}
namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
@@ -22,6 +20,5 @@ namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
//{
// var x = CastTo2<ClientObjectProxy>(new ClientObjectProxy(default));
//}
}
}
@@ -3,7 +3,5 @@ using Microsoft.SharePoint.Client;
namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
{
// [ProxyInterfaceGenerator.Proxy(typeof(SecurableObject))]
public partial interface ISecurableObject : IClientObject
{
}
public partial interface ISecurableObject : IClientObject { }
}
@@ -2,7 +2,5 @@ using Microsoft.SharePoint.Client;
namespace ProxyInterfaceSourceGeneratorTests.Source.PnP
{
public partial interface IWeb : ISecurableObject
{
}
public partial interface IWeb : ISecurableObject { }
}