From f76db7e32070de5a5059a1e166d6b7f8c40f61f9 Mon Sep 17 00:00:00 2001 From: Simon Krajewski Date: Mon, 13 Nov 2023 11:51:29 +0100 Subject: [PATCH] [macro] respect imports on `@:build` --- src/context/resolution.ml | 9 ++++-- src/core/ast.ml | 6 ++-- src/typing/typeloadFields.ml | 29 ++++++++++++++----- tests/misc/projects/Issue11373/Main.hx | 18 ++++++++++++ tests/misc/projects/Issue11373/compile.hxml | 2 ++ .../projects/Issue11373/compile.hxml.stdout | 1 + .../projects/Issue11373/pack/BuildMacro.hx | 21 ++++++++++++++ 7 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 tests/misc/projects/Issue11373/Main.hx create mode 100644 tests/misc/projects/Issue11373/compile.hxml create mode 100644 tests/misc/projects/Issue11373/compile.hxml.stdout create mode 100644 tests/misc/projects/Issue11373/pack/BuildMacro.hx diff --git a/src/context/resolution.ml b/src/context/resolution.ml index dd4f7c022e8..2e2de852619 100644 --- a/src/context/resolution.ml +++ b/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) diff --git a/src/core/ast.ml b/src/core/ast.ml index d62f62ecf3d..b2eb7f63649 100644 --- a/src/core/ast.ml +++ b/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) = diff --git a/src/typing/typeloadFields.ml b/src/typing/typeloadFields.ml index e964d3ae775..72c23f2fa89 100644 --- a/src/typing/typeloadFields.ml +++ b/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 diff --git a/tests/misc/projects/Issue11373/Main.hx b/tests/misc/projects/Issue11373/Main.hx new file mode 100644 index 00000000000..7af488a0f9e --- /dev/null +++ b/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()); +} \ No newline at end of file diff --git a/tests/misc/projects/Issue11373/compile.hxml b/tests/misc/projects/Issue11373/compile.hxml new file mode 100644 index 00000000000..b30a755894b --- /dev/null +++ b/tests/misc/projects/Issue11373/compile.hxml @@ -0,0 +1,2 @@ +--main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue11373/compile.hxml.stdout b/tests/misc/projects/Issue11373/compile.hxml.stdout new file mode 100644 index 00000000000..a2290538b2f --- /dev/null +++ b/tests/misc/projects/Issue11373/compile.hxml.stdout @@ -0,0 +1 @@ +Main.hx:17: ClassImport, ClassImportAlias, SubClassImport, SubClassImportAlias \ No newline at end of file diff --git a/tests/misc/projects/Issue11373/pack/BuildMacro.hx b/tests/misc/projects/Issue11373/pack/BuildMacro.hx new file mode 100644 index 00000000000..5237d9e98fe --- /dev/null +++ b/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 { + #if macro + builtTypes.push("" + Context.getLocalClass()); + #end + return null; + } + + macro static public function report() { + builtTypes.sort(Reflect.compare); + return macro $v{builtTypes.join(", ")}; + } +} \ No newline at end of file