Add new API_TYPEDEF metadata for Scriptign API types instantiation (with Alias option)
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Flax.Build.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The native type information for bindings generator.
|
||||
/// </summary>
|
||||
public class ApiTypeInfo : IBindingsCache
|
||||
public class ApiTypeInfo : IBindingsCache, ICloneable
|
||||
{
|
||||
public ApiTypeInfo Parent;
|
||||
public List<ApiTypeInfo> Children = new List<ApiTypeInfo>();
|
||||
@@ -136,5 +138,20 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Clone()
|
||||
{
|
||||
var clone = (ApiTypeInfo)Activator.CreateInstance(GetType());
|
||||
using (var stream = new MemoryStream(1024))
|
||||
{
|
||||
using (var writer = new BinaryWriter(stream, Encoding.UTF8, true))
|
||||
Write(writer);
|
||||
stream.Position = 0;
|
||||
using (var reader = new BinaryReader(stream))
|
||||
clone.Read(reader);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Flax.Build.Bindings
|
||||
public const string Field = "API_FIELD";
|
||||
public const string Event = "API_EVENT";
|
||||
public const string Param = "API_PARAM";
|
||||
public const string Typedef = "API_TYPEDEF";
|
||||
public const string InjectCppCode = "API_INJECT_CPP_CODE";
|
||||
public const string AutoSerialization = "API_AUTO_SERIALIZATION";
|
||||
|
||||
@@ -29,6 +30,7 @@ namespace Flax.Build.Bindings
|
||||
Class,
|
||||
Struct,
|
||||
Interface,
|
||||
Typedef,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -306,6 +308,8 @@ namespace Flax.Build.Bindings
|
||||
if (child.Name == typeInfo.Type)
|
||||
{
|
||||
child.EnsureInited(buildData);
|
||||
if (child is TypedefInfo typedef)
|
||||
return typedef.Typedef;
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
@@ -311,7 +311,7 @@ namespace Flax.Build.Bindings
|
||||
currentParam.Attributes = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on parameter at line {context.Tokenizer.CurrentLine}.");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {"function parameter"} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -567,7 +567,7 @@ namespace Flax.Build.Bindings
|
||||
desc.Namespace = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on class {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -648,7 +648,7 @@ namespace Flax.Build.Bindings
|
||||
desc.Namespace = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on interface {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -775,7 +775,7 @@ namespace Flax.Build.Bindings
|
||||
desc.IsHidden = true;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on function {desc.Name}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -965,7 +965,7 @@ namespace Flax.Build.Bindings
|
||||
entry.Attributes = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on enum {desc.Name} entry at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name + " enum entry"} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1029,7 +1029,7 @@ namespace Flax.Build.Bindings
|
||||
desc.Namespace = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on enum {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1093,7 +1093,7 @@ namespace Flax.Build.Bindings
|
||||
desc.Namespace = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on struct {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1211,7 +1211,7 @@ namespace Flax.Build.Bindings
|
||||
desc.NoArray = true;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on field {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1273,7 +1273,7 @@ namespace Flax.Build.Bindings
|
||||
desc.IsHidden = true;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on event {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1291,5 +1291,59 @@ namespace Flax.Build.Bindings
|
||||
context.Tokenizer.ExpectToken(TokenType.RightParent);
|
||||
return desc;
|
||||
}
|
||||
|
||||
private static TypedefInfo ParseTypedef(ref ParsingContext context)
|
||||
{
|
||||
var desc = new TypedefInfo
|
||||
{
|
||||
};
|
||||
|
||||
// Read the documentation comment
|
||||
desc.Comment = ParseComment(ref context);
|
||||
|
||||
// Read parameters from the tag
|
||||
var tagParams = ParseTagParameters(ref context);
|
||||
|
||||
// Read 'typedef' keyword
|
||||
var token = context.Tokenizer.NextToken();
|
||||
if (token.Value != "typedef")
|
||||
throw new Exception($"Invalid {ApiTokens.Typedef} usage (expected 'typedef' keyword but got '{token.Value} {context.Tokenizer.NextToken().Value}').");
|
||||
|
||||
// Read type definition
|
||||
desc.Type = ParseType(ref context);
|
||||
|
||||
// Read name
|
||||
desc.Name = ParseName(ref context);
|
||||
|
||||
// Read ';'
|
||||
context.Tokenizer.ExpectToken(TokenType.SemiColon);
|
||||
|
||||
// Process tag parameters
|
||||
foreach (var tag in tagParams)
|
||||
{
|
||||
switch (tag.Tag.ToLower())
|
||||
{
|
||||
case "alias":
|
||||
desc.IsAlias = true;
|
||||
break;
|
||||
case "inbuild":
|
||||
desc.IsInBuild = true;
|
||||
break;
|
||||
case "attributes":
|
||||
desc.Attributes = tag.Value;
|
||||
break;
|
||||
case "name":
|
||||
desc.Name = tag.Value;
|
||||
break;
|
||||
case "namespace":
|
||||
desc.Namespace = tag.Value;
|
||||
break;
|
||||
default:
|
||||
Log.Warning($"Unknown or not supported tag parameter {tag} used on {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +296,11 @@ namespace Flax.Build.Bindings
|
||||
else
|
||||
throw new Exception($"Not supported location for event {eventInfo.Name} at line {tokenizer.CurrentLine}. Place it in the class to use API bindings for it.");
|
||||
}
|
||||
else if (string.Equals(token.Value, ApiTokens.Typedef, StringComparison.Ordinal))
|
||||
{
|
||||
var typeInfo = ParseTypedef(ref context);
|
||||
fileInfo.AddChild(typeInfo);
|
||||
}
|
||||
else if (string.Equals(token.Value, ApiTokens.InjectCppCode, StringComparison.Ordinal))
|
||||
{
|
||||
var injectCppCodeInfo = ParseInjectCppCode(ref context);
|
||||
|
||||
139
Source/Tools/Flax.Build/Bindings/TypedefInfo.cs
Normal file
139
Source/Tools/Flax.Build/Bindings/TypedefInfo.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Flax.Build.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The type definition for bindings generator.
|
||||
/// </summary>
|
||||
public class TypedefInfo : ApiTypeInfo
|
||||
{
|
||||
public bool IsAlias;
|
||||
public TypeInfo Type;
|
||||
public ApiTypeInfo Typedef;
|
||||
|
||||
public override void Init(Builder.BuildData buildData)
|
||||
{
|
||||
base.Init(buildData);
|
||||
|
||||
// Remove previous typedef (if any)
|
||||
if (Typedef == null)
|
||||
{
|
||||
foreach (var e in Parent.Children)
|
||||
{
|
||||
if (e != this && e.Name == Name)
|
||||
{
|
||||
Typedef = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Typedef != null)
|
||||
{
|
||||
Typedef.Parent = null;
|
||||
Parent.Children.Remove(Typedef);
|
||||
Typedef = null;
|
||||
}
|
||||
|
||||
// Find typedef type
|
||||
var apiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, Type, Parent);
|
||||
if (apiTypeInfo == null)
|
||||
throw new Exception(string.Format("Unknown type '{0}' for typedef '{1}'.", Type, Name));
|
||||
apiTypeInfo.EnsureInited(buildData);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Duplicate type
|
||||
var typedef = (ApiTypeInfo)apiTypeInfo.Clone();
|
||||
typedef.NativeName = NativeName ?? Name;
|
||||
typedef.Name = Name;
|
||||
typedef.Namespace = Namespace;
|
||||
if (!string.IsNullOrEmpty(Attributes))
|
||||
{
|
||||
if (string.IsNullOrEmpty(typedef.Attributes))
|
||||
typedef.Attributes = Attributes;
|
||||
else
|
||||
typedef.Attributes += ',' + Attributes;
|
||||
}
|
||||
if (Comment != null && Comment.Length != 0)
|
||||
typedef.Comment = Comment;
|
||||
typedef.IsInBuild |= IsInBuild;
|
||||
typedef.IsDeprecated |= IsDeprecated;
|
||||
if (typedef is ClassStructInfo typedefClassStruct && typedefClassStruct.IsTemplate)
|
||||
{
|
||||
// Inflate template type
|
||||
typedefClassStruct.IsTemplate = false;
|
||||
if (typedefClassStruct is ClassInfo typedefClass)
|
||||
{
|
||||
foreach (var fieldInfo in typedefClass.Fields)
|
||||
InflateType(buildData, typedefClassStruct, ref fieldInfo.Type);
|
||||
}
|
||||
else if (typedefClassStruct is StructureInfo typedefStruct)
|
||||
{
|
||||
foreach (var fieldInfo in typedefStruct.Fields)
|
||||
InflateType(buildData, typedefStruct, ref fieldInfo.Type);
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the hierarchy
|
||||
typedef.Parent = Parent;
|
||||
Parent.Children.Add(typedef);
|
||||
typedef.EnsureInited(buildData);
|
||||
Typedef = typedef;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log.Error($"Failed to typedef '{Type}' as '{Name}'.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void InflateType(Builder.BuildData buildData, ClassStructInfo typedef, ref TypeInfo typeInfo)
|
||||
{
|
||||
if (BindingsGenerator.CSharpNativeToManagedBasicTypes.ContainsKey(typeInfo.Type))
|
||||
return;
|
||||
if (BindingsGenerator.CSharpNativeToManagedDefault.ContainsKey(typeInfo.Type))
|
||||
return;
|
||||
|
||||
// Find API type info for this field type
|
||||
var apiType = BindingsGenerator.FindApiTypeInfo(buildData, typeInfo, typedef);
|
||||
if (apiType == null)
|
||||
{
|
||||
// TODO: implement more advanced template types inflating with tokenization of the generic definition
|
||||
typeInfo = Type.GenericArgs[0];
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(IsAlias);
|
||||
BindingsGenerator.Write(writer, Type);
|
||||
|
||||
base.Write(writer);
|
||||
}
|
||||
|
||||
public override void Read(BinaryReader reader)
|
||||
{
|
||||
IsAlias = reader.ReadBoolean();
|
||||
Type = BindingsGenerator.Read(reader, Type);
|
||||
|
||||
base.Read(reader);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "typedef " + Type + " " + Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@
|
||||
<Compile Include="Bindings\ModuleInfo.cs" />
|
||||
<Compile Include="Bindings\PropertyInfo.cs" />
|
||||
<Compile Include="Bindings\StructureInfo.cs" />
|
||||
<Compile Include="Bindings\TypedefInfo.cs" />
|
||||
<Compile Include="Bindings\TypeInfo.cs" />
|
||||
<Compile Include="Build\Assembler.cs" />
|
||||
<Compile Include="Build\Builder.cs" />
|
||||
|
||||
Reference in New Issue
Block a user