Преглед изворни кода

[macro] Catch eval runtime failures when decoding (#11633)

* [eval] Catch runtime exceptions in safe_decode

* [macro] narrow build macro eval failures to individual field (hacky...)

* [tests] add test for 11632

* Less hacky way to retrieve haxe.macro.Field type

* [tests] remove unneeded import
Rudy Ges пре 1 година
родитељ
комит
72175301c3

+ 0 - 1
src/macro/macroApi.ml

@@ -846,7 +846,6 @@ and decode_field v =
 	}
 
 and decode_ctype t =
-	if t = vnull then raise Invalid_expr;
 	let (i,args),p = decode_enum_with_pos t in
 	(match i,args with
 	| 0, [p] ->

+ 12 - 5
src/typing/macroContext.ml

@@ -41,15 +41,20 @@ module HxbWriterConfigWriterEval = HxbWriterConfig.WriterConfigWriter(EvalDataAp
 let macro_interp_cache = ref None
 
 let safe_decode com v expected t p f =
-	try
-		f ()
-	with MacroApi.Invalid_expr ->
+	let raise_decode_error s =
 		let path = [dump_path com;"decoding_error"] in
 		let ch = Path.create_file false ".txt" [] path  in
 		let errors = Interp.handle_decoding_error (output_string ch) v t in
 		List.iter (fun (s,i) -> Printf.fprintf ch "\nline %i: %s" i s) (List.rev errors);
 		close_out ch;
-		raise_typing_error (Printf.sprintf "Expected %s but got %s (see %s.txt for details)" expected (Interp.value_string v) (String.concat "/" path)) p
+		raise_typing_error (Printf.sprintf "%s (see %s.txt for details)" s (String.concat "/" path)) p
+	in
+
+	try f () with
+		| EvalContext.RunTimeException (VString emsg,_,_) ->
+			raise_decode_error (Printf.sprintf "Eval runtime exception: %s" emsg.sstring)
+		| MacroApi.Invalid_expr ->
+			raise_decode_error (Printf.sprintf "Expected %s but got %s" expected (Interp.value_string v))
 
 
 let macro_timer com l =
@@ -960,7 +965,9 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 								| None -> die "" __LOC__
 								| Some (_,_,fields) -> fields)
 							else
-								List.map Interp.decode_field (Interp.decode_array v)
+								let ct = make_ptp_th (mk_type_path ~sub:"Field" (["haxe";"macro"], "Expr")) null_pos in
+								let t = Typeload.load_complex_type mctx false LoadNormal ct in
+								List.map (fun f -> safe_decode ctx.com f "Field" t p (fun () -> Interp.decode_field f)) (Interp.decode_array v)
 						in
 						MSuccess (EVars [mk_evar ~t:(CTAnonymous fields,p) ("fields",null_pos)],p)
 					)

+ 15 - 0
tests/misc/projects/Issue11632/Main.hx

@@ -0,0 +1,15 @@
+#if macro
+import haxe.macro.Expr;
+#end
+
+#if !macro @:build(Macro.build()) #end
+class Main {}
+
+class Macro {
+	public static function build() {
+		var ct = TPath({pack: [], name: "Null", params: [TPType(null)]});
+		return (macro class {
+			var foo:$ct;
+		}).fields;
+	}
+}

+ 6 - 0
tests/misc/projects/Issue11632/Test.hx

@@ -0,0 +1,6 @@
+import sys.io.File;
+
+function main() {
+	var dump = File.getContent("dump/decoding_error.txt");
+	Sys.println(dump);
+}

+ 1 - 0
tests/misc/projects/Issue11632/compile-fail.hxml

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

+ 1 - 0
tests/misc/projects/Issue11632/compile-fail.hxml.stderr

@@ -0,0 +1 @@
+Main.hx:5: characters 12-19 : Eval runtime exception: Null Access (see dump/decoding_error.txt for details)

+ 1 - 0
tests/misc/projects/Issue11632/compile-test.hxml

@@ -0,0 +1 @@
+--run Test

+ 14 - 0
tests/misc/projects/Issue11632/compile-test.hxml.stdout

@@ -0,0 +1,14 @@
+{
+	access: null
+	doc: null
+	kind: FVar(TPath({
+		name: Null
+		pack: []
+		params: [TPType(null <- expected enum value)]
+		sub: null
+	}), null)
+	meta: null
+	name: foo
+	pos: #pos
+}
+line 7: expected enum value