فهرست منبع

add diagnostics display mode with unused import detection (closes #5170)

Simon Krajewski 9 سال پیش
والد
کامیت
8e7f732760
6فایلهای تغییر یافته به همراه186 افزوده شده و 74 حذف شده
  1. 41 5
      src/display/display.ml
  2. 10 4
      src/main.ml
  3. 16 0
      src/typing/common.ml
  4. 5 5
      src/typing/typecore.ml
  5. 85 42
      src/typing/typeload.ml
  6. 29 18
      src/typing/typer.ml

+ 41 - 5
src/display/display.ml

@@ -18,6 +18,7 @@ type identifier_type =
 	| ITType of module_type
 	| ITPackage of string
 
+exception Diagnostics of string
 exception ModuleSymbols of string
 exception DisplaySignatures of (t * documentation) list
 exception DisplayType of t * pos
@@ -26,10 +27,6 @@ exception DisplaySubExpression of Ast.expr
 exception DisplayFields of (string * t * display_field_kind option * documentation) list
 exception DisplayToplevel of identifier_type list
 
-let requires_full_typing = function
-	| DMUsage | DMNone -> true
-	| DMPosition | DMResolve _ | DMDefault | DMModuleSymbols | DMToplevel | DMType -> false
-
 let is_display_file p =
 	Common.unique_full_path p.pfile = (!Parser.resume_display).pfile
 
@@ -332,4 +329,43 @@ let convert_import_to_something_usable path =
 let process_expr com e = match com.display with
 	| DMToplevel -> find_enclosing com e
 	| DMPosition | DMUsage | DMType -> find_before_pos com e
-	| _ -> e
+	| _ -> e
+
+let add_import_position com p =
+	com.shared.display_information.import_positions <- PMap.add p (ref false) com.shared.display_information.import_positions
+
+let mark_import_position com p =
+	try
+		if not (is_display_file p) then raise Not_found;
+		let r = PMap.find p com.shared.display_information.import_positions in
+		r := true
+	with Not_found ->
+		()
+
+module DiagnosticsKind = struct
+	type t =
+		| DKUnusedImport
+
+	let to_int = function
+		| DKUnusedImport -> 0
+end
+
+module Diagnostics = struct
+	open DiagnosticsKind
+
+	type t = DiagnosticsKind.t * pos
+
+	let print_diagnostics com =
+		let diag = DynArray.create() in
+		PMap.iter (fun p r ->
+			if not !r then DynArray.add diag (DKUnusedImport,p)
+		) com.shared.display_information.import_positions;
+		let jl = DynArray.fold_left (fun acc (dk,p) ->
+			(JObject ["kind",JInt (to_int dk);"range",pos_to_json_range p]) :: acc
+		) [] diag in
+		let js = JArray jl in
+		let b = Buffer.create 0 in
+		write_json (Buffer.add_string b) js;
+		Buffer.contents b
+end
+

+ 10 - 4
src/main.ml

@@ -1276,6 +1276,9 @@ try
 					| "module-symbols" ->
 						Common.define com Define.NoCOpt;
 						DMModuleSymbols;
+					| "diagnostics" ->
+						Common.define com Define.NoCOpt;
+						DMDiagnostics;
 					| "" ->
 						DMDefault
 					| _ ->
@@ -1566,9 +1569,12 @@ try
 		Typer.finalize tctx;
 		t();
 		if ctx.has_error then raise Abort;
-		if not (Display.requires_full_typing ctx.com.display) then begin
-			if ctx.has_next then raise Abort;
-			failwith "No completion point was found";
+		begin match ctx.com.display with
+			| DMNone | DMUsage ->
+				()
+			| _ ->
+				if ctx.has_next then raise Abort;
+				failwith "No completion point was found";
 		end;
 		let t = Common.timer "filters" in
 		let main, types, modules = Typer.generate tctx in
@@ -1823,7 +1829,7 @@ with
 				raise (Completion c)
 			| _ ->
 				error ctx ("Could not load module " ^ (Ast.s_type_path (p,c))) Ast.null_pos)
-	| Display.ModuleSymbols s ->
+	| Display.ModuleSymbols s | Display.Diagnostics s ->
 		raise (Completion s)
 	| Interp.Sys_exit i ->
 		ctx.flush();

+ 16 - 0
src/typing/common.ml

@@ -99,6 +99,7 @@ type display_mode =
 	| DMResolve of string
 	| DMType
 	| DMModuleSymbols
+	| DMDiagnostics
 
 type compiler_callback = {
 	mutable after_typing : (module_type list -> unit) list;
@@ -106,10 +107,20 @@ type compiler_callback = {
 	mutable after_generation : (unit -> unit) list;
 }
 
+type display_information = {
+	mutable import_positions : (pos,bool ref) PMap.t;
+}
+
+(* This information is shared between normal and macro context. *)
+type shared_context = {
+	display_information : display_information;
+}
+
 type context = {
 	(* config *)
 	version : int;
 	args : string list;
+	shared : shared_context;
 	mutable sys_args : string list;
 	mutable display : display_mode;
 	mutable debug : bool;
@@ -667,6 +678,11 @@ let create version s_version args =
 	{
 		version = version;
 		args = args;
+		shared = {
+			display_information = {
+				import_positions = PMap.empty;
+			}
+		};
 		sys_args = args;
 		debug = false;
 		display = !display_default;

+ 5 - 5
src/typing/typecore.ml

@@ -55,10 +55,10 @@ type typer_pass =
 
 type typer_module = {
 	curmod : module_def;
-	mutable module_types : module_type list;
-	mutable module_using : tclass list;
-	mutable module_globals : (string, (module_type * string)) PMap.t;
-	mutable wildcard_packages : string list list;
+	mutable module_types : (module_type * pos) list;
+	mutable module_using : (tclass * pos) list;
+	mutable module_globals : (string, (module_type * string * pos)) PMap.t;
+	mutable wildcard_packages : (string list * pos) list;
 	mutable module_imports : Ast.import list;
 }
 
@@ -76,7 +76,7 @@ type typer_globals = {
 	mutable global_metadata : (string list * Ast.metadata_entry * (bool * bool * bool)) list;
 	mutable get_build_infos : unit -> (module_type * t list * Ast.class_field list) option;
 	delayed_macros : (unit -> unit) DynArray.t;
-	mutable global_using : tclass list;
+	mutable global_using : (tclass * Ast.pos) list;
 	(* api *)
 	do_inherit : typer -> Type.tclass -> Ast.pos -> (bool * Ast.placed_type_path) -> bool;
 	do_create : Common.context -> typer;

+ 85 - 42
src/typing/typeload.ml

@@ -298,10 +298,16 @@ let rec load_type_def ctx p t =
 	let tname = (match t.tsub with None -> t.tname | Some n -> n) in
 	try
 		if t.tsub <> None then raise Not_found;
-		List.find (fun t2 ->
+		let path_matches t2 =
 			let tp = t_path t2 in
 			tp = (t.tpackage,tname) || (no_pack && snd tp = tname)
-		) (ctx.m.curmod.m_types @ ctx.m.module_types)
+		in
+		try
+			List.find path_matches ctx.m.curmod.m_types
+		with Not_found ->
+			let t,pi = List.find (fun (t2,pi) -> path_matches t2) ctx.m.module_types in
+			Display.mark_import_position ctx.com pi;
+			t
 	with
 		Not_found ->
 			let next() =
@@ -323,11 +329,13 @@ let rec load_type_def ctx p t =
 			(* lookup in wildcard imported packages *)
 			try
 				if not no_pack then raise Exit;
-				let rec loop = function
+				let rec loop l = match l with
 					| [] -> raise Exit
-					| wp :: l ->
+					| (wp,pi) :: l ->
 						try
-							load_type_def ctx p { t with tpackage = wp }
+							let t = load_type_def ctx p { t with tpackage = wp } in
+							Display.mark_import_position ctx.com pi;
+							t
 						with
 							| Error (Module_not_found _,p2)
 							| Error (Type_not_found _,p2) when p == p2 -> loop l
@@ -1463,8 +1471,14 @@ module Inheritance = struct
 			| _ :: _ -> t,p
 			| [] ->
 				try
-					let find = List.find (fun lt -> snd (t_path lt) = t.tname) in
-					let lt = try find ctx.m.curmod.m_types with Not_found -> find ctx.m.module_types in
+					let path_matches lt = snd (t_path lt) = t.tname in
+					let lt = try
+						List.find path_matches ctx.m.curmod.m_types
+					with Not_found ->
+						let t,pi = List.find (fun (lt,_) -> path_matches lt) ctx.m.module_types in
+						Display.mark_import_position ctx.com pi;
+						t
+					in
 					{ t with tpackage = fst (t_path lt) },p
 				with
 					Not_found -> t,p
@@ -2099,7 +2113,17 @@ module ClassInitializer = struct
 			| TMono r -> (match !r with None -> false | Some t -> is_full_type t)
 			| TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true
 		in
-		if Display.requires_full_typing ctx.com.display then begin
+		let handle_display_field () =
+			if fctx.is_macro && not ctx.in_macro then
+				(* force macro system loading of this class in order to get completion *)
+				delay ctx PTypeField (fun() -> try ignore(ctx.g.do_macro ctx MDisplay c.cl_path cf.cf_name [] p) with Exit -> ())
+			else begin
+				cf.cf_type <- TLazy r;
+				cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr;
+			end
+		in
+		begin match ctx.com.display with
+			| DMNone | DMUsage ->
 				if fctx.is_macro && not ctx.in_macro then
 					()
 				else begin
@@ -2107,21 +2131,17 @@ module ClassInitializer = struct
 					(* is_lib ? *)
 					cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr;
 				end
-		end else begin
-			if fctx.is_display_field then begin
-				if fctx.is_macro && not ctx.in_macro then
-					(* force macro system loading of this class in order to get completion *)
-					delay ctx PTypeField (fun() -> ignore(ctx.g.do_macro ctx MDisplay c.cl_path cf.cf_name [] p))
-				else begin
-					cf.cf_type <- TLazy r;
-					cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr;
+			| DMDiagnostics ->
+				handle_display_field()
+			| _ ->
+				if fctx.is_display_field then begin
+					handle_display_field()
+				end else begin
+					if not (is_full_type cf.cf_type) then begin
+						cctx.delayed_expr <- (ctx, None) :: cctx.delayed_expr;
+						cf.cf_type <- TLazy r;
+					end;
 				end
-			end else begin
-				if not (is_full_type cf.cf_type) then begin
-					cctx.delayed_expr <- (ctx, None) :: cctx.delayed_expr;
-					cf.cf_type <- TLazy r;
-				end;
-			end
 		end
 
 	let bind_var (ctx,cctx,fctx) cf e =
@@ -2827,7 +2847,6 @@ module ClassInitializer = struct
 			| None -> ()
 			| Some r -> delay ctx PTypeField (fun() -> ignore((!r)())))
 		) cctx.delayed_expr
-
 end
 
 let resolve_typedef t =
@@ -2896,7 +2915,10 @@ let init_module_type ctx context_init do_init (decl,p) =
 	match decl with
 	| EImport (path,mode) ->
 		ctx.m.module_imports <- (path,mode) :: ctx.m.module_imports;
-		if Display.is_display_file p then handle_path_display ctx path p;
+		if Display.is_display_file p then begin
+			Display.add_import_position ctx.com p;
+			handle_path_display ctx path p;
+		end;
 		let rec loop acc = function
 			| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 			| rest -> List.rev acc, rest
@@ -2906,7 +2928,7 @@ let init_module_type ctx context_init do_init (decl,p) =
 		| [] ->
 			(match mode with
 			| IAll ->
-				ctx.m.wildcard_packages <- List.map fst pack :: ctx.m.wildcard_packages
+				ctx.m.wildcard_packages <- (List.map fst pack,p) :: ctx.m.wildcard_packages
 			| _ ->
 				(match List.rev path with
 				| [] -> assert false
@@ -2916,7 +2938,7 @@ let init_module_type ctx context_init do_init (decl,p) =
 			let p_type = punion p1 p2 in
 			let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in
 			let types = md.m_types in
-			let no_private t = not (t_infos t).mt_private in
+			let no_private (t,_) = not (t_infos t).mt_private in
 			let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in
 			let has_name name t = snd (t_infos t).mt_path = name in
 			let get_type tname =
@@ -2946,10 +2968,10 @@ let init_module_type ctx context_init do_init (decl,p) =
 				| TClassDecl c ->
 					ignore(c.cl_build());
 					ignore(PMap.find s c.cl_statics);
-					ctx.m.module_globals <- PMap.add name (TClassDecl c,s) ctx.m.module_globals
+					ctx.m.module_globals <- PMap.add name (TClassDecl c,s,p) ctx.m.module_globals
 				| TEnumDecl e ->
 					ignore(PMap.find s e.e_constrs);
-					ctx.m.module_globals <- PMap.add name (TEnumDecl e,s) ctx.m.module_globals
+					ctx.m.module_globals <- PMap.add name (TEnumDecl e,s,p) ctx.m.module_globals
 				| _ ->
 					raise Not_found
 			in
@@ -2960,15 +2982,15 @@ let init_module_type ctx context_init do_init (decl,p) =
 				| [] ->
 					(match name with
 					| None ->
-						ctx.m.module_types <- List.filter no_private types @ ctx.m.module_types
+						ctx.m.module_types <- List.filter no_private (List.map (fun t -> t,p) types) @ ctx.m.module_types
 					| Some newname ->
-						ctx.m.module_types <- rebind (get_type tname) newname :: ctx.m.module_types);
+						ctx.m.module_types <- (rebind (get_type tname) newname,p) :: ctx.m.module_types);
 				| [tsub,p2] ->
-					let p = punion p1 p2 in
+					let pu = punion p1 p2 in
 					(try
 						let tsub = List.find (has_name tsub) types in
-						chk_private tsub p;
-						ctx.m.module_types <- (match name with None -> tsub | Some n -> rebind tsub n) :: ctx.m.module_types
+						chk_private tsub pu;
+						ctx.m.module_types <- ((match name with None -> tsub | Some n -> rebind tsub n),p) :: ctx.m.module_types
 					with Not_found ->
 						(* this might be a static property, wait later to check *)
 						let tmain = get_type tname in
@@ -3001,15 +3023,18 @@ let init_module_type ctx context_init do_init (decl,p) =
 					| TClassDecl c
 					| TAbstractDecl {a_impl = Some c} ->
 						ignore(c.cl_build());
-						PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name) ctx.m.module_globals) c.cl_statics
+						PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals) c.cl_statics
 					| TEnumDecl e ->
-						PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name) ctx.m.module_globals) e.e_constrs
+						PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name,p) ctx.m.module_globals) e.e_constrs
 					| _ ->
 						error "No statics to import from this type" p
 				) :: !context_init
 			))
 	| EUsing path ->
-		if Display.is_display_file p then handle_path_display ctx path p;
+		if Display.is_display_file p then begin
+			Display.add_import_position ctx.com p;
+			handle_path_display ctx path p;
+		end;
 		let t = match List.rev path with
 			| (s1,_) :: (s2,_) :: sl ->
 				if is_lower_ident s2 then { tpackage = (List.rev (s2 :: List.map fst sl)); tname = s1; tsub = None; tparams = [] }
@@ -3024,11 +3049,11 @@ let init_module_type ctx context_init do_init (decl,p) =
 			| None ->
 				let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in
 				let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in
-				ctx.m.module_types <- types @ ctx.m.module_types;
+				ctx.m.module_types <- (List.map (fun t -> t,p) types) @ ctx.m.module_types;
 				types
 			| Some _ ->
 				let t = load_type_def ctx p t in
-				ctx.m.module_types <- t :: ctx.m.module_types;
+				ctx.m.module_types <- (t,p) :: ctx.m.module_types;
 				[t]
 		) in
 		(* delay the using since we need to resolve typedefs *)
@@ -3037,7 +3062,7 @@ let init_module_type ctx context_init do_init (decl,p) =
 				| td :: l ->
 					(match resolve_typedef td with
 					| TClassDecl c | TAbstractDecl({a_impl = Some c}) ->
-						loop (c :: acc) l
+						loop ((c,p) :: acc) l
 					| td ->
 						loop acc l)
 				| [] ->
@@ -3370,7 +3395,7 @@ let type_types_into_module ctx m tdecls p =
 		t = ctx.t;
 		m = {
 			curmod = m;
-			module_types = ctx.g.std.m_types;
+			module_types = List.map (fun t -> t,null_pos) ctx.g.std.m_types;
 			module_using = [];
 			module_globals = PMap.empty;
 			wildcard_packages = [];
@@ -3452,6 +3477,24 @@ let type_module ctx mpath file ?(is_extern=false) tdecls p =
 	let tdecls = handle_import_hx ctx m tdecls p in
 	type_types_into_module ctx m tdecls p;
 	if is_extern then m.m_extra.m_kind <- MExtern;
+	begin if Common.unique_full_path file = (!Parser.resume_display).pfile then match ctx.com.display with
+		| DMDiagnostics ->
+			List.iter (fun mt -> match mt with
+				| TClassDecl c | TAbstractDecl({a_impl = Some c}) ->
+					ignore(c.cl_build());
+					let field cf =
+						ignore(follow cf.cf_type);
+					in
+					List.iter field c.cl_ordered_fields;
+					List.iter field c.cl_ordered_statics;
+					(match c.cl_constructor with None -> () | Some cf -> field cf);
+				| _ ->
+					()
+			) m.m_types;
+			raise (Display.Diagnostics (Display.Diagnostics.print_diagnostics ctx.com))
+		| _ ->
+			()
+	end;
 	m
 
 let resolve_module_file com m remap p =
@@ -3799,7 +3842,7 @@ let rec build_generic ctx c p tl =
 		load_instance ctx ({ tpackage = pack; tname = name; tparams = []; tsub = None },p) false p
 	with Error(Module_not_found path,_) when path = (pack,name) ->
 		let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in
-		let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in
+		(* let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in *)
 		ignore(c.cl_build()); (* make sure the super class is already setup *)
 		let mg = {
 			m_id = alloc_mid();
@@ -4028,7 +4071,7 @@ let get_macro_path ctx e args p =
 				if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found;
 				ctx.curclass.cl_path
 			with Not_found -> try
-				(t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path
+				(t_infos (let path,_,_ = PMap.find i ctx.m.module_globals in path)).mt_path
 			with Not_found ->
 				error "Invalid macro call" p
 			in

+ 29 - 18
src/typing/typer.ml

@@ -412,10 +412,10 @@ let collect_toplevel_identifiers ctx =
 			) e.e_constrs;
 	in
 	List.iter enum_ctors ctx.m.curmod.m_types;
-	List.iter enum_ctors ctx.m.module_types;
+	List.iter enum_ctors (List.map fst ctx.m.module_types);
 
 	(* imported globals *)
-	PMap.iter (fun _ (mt,s) ->
+	PMap.iter (fun _ (mt,s,_) ->
 		try
 			let t = match Typeload.resolve_typedef mt with
 				| TClassDecl c -> (PMap.find s c.cl_statics).cf_type
@@ -442,10 +442,10 @@ let collect_toplevel_identifiers ctx =
 	List.iter add_type ctx.m.curmod.m_types;
 
 	(* module imports *)
-	List.iter add_type ctx.m.module_types;
+	List.iter add_type (List.map fst ctx.m.module_types);
 
 	(* module using *)
-	List.iter (fun c ->
+	List.iter (fun (c,_) ->
 		add_type (TClassDecl c)
 	) ctx.m.module_using;
 
@@ -1244,7 +1244,7 @@ let rec using_field ctx mode e i p =
 	let rec loop = function
 	| [] ->
 		raise Not_found
-	| c :: l ->
+	| (c,pc) :: l ->
 		try
 			let cf = PMap.find i c.cl_statics in
 			if Meta.has Meta.NoUsing cf.cf_meta || not (can_access ctx c cf true) then raise Not_found;
@@ -1262,6 +1262,7 @@ let rec using_field ctx mode e i p =
 						| _ -> ()
 					) monos cf.cf_params;
 					let et = type_module_type ctx (TClassDecl c) None p in
+					Display.mark_import_position ctx.com pc;
 					AKUsing (mk (TField (et,FStatic (c,cf))) t p,c,cf,e)
 				| _ ->
 					raise Not_found
@@ -1371,7 +1372,7 @@ let rec type_ident_raise ctx i p mode =
 		let rec loop l =
 			match l with
 			| [] -> raise Not_found
-			| t :: l ->
+			| (t,pt) :: l ->
 				match t with
 				| TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta ->
 					begin try
@@ -1382,6 +1383,7 @@ let rec type_ident_raise ctx i p mode =
 							let et = type_module_type ctx (TClassDecl c) None p in
 							let fa = FStatic(c,cf) in
 							let t = monomorphs cf.cf_params cf.cf_type in
+							Display.mark_import_position ctx.com pt;
 							begin match cf.cf_kind with
 								| Var {v_read = AccInline} -> AKInline(et,cf,fa,t)
 								| _ -> AKExpr (mk (TField(et,fa)) t p)
@@ -1394,7 +1396,7 @@ let rec type_ident_raise ctx i p mode =
 					loop l
 				| TTypeDecl t ->
 					(match follow t.t_type with
-					| TEnum (e,_) -> loop ((TEnumDecl e) :: l)
+					| TEnum (e,_) -> loop ((TEnumDecl e,pt) :: l)
 					| _ -> loop l)
 				| TEnumDecl e ->
 					try
@@ -1402,14 +1404,16 @@ let rec type_ident_raise ctx i p mode =
 						let et = type_module_type ctx t None p in
 						let monos = List.map (fun _ -> mk_mono()) e.e_params in
 						let monos2 = List.map (fun _ -> mk_mono()) ef.ef_params in
+						Display.mark_import_position ctx.com pt;
 						wrap (mk (TField (et,FEnum (e,ef))) (enum_field_type ctx e ef monos monos2 p) p)
 					with
 						Not_found -> loop l
 		in
-		(try loop (List.rev ctx.m.curmod.m_types) with Not_found -> loop ctx.m.module_types)
+		(try loop (List.rev_map (fun t -> t,null_pos) ctx.m.curmod.m_types) with Not_found -> loop ctx.m.module_types)
 	with Not_found ->
 		(* lookup imported globals *)
-		let t, name = PMap.find i ctx.m.module_globals in
+		let t, name, pi = PMap.find i ctx.m.module_globals in
+		Display.mark_import_position ctx.com pi;
 		let e = type_module_type ctx t None p in
 		type_field ctx e name p mode
 
@@ -2696,7 +2700,14 @@ and handle_efield ctx e p mode =
 					(match pack with
 					| [] ->
 						(try
-							let t = List.find (fun t -> snd (t_infos t).mt_path = name) (ctx.m.curmod.m_types @ ctx.m.module_types) in
+							let path_match t = snd (t_infos t).mt_path = name in
+							let t = try
+								List.find path_match ctx.m.curmod.m_types
+							with Not_found ->
+								let t,p = List.find (fun (t,_) -> path_match t) ctx.m.module_types in
+								Display.mark_import_position ctx.com p;
+								t
+							in
 							(* if the static is not found, look for a subtype instead - #1916 *)
 							get_static true t
 						with Not_found ->
@@ -3868,7 +3879,7 @@ and handle_display ctx e_ast iscall with_type =
 		raise (Display.DisplayPosition pl);
 	| DMToplevel ->
 		collect_toplevel_identifiers ctx;
-	| DMDefault | DMNone | DMModuleSymbols ->
+	| DMDefault | DMNone | DMModuleSymbols | DMDiagnostics ->
 		let opt_args args ret = TFun(List.map(fun (n,o,t) -> n,true,t) args,ret) in
 		let e,tl_overloads,doc = match e.eexpr with
 			| TField (e1,fa) ->
@@ -3932,7 +3943,7 @@ and handle_display ctx e_ast iscall with_type =
 				loop c params
 			| TAbstract({a_impl = Some c} as a,pl) ->
 				if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc c;
-				ctx.m.module_using <- c :: ctx.m.module_using;
+				ctx.m.module_using <- (c,null_pos) :: ctx.m.module_using;
 				let fields = try
 					let _,el,_ = Meta.get Meta.Forward a.a_meta in
 					let sl = ExtList.List.filter_map (fun e -> match fst e with
@@ -3987,7 +3998,7 @@ and handle_display ctx e_ast iscall with_type =
 		*)
 		let rec loop acc = function
 			| [] -> acc
-			| c :: l ->
+			| (c,_) :: l ->
 				let acc = ref (loop acc l) in
 				let rec dup t = Type.map dup t in
 				List.iter (fun f ->
@@ -4731,7 +4742,7 @@ let make_macro_api ctx p =
 			ctx.curfield.cf_name;
 		);
 		Interp.get_local_using = (fun() ->
-			ctx.m.module_using;
+			List.map fst ctx.m.module_using;
 		);
 		Interp.get_local_imports = (fun() ->
 			ctx.m.module_imports;
@@ -4982,7 +4993,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	let expr = Typeload.load_instance mctx (ctexpr,null_pos) false p in
 	(match mode with
 	| MDisplay ->
-		()
+		raise Exit (* We don't have to actually call the macro. *)
 	| MExpr ->
 		unify mctx mret expr mpos;
 	| MBuild ->
@@ -5250,7 +5261,7 @@ let rec create com =
 		Error (Module_not_found ([],"StdTypes"),_) -> error "Standard library not found" null_pos
 	);
 	(* We always want core types to be available so we add them as default imports (issue #1904 and #3131). *)
-	ctx.m.module_types <- ctx.g.std.m_types;
+	ctx.m.module_types <- List.map (fun t -> t,null_pos) ctx.g.std.m_types;
 	List.iter (fun t ->
 		match t with
 		| TAbstractDecl a ->
@@ -5300,11 +5311,11 @@ let rec create com =
 	with Exit -> ());
 	let m = Typeload.load_module ctx (["haxe"],"EnumTools") null_pos in
 	(match m.m_types with
-	| [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- c1 :: c2 :: ctx.g.global_using
+	| [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
 	| [TClassDecl c1] ->
 		let m = Typeload.load_module ctx (["haxe"],"EnumValueTools") null_pos in
 		(match m.m_types with
-		| [TClassDecl c2 ] -> ctx.g.global_using <- c1 :: c2 :: ctx.g.global_using
+		| [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
 		| _ -> assert false);
 	| _ -> assert false);
 	ctx