Skip to content

Commit

Permalink
[unity] support generation for generic types with constraints && fix …
Browse files Browse the repository at this point in the history
…the constraints filter ignored optional parameters fix #937
  • Loading branch information
zombieyang committed Aug 31, 2022
1 parent 08ff731 commit 7140e2c
Show file tree
Hide file tree
Showing 18 changed files with 485 additions and 399 deletions.
3 changes: 2 additions & 1 deletion unity/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
/native_src/v8*
/native_src/nodejs*
/native_src/quickjs*
/native_src/puerts-cpp-tester
/native_src/puerts-cpp-tester
/native_src/node_modules
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ module.exports = function TypingTemplate(data) {
namespace PuertsStaticWrap
{
public static class ${data.WrapClassName}${data.IsGenericWrapper ? `<${makeTSR(data.GenericArgumentsCount)}>` : ''}
public static class ${data.WrapClassName}${data.IsGenericWrapper ? `<${makeGenericAlphaBet(data.GenericArgumentsInfo)}>` : ''} ${data.IsGenericWrapper ? makeConstraints(data.GenericArgumentsInfo) : ''}
{
`
data.BlittableCopy && tt`
Expand Down Expand Up @@ -193,7 +193,7 @@ namespace PuertsStaticWrap
toJsArray(overloadGroup).forEach(overload => {

data.Constructor.HasOverloads && overload.ParameterInfos.Length > 0 &&
tt`
tt`
if (${toJsArray(overload.ParameterInfos).map((paramInfo, idx) => `argHelper${idx}.IsMatch(${paramInfo.ExpectJsType}, ${paramInfo.ExpectCsType}, ${paramInfo.IsByRef}, ${paramInfo.IsOut})`).join(' && ')})
`;

Expand Down Expand Up @@ -273,8 +273,8 @@ namespace PuertsStaticWrap
toJsArray(overloadGroup).forEach(overload => {
method.HasOverloads && overload.ParameterInfos.Length > 0 && tt`
if (${toJsArray(overload.ParameterInfos).map((paramInfo, idx) =>
`argHelper${idx}.${paramInfo.IsParams ? "IsMatchParams" : "IsMatch"}(${paramInfo.ExpectJsType}, ${paramInfo.ExpectCsType}, ${paramInfo.IsParams ? idx : paramInfo.IsByRef}, ${paramInfo.IsParams ? "paramLen" : paramInfo.IsOut})`).join(' && ')
})
`argHelper${idx}.${paramInfo.IsParams ? "IsMatchParams" : "IsMatch"}(${paramInfo.ExpectJsType}, ${paramInfo.ExpectCsType}, ${paramInfo.IsParams ? idx : paramInfo.IsByRef}, ${paramInfo.IsParams ? "paramLen" : paramInfo.IsOut})`).join(' && ')
})
`
tt`
{
Expand Down Expand Up @@ -558,10 +558,10 @@ namespace PuertsStaticWrap
{"${property.Name}", new Puerts.PropertyRegisterInfo(){ IsStatic = ${property.IsStatic}, Getter = ${property.HasGetter ? "G_" + property.Name : "null"}, Setter = ${property.HasSetter ? "S_" + property.Name : "null"}} }`).join(',\n')}
},
LazyMembers = new System.Collections.Generic.List<Puerts.LazyMemberRegisterInfo>()
{ ${toJsArray(data.LazyMembers).map(item=> {
return `
{ ${toJsArray(data.LazyMembers).map(item => {
return `
new Puerts.LazyMemberRegisterInfo() { Name = "${item.Name}", IsStatic = ${item.IsStatic}, Type = (Puerts.LazyMemberType)${item.Type}, HasGetter = ${item.HasGetter}, HasSetter = ${item.HasSetter} }`
})}
})}
}
};
}
Expand Down Expand Up @@ -664,11 +664,29 @@ function paramLenCheck(group) {
return group.get_Item(0).HasParams ? `paramLen >= ${len - 1}` : `paramLen == ${len}`;
}

function makeTSR(count) {
function makeGenericAlphaBet(info) {
const arr = [];
const startCharCode = 'T'.charCodeAt(0);
for (var i = 0; i < count; i++) {
arr.push(String.fromCharCode(startCharCode - i));
for (var i = 0; i < info.Length; i++) {
arr.push(info.get_Item(i).Name);
}
return arr.join(',')
}

function makeConstraints(info) {
const ret = [];
if (info.Length == 0) {
return '';
}
for (var i = 0; i < info.Length; i++) {
const item = info.get_Item(i);
if (item.Constraints.Length == 0) {
continue;
}
var consstr = [];
for (var j = 0; j < item.Constraints.Length; j++) {
consstr.push(item.Constraints.get_Item(j));
}
ret.push(`where ${item.Name} : ` + consstr.join(', '))
}
return ret.join(' ');
}
4 changes: 2 additions & 2 deletions unity/Assets/Puerts/Editor/Src/Generator/FileExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ public static void ExportWrapper(string saveTo, ILoader loader = null)
continue;
}
while (makeFileUniqueMap.ContainsKey(filePath.ToLower()))
{
// ���ڴ�Сд�ظ����������һ��idȥ��
{
// 存在大小写重复的情况,用一个id去重
filePath = saveTo + staticWrapperInfo.WrapClassName + "_" + uniqueId + ".cs";
uniqueId++;
}
Expand Down
1 change: 1 addition & 0 deletions unity/Assets/Puerts/Editor/Src/Generator/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using static Puerts.Editor.Generator.Wrapper.StaticWrapperInfo;

namespace Puerts.Editor
{
Expand Down
109 changes: 59 additions & 50 deletions unity/Assets/Puerts/Editor/Src/Generator/Wrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,6 @@ namespace Generator

namespace Wrapper
{
internal class GenericTSRMananger
{
protected static Dictionary<int, Type> DynamicTypes = new Dictionary<int, Type>();

protected static ModuleBuilder MB;
protected static AssemblyBuilder AB;
public static Type GetDynamicGenericType(int index) {
char startChar = 'T';
if (DynamicTypes.ContainsKey(index))
{
return DynamicTypes[index];
}
if (AB == null)
{
AB = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("PuertsEditor_Generic"), AssemblyBuilderAccess.Run);
MB = AB.DefineDynamicModule("MainModule");
}
var TB = MB.DefineType(new String((char)(startChar - index), 1));
DynamicTypes[index] = TB.CreateType();
return DynamicTypes[index];
}
}

public class LazyMemberCollector
{
public Dictionary<string, LazyMemberRegisterInfo> LazyMembers = new Dictionary<string, LazyMemberRegisterInfo>();
Expand Down Expand Up @@ -115,11 +92,16 @@ public LazyMemberRegisterInfo[] ToArray()

public class StaticWrapperInfo
{

public class TypeGenericArgumentsGenInfo {
public string Name;
public string[] Constraints;
}
public string Name;
public string WrapClassName;
public string CSharpTypeName;
public bool IsGenericWrapper;
public int GenericArgumentsCount;
public TypeGenericArgumentsGenInfo[] GenericArgumentsInfo;
public string[] Namespaces;
public MethodGenInfo[] Methods;
public bool IsValueType;
Expand All @@ -132,42 +114,67 @@ public class StaticWrapperInfo
public LazyMemberRegisterInfo[] LazyMembers;
public bool BlittableCopy;

public bool wroted;

public static StaticWrapperInfo FromType(Type type, List<Type> genTypes)
{
bool IsGenericWrapper = false;
int GenericArgumentsCount = 0;
#if (PUERTS_GENERAL || UNITY_2019_OR_NEWER) && PUERTS_FEATURE_GENERIC_WRAPPER
TypeGenericArgumentsGenInfo[] GenericArgumentsInfos = null;

#if PUERTS_GENERAL || UNITY_2019_OR_NEWER
// 如果是泛型类,且泛型参数对于PuerTS来说是一个NativeObject类型,则Wrapper可以用泛型处理。
// 这里要先识别出NativeObject的参数位置,并将其替换
if (type.IsGenericType) {
var genericArguments = type.GetGenericArguments();
var definitionType = type.GetGenericTypeDefinition();
var definitionGenericArguments = definitionType.GetGenericArguments();

if (
genericArguments
.Where((t, index)=>
!t.IsPrimitive && t != typeof(System.String) && t != typeof(DateTime)
&& (definitionGenericArguments[index].GetGenericParameterConstraints().Length == 0 || definitionGenericArguments[index].BaseType == null)
)
.Count() > 0
) {
.Where((t, index) => !t.IsPrimitive && t != typeof(System.String) && t != typeof(DateTime))
.Count() > 0
)
{
var definitionType = type.GetGenericTypeDefinition();
var definitionGenericArguments = definitionType.GetGenericArguments();
IsGenericWrapper = true;
type = definitionType.MakeGenericType(
genericArguments.Select((t, index)=> {
if (
!t.IsPrimitive && t != typeof(System.String) && t != typeof(DateTime)
&& (definitionGenericArguments[index].GetGenericParameterConstraints().Length == 0 || definitionGenericArguments[index].BaseType == null)
)
{
GenericArgumentsCount++;
return GenericTSRMananger.GetDynamicGenericType(GenericArgumentsCount - 1);
}
return t;
definitionGenericArguments.Select((dType, index)=> {
Type t = genericArguments[index];
if (!t.IsPrimitive && t != typeof(System.String) && t != typeof(DateTime)) return dType;
else return t;
}).ToArray()
);

GenericArgumentsInfos = definitionGenericArguments.Select((ga, index) =>
{
Type t = genericArguments[index];
if (!(!t.IsPrimitive && t != typeof(System.String) && t != typeof(DateTime))) return null;
var constraintsInfo = new List<string>();
var contraintTypes = ga.GetGenericParameterConstraints();
GenericParameterAttributes constraints = ga.GenericParameterAttributes &
GenericParameterAttributes.SpecialConstraintMask;
bool hasValueTypeConstraint = false;
for (var i = 0; i < contraintTypes.Length; i++)
{
if (contraintTypes[i] == typeof(System.ValueType))
{
hasValueTypeConstraint = true;
continue;
}
constraintsInfo.Add(contraintTypes[i].GetFriendlyName());
}
if ((constraints & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
constraintsInfo.Add("class");
if (hasValueTypeConstraint && (constraints & GenericParameterAttributes.DefaultConstructorConstraint) != 0 && (constraints & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
constraintsInfo.Add("struct");
else if ((constraints & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
constraintsInfo.Add("new()");
var genericArgumentsGenInfo = new TypeGenericArgumentsGenInfo();
genericArgumentsGenInfo.Constraints = constraintsInfo.ToArray();
genericArgumentsGenInfo.Name = ga.Name;
return genericArgumentsGenInfo;
}).Where(t => t != null).ToArray();
}
}
#endif
Expand Down Expand Up @@ -276,7 +283,7 @@ public static StaticWrapperInfo FromType(Type type, List<Type> genTypes)
Name = type.GetFriendlyName(),
IsValueType = type.IsValueType,
IsGenericWrapper = IsGenericWrapper,
GenericArgumentsCount = GenericArgumentsCount,
GenericArgumentsInfo = GenericArgumentsInfos,

Methods = methodGroups
.Select(kv =>
Expand Down Expand Up @@ -345,7 +352,7 @@ public static StaticWrapperInfo FromType(Type type, List<Type> genTypes)

public class DataTypeInfo
{
public string TypeName;
public string TypeName; // If it is a methodGenInfo, TypeName represents the return type
public bool IsEnum;
public string UnderlyingTypeName;
}
Expand Down Expand Up @@ -514,9 +521,11 @@ public static List<OverloadGenInfo> FromMethodBase(MethodBase methodBase, bool e
OverloadGenInfo optionalInfo = null;
if (ps[i].IsOptional || mainInfo.ParameterInfos[i].IsParams)
{
ParameterInfo[] pinfos = parameters.Take(i).ToArray();
if (!Puerts.Utils.IsNotGenericOrValidGeneric((MethodInfo)methodBase, pinfos)) continue;
optionalInfo = new OverloadGenInfo()
{
ParameterInfos = parameters.Select(info => ParameterGenInfo.FromParameterInfo(info)).Take(i).ToArray(),
ParameterInfos = pinfos.Select(info => ParameterGenInfo.FromParameterInfo(info)).ToArray(),
TypeName = Utils.RemoveRefAndToConstraintType(methodInfo.ReturnType).GetFriendlyName(),
IsVoid = methodInfo.ReturnType == typeof(void),
EllipsisedParameters = true,
Expand Down
8 changes: 6 additions & 2 deletions unity/Assets/Puerts/Runtime/Src/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,17 @@ public static string GetFriendlyName(this Type type)
{
if (type.GetArrayRank() > 1)
{
return GetFriendlyName(type.GetElementType()) + "["+ new String(',', type.GetArrayRank() - 1) + "]";
return GetFriendlyName(type.GetElementType()) + "[" + new String(',', type.GetArrayRank() - 1) + "]";
}
else
{
return GetFriendlyName(type.GetElementType()) + "[]";
}
}
else if (type.IsGenericParameter)
{
return type.Name;
}
else if (type.IsNested)
{
if (type.DeclaringType.IsGenericTypeDefinition)
Expand All @@ -214,7 +218,7 @@ public static string GetFriendlyName(this Type type)
{
var genericArgumentNames = type.GetGenericArguments()
.Select(x => GetFriendlyName(x)).ToArray();
return type.FullName.Split('`')[0] + "<" + string.Join(", ", genericArgumentNames) + ">";
return (type.FullName == null ? type.Namespace + "." + type.Name : type.FullName).Split('`')[0] + "<" + string.Join(", ", genericArgumentNames) + ">";
}
else
return type.FullName;
Expand Down
5 changes: 3 additions & 2 deletions unity/Assets/Puerts/Runtime/Src/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,16 @@ private static bool HasValidContraint(Type type, List<Type> validTypes)
}
}

public static bool IsNotGenericOrValidGeneric(MethodInfo method)
public static bool IsNotGenericOrValidGeneric(MethodInfo method, ParameterInfo[] pinfos = null)
{
// 不包含泛型参数,肯定支持
if (!method.ContainsGenericParameters)
return true;

List<Type> validGenericParameter = new List<Type>();

foreach (var parameters in method.GetParameters())
if (pinfos == null) pinfos = method.GetParameters();
foreach (var parameters in pinfos)
{
Type parameterType = parameters.ParameterType;

Expand Down

0 comments on commit 7140e2c

Please sign in to comment.