Added IsClass and FilterFields methods to streamline types creation, added more documentation
This commit is contained in:
@@ -69,10 +69,6 @@ namespace CodeGenerator {
|
|||||||
_customTypes = new();
|
_customTypes = new();
|
||||||
|
|
||||||
foreach (var type in _blendfile.SdnaStructs) {
|
foreach (var type in _blendfile.SdnaStructs) {
|
||||||
Log($"Generating struct {type.Type}");
|
|
||||||
bool referenceSelf = false;
|
|
||||||
bool referencePointer = false;
|
|
||||||
|
|
||||||
//Add the type to the custom types list
|
//Add the type to the custom types list
|
||||||
_customTypes.Add(type.Type);
|
_customTypes.Add(type.Type);
|
||||||
|
|
||||||
@@ -82,27 +78,27 @@ namespace CodeGenerator {
|
|||||||
new CodeAttributeArgument(new CodePrimitiveExpression(type.IdxType)),
|
new CodeAttributeArgument(new CodePrimitiveExpression(type.IdxType)),
|
||||||
new CodeAttributeArgument(new CodePrimitiveExpression(type.Type))
|
new CodeAttributeArgument(new CodePrimitiveExpression(type.Type))
|
||||||
));
|
));
|
||||||
//TODO: when encountering a list, run trough the fields to find a count/lenght or similar data.
|
|
||||||
foreach (var field in type.Fields) {
|
Log($"Generating type from struct {type.Type}");
|
||||||
if (field.Name.Contains("*")) {
|
|
||||||
referencePointer = true;
|
if(IsClass(type)) {
|
||||||
}
|
Log($"Marking {type.Type} as class");
|
||||||
if (field.Type.Contains(type.Type)) {
|
|
||||||
referenceSelf = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (referenceSelf || referencePointer) {
|
|
||||||
Log("Struct contains references");
|
|
||||||
ctd.IsClass = true;
|
ctd.IsClass = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ctd.IsStruct = true;
|
Log($"Marking {type.Type} as struct");
|
||||||
|
ctd.IsStruct = !ctd.IsClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add the class to the namespace
|
//Add the class to the namespace
|
||||||
ns.Types.Add(ctd);
|
ns.Types.Add(ctd);
|
||||||
|
|
||||||
|
//TODO: when encountering a list, run trough the fields to find a count/lenght or similar data.
|
||||||
|
List<BlendFile.DnaField> normalFields; //Fields that are not lists nor lenghts of lists
|
||||||
|
List<(BlendFile.DnaField, BlendFile.DnaField)> listFields; //Fields that are lists, and their corresponding length fields
|
||||||
|
|
||||||
|
//filter the fields we want to include in the class minus the lists
|
||||||
|
FilterFields(type.Fields, out normalFields, out listFields);
|
||||||
|
|
||||||
var totalSize = 0;
|
var totalSize = 0;
|
||||||
|
|
||||||
//Add the fields to the class
|
//Add the fields to the class
|
||||||
@@ -142,6 +138,76 @@ namespace CodeGenerator {
|
|||||||
return ns;
|
return ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the type has to be serialized as a class or a struct
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"><see cref="BlendFile.DnaStruct"/> istance to analyze</param>
|
||||||
|
/// <returns> <see langword="true"/> if there is any pointer or self reference, otherwise <see langword="false"/></returns>
|
||||||
|
private static bool IsClass(BlendFile.DnaStruct type) {
|
||||||
|
foreach (var field in type.Fields) {
|
||||||
|
if (field.Name.Contains("*")) {
|
||||||
|
Log($"Pointer detected. {field.Type} {field.Name}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (field.Type.Contains(type.Type)) {
|
||||||
|
Log($"Self reference detected. {field.Type} {field.Name}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log($"No pointer or self reference detected in {type.Type}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filters the fields into normal fields and list fields pairs
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fields"><see cref="IEnumerable{T}"/> of <see cref="BlendFile.DnaField"/>s from all parameters</param>
|
||||||
|
/// <param name="normalFields"><see cref="List{T}"/> of <see cref="BlendFile.DnaField"/> containing all fields not part of a List</param>
|
||||||
|
/// <param name="listFields"><see cref="List{T}"/> of (<see cref="BlendFile.DnaField"/>, <see cref="BlendFile.DnaField"/>) collection where Item1 is the ListPointer and Item2 is the list lenght</param>
|
||||||
|
private static void FilterFields(IEnumerable<BlendFile.DnaField> fields,
|
||||||
|
out List<BlendFile.DnaField> normalFields,
|
||||||
|
out List<(BlendFile.DnaField, BlendFile.DnaField)> listFields) {
|
||||||
|
normalFields = new(); //Fields that are not lists nor lengths of lists
|
||||||
|
listFields = new(); //Fields that are lists, and their corresponding length fields
|
||||||
|
//Cast to array the fields to avoid multiple enumerations
|
||||||
|
var dnaFields = fields as BlendFile.DnaField[] ?? fields.ToArray();
|
||||||
|
foreach (var field in dnaFields) {
|
||||||
|
if (ListMarkerStr.Any(s => field.Name.Contains(s))) {
|
||||||
|
Log($"Found list field {field.Name}");
|
||||||
|
Log($"Searching for list length field");
|
||||||
|
var listLengthField = dnaFields.FirstOrDefault(f =>
|
||||||
|
f.Name.Contains(field.Name) && ListLenghtStr.Any(s => f.Name.Contains(s)));
|
||||||
|
|
||||||
|
if (listLengthField == null)
|
||||||
|
Log($"No list length field found for {field.Name}");
|
||||||
|
else {
|
||||||
|
Log($"Found list length field {listLengthField.Name}");
|
||||||
|
listFields.Add((field, listLengthField));
|
||||||
|
|
||||||
|
//Remove the list length field from the normal fields (if present)
|
||||||
|
if(normalFields.Remove(listLengthField))
|
||||||
|
Log($"Removed list length field {listLengthField.Name}");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Skip fields that are recognized as listLengths
|
||||||
|
if (listFields.Select(f => f.Item2).Contains(field)) {
|
||||||
|
Log($"Skipping known list length field {field.Name}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log($"Adding normal field {field.Name}");
|
||||||
|
normalFields.Add(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the following attribute types <c>DNAAttribute, DNAFieldAttribute, DNAClassAttribute, DNAListAttribute</c>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns><see cref="CodeTypeDeclaration"/> array containing the generated attribute types</returns>
|
||||||
|
/// <remarks>This internally uses a single instance of <see cref="AttributeBuilder"/> and sequentially generates the various attributes.</remarks>
|
||||||
private static CodeTypeDeclaration[] GenerateTypeDeclarations() {
|
private static CodeTypeDeclaration[] GenerateTypeDeclarations() {
|
||||||
var attributeBuilder = new AttributeBuilder();
|
var attributeBuilder = new AttributeBuilder();
|
||||||
|
|
||||||
@@ -190,6 +256,7 @@ namespace CodeGenerator {
|
|||||||
return typeDeclarations;
|
return typeDeclarations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: use AttributeBuilder inside here
|
||||||
private static CodeAttributeDeclaration GenerateDnaFieldAttribute(int index, BlendFile.DnaField field,
|
private static CodeAttributeDeclaration GenerateDnaFieldAttribute(int index, BlendFile.DnaField field,
|
||||||
BlendFile.Dna1Body body, int offset, out int size) {
|
BlendFile.Dna1Body body, int offset, out int size) {
|
||||||
string t;
|
string t;
|
||||||
@@ -236,7 +303,7 @@ namespace CodeGenerator {
|
|||||||
});
|
});
|
||||||
return cad;
|
return cad;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CodeMemberField CreateMemberField(BlendFile.DnaField field) {
|
private static CodeMemberField CreateMemberField(BlendFile.DnaField field) {
|
||||||
Type t = Type.GetType(field.Type.ParseFType());
|
Type t = Type.GetType(field.Type.ParseFType());
|
||||||
CodeMemberField cmf;
|
CodeMemberField cmf;
|
||||||
|
|||||||
Reference in New Issue
Block a user