Add proper template types inflating with typedef searching for new scripting api features usage

This commit is contained in:
Wojtek Figat
2022-05-25 19:55:22 +02:00
parent edbf0761d2
commit 1303740611
4 changed files with 82 additions and 9 deletions

View File

@@ -43,6 +43,17 @@ namespace Flax.Build.Bindings
}
}
public ModuleInfo ParentModule
{
get
{
var result = this;
while (result != null && !(result is ModuleInfo))
result = result.Parent;
return result as ModuleInfo;
}
}
/// <summary>
/// Gets the name of the type as it would be referenced from the parent module namespace in the native code. It includes the nesting parent types and typename. For instance enum defined in class will have prefix of that class name.
/// </summary>

View File

@@ -255,22 +255,56 @@ namespace Flax.Build.Bindings
private static ApiTypeInfo FindApiTypeInfoInner(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo parent)
{
ApiTypeInfo result = null;
foreach (var child in parent.Children)
{
if (child.Name == typeInfo.Type)
{
child.EnsureInited(buildData);
if (child is TypedefInfo typedef)
return typedef.Typedef;
return child;
result = child;
// Special case when searching for template types (use instantiated template if input type has generic arguments)
if (child is ClassStructInfo classStructInfo && classStructInfo.IsTemplate && typeInfo.GenericArgs != null)
{
// Support instantiated template type with instantiated arguments (eg. 'typedef Vector3Base<Real> Vector3' where 'typedef float Real')
var inflatedType = typeInfo.Inflate(buildData, child);
// Find any typedef which introduced this type (eg. 'typedef Vector3Base<float> Float3')
result = FindTypedef(buildData, inflatedType, parent.ParentModule);
if (result == TypedefInfo.Current)
result = child; // Use template type for the current typedef
else if (result == null)
continue; // Invalid template match
}
result.EnsureInited(buildData);
if (result is TypedefInfo typedef)
result = typedef.Typedef;
break;
}
var result = FindApiTypeInfoInner(buildData, typeInfo, child);
result = FindApiTypeInfoInner(buildData, typeInfo, child);
if (result != null)
return result;
break;
}
return result;
}
return null;
private static ApiTypeInfo FindTypedef(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo parent)
{
ApiTypeInfo result = null;
foreach (var child in parent.Children)
{
if (child is TypedefInfo typedef && typedef.Type.Equals(typeInfo))
{
result = child;
break;
}
result = FindTypedef(buildData, typeInfo, child);
if (result != null)
break;
}
return result;
}
}
}

View File

@@ -55,6 +55,30 @@ namespace Flax.Build.Bindings
GenericArgs = other.GenericArgs != null ? new List<TypeInfo>(other.GenericArgs) : null;
}
/// <summary>
/// Inflates the type with typedefs for generic arguments.
/// </summary>
public TypeInfo Inflate(Builder.BuildData buildData, ApiTypeInfo caller)
{
if (GenericArgs != null && GenericArgs.Count != 0)
{
var inflated = new TypeInfo(this);
for (int i = 0; i < inflated.GenericArgs.Count; i++)
{
var arg = new TypeInfo(inflated.GenericArgs[i]);
var argType = BindingsGenerator.FindApiTypeInfo(buildData, arg, caller);
if (argType != null)
{
arg.Type = argType.Name;
arg.GenericArgs = null;
}
inflated.GenericArgs[i] = arg;
}
return inflated;
}
return this;
}
/// <summary>
/// Gets a value indicating whether this type is POD (plain old data).
/// </summary>

View File

@@ -14,6 +14,9 @@ namespace Flax.Build.Bindings
public TypeInfo Type;
public ApiTypeInfo Typedef;
// Guards to prevent looped initialization for typedefs that are recursive
internal static TypedefInfo Current;
public override void Init(Builder.BuildData buildData)
{
base.Init(buildData);
@@ -38,7 +41,10 @@ namespace Flax.Build.Bindings
}
// Find typedef type
var current = Current;
Current = this;
var apiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, Type, Parent);
Current = current;
if (apiTypeInfo == null)
throw new Exception(string.Format("Unknown type '{0}' for typedef '{1}'.", Type, Name));
apiTypeInfo.EnsureInited(buildData);
@@ -46,8 +52,6 @@ namespace Flax.Build.Bindings
// Alias type without introducing any new type
if (IsAlias || apiTypeInfo is LangType)
{
if (apiTypeInfo is ClassStructInfo typedefClassStruct && typedefClassStruct.IsTemplate)
throw new Exception(string.Format("Cannot use typedef '{0}' for type '{1}' that is a template.", Name, Type));
Typedef = apiTypeInfo;
return;
}