Skip to content

Instantly share code, notes, and snippets.

@KinoAR

KinoAR/DepotMacros.hx

Last active Mar 29, 2021
Embed
What would you like to do?
Macro for Depot that turns your database elements/spreadsheet rows into a part of your code base.
package macros;
#if macro
import haxe.DynamicAccess;
import Types.DepotFile;
import sys.io.File;
import sys.FileSystem;
import haxe.macro.Expr.Field;
import haxe.Json;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
#end
import haxe.extern.EitherType;
using Lambda;
using StringTools;
using ext.StringExt;
// Depot Information
typedef DepotFile = {
var sheets:Array<DepotSheet>;
}
typedef DepotSheet = {
var name:String;
var description:String;
var displayColumn:String;
var guid:String;
var columns:Array<ColumnInfo>;
var lines:Array<LineInfo>;
var hidden:Bool;
var configurable:{
var name:String;
var description:String;
var displayColumn:String;
}
var ?parentSheetGUID:String;
var ?columnGUID:String;
}
typedef ColumnInfo = {
var typeStr:TypeString;
var guid:String;
var name:String;
var description:String;
var defaultValue:String;
var sheet:String;
var iconName:String;
var configurable:ConfigInfo;
}
typedef ConfigInfo = {
var name:String;
var description:String;
var defaultValue:EitherType<String, Array<Dynamic>>;
}
typedef LineInfo = {
var guid:String;
var id:String;
}
enum abstract TypeString(String) from String to String {
public var TEXT = 'text';
public var LONGTEXT = 'longtext';
public var BOOL = 'bool';
public var INT = 'int';
public var FLOAT = 'float';
public var IMAGE = 'image';
public var LIST = 'list';
public var ENUM = 'enum';
}
// using StringExtensions;
/**
* Contains the build macros for creating Depot
* integration within the Haxe programming language.
*/
class DepotMacros {
#if macro
public static macro function buildDepotFile(filePath:String):Array<Field> {
//Get the fields on the associated class
var buildFields = Context.getBuildFields();
if (FileSystem.exists(filePath)) {
var fileData = File.getContent(filePath);
var depotData:DepotFile = Json.parse(fileData);
// Depot Starts from inside the data element
//Iterates through each sheet
depotData.sheets.iter((sheet) -> {
var dynamicSheet:DynamicAccess<Dynamic> = cast sheet;
dynamicSheet.remove('columns'); // Remove unnecessary columns
var cleanName = ~/!|\$|-|\s+/g.replace(sheet.name, '_')
.capitalize();
var sheetFields = new Map<String, ObjectField>();
for (key => value in dynamicSheet) {
var cleanKey = ~/!|\$|-|\s+/g.replace(key, '_');
// Handles Finding Important Fields
var endVal = macro $v{value};
var includeField = true;
switch (endVal.expr) {
case EObjectDecl(fields):
endVal = {
expr: EObjectDecl(fields.filter((field) -> {
return switch (field.expr.expr) {
case EArrayDecl(values):
values.length > 0 ? true : false;
case _:
true;
}
})),
pos: Context.currentPos()
};
// Start Of Lines and other array declarations
case EArrayDecl(values):
if (values.length < 1) {
includeField = false;
} else {
var newValues = [];
values.iter((arrExpr) -> {
// trace(arrExpr);
switch (arrExpr.expr) {
case EArrayDecl(values):
if (values.length > 0) {
newValues.push(arrExpr);
}
case EObjectDecl(fields):
// Creates the lines in the DepotData
var lineName = '';
var newDecl = EObjectDecl(fields.filter((field) ->
{
return
switch (field.expr.expr) {
case EArrayDecl(values):
values.length > 0 ? true : false;
case _:
true;
}
})
.map((field -> {
field.field = ~/!|\$|-|\s+/g.replace(field.field,
'_');
// Name Individual Lines
lineName = field.field.contains('name')
&& lineName == '' ? field.expr.toString() : lineName;
return field;
})));
// Final Result for the line
var objExpr = {
expr: newDecl,
pos: Context.currentPos()
};
// Take Result and Convert to individual element
var valueComplexType = Context.toComplexType(Context.typeof(objExpr));
var cleanLineName = lineName.replace("\"",
"");
cleanLineName = ~/!|\$|-|\s+/g.replace(cleanLineName,
"_");
var newField:Field = {
name: '${cleanName}_${cleanLineName}',
pos: Context.currentPos(),
kind: FVar(valueComplexType,
objExpr),
access: [Access.APublic, Access.AStatic]
};
// Push line as a class property with sheet prefix
buildFields.push(newField);
// Push Lines to their individual Sheets
newValues.push(objExpr);
case _:
newValues.push(arrExpr);
}
});
endVal = {
expr: EArrayDecl(newValues),
pos: Context.currentPos()
}
}
case _:
// Do nothing
}
// Includes a Field in the sheet, such as lines
if (includeField) {
sheetFields.set(cleanKey, {
field: cleanKey,
expr: endVal,
});
}
}
var valueExpr = EObjectDecl(sheetFields.array());
var result = {expr: valueExpr, pos: Context.currentPos()};
var valueComplexType = Context.toComplexType(Context.typeof(result));
var newField:Field = {
name: cleanName,
pos: Context.currentPos(),
kind: FVar(valueComplexType, result),
access: [Access.APublic, Access.AStatic]
};
buildFields.push(newField);
});
}
//Returns the fields of the class with the newly added elements included.
return buildFields;
}
#end
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment