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 11, 2022
1 parent 60acd1c commit 6e914ae
Show file tree
Hide file tree
Showing 15 changed files with 446 additions and 313 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 ? `<${makeTSR(data.GenericArgumentsInfo)}>` : ''} ${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 @@ -665,11 +665,29 @@ function paramLenCheck(group) {
return group.get_Item(0).HasParams ? `paramLen >= ${len - 1}` : `paramLen == ${len}`;
}

function makeTSR(count) {
function makeTSR(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).GenericAlphabet);
}
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.GenericAlphabet} : ` + consstr.join(', '))
}
return ret.join(' ');
}
105 changes: 82 additions & 23 deletions unity/Assets/Puerts/Editor/Src/Generator/Wrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,38 @@ namespace Wrapper
internal class GenericTSRMananger
{
protected static Dictionary<int, Type> DynamicTypes = new Dictionary<int, Type>();
protected static Dictionary<Type, Type> TypesWithBaseType = new Dictionary<Type, Type>();

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

Expand Down Expand Up @@ -115,11 +130,16 @@ public LazyMemberRegisterInfo[] ToArray()

public class StaticWrapperInfo
{

public class TypeGenericArgumentsGenInfo {
public string GenericAlphabet;
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 @@ -137,7 +157,8 @@ public class StaticWrapperInfo
public static StaticWrapperInfo FromType(Type type, List<Type> genTypes)
{
bool IsGenericWrapper = false;
int GenericArgumentsCount = 0;

var GenericArgumentsInfos = new List<TypeGenericArgumentsGenInfo>();
#if PUERTS_GENERAL || UNITY_2019_OR_NEWER || PUERTS_FEATURE_GENERIC_WRAPPER
// 如果是泛型类,且泛型参数对于PuerTS来说是一个NativeObject类型,则Wrapper可以用泛型处理。
// 这里要先识别出NativeObject的参数位置,并将其替换
Expand All @@ -148,22 +169,58 @@ public static StaticWrapperInfo FromType(Type type, List<Type> genTypes)

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
) {
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)
)
if (!t.IsPrimitive && t != typeof(System.String) && t != typeof(DateTime))
{
GenericArgumentsCount++;
return GenericTSRMananger.GetDynamicGenericType(GenericArgumentsCount - 1);
var contraintTypes = definitionGenericArguments[index].GetGenericParameterConstraints();
var genericArgumentsGenInfo = new TypeGenericArgumentsGenInfo();
var constraintsInfo = new List<string>();
GenericArgumentsInfos.Add(genericArgumentsGenInfo);
GenericParameterAttributes constraints = definitionGenericArguments[index].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].FullName);
}
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()");
}
Type retType;
if (constraintsInfo.Count > 0)
{
retType = GenericTSRMananger.GetDynamicGenericType(GenericArgumentsInfos.Count - 1, hasValueTypeConstraint ? typeof(System.ValueType) : t);
}
else
{
retType = GenericTSRMananger.GetDynamicGenericType(GenericArgumentsInfos.Count - 1);
}
genericArgumentsGenInfo.Constraints = constraintsInfo.ToArray();
genericArgumentsGenInfo.GenericAlphabet = retType.Name;
return retType;
}
return t;
}).ToArray()
Expand Down Expand Up @@ -275,7 +332,7 @@ public static StaticWrapperInfo FromType(Type type, List<Type> genTypes)
Name = type.GetFriendlyName(),
IsValueType = type.IsValueType,
IsGenericWrapper = IsGenericWrapper,
GenericArgumentsCount = GenericArgumentsCount,
GenericArgumentsInfo = GenericArgumentsInfos.ToArray(),

Methods = methodGroups
.Select(kv =>
Expand Down Expand Up @@ -513,9 +570,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
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 6e914ae

Please sign in to comment.