Selaa lähdekoodia

[display] fix `#if macro` situations if there is no macro

Simon Krajewski 7 vuotta sitten
vanhempi
commit
37cca18db2

+ 7 - 5
src/compiler/displayOutput.ml

@@ -745,26 +745,28 @@ let process_display_file com classes =
 	in
 	in
 	match com.display.dms_display_file_policy with
 	match com.display.dms_display_file_policy with
 		| DFPNo ->
 		| DFPNo ->
-			()
+			None
 		| dfp ->
 		| dfp ->
 			if dfp = DFPOnly then begin
 			if dfp = DFPOnly then begin
 				classes := [];
 				classes := [];
 				com.main_class <- None;
 				com.main_class <- None;
 			end;
 			end;
 			let real = Path.get_real_path (!Parser.resume_display).pfile in
 			let real = Path.get_real_path (!Parser.resume_display).pfile in
-			(match get_module_path_from_file_path com real with
+			let path = match get_module_path_from_file_path com real with
 			| Some path ->
 			| Some path ->
 				if com.display.dms_kind = DMPackage then raise (DisplayPackage (fst path));
 				if com.display.dms_kind = DMPackage then raise (DisplayPackage (fst path));
-				classes := path :: !classes
+				classes := path :: !classes;
+				Some path
 			| None ->
 			| None ->
 				if not (Sys.file_exists real) then failwith "Display file does not exist";
 				if not (Sys.file_exists real) then failwith "Display file does not exist";
 				(match List.rev (ExtString.String.nsplit real Path.path_sep) with
 				(match List.rev (ExtString.String.nsplit real Path.path_sep) with
 				| file :: _ when file.[0] >= 'a' && file.[0] <= 'z' -> failwith ("Display file '" ^ file ^ "' should not start with a lowercase letter")
 				| file :: _ when file.[0] >= 'a' && file.[0] <= 'z' -> failwith ("Display file '" ^ file ^ "' should not start with a lowercase letter")
 				| _ -> ());
 				| _ -> ());
 				failwith "Display file was not found in class path"
 				failwith "Display file was not found in class path"
-			);
+			in
 			Common.log com ("Display file : " ^ real);
 			Common.log com ("Display file : " ^ real);
-			Common.log com ("Classes found : ["  ^ (String.concat "," (List.map s_type_path !classes)) ^ "]")
+			Common.log com ("Classes found : ["  ^ (String.concat "," (List.map s_type_path !classes)) ^ "]");
+			path
 
 
 let process_global_display_mode com tctx = match com.display.dms_kind with
 let process_global_display_mode com tctx = match com.display.dms_kind with
 	| DMUsage with_definition ->
 	| DMUsage with_definition ->

+ 22 - 1
src/compiler/main.ml

@@ -803,7 +803,7 @@ try
 		with _ ->
 		with _ ->
 			() (* ignore *)
 			() (* ignore *)
 	end;
 	end;
-	DisplayOutput.process_display_file com classes;
+	let display_file_dot_path = DisplayOutput.process_display_file com classes in
 	let ext = Initialize.initialize_target ctx com classes in
 	let ext = Initialize.initialize_target ctx com classes in
 	(* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *)
 	(* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *)
 	if com.display.dms_display then begin match com.display.dms_kind with
 	if com.display.dms_display then begin match com.display.dms_kind with
@@ -826,8 +826,21 @@ try
 		Finalization.finalize tctx;
 		Finalization.finalize tctx;
 		t();
 		t();
 		if not ctx.com.display.dms_display && ctx.has_error then raise Abort;
 		if not ctx.com.display.dms_display && ctx.has_error then raise Abort;
+		(* TODO: We don't want this to cause any errors. Needs proper exception handling that doesn't swallow display exceptions... *)
+		let load_display_module_in_macro () = match display_file_dot_path with
+			| Some cpath ->
+				let p = null_pos in
+				let _ = MacroContext.load_macro_module tctx cpath true p in
+				let _, mctx = MacroContext.get_macro_context tctx p in
+				Finalization.finalize mctx;
+				Some mctx
+			| None ->
+				None
+		in
 		if ctx.com.display.dms_exit_during_typing then begin
 		if ctx.com.display.dms_exit_during_typing then begin
 			if ctx.has_next || ctx.has_error then raise Abort;
 			if ctx.has_next || ctx.has_error then raise Abort;
+			(* If we didn't find a completion point, load the display file in macro mode. *)
+			ignore(load_display_module_in_macro ());
 			failwith "No completion point was found";
 			failwith "No completion point was found";
 		end;
 		end;
 		let t = Timer.timer ["filters"] in
 		let t = Timer.timer ["filters"] in
@@ -835,6 +848,14 @@ try
 		com.main <- main;
 		com.main <- main;
 		com.types <- types;
 		com.types <- types;
 		com.modules <- modules;
 		com.modules <- modules;
+		if ctx.com.display.dms_force_macro_typing then begin match load_display_module_in_macro () with
+			| None -> ()
+			| Some mctx ->
+				(* We don't need a full macro flush here because we're not going to run any macros. *)
+				let _, types, modules = Finalization.generate mctx in
+				mctx.Typecore.com.types <- types;
+				mctx.Typecore.com.Common.modules <- modules
+		end;
 		DisplayOutput.process_global_display_mode com tctx;
 		DisplayOutput.process_global_display_mode com tctx;
 		if not (Common.defined com Define.NoDeprecationWarnings) then
 		if not (Common.defined com Define.NoDeprecationWarnings) then
 			Display.DeprecationCheck.run com;
 			Display.DeprecationCheck.run com;

+ 19 - 14
src/typing/macroContext.ml

@@ -519,6 +519,23 @@ let get_macro_context ctx p =
 		create_macro_interp ctx mctx;
 		create_macro_interp ctx mctx;
 		api, mctx
 		api, mctx
 
 
+let load_macro_module ctx cpath display p =
+	let api, mctx = get_macro_context ctx p in
+	let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in
+	(* Temporarily enter display mode while typing the macro. *)
+	if display then mctx.com.display <- ctx.com.display;
+	let mloaded = TypeloadModule.load_module mctx m p in
+	api.MacroApi.current_macro_module <- (fun() -> mloaded);
+	mctx.m <- {
+		curmod = mloaded;
+		module_types = [];
+		module_using = [];
+		module_globals = PMap.empty;
+		wildcard_packages = [];
+		module_imports = [];
+	};
+	mloaded
+
 let load_macro ctx display cpath f p =
 let load_macro ctx display cpath f p =
 	let api, mctx = get_macro_context ctx p in
 	let api, mctx = get_macro_context ctx p in
 	let mint = Interp.get_ctx() in
 	let mint = Interp.get_ctx() in
@@ -528,20 +545,7 @@ let load_macro ctx display cpath f p =
 	) in
 	) in
 	let meth = try Hashtbl.find mctx.com.cached_macros (cpath,f) with Not_found ->
 	let meth = try Hashtbl.find mctx.com.cached_macros (cpath,f) with Not_found ->
 		let t = macro_timer ctx ["typing";s_type_path cpath ^ "." ^ f] in
 		let t = macro_timer ctx ["typing";s_type_path cpath ^ "." ^ f] in
-		(* Temporarily enter display mode while typing the macro. *)
-		if display then mctx.com.display <- ctx.com.display;
-		let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in
-		let mloaded = TypeloadModule.load_module mctx m p in
-		api.MacroApi.current_macro_module <- (fun() -> mloaded);
-		mctx.m <- {
-			curmod = mloaded;
-			module_types = [];
-			module_using = [];
-			module_globals = PMap.empty;
-			wildcard_packages = [];
-			module_imports = [];
-		};
-		add_dependency ctx.m.curmod mloaded;
+		let mloaded = load_macro_module ctx cpath display p in
 		let mt = Typeload.load_type_def mctx p { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = sub } in
 		let mt = Typeload.load_type_def mctx p { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = sub } in
 		let cl, meth = (match mt with
 		let cl, meth = (match mt with
 			| TClassDecl c ->
 			| TClassDecl c ->
@@ -549,6 +553,7 @@ let load_macro ctx display cpath f p =
 				c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p)
 				c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p)
 			| _ -> error "Macro should be called on a class" p
 			| _ -> error "Macro should be called on a class" p
 		) in
 		) in
+		api.MacroApi.current_macro_module <- (fun() -> mloaded);
 		if not (Common.defined ctx.com Define.NoDeprecationWarnings) then
 		if not (Common.defined ctx.com Define.NoDeprecationWarnings) then
 			Display.DeprecationCheck.check_cf mctx.com meth p;
 			Display.DeprecationCheck.check_cf mctx.com meth p;
 		let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in
 		let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in

+ 37 - 0
tests/display/src/cases/InMacro.hx

@@ -0,0 +1,37 @@
+package cases;
+
+class InMacro extends DisplayTestCase {
+	/**
+
+	import haxe.macro.Context;
+
+	class Main {
+
+		#if macro
+
+		static function buildTypeDef( {-4-}t{-5-} : haxe.macro.Type ) : Expr {
+			Context.error("Unsupp{-1-}orted type "+Std.string({-2-}t{-3-}),Context.currentPos());
+			return null;
+		}
+
+		#else
+
+		static function buildTypeDef( {-14-}t{-15-} : haxe.macro.Type) : Expr {
+			trace("not{-11-} a macro" + {-12-}t{-13-});
+			return null;
+		}
+
+		#end
+	}
+	**/
+	function testMacro1() {
+		eq("String", type(pos(1)));
+		arrayEq([range(2, 3)], usage(pos(4)));
+		eq(range(4, 5), position(pos(2)));
+
+		eq("String", type(pos(11)));
+		arrayEq([range(12, 13)], usage(pos(14)));
+		eq(range(14, 15), position(pos(12)));
+	}
+
+}