Hello! I’m trying to write a macro, that creates a class with fields of every subclass of given interface. I do it by using @:autobuild(spork.core.Macro.registerProperty())
for interface SharedProperty
and defining a new type spork.core.PropertyHolder
in onAfterTyping
callback.
However, when I try to create an instance of spork.core.PropertyHolder
, it results in:
Type not found : spork.core.PropertyHolder
I tried using a onTypeNotFound
callback, but it never gets called for PropertyHolder
, apparently.
The Macro class looks like this:
private static var setupFinished = false;
private static var holder: TypeDefinition = null;
private static var holderFields: StringMap<ComplexType> = new StringMap<ComplexType>();
public static function typeNotFoundCallback(typename: String): TypeDefinition {
if (typename.indexOf("PropertyHolder") != -1) {
trace("getting property holder");
return holder;
} else {
return null;
}
}
public static function buildPropHolder(types: Array<ModuleType>): Void {
if (holder == null) {
holder = macro class PropertyHolder {
public function new() {}
};
holder.pack = ["spork", "core"];
//add shared property fields
for (iter in holderFields.keyValueIterator()) {
holder.fields.push({
name: iter.key,
access: [APublic],
pos: Context.currentPos(),
kind: FVar(iter.value, null)
});
}
Context.defineType(holder);
}
}
public static macro function buildComponent(): Array<Field> {
var fields = Context.getBuildFields();
return fields;
}
public static macro function registerProperty(): Array<Field> {
var fields = Context.getBuildFields();
// register callbacks for after typing and type not found
if (!setupFinished) {
Context.onAfterTyping(buildPropHolder);
Context.onTypeNotFound(typeNotFoundCallback);
setupFinished = true;
}
// get field name for property holder
var clazz = Context.getLocalClass().get();
var meta = clazz.meta.extract("name");
var fieldName = "";
// if metadata has field name, use it
if (meta.length != 0 && meta[0].params.length != 0) {
fieldName = ExprTools.getValue(meta[0].params[0]);
} else {
// otherwise, generate from path
clazz.pack.push(clazz.name);
fieldName = makeVarName(clazz.pack);
}
holderFields.set(fieldName, TypeTools.toComplexType(Context.getLocalType()));
return fields;
}
/**
* Gets a field name for property from package, according to the following format:
* org.example.Module.Type -> orgExampleModuleType
* @param pack package array
* @return String
*/
public static inline function makeVarName(pack: Array<String>): String {
//irrelevant code here
}
}
I would really appreciate your help.