Skip to content

Commit

Permalink
[macro] respect imports on @:build (HaxeFoundation#11373)
Browse files Browse the repository at this point in the history
  • Loading branch information
Simn authored and 0b1kn00b committed Jan 25, 2024
1 parent 6d621da commit f77157a
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 14 deletions.
9 changes: 6 additions & 3 deletions src/context/resolution.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions src/core/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down
29 changes: 21 additions & 8 deletions src/typing/typeloadFields.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
18 changes: 18 additions & 0 deletions tests/misc/projects/Issue11373/Main.hx
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 0 deletions tests/misc/projects/Issue11373/compile.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--main Main
--interp
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11373/compile.hxml.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main.hx:17: ClassImport, ClassImportAlias, SubClassImport, SubClassImportAlias
21 changes: 21 additions & 0 deletions tests/misc/projects/Issue11373/pack/BuildMacro.hx
Original file line number Diff line number Diff line change
@@ -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(", ")};
}
}

0 comments on commit f77157a

Please sign in to comment.