2
0
Эх сурвалжийг харах

[display] properly deal with macro context

* remove special `#if macro` handling
* if we come across a macro field which happens to be the display field (or if we simply want to type macros in general), type the macro (but don't call it)
* recurse into macro context when collecting statistics

closes #6094
closes #6405
Simon Krajewski 7 жил өмнө
parent
commit
a016cc85ad

+ 18 - 7
src/context/display.ml

@@ -577,9 +577,12 @@ module Statistics = struct
 	let collect_statistics ctx =
 		let relations = Hashtbl.create 0 in
 		let symbols = Hashtbl.create 0 in
+		let handled_modules = Hashtbl.create 0 in
 		let add_relation pos r =
 			if pos <> null_pos then try
-				Hashtbl.replace relations pos (r :: Hashtbl.find relations pos)
+				let l = Hashtbl.find relations pos in
+				if not (List.mem r l) then
+					Hashtbl.replace relations pos (r :: l)
 			with Not_found ->
 				Hashtbl.add relations pos [r]
 		in
@@ -675,7 +678,6 @@ module Statistics = struct
 			| TDynamic _ -> ()
 			| TFun _ | TAnon _ -> ()
 		in
-		let handled_modules = Hashtbl.create 0 in
 		let check_module m =
 			if not (Hashtbl.mem handled_modules m.m_path) then begin
 				Hashtbl.add handled_modules m.m_path true;
@@ -715,17 +717,26 @@ module Statistics = struct
 				declare (SKAbstract a) a.a_name_pos
 		in
 		begin match CompilationServer.get () with
-			| None -> List.iter f ctx.com.types
+			| None ->
+				let rec loop com =
+					List.iter f com.types;
+					Option.may loop (com.get_macros())
+				in
+				loop ctx.com
 			| Some cs ->
-				CompilationServer.cache_context cs ctx.com;
-				CompilationServer.iter_modules cs ctx.com (fun m -> List.iter f m.m_types);
+				let rec loop com =
+					CompilationServer.cache_context cs com;
+					CompilationServer.iter_modules cs com (fun m -> List.iter f m.m_types);
+					Option.may loop (com.get_macros())
+				in
+				loop ctx.com
 		end;
 		let l = List.fold_left (fun acc (_,cfi,_,cfo) -> match cfo with
 			| Some cf -> if List.mem_assoc cf.cf_name_pos acc then acc else (cf.cf_name_pos,cfi.cf_name_pos) :: acc
 			| None -> acc
 		) [] ctx.com.display_information.interface_field_implementations in
 		List.iter (fun (p,p') -> add_relation p' (Implemented,p)) l;
-		let deal_with_imports paths =
+		(* let deal_with_imports paths =
 			let check_subtype m s p =
 				try
 					let mt = List.find (fun mt -> snd (t_infos mt).mt_path = s) m.m_types in
@@ -765,6 +776,6 @@ module Statistics = struct
 					()
 			) paths
 		in
-		if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions;
+		if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions; *)
 		symbols,relations
 end

+ 4 - 1
src/context/displayTypes.ml

@@ -232,6 +232,7 @@ module DisplayMode = struct
 		| DMDefault | DMDefinition | DMResolve _ | DMPackage | DMHover | DMSignature -> settings
 		| DMUsage _ -> { settings with
 				dms_full_typing = true;
+				dms_force_macro_typing = true;
 				dms_collect_data = true;
 				dms_display_file_policy = DFPAlso;
 				dms_exit_during_typing = false
@@ -246,6 +247,7 @@ module DisplayMode = struct
 				dms_error_policy = EPCollect;
 				dms_collect_data = true;
 				dms_inline = true;
+				dms_force_macro_typing = true;
 				dms_display_file_policy = if global then DFPNo else DFPAlso;
 				dms_exit_during_typing = false;
 			}
@@ -254,7 +256,8 @@ module DisplayMode = struct
 				dms_collect_data = true;
 				dms_inline = false;
 				dms_display_file_policy = DFPAlso;
-				dms_exit_during_typing = false
+				dms_exit_during_typing = false;
+				dms_force_macro_typing = true;
 			}
 
 	let to_string = function

+ 1 - 1
src/syntax/parserEntry.ml

@@ -124,7 +124,7 @@ let parse ctx code =
 	and enter_macro p =
 		let tk, e = parse_macro_cond sraw in
 		let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in
-		if is_true (eval ctx e) || (match fst e with EConst (Ident "macro") when Path.unique_full_path p.pfile = (!resume_display).pfile -> true | _ -> false) then begin
+		if is_true (eval ctx e) then begin
 			mstack := p :: !mstack;
 			tk
 		end else

+ 2 - 0
src/typing/typeloadFields.ml

@@ -943,6 +943,8 @@ let create_method (ctx,cctx,fctx) c f fd p =
 		cf_params = params;
 		cf_extern = fctx.is_extern;
 	} in
+	if fctx.is_macro && (ctx.com.display.dms_force_macro_typing || fctx.is_display_field) then
+		delay ctx PTypeField (fun() -> try ignore(ctx.g.do_macro ctx MDisplay c.cl_path cf.cf_name [] p) with Exit | Error _ -> ());
 	cf.cf_meta <- List.map (fun (m,el,p) -> match m,el with
 		| Meta.AstSource,[] -> (m,(match fd.f_expr with None -> [] | Some e -> [e]),p)
 		| _ -> m,el,p

+ 27 - 0
tests/display/src/cases/Issue6405.hx

@@ -0,0 +1,27 @@
+package cases;
+
+class Issue6405 extends DisplayTestCase {
+	/**
+	import haxe.macro.Expr;
+	import haxe.macro.Context;
+	using haxe.macro.ExprTools;
+
+	class Macros {
+
+		public static macro function makeTypeDef( {-2-}e{-3-} : Expr ) {
+			var t = Context.getType({-1-}e{-5-}.{-4-}toString());
+			return macro {};
+		}
+
+	}
+	**/
+	function test() {
+		eq(range(2, 3), position(pos(1)));
+		var usage = usage(pos(2));
+		arrayEq([range(1, 5)], usage);
+		eq("haxe.macro.Expr", type(pos(1)));
+		var fields = fields(pos(4));
+		eq(true, hasField(fields, "expr", "haxe.macro.ExprDef"));
+		eq(true, hasField(fields, "toString", "Void -> String"));
+	}
+}