Rhino required fixes (#9)
* add fixes for structs * handle null non-nullables to nullable nulls * test fix * add enum test even if it's gross looking * generate nullable adapt when needed * fix adapter tests * don't generate static events * fmt * mark for release
This commit is contained in:
@@ -7,30 +7,4 @@ namespace Speckle.ProxyGenerator.Extensions;
|
||||
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
|
||||
)
|
||||
{
|
||||
var getIsPublic = property.GetMethod.IsPublic();
|
||||
var setIsPublic = property.SetMethod.IsPublic();
|
||||
|
||||
if (!getIsPublic && !setIsPublic)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
return (type!, property.GetSanitizedName(), $"{{ {get}{set}}}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ internal abstract class BaseGenerator
|
||||
SupportsNullable = supportsNullable;
|
||||
}
|
||||
|
||||
protected string GetPropertyType(IPropertySymbol property, out bool isReplaced)
|
||||
protected FixedType GetPropertyType(IPropertySymbol property, out bool isReplaced)
|
||||
{
|
||||
return GetReplacedTypeAsString(property.Type, out isReplaced);
|
||||
return GetReplacedTypeAsString(property.Type, null, out isReplaced);
|
||||
}
|
||||
|
||||
protected string GetParameterType(IParameterSymbol property, out bool isReplaced)
|
||||
protected FixedType GetParameterType(IParameterSymbol property, out bool isReplaced)
|
||||
{
|
||||
return GetReplacedTypeAsString(property.Type, out isReplaced);
|
||||
return GetReplacedTypeAsString(property.Type, property.GetDefaultValue(), out isReplaced);
|
||||
}
|
||||
|
||||
protected bool TryFindProxyDataByTypeName(
|
||||
@@ -119,7 +119,8 @@ internal abstract class BaseGenerator
|
||||
{
|
||||
if (replaceIt)
|
||||
{
|
||||
constraints.Add(GetReplacedTypeAsString(namedTypeSymbol, out _));
|
||||
var (_, type) = GetReplacedTypeAsString(namedTypeSymbol, null, out _);
|
||||
constraints.Add(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -152,7 +153,11 @@ internal abstract class BaseGenerator
|
||||
| SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier
|
||||
);
|
||||
|
||||
protected string GetReplacedTypeAsString(ITypeSymbol typeSymbol, out bool isReplaced)
|
||||
protected FixedType GetReplacedTypeAsString(
|
||||
ITypeSymbol typeSymbol,
|
||||
string? defaultValue,
|
||||
out bool isReplaced
|
||||
)
|
||||
{
|
||||
isReplaced = false;
|
||||
|
||||
@@ -170,7 +175,7 @@ internal abstract class BaseGenerator
|
||||
}
|
||||
|
||||
isReplaced = true;
|
||||
return FixType(existing.FullInterfaceName, typeSymbol.NullableAnnotation);
|
||||
return FixType(existing.FullInterfaceName, typeSymbol.NullableAnnotation, defaultValue);
|
||||
}
|
||||
|
||||
ITypeSymbol[] typeArguments;
|
||||
@@ -184,7 +189,7 @@ internal abstract class BaseGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
return FixType(typeSymbolAsString, typeSymbol.NullableAnnotation);
|
||||
return FixType(typeSymbolAsString, typeSymbol.NullableAnnotation, defaultValue);
|
||||
}
|
||||
|
||||
var propertyTypeAsStringToBeModified = nullableTypeSymbolAsString;
|
||||
@@ -211,7 +216,11 @@ internal abstract class BaseGenerator
|
||||
}
|
||||
}
|
||||
|
||||
return FixType(propertyTypeAsStringToBeModified, typeSymbol.NullableAnnotation);
|
||||
return FixType(
|
||||
propertyTypeAsStringToBeModified,
|
||||
typeSymbol.NullableAnnotation,
|
||||
defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
protected bool TryGetNamedTypeSymbolByFullName(
|
||||
@@ -272,13 +281,14 @@ internal abstract class BaseGenerator
|
||||
{
|
||||
if (parameterSymbol.GetTypeEnum() == TypeEnum.Complex)
|
||||
{
|
||||
type = GetParameterType(parameterSymbol, out _);
|
||||
(_, type) = GetParameterType(parameterSymbol, out _);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FixType(
|
||||
(_, type) = FixType(
|
||||
parameterSymbol.Type.ToFullyQualifiedDisplayString(),
|
||||
parameterSymbol.NullableAnnotation
|
||||
parameterSymbol.NullableAnnotation,
|
||||
parameterSymbol.GetDefaultValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -316,15 +326,23 @@ internal abstract class BaseGenerator
|
||||
return extendsProxyClasses;
|
||||
}
|
||||
|
||||
internal static string FixType(string type, NullableAnnotation nullableAnnotation)
|
||||
{
|
||||
if (
|
||||
nullableAnnotation == NullableAnnotation.Annotated
|
||||
&& !type.EndsWith("?", StringComparison.Ordinal)
|
||||
internal FixedType FixType(
|
||||
string type,
|
||||
NullableAnnotation nullableAnnotation,
|
||||
string? defaultValue
|
||||
)
|
||||
{
|
||||
return $"{type}?";
|
||||
var na = nullableAnnotation;
|
||||
if (SupportsNullable && defaultValue == " = null")
|
||||
{
|
||||
na = NullableAnnotation.Annotated;
|
||||
}
|
||||
return type;
|
||||
if (na == NullableAnnotation.Annotated && !type.EndsWith("?", StringComparison.Ordinal))
|
||||
{
|
||||
return new(true, $"{type}?");
|
||||
}
|
||||
return new(false, type);
|
||||
}
|
||||
}
|
||||
|
||||
internal record FixedType(bool Fixed, string Type);
|
||||
|
||||
@@ -151,6 +151,18 @@ namespace Speckle.ProxyGenerator
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}}
|
||||
public static class MapsterAdapter
|
||||
{{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{{
|
||||
if (source is null)
|
||||
{{
|
||||
return default;
|
||||
}}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}}
|
||||
}}
|
||||
{supportsNullable.IIf("#nullable restore")}
|
||||
}}"
|
||||
);
|
||||
|
||||
@@ -191,11 +191,11 @@ methods}
|
||||
)
|
||||
)
|
||||
{
|
||||
var type = GetPropertyType(property, out var isReplaced);
|
||||
var (_, type) = GetPropertyType(property, out var isReplaced);
|
||||
|
||||
var getterSetter = isReplaced
|
||||
? property.ToPropertyDetails(type)
|
||||
: property.ToPropertyDetails();
|
||||
? ToPropertyDetails(property, type)
|
||||
: ToPropertyDetails(property);
|
||||
if (getterSetter is null)
|
||||
{
|
||||
continue;
|
||||
@@ -241,8 +241,9 @@ methods}
|
||||
str.AppendLine($" {attribute}");
|
||||
}
|
||||
|
||||
var (_, type) = GetReplacedTypeAsString(method.ReturnType, null, out _);
|
||||
str.AppendLine(
|
||||
$" {GetReplacedTypeAsString(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement};"
|
||||
$" {type} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement};"
|
||||
);
|
||||
str.AppendLine();
|
||||
}
|
||||
@@ -262,10 +263,16 @@ methods}
|
||||
)
|
||||
{
|
||||
var ps = @event.First().Parameters.First();
|
||||
var type =
|
||||
ps.GetTypeEnum() == TypeEnum.Complex
|
||||
? GetParameterType(ps, out _)
|
||||
: ps.Type.ToString();
|
||||
|
||||
string? type;
|
||||
if (ps.GetTypeEnum() == TypeEnum.Complex)
|
||||
{
|
||||
(_, type) = GetParameterType(ps, out _);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = ps.Type.ToString();
|
||||
}
|
||||
|
||||
foreach (var attribute in ps.GetAttributesAsList())
|
||||
{
|
||||
@@ -278,4 +285,37 @@ methods}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
public (string PropertyType, string? PropertyName, string GetSet)? ToPropertyDetails(
|
||||
IPropertySymbol property,
|
||||
string? overrideType = null
|
||||
)
|
||||
{
|
||||
var getIsPublic = property.GetMethod.IsPublic();
|
||||
var setIsPublic = property.SetMethod.IsPublic();
|
||||
|
||||
if (!getIsPublic && !setIsPublic)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var get = getIsPublic ? "get; " : string.Empty;
|
||||
var set = setIsPublic ? "set; " : string.Empty;
|
||||
|
||||
string? type;
|
||||
if (!string.IsNullOrEmpty(overrideType))
|
||||
{
|
||||
type = overrideType;
|
||||
}
|
||||
else
|
||||
{
|
||||
(_, type) = FixType(
|
||||
property.Type.ToFullyQualifiedDisplayString(),
|
||||
property.NullableAnnotation,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
return (type!, property.GetSanitizedName(), $"{{ {get}{set}}}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ using System;
|
||||
|
||||
foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyData))
|
||||
{
|
||||
var type = GetPropertyType(property, out var isReplaced);
|
||||
var (_, type) = GetPropertyType(property, out var isReplaced);
|
||||
|
||||
var instance = !property.IsStatic ? "_Instance" : $"{targetClassSymbol.Symbol}";
|
||||
|
||||
@@ -261,7 +261,7 @@ using System;
|
||||
|
||||
foreach (var parameterSymbol in method.Parameters)
|
||||
{
|
||||
var type = GetParameterType(parameterSymbol, out _);
|
||||
var (_, type) = GetParameterType(parameterSymbol, out _);
|
||||
|
||||
methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type));
|
||||
|
||||
@@ -285,8 +285,9 @@ using System;
|
||||
overrideOrVirtual = "virtual ";
|
||||
}
|
||||
|
||||
string returnTypeAsString = GetReplacedTypeAsString(
|
||||
var (_, returnTypeAsString) = GetReplacedTypeAsString(
|
||||
method.ReturnType,
|
||||
null,
|
||||
out var returnIsReplaced
|
||||
);
|
||||
|
||||
@@ -304,9 +305,10 @@ using System;
|
||||
|
||||
foreach (var ps in method.Parameters.Where(p => !p.IsRef()))
|
||||
{
|
||||
var type = FixType(
|
||||
var (wasFixed, type) = FixType(
|
||||
ps.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
||||
ps.Type.NullableAnnotation
|
||||
ps.Type.NullableAnnotation,
|
||||
ps.GetDefaultValue()
|
||||
);
|
||||
string normalOrMap = $" = {ps.GetSanitizedName()}";
|
||||
if (ps.RefKind == RefKind.Out)
|
||||
@@ -317,11 +319,19 @@ using System;
|
||||
{
|
||||
_ = GetParameterType(ps, out var isReplaced); // TODO : response is not used?
|
||||
if (isReplaced)
|
||||
{
|
||||
if (wasFixed)
|
||||
{
|
||||
normalOrMap =
|
||||
$" = Speckle.ProxyGenerator.MapsterAdapter.AdaptNull<{type}>({ps.GetSanitizedName()})";
|
||||
}
|
||||
else
|
||||
{
|
||||
normalOrMap =
|
||||
$" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str.AppendLine($" {type} {ps.GetSanitizedName()}_{normalOrMap};");
|
||||
}
|
||||
@@ -350,7 +360,7 @@ using System;
|
||||
foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
|
||||
{
|
||||
string normalOrMap = $" = {ps.GetSanitizedName()}_";
|
||||
var type = GetParameterType(ps, out var isReplaced);
|
||||
var (_, type) = GetParameterType(ps, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)";
|
||||
@@ -385,12 +395,21 @@ using System;
|
||||
var str = new StringBuilder();
|
||||
foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyData))
|
||||
{
|
||||
if (@event.Key.IsStatic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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 = string.Empty;
|
||||
if (ps.GetTypeEnum() == TypeEnum.Complex)
|
||||
{
|
||||
(_, type) = GetParameterType(ps, out _);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = ps.Type.ToString();
|
||||
}
|
||||
|
||||
foreach (var attribute in ps.GetAttributesAsList())
|
||||
{
|
||||
@@ -417,6 +436,10 @@ using System;
|
||||
|
||||
private string GenerateOperators(ClassSymbol targetClassSymbol, ProxyData proxyData)
|
||||
{
|
||||
if (targetClassSymbol.Symbol.TypeKind != TypeKind.Class)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
var str = new StringBuilder();
|
||||
foreach (
|
||||
var @operator in MemberHelper.GetPublicStaticOperators(targetClassSymbol, proxyData)
|
||||
@@ -438,7 +461,11 @@ using System;
|
||||
var operatorType = @operator.Name.ToLowerInvariant().Replace("op_", string.Empty);
|
||||
if (operatorType == "explicit")
|
||||
{
|
||||
var returnTypeAsString = GetReplacedTypeAsString(@operator.ReturnType, out _);
|
||||
var (_, returnTypeAsString) = GetReplacedTypeAsString(
|
||||
@operator.ReturnType,
|
||||
null,
|
||||
out _
|
||||
);
|
||||
|
||||
str.AppendLine(
|
||||
$" public static explicit operator {returnTypeAsString}({proxyClassName} {parameter.Name})"
|
||||
@@ -451,7 +478,7 @@ using System;
|
||||
}
|
||||
else
|
||||
{
|
||||
var returnTypeAsString = GetReplacedTypeAsString(parameter.Type, out _);
|
||||
var (_, returnTypeAsString) = GetReplacedTypeAsString(parameter.Type, null, out _);
|
||||
|
||||
str.AppendLine(
|
||||
$" public static implicit operator {proxyClassName}({returnTypeAsString} {parameter.Name})"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>0.1.9</Version>
|
||||
<Version>0.1.10</Version>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
+12
@@ -207,6 +207,18 @@ namespace Speckle.ProxyGenerator
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}
|
||||
public static class MapsterAdapter
|
||||
{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{
|
||||
if (source is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
}
|
||||
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
[
|
||||
{
|
||||
HintName: ProxyInterfaceSourceGeneratorTests.Source.IFooNotNullable.g.cs,
|
||||
Source:
|
||||
//----------------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by https://github.com/specklesystems/ProxyGenerator.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace ProxyInterfaceSourceGeneratorTests.Source
|
||||
{
|
||||
public partial interface IFooNotNullable
|
||||
{
|
||||
global::ProxyInterfaceSourceGeneratorTests.Source.FooNotNullable _Instance { get; }
|
||||
|
||||
void Test(global::ProxyInterfaceSourceGeneratorTests.Source.FooEnum z = 1, global::System.Collections.Generic.IEnumerable<string>? v = null);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
},
|
||||
{
|
||||
HintName: ProxyInterfaceSourceGeneratorTests.Source.FooNotNullableProxy.g.cs,
|
||||
Source:
|
||||
//----------------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by https://github.com/specklesystems/ProxyGenerator.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace ProxyInterfaceSourceGeneratorTests.Source
|
||||
{
|
||||
public partial class FooNotNullableProxy : global::ProxyInterfaceSourceGeneratorTests.Source.IFooNotNullable
|
||||
{
|
||||
public global::ProxyInterfaceSourceGeneratorTests.Source.FooNotNullable _Instance { get; }
|
||||
|
||||
public void Test(global::ProxyInterfaceSourceGeneratorTests.Source.FooEnum z = 1, global::System.Collections.Generic.IEnumerable<string>? v = null)
|
||||
{
|
||||
global::ProxyInterfaceSourceGeneratorTests.Source.FooEnum z_ = z;
|
||||
global::System.Collections.Generic.IEnumerable<string>? v_ = v;
|
||||
_Instance.Test(z_, v_);
|
||||
}
|
||||
|
||||
|
||||
public FooNotNullableProxy(global::ProxyInterfaceSourceGeneratorTests.Source.FooNotNullable instance)
|
||||
{
|
||||
_Instance = instance;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
},
|
||||
{
|
||||
HintName: Speckle.ProxyGenerator.Extra.g.cs,
|
||||
Source:
|
||||
//----------------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by https://github.com/specklesystems/ProxyGenerator
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace Speckle.ProxyGenerator
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface)]
|
||||
internal sealed class ProxyAttribute : Attribute
|
||||
{
|
||||
public Type Type { get; }
|
||||
public ImplementationOptions Options { get; }
|
||||
public ProxyClassAccessibility Accessibility { get; }
|
||||
public string[]? MembersToIgnore { get; }
|
||||
|
||||
public ProxyAttribute(Type type) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyAttribute(Type type, ImplementationOptions options) : this(type, options, ProxyClassAccessibility.Public)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyAttribute(Type type, ProxyClassAccessibility accessibility) : this(type, ImplementationOptions.None, accessibility)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility) : this(type, options, accessibility, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyAttribute(Type type, string[]? membersToIgnore) : this(type, ImplementationOptions.None, ProxyClassAccessibility.Public, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyAttribute(Type type, ImplementationOptions options, string[]? membersToIgnore) : this(type, options, ProxyClassAccessibility.Public, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyAttribute(Type type, ImplementationOptions options, ProxyClassAccessibility accessibility, string[]? membersToIgnore)
|
||||
{
|
||||
Type = type;
|
||||
Options = options;
|
||||
Accessibility = accessibility;
|
||||
MembersToIgnore = membersToIgnore;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum ProxyClassAccessibility
|
||||
{
|
||||
Public = 0,
|
||||
|
||||
Internal = 1
|
||||
}
|
||||
[Flags]
|
||||
internal enum ImplementationOptions
|
||||
{
|
||||
None = 0,
|
||||
|
||||
ProxyBaseClasses = 1,
|
||||
|
||||
ProxyInterfaces = 2,
|
||||
|
||||
UseExtendedInterfaces = 4,
|
||||
|
||||
ProxyForBaseInterface = 8
|
||||
}
|
||||
|
||||
public static class ProxyMap
|
||||
{
|
||||
private static readonly global::System.Collections.Concurrent.ConcurrentDictionary<Type, Type> s_revitToInterfaceMap = new();
|
||||
private static readonly global::System.Collections.Concurrent.ConcurrentDictionary<Type, Type> s_proxyToInterfaceMap = new();
|
||||
private static readonly global::System.Collections.Concurrent.ConcurrentDictionary<Type, Type> s_interfaceToRevit = new();
|
||||
private static readonly global::System.Collections.Concurrent.ConcurrentDictionary<Type, Func<object, object>> s_proxyFactory = new();
|
||||
|
||||
static ProxyMap()
|
||||
{
|
||||
Add<ProxyInterfaceSourceGeneratorTests.Source.FooNotNullable, global::ProxyInterfaceSourceGeneratorTests.Source.IFooNotNullable, ProxyInterfaceSourceGeneratorTests.Source.FooNotNullableProxy>(x => new ProxyInterfaceSourceGeneratorTests.Source.FooNotNullableProxy(x));
|
||||
|
||||
}
|
||||
|
||||
private static void Add<T, TInterface, TProxy>(Func<T, TProxy> f)
|
||||
where TInterface : notnull
|
||||
where TProxy : TInterface
|
||||
{
|
||||
s_revitToInterfaceMap.TryAdd(typeof(T), typeof(TInterface));
|
||||
s_proxyToInterfaceMap.TryAdd(typeof(TProxy), typeof(TInterface));
|
||||
s_proxyFactory.TryAdd(typeof(TInterface), w => f((T)w));
|
||||
s_interfaceToRevit.TryAdd(typeof(TInterface), typeof(T));
|
||||
}
|
||||
|
||||
public static Type? GetMappedTypeFromHostType(Type type)
|
||||
{
|
||||
if (s_revitToInterfaceMap.TryGetValue(type, out var t))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Type? GetMappedTypeFromProxyType(Type type)
|
||||
{
|
||||
if (s_proxyToInterfaceMap.TryGetValue(type, out var t))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Type? GetHostTypeFromMappedType(Type type)
|
||||
{
|
||||
if (s_interfaceToRevit.TryGetValue(type, out var t))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}
|
||||
public static class MapsterAdapter
|
||||
{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{
|
||||
if (source is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
}
|
||||
]
|
||||
+12
@@ -215,6 +215,18 @@ namespace Speckle.ProxyGenerator
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}
|
||||
public static class MapsterAdapter
|
||||
{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{
|
||||
if (source is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -217,6 +217,18 @@ namespace Speckle.ProxyGenerator
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}
|
||||
public static class MapsterAdapter
|
||||
{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{
|
||||
if (source is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -268,6 +268,18 @@ Add<ProxyInterfaceSourceGeneratorTests.Source.Bar3, global::ProxyInterfaceSource
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}
|
||||
public static class MapsterAdapter
|
||||
{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{
|
||||
if (source is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -280,6 +280,18 @@ Add<ProxyInterfaceSourceGeneratorTests.Source.MyStruct2, global::ProxyInterfaceS
|
||||
public static object CreateProxy(Type type, object toWrap) => s_proxyFactory[type](toWrap);
|
||||
public static T CreateProxy<T>(object toWrap) => (T)CreateProxy(typeof(T), toWrap);
|
||||
}
|
||||
public static class MapsterAdapter
|
||||
{
|
||||
public static TDestination? AdaptNull<TDestination>(object? source)
|
||||
{
|
||||
if (source is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Mapster.TypeAdapter.Adapt<TDestination>(source);
|
||||
}
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,40 @@ public class ProxyInterfaceSourceGeneratorTest
|
||||
return Verify(results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles_NotNullable()
|
||||
{
|
||||
// Arrange
|
||||
var fileNames = new[]
|
||||
{
|
||||
"ProxyInterfaceSourceGeneratorTests.Source.IFooNotNullable.g.cs",
|
||||
"ProxyInterfaceSourceGeneratorTests.Source.FooNotNullableProxy.g.cs"
|
||||
};
|
||||
|
||||
var path = "./Source/IFooNotNullable.cs";
|
||||
var sourceFile = new SourceFile
|
||||
{
|
||||
Path = path,
|
||||
Text = File.ReadAllText(path),
|
||||
AttributeToAddToInterface = new ExtraAttribute
|
||||
{
|
||||
Name = "Speckle.ProxyGenerator.Proxy",
|
||||
ArgumentList = "typeof(ProxyInterfaceSourceGeneratorTests.Source.FooNotNullable)"
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _sut.Execute(new[] { sourceFile });
|
||||
|
||||
// Assert
|
||||
result.Valid.Should().BeTrue();
|
||||
result.Files.Should().HaveCount(fileNames.Length + 1);
|
||||
|
||||
// Verify
|
||||
var results = result.GeneratorDriver.GetRunResult().Results.First().GeneratedSources;
|
||||
return Verify(results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task GenerateFiles_ForClassWithArray_Should_GenerateCorrectFiles()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ProxyInterfaceSourceGeneratorTests.Source;
|
||||
|
||||
public enum FooEnumImplement
|
||||
{
|
||||
X,
|
||||
Y
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ProxyInterfaceSourceGeneratorTests.Source;
|
||||
|
||||
#nullable disable
|
||||
public class FooNotNullable
|
||||
{
|
||||
public void Test(FooEnum z = FooEnum.Y, IEnumerable<string> v = null) { }
|
||||
}
|
||||
|
||||
public enum FooEnum
|
||||
{
|
||||
X,
|
||||
Y
|
||||
}
|
||||
#nullable restore
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ProxyInterfaceSourceGeneratorTests.Source;
|
||||
|
||||
public partial interface IFooNotNullable
|
||||
{
|
||||
public void Test(FooEnumImplement z = FooEnumImplement.Y, IEnumerable<string>? v = null) { }
|
||||
}
|
||||
Reference in New Issue
Block a user