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();
|
||||
|
||||
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
|
||||
_customTypes.Add(type.Type);
|
||||
|
||||
@@ -82,27 +78,27 @@ namespace CodeGenerator {
|
||||
new CodeAttributeArgument(new CodePrimitiveExpression(type.IdxType)),
|
||||
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) {
|
||||
if (field.Name.Contains("*")) {
|
||||
referencePointer = true;
|
||||
}
|
||||
if (field.Type.Contains(type.Type)) {
|
||||
referenceSelf = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (referenceSelf || referencePointer) {
|
||||
Log("Struct contains references");
|
||||
Log($"Generating type from struct {type.Type}");
|
||||
|
||||
if(IsClass(type)) {
|
||||
Log($"Marking {type.Type} as class");
|
||||
ctd.IsClass = true;
|
||||
}
|
||||
else {
|
||||
ctd.IsStruct = true;
|
||||
Log($"Marking {type.Type} as struct");
|
||||
ctd.IsStruct = !ctd.IsClass;
|
||||
}
|
||||
|
||||
//Add the class to the namespace
|
||||
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;
|
||||
|
||||
//Add the fields to the class
|
||||
@@ -142,6 +138,76 @@ namespace CodeGenerator {
|
||||
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() {
|
||||
var attributeBuilder = new AttributeBuilder();
|
||||
|
||||
@@ -190,6 +256,7 @@ namespace CodeGenerator {
|
||||
return typeDeclarations;
|
||||
}
|
||||
|
||||
//TODO: use AttributeBuilder inside here
|
||||
private static CodeAttributeDeclaration GenerateDnaFieldAttribute(int index, BlendFile.DnaField field,
|
||||
BlendFile.Dna1Body body, int offset, out int size) {
|
||||
string t;
|
||||
|
||||
Reference in New Issue
Block a user