浏览代码

[macro] respect imports on `@:build` (#11373)

Simon Krajewski 1 年之前
父节点
当前提交
7c750b32ed

+ 6 - 3
src/context/resolution.ml

@@ -2,7 +2,7 @@ open Globals
 open Type
 
 type resolution_kind =
-	| RTypeImport of string* module_type
+	| RTypeImport of string * module_type
 	| RClassFieldImport of string * tclass * tclass_field
 	| RAbstractFieldImport of string * tabstract * tclass * tclass_field
 	| REnumConstructorImport of string * tenum * tenum_field
@@ -107,8 +107,7 @@ class resolution_list (id : string list) = object(self)
 			l <- loop [] l;
 		end
 
-	method resolve (i : string) : resolution =
-		self#resolve_lazies;
+	method resolve' (i : string) : resolution =
 		let rec loop l = match l with
 			| [] ->
 				raise Not_found
@@ -148,6 +147,10 @@ class resolution_list (id : string list) = object(self)
 		in
 		loop l
 
+	method resolve (i : string) : resolution =
+		self#resolve_lazies;
+		self#resolve' i
+
 	method expand_enum_constructors (mt : module_type) = match mt with
 		| TAbstractDecl ({a_impl = Some c} as a) when a.a_enum ->
 			Some (class_statics_resolution c null_pos)

+ 3 - 3
src/core/ast.ml

@@ -1008,10 +1008,10 @@ let get_value_meta meta =
 
 (* Type path related functions *)
 
-let rec string_list_of_expr_path_raise (e,p) =
+let rec string_list_of_expr_path_raise ?root_cb (e,p) =
 	match e with
-	| EConst (Ident i) -> [i]
-	| EField (e,f,_) -> f :: string_list_of_expr_path_raise e
+	| EConst (Ident i) -> (match root_cb with None -> [i] | Some f -> f i)
+	| EField (e,f,_) -> f :: string_list_of_expr_path_raise ?root_cb e
 	| _ -> raise Exit
 
 let rec string_pos_list_of_expr_path_raise (e,p) =

+ 21 - 8
src/typing/typeloadFields.ml

@@ -459,12 +459,18 @@ let build_enum_abstract ctx c a fields p =
 	) fields;
 	EVars [mk_evar ~t:(CTAnonymous fields,p) ("",null_pos)],p
 
-let apply_macro ctx mode path el p =
-	let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with
-		| meth :: name :: pack -> (List.rev pack,name), meth
-		| _ -> raise_typing_error "Invalid macro path" p
-	) in
-	ctx.g.do_macro ctx mode cpath meth el p
+let resolve_type_import ctx p i =
+	try
+		let res = ctx.m.import_resolution#resolve' i in
+		begin match res.r_kind with
+		| RTypeImport(_,mt) ->
+			let path = t_path mt in
+			snd path :: (List.rev (fst path))
+		| _ ->
+			raise_typing_error "Type path expected" p
+		end
+	with Not_found ->
+		[i]
 
 let build_module_def ctx mt meta fvars fbuild =
 	let is_typedef = match mt with TTypeDecl _ -> true | _ -> false in
@@ -474,11 +480,18 @@ let build_module_def ctx mt meta fvars fbuild =
 					| [ECall (epath,el),p] -> epath, el
 					| _ -> raise_typing_error "Invalid build parameters" p
 				) in
-				let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error { err_pos = p } -> raise_typing_error "Build call parameter must be a class path" p in
+				let cpath, meth =
+					let sl = try string_list_of_expr_path_raise ~root_cb:(resolve_type_import ctx p) epath with Exit -> raise_typing_error "Build call parameter must be a class path" p in
+					match sl with
+					| meth :: name :: pack ->
+						(List.rev pack,name), meth
+					| _ ->
+						raise_typing_error "Invalid macro path" p
+				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.get_build_infos in
 				ctx.get_build_infos <- (fun() -> Some (mt, extract_param_types (t_infos mt).mt_params, fvars()));
-				let r = try apply_macro ctx MBuild s el p with e -> ctx.get_build_infos <- old; raise e in
+				let r = try ctx.g.do_macro ctx MBuild cpath meth el p with e -> ctx.get_build_infos <- old; raise e in
 				ctx.get_build_infos <- old;
 				(match r with
 				| None -> raise_typing_error "Build failure" p

+ 18 - 0
tests/misc/projects/Issue11373/Main.hx

@@ -0,0 +1,18 @@
+import pack.BuildMacro;
+import pack.BuildMacro as BM;
+
+@:build(BuildMacro.build())
+class ClassImport {}
+
+@:build(BuildMacro.BuildMacro.build())
+class SubClassImport {}
+
+@:build(BM.build())
+class ClassImportAlias {}
+
+@:build(BM.BuildMacro.build())
+class SubClassImportAlias {}
+
+function main() {
+	trace(BuildMacro.report());
+}

+ 2 - 0
tests/misc/projects/Issue11373/compile.hxml

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

+ 1 - 0
tests/misc/projects/Issue11373/compile.hxml.stdout

@@ -0,0 +1 @@
+Main.hx:17: ClassImport, ClassImportAlias, SubClassImport, SubClassImportAlias

+ 21 - 0
tests/misc/projects/Issue11373/pack/BuildMacro.hx

@@ -0,0 +1,21 @@
+package pack;
+
+import haxe.macro.Context;
+
+class BuildMacro {
+	#if macro
+	static var builtTypes = [];
+	#end
+
+	static public function build():Array<haxe.macro.Expr.Field> {
+		#if macro
+		builtTypes.push("" + Context.getLocalClass());
+		#end
+		return null;
+	}
+
+	macro static public function report() {
+		builtTypes.sort(Reflect.compare);
+		return macro $v{builtTypes.join(", ")};
+	}
+}