DefineType with module dependency, build macro, haxe.macro.Context.currentPos()?

Hej,

A new filt3rek’s topic as i know you all have been waiting for it ! :rofl:

I never really know how to use haxe.macro.Context.currentPos() and what consequencies it can have if it’s not well done, I mean is it only for error reporting or does it have more impacts ? (Maybe if someone can give me some examples of impacts ?)

I’m talking about that because i’m trying to define a new type in onAfterTyping macro context, this type has a @:build meta on it, so it’s executed but in this context, when I try to get another type that is already typed, I can’t reach it.

Maybe a minimal example will be more clear : Try Haxe !
Macro.hx :

import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.TypeTools;

class Macro {
	static var first = true;

	public static function test() {
		var cl = TypeTools.getClass(Context.getType("A"));	// Works
		haxe.macro.Context.onAfterTyping(_ -> {
			if (first) {
				var newT = {
					pack: cl.pack,
					name: "B",
					meta: cl.meta.get().concat([{name: ':build', params: [macro Macro.build()], pos: Context.currentPos()},]),
					fields: [],
					kind: {
						var superClassTP = cl.superClass != null ? @:privateAccess haxe.macro.TypeTools.toTypePath(cl.superClass.t.get(),
							cl.superClass.params) : null;
						TDClass(superClassTP, cl.interfaces.map(i -> @:privateAccess haxe.macro.TypeTools.toTypePath(i.t.get(), i.params)), cl.isInterface,
							cl.isFinal, cl.isAbstract);
					},
					pos: cl.pos
				}
				Context.defineType(newT, cl.module);

				first = false;
			}
		});
		return null;
	}

	public static function build() {
		trace(Context.getType("A")); 		// Doesn't Work : Uncaught exception Type not found 'A'
		//trace(Context.getType("Test.A")); // Works
		return null;
	}
}

Test.hx :

class A {}

@:build(Macro.test())
class Test {
	static function main() {
		trace(A);
	}
}

If someone can enlighten me ?

Note : I use here a build macro because in try.haxe we can’t set an init macro, but I think it’s ok with this example…

Thanks

1 Like

It’s almost exclusively for error reporting. Using a relevant Position may help your users find errors more easily.

I think the problem is that defineType()'s module dependency doesn’t exactly put the class in that module, it just ensures the module is compiled. Which it usually already was.

I’ve tried to do the same thing for a slightly different reason. I figured if I could insert a new class into an existing module, the new class would use that module’s imports and usings. But nope, neither defineType() nor defineModule() work like that. Fortunately defineModule() lets you pass a new list of imports and usings, so I was able to copy them over. Mostly.

In your case, I think the solution is to access Test.A rather than A.

1 Like

Thanks you so much for your explanation !

So for Position it’s what I thought, it doesn’t influence here the class to be in the A module’s position for example …

And what about defineType, if it doesn’t include the new type into the given module (dependency), what is the solution to do that (to define a new type inside an existing module) ? I haven’t well understood your trick with defineModule

Neither defineType() nor defineModule() work like that. As far as I know, there’s no way to insert a new type into an existing module.

I’ve raised an issue on Haxe Github asking if there is a way for that, maybe it would be good to have something like that …
Anyway, many thanks for taking time to answer me !
Regards,

I’ve just tested and it seems that giving pack: ["Test"], when defining the new type, puts it in the module … but then it mess a bit I think : Try Haxe !
I keep testing…

Note : Modules, types, subs… the type paths in Haxe are hell…