[macro] add ClassTypeMacro and FieldMacro

This commit is contained in:
2019-11-15 16:32:57 +03:00
parent fcbac5587e
commit 74ed2d4425
9 changed files with 108 additions and 141 deletions

View File

@@ -0,0 +1,21 @@
package haxework.macro;
import haxe.macro.Expr;
import haxe.macro.Type;
class ClassTypeMacro {
public var metaName(default, null):String;
public function new(metaName:String) {
this.metaName = metaName;
}
public function has(classType:ClassType):Bool {
return classType.meta.has(metaName);
}
public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
return fields;
}
}

View File

@@ -6,20 +6,10 @@ import haxe.macro.ExprTools;
import haxe.macro.Expr;
import haxe.macro.Type;
class DispatcherMacro {
class DispatcherMacro extends ClassTypeMacro {
private static inline var metaName:String = ':dispatcher';
public static function has(classType:ClassType):Bool {
return classType.meta.has(metaName);
}
private var classType:ClassType;
private var fields:Array<Field>;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
public function new() {
super(":dispatcher");
}
private static inline function signalName(fieldName:String):String {
@@ -30,7 +20,7 @@ class DispatcherMacro {
}
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var result:Array<Field> = fields.slice(0);
var typeName = ExprTools.toString(classType.meta.extract(metaName)[0].params[0]);
var type:ClassType = switch Context.getType(typeName) {

View File

@@ -0,0 +1,21 @@
package haxework.macro;
import haxe.macro.Expr;
using haxework.macro.Util;
class FieldMacro {
public var metaName(default, null):String;
public function new(metaName:String) {
this.metaName = metaName;
}
public function has(field:Field):Bool {
return field.getFieldMeta(metaName) != null;
}
public function apply(field:Field):Array<Field> {
return [];
}
}

View File

@@ -5,23 +5,14 @@ import haxe.macro.Expr;
using haxework.macro.Util;
class ProvideMacro {
class ProvideMacro extends FieldMacro {
private static var metaName = ":provide";
public static function has(field:Field):Bool {
return field.getFieldMeta(metaName) != null;
public function new() {
super(":provide");
}
private var field:Field;
private var meta:MetadataEntry;
public function new(field:Field) {
this.field = field;
this.meta = field.getFieldMeta(metaName);
}
public function apply():Array<Field> {
override public function apply(field:Field):Array<Field> {
var meta:MetadataEntry = field.getFieldMeta(metaName);
var result:Array<Field> = [];
var type:ComplexType = switch field.kind {
case FVar(t): t;
@@ -33,12 +24,7 @@ class ProvideMacro {
}
var provideType:String = meta.params.length == 0 ? null : Util.getExprString(meta.params[0].expr);
var isStatic = Lambda.exists(field.access, function(a: Access) return a == AStatic);
result.push({
name: field.name,
access: isStatic ? [APublic, AStatic] : [APublic],
pos: field.pos,
kind: FProp('get', 'set', type),
});
field.kind = FProp('get', 'set', type);
var access = [APrivate, AInline];
if (isStatic) access.push(AStatic);
var args = [name];

View File

@@ -1,22 +1,10 @@
package haxework.macro;
import haxe.macro.Expr;
using haxework.macro.Util;
class ResourceMacro {
public static function has(field:Field):Bool {
return field.getFieldMeta(":resource") != null;
}
class ResourceMacro extends FieldMacro {
private var field:Field;
public function new(field:Field) {
this.field = field;
}
public function apply():Array<Field> {
var result:Array<Field> = [];
return result;
public function new() {
super(":resource");
}
}

View File

@@ -1,29 +1,17 @@
package haxework.macro;
import haxe.macro.TypeTools;
import haxe.macro.Context;
import haxe.macro.ExprTools;
import haxe.macro.Expr;
import haxe.macro.Type;
class SingletonMacro {
class SingletonMacro extends ClassTypeMacro {
private static inline var metaName:String = ":singleton";
public static function has(classType:ClassType):Bool {
return classType.meta.has(metaName);
}
private var classType:ClassType;
private var fields:Array<Field>;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
public function new() {
super(":singleton");
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var result:Array<Field> = fields.slice(0);
var classTypePath:TypePath = {
pack: classType.pack,

View File

@@ -13,21 +13,10 @@ typedef TProperty<T> = {
var defaultValue: T;
}
class StyleMacro {
private static inline var metaName:String = ':style';
class StyleMacro extends ClassTypeMacro {
public static function has(classType:ClassType):Bool {
return classType.getClassMeta(metaName) != null;
}
private var classType:ClassType;
private var fields:Array<Field>;
private var overrideStyle:Bool;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
this.overrideStyle = classType.getClassMeta(":style").params.length > 0;
public function new() {
super(":style");
}
private static function processPropertyField(field:Field):Array<Field> {
@@ -201,14 +190,15 @@ class StyleMacro {
return result;
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var overrideStyle = classType.getClassMeta(metaName).params.length > 0;
var result:Array<Field> = fields.slice(0);
var styleds:Array<Field> = [];
var properties:Array<Field> = [];
var newFields:Array<Field> = [];
var hasOnStyle:Bool = fields.getField("onStyle") != null;
for (field in fields) if (field.meta != null) {
var meta = field.getFieldMeta(":style");
var meta = field.getFieldMeta(metaName);
if (meta != null) {
if (meta.params.length > 0) {
newFields = newFields.concat(processPropertyField(field));

View File

@@ -1,46 +1,24 @@
package haxework.macro;
import Lambda;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxework.macro.PositionJsonParser;
import Lambda;
using haxework.macro.Util;
class TemplateMacro {
class TemplateMacro extends ClassTypeMacro {
private static inline var metaName:String = ':template';
public static function has(classType:ClassType):Bool {
return classType.getClassMeta(metaName) != null;
}
private var classType:ClassType;
private var fields:Array<Field>;
private var bindings:Map<String, String>;
private var meta:MetadataEntry;
private var templateFile:String;
private var template:Dynamic;
private var i:Int;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.meta = classType.getClassMeta(metaName);
this.fields = fields;
var params = Util.getMetaParams(meta);
var filePath = params[0];
if (filePath == null) {
filePath = classType.pack.join("/") + "/" + classType.name + ".yaml";
}
templateFile = Context.resolvePath(filePath);
template = FileUtil.loadFile(templateFile);
bindings = findViewsBindings(fields);
public function new() {
super(":template");
}
private static function getSpecField(object:Dynamic, field:String):Dynamic {
if (Reflect.hasField(object, "@" + field)) {
return Reflect.field(object, "@" + field);
@@ -215,8 +193,18 @@ class TemplateMacro {
return result;
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
i = 0;
var meta = classType.getClassMeta(metaName);
var params = Util.getMetaParams(meta);
var filePath = params[0];
if (filePath == null) {
filePath = classType.pack.join("/") + "/" + classType.name + ".yaml";
}
// ToDo: template builder
templateFile = Context.resolvePath(filePath);
template = FileUtil.loadFile(templateFile);
bindings = findViewsBindings(fields);
var result:Array<Field> = fields.slice(0);
var exprs:Array<Expr> = [];
var init = Lambda.exists(result, function(f) return f.name == "init");

View File

@@ -1,18 +1,32 @@
package haxework.parser;
import haxework.macro.SingletonMacro.SingletonMacro;
import haxework.macro.StyleMacro;
import haxe.macro.TypeTools;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxe.macro.TypeTools;
import haxework.macro.ClassTypeMacro;
import haxework.macro.DispatcherMacro;
import haxework.macro.FieldMacro;
import haxework.macro.ProvideMacro;
import haxework.macro.ResourceMacro;
import haxework.macro.SingletonMacro;
import haxework.macro.StyleMacro;
import haxework.macro.TemplateMacro;
class Parser {
private static var classTypeMacros:Array<ClassTypeMacro> = [
new TemplateMacro(),
new DispatcherMacro(),
new StyleMacro(),
new SingletonMacro(),
];
private static var fieldMacros:Array<FieldMacro> = [
new ProvideMacro(),
new ResourceMacro(),
];
private static var processed:Map<String, Bool> = new Map();
private static function auto():Void {
@@ -30,44 +44,25 @@ class Parser {
var modify:Bool = false;
var fields:Array<Field> = Context.getBuildFields();
var result:Array<Field> = [];
var appends:Array<Field> = [];
// process fields meta
for (field in fields) {
if (ProvideMacro.has(field)) {
modify = true;
var provide = new ProvideMacro(field);
result = result.concat(provide.apply());
} else if (ResourceMacro.has(field)) {
modify = true;
var resource = new ResourceMacro(field);
result = result.concat(resource.apply());
} else {
result.push(field);
result.push(field);
for (item in fieldMacros) {
if (item.has(field)) {
modify = true;
result = result.concat(item.apply(field));
}
}
}
if (modify) {
fields = result;
}
// process class meta
if (TemplateMacro.has(ct)) {
modify = true;
var template = new TemplateMacro(ct, fields);
fields = template.apply();
}
if (DispatcherMacro.has(ct)) {
modify = true;
var dispatcher = new DispatcherMacro(ct, fields);
fields = dispatcher.apply();
}
if (StyleMacro.has(ct)) {
modify = true;
var style = new StyleMacro(ct, fields);
fields = style.apply();
}
if (SingletonMacro.has(ct)) {
modify = true;
var singleton = new SingletonMacro(ct, fields);
fields = singleton.apply();
for (item in classTypeMacros) {
if (item.has(ct)) {
modify = true;
fields = item.apply(ct, fields);
}
}
processed.set(localName, true);
modify ? fields : null;