فهرست منبع

Apply @:using after build macros (#11625)

* Apply @:using after running build macro

Allows build macro to provide such metadata

* [tests] Add test for @:using added by build macro

* Factorize t_infos calls
Rudy Ges 1 سال پیش
والد
کامیت
2aa1b528f9

+ 23 - 21
src/typing/typeloadFields.ml

@@ -377,7 +377,11 @@ let resolve_type_import ctx p i =
 		[i]
 
 let build_module_def ctx mt meta fvars fbuild =
-	let is_typedef = match mt with TTypeDecl _ -> true | _ -> false in
+	let is_typedef, ti = match mt with
+		| TClassDecl { cl_kind = KAbstractImpl a } -> false, t_infos (TAbstractDecl a)
+		| TTypeDecl _ -> true, t_infos mt
+		| _ -> false, t_infos mt
+	in
 	let loop f_build = function
 		| Meta.Build,args,p when not is_typedef -> (fun () ->
 				let epath, el = (match args with
@@ -394,31 +398,13 @@ let build_module_def ctx mt meta fvars fbuild =
 				in
 				if ctx.com.is_macro_context then raise_typing_error "You cannot use @:build inside a macro : make sure that your type is not used in macro" p;
 				let old = ctx.c.get_build_infos in
-				ctx.c.get_build_infos <- (fun() -> Some (mt, extract_param_types (t_infos mt).mt_params, fvars()));
+				ctx.c.get_build_infos <- (fun() -> Some (mt, extract_param_types ti.mt_params, fvars()));
 				let r = try ctx.g.do_macro ctx MBuild cpath meth el p with e -> ctx.c.get_build_infos <- old; raise e in
 				ctx.c.get_build_infos <- old;
 				(match r with
 				| MError | MMacroInMacro -> raise_typing_error "Build failure" p
 				| MSuccess e -> fbuild e)
 			) :: f_build
-		| Meta.Using,el,p -> (fun () ->
-			List.iter (fun e ->
-				try
-					let path = List.rev (string_pos_list_of_expr_path_raise e) in
-					let types,filter_classes = ImportHandling.handle_using ctx path (pos e) in
-					let ti =
-						match mt with
-							| TClassDecl { cl_kind = KAbstractImpl a } -> t_infos (TAbstractDecl a)
-							| _ -> t_infos mt
-					in
-					(* Delay for #10107, but use delay_late to make sure base classes run before their children do. *)
-					delay_late ctx.g PConnectField (fun () ->
-						ti.mt_using <- (filter_classes types) @ ti.mt_using
-					)
-				with Exit ->
-					raise_typing_error "dot path expected" (pos e)
-			) el;
-		) :: f_build
 		| _ ->
 			f_build
 	in
@@ -432,7 +418,6 @@ let build_module_def ctx mt meta fvars fbuild =
 			)
 		| TClassDecl { cl_super = csup; cl_implements = interfaces; cl_kind = kind } ->
 			(* Go for @:using in parents and interfaces *)
-			let ti = t_infos mt in
 			let inherit_using (c,_) =
 				ti.mt_using <- ti.mt_using @ (t_infos (TClassDecl c)).mt_using
 			in
@@ -445,6 +430,23 @@ let build_module_def ctx mt meta fvars fbuild =
 			None
 	in
 	List.iter (fun f -> f()) (List.rev f_build);
+	let apply_using = function
+		| Meta.Using,el,p ->
+			List.iter (fun e ->
+				try
+					let path = List.rev (string_pos_list_of_expr_path_raise e) in
+					let types,filter_classes = ImportHandling.handle_using ctx path (pos e) in
+					(* Delay for #10107, but use delay_late to make sure base classes run before their children do. *)
+					delay_late ctx.g PConnectField (fun () ->
+						ti.mt_using <- (filter_classes types) @ ti.mt_using
+					)
+				with Exit ->
+					raise_typing_error "dot path expected" (pos e)
+			) el;
+		| _ ->
+			()
+	in
+	List.iter apply_using ti.mt_meta;
 	(match f_enum with None -> () | Some f -> f())
 
 let create_class_context c p =

+ 5 - 0
tests/misc/projects/Issue11625/Macro.hx

@@ -0,0 +1,5 @@
+function build() {
+	var cls = haxe.macro.Context.getLocalClass().get();
+	cls.meta.add(":using", [macro Main.Extensions], cls.pos);
+	return null;
+}

+ 10 - 0
tests/misc/projects/Issue11625/Main.hx

@@ -0,0 +1,10 @@
+function main() {
+	Foo.test();
+}
+
+class Extensions {
+	public static function test<T>(c:Class<T>) trace("ok");
+}
+
+@:build(Macro.build())
+class Foo {}

+ 1 - 0
tests/misc/projects/Issue11625/compile.hxml

@@ -0,0 +1 @@
+-main Main