فهرست منبع

[display] use CompletionItem for hover

Simon Krajewski 7 سال پیش
والد
کامیت
33bbdf5c82

+ 18 - 14
src/compiler/displayOutput.ml

@@ -49,7 +49,7 @@ let print_keywords () =
 let print_fields fields =
 	let b = Buffer.create 0 in
 	Buffer.add_string b "<list>\n";
-	let convert k = match k with
+	let convert k = match k.ci_kind with
 		| ITClassField({field = cf}) | ITEnumAbstractField(_,{field = cf}) ->
 			let kind = match cf.cf_kind with
 				| Method _ -> "method"
@@ -70,7 +70,9 @@ let print_fields fields =
 		| ITModule s -> "type",s,"",None
 		| ITMetadata(s,doc) -> "metadata",s,"",doc
 		| ITTimer(name,value) -> "timer",name,"",Some value
-		| ITLiteral(s,t) -> "literal",s,s_type (print_context()) t,None
+		| ITLiteral s ->
+			let t = Option.default t_dynamic k.ci_type in
+			"literal",s,s_type (print_context()) t,None
 		| ITLocal v -> "local",v.v_name,s_type (print_context()) v.v_type,None
 		| ITKeyword kwd -> "keyword",Ast.s_keyword kwd,"",None
 		| ITExpression _ | ITAnonymous _ -> assert false
@@ -100,7 +102,7 @@ let print_toplevel il =
 			true
 		end
 	in
-	List.iter (fun id -> match id with
+	List.iter (fun id -> match id.ci_kind with
 		| ITLocal v ->
 			if check_ident v.v_name then Buffer.add_string b (Printf.sprintf "<i k=\"local\" t=\"%s\">%s</i>\n" (s_type v.v_type) v.v_name);
 		| ITClassField({field = cf;scope = CFSMember}) ->
@@ -118,7 +120,7 @@ let print_toplevel il =
 			Buffer.add_string b (Printf.sprintf "<i k=\"type\" p=\"%s\"%s>%s</i>\n" (s_type_path path) ("") cm.name);
 		| ITPackage(path,_) ->
 			Buffer.add_string b (Printf.sprintf "<i k=\"package\">%s</i>\n" (snd path))
-		| ITLiteral(s,_) ->
+		| ITLiteral s ->
 			Buffer.add_string b (Printf.sprintf "<i k=\"literal\">%s</i>\n" s)
 		| ITTimer(s,_) ->
 			Buffer.add_string b (Printf.sprintf "<i k=\"timer\">%s</i>\n" s)
@@ -371,8 +373,8 @@ module TypePathHandler = struct
 		if packs = [] && modules = [] then
 			(abort ("No classes found in " ^ String.concat "." p) null_pos)
 		else
-			let packs = List.map (fun n -> ITPackage((p,n),[])) packs in
-			let modules = List.map (fun n -> ITModule n) modules in
+			let packs = List.map (fun n -> make_ci_package (p,n) []) packs in
+			let modules = List.map (fun n -> make_ci_module n) modules in
 			Some (packs @ modules)
 
 	(** raise field completion listing module sub-types and static fields *)
@@ -403,7 +405,7 @@ module TypePathHandler = struct
 				if is_import && is_module_type then begin match t with
 					| TClassDecl c ->
 						ignore(c.cl_build());
-						statics := Some c.cl_ordered_statics
+						statics := Some c
 					| TEnumDecl en ->
 						enum_statics := Some en
 					| _ -> ()
@@ -415,19 +417,21 @@ module TypePathHandler = struct
 					[]
 				else
 					List.map (fun mt ->
-						ITType(CompletionItem.CompletionModuleType.of_module_type mt,ImportStatus.Imported)
+						make_ci_type (CompletionItem.CompletionModuleType.of_module_type mt) ImportStatus.Imported None
 					) public_types
 			in
-			let make_field_doc cf =
-				ITClassField (CompletionClassField.make cf CFSStatic (Self (TClassDecl null_class)) true)
+			let make_field_doc c cf =
+				make_ci_class_field (CompletionClassField.make cf CFSStatic (Self (TClassDecl c)) true) cf.cf_type
 			in
 			let fields = match !statics with
 				| None -> types
-				| Some cfl -> types @ (List.map make_field_doc (List.filter (fun cf -> cf.cf_public) cfl))
+				| Some c -> types @ (List.map (make_field_doc c) (List.filter (fun cf -> cf.cf_public) c.cl_ordered_statics))
 			in
 			let fields = match !enum_statics with
 				| None -> fields
-				| Some en -> PMap.fold (fun ef acc -> ITEnumField(CompletionEnumField.make ef (Self (TEnumDecl en)) true) :: acc) en.e_constrs fields
+				| Some en -> PMap.fold (fun ef acc ->
+					make_ci_enum_field (CompletionEnumField.make ef (Self (TEnumDecl en)) true) ef.ef_type :: acc
+				) en.e_constrs fields
 			in
 			Some fields
 		with _ ->
@@ -660,11 +664,11 @@ let handle_syntax_completion com kind p = match com.json_out with
 	| Some(f,_) ->
 		match kind with
 		| Parser.SCClassRelation ->
-			let l = [ITKeyword Extends;ITKeyword Implements] in
+			let l = [make_ci_keyword Extends;make_ci_keyword Implements] in
 			let ctx = Genjson.create_context GMFull in
 			f(fields_to_json ctx l CRTypeRelation None false)
 		| Parser.SCInterfaceRelation ->
-			let l = [ITKeyword Extends] in
+			let l = [make_ci_keyword Extends] in
 			let ctx = Genjson.create_context GMFull in
 			f(fields_to_json ctx l CRTypeRelation None false)
 		| Parser.SCComment ->

+ 7 - 7
src/compiler/main.ml

@@ -951,7 +951,7 @@ with
 	| DisplayException(DisplayHover _ | DisplayPosition _ | DisplayFields _ | DisplayPackage _  | DisplaySignatures _ as de) when ctx.com.json_out <> None ->
 		begin match ctx.com.json_out with
 		| Some (f,_) ->
-			let ctx = DisplayJson.create_json_context() in
+			let ctx = DisplayJson.create_json_context (match de with DisplayFields _ -> true | _ -> false) in
 			f (DisplayException.to_json ctx de)
 		| _ -> assert false
 		end
@@ -970,7 +970,7 @@ with
 		let fields = if !measure_times then begin
 			Timer.close_times();
 			(List.map (fun (name,value) ->
-				CompletionItem.ITTimer("@TIME " ^ name,value)
+				CompletionItem.make_ci_timer ("@TIME " ^ name) value
 			) (DisplayOutput.get_timer_fields !start_time)) @ fields
 		end else
 			fields
@@ -994,9 +994,9 @@ with
 				DisplayOutput.print_fields fields
 		in
 		raise (DisplayOutput.Completion s)
-	| DisplayException(DisplayHover (Some t,p,doc)) ->
-		let doc = match doc with Some _ -> doc | None -> DisplayOutput.find_doc t in
-		raise (DisplayOutput.Completion (DisplayOutput.print_type t p doc))
+	| DisplayException(DisplayHover ({hitem = {CompletionItem.ci_type = Some t}} as hover)) ->
+		let doc = CompletionItem.get_documentation hover.hitem in
+		raise (DisplayOutput.Completion (DisplayOutput.print_type t hover.hpos doc))
 	| DisplayException(DisplaySignatures(signatures,_,display_arg)) ->
 		if ctx.com.display.dms_kind = DMSignature then
 			raise (DisplayOutput.Completion (DisplayOutput.print_signature signatures display_arg))
@@ -1020,9 +1020,9 @@ with
 		| Some fields ->
 			begin match ctx.com.json_out with
 			| Some (f,_) ->
-				let ctx = DisplayJson.create_json_context() in
+				let ctx = DisplayJson.create_json_context false in
 				let pos = Parser.cut_pos_at_display pos in
-				let kind = CRField ((CompletionItem.ITModule((String.concat "." p)),pos)) in
+				let kind = CRField ((CompletionItem.make_ci_module (String.concat "." p),pos)) in
 				f (DisplayException.fields_to_json ctx fields kind None false);
 			| _ -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))
 			end

+ 3 - 1
src/compiler/server.ml

@@ -414,7 +414,9 @@ let rec wait_loop process_params verbose accept =
 				ServerMessage.signature ctx.com "" sign;
 				ServerMessage.display_position ctx.com "" (!Parser.resume_display);
 				Parser.display_error := (fun e p -> has_parse_error := true; ctx.com.error (Parser.error_msg e) p);
-				if ctx.com.display.dms_display then begin
+				(* Special case for diagnostics: It's not treated as a display mode, but we still want to invalidate the
+				   current file in order to run diagnostics on it again. *)
+				if ctx.com.display.dms_display || (match ctx.com.display.dms_kind with DMDiagnostics _ -> true | _ -> false) then begin
 					let file = (!Parser.resume_display).pfile in
 					let fkey = (file,sign) in
 					(* force parsing again : if the completion point have been changed *)

+ 28 - 20
src/context/display/displayEmitter.ml

@@ -30,14 +30,17 @@ let patch_type ctx t =
 let display_module_type ctx mt p = match ctx.com.display.dms_kind with
 	| DMDefinition -> raise_position [(t_infos mt).mt_name_pos];
 	| DMUsage _ -> reference_position := (t_infos mt).mt_name_pos
-	| DMHover -> raise_hover (Some (patch_type ctx (type_of_module_type mt))) p (t_infos mt).mt_doc
+	| DMHover ->
+		let t = patch_type ctx (type_of_module_type mt) in
+		raise_hover (make_ci_type (CompletionModuleType.of_module_type mt) ImportStatus.Imported (Some t)) p
 	| _ -> ()
 
 let rec display_type ctx t p =
 	let dm = ctx.com.display in
 	match dm.dms_kind with
 	| DMHover ->
-		raise_hover (Some (patch_type ctx t)) p None
+		let t = patch_type ctx t in
+		raise_hover (make_ci_expr (mk (TConst TNull) t p)) p
 	| _ ->
 		try display_module_type ctx (module_type_of_type t) p
 		with Exit -> match follow t,follow !t_dynamic_def with
@@ -62,32 +65,37 @@ let check_display_type ctx t p =
 let display_variable ctx v p = match ctx.com.display.dms_kind with
 	| DMDefinition -> raise_position [v.v_pos]
 	| DMUsage _ -> reference_position := v.v_pos
-	| DMHover -> raise_hover (Some (patch_type ctx v.v_type)) p None
+	| DMHover ->
+		let t = patch_type ctx v.v_type in
+		raise_hover (make_ci_local v t) p
 	| _ -> ()
 
-let display_field ctx c cf p = match ctx.com.display.dms_kind with
+let display_field ctx origin scope cf p = match ctx.com.display.dms_kind with
 	| DMDefinition -> raise_position [cf.cf_name_pos]
 	| DMUsage _ -> reference_position := cf.cf_name_pos
 	| DMHover ->
-		let t = if Meta.has Meta.Impl cf.cf_meta then
-			(prepare_using_field cf).cf_type
+		let cf = if Meta.has Meta.Impl cf.cf_meta then
+			prepare_using_field cf
 		else
-			cf.cf_type
+			cf
 		in
-		let t = match c,follow t with
-			| Some c,TFun(tl,_) when cf.cf_name = "new" -> TFun(tl,TInst(c,List.map snd c.cl_params))
-			| _ -> t
-		in
-		raise_hover (Some (patch_type ctx t)) p cf.cf_doc
+        let cf = match origin,scope,follow cf.cf_type with
+            | Self (TClassDecl c),CFSConstructor,TFun(tl,_) -> {cf with cf_type = TFun(tl,TInst(c,List.map snd c.cl_params))}
+            | _ -> cf
+        in
+		let t = patch_type ctx cf.cf_type in
+		raise_hover (make_ci_class_field (CompletionClassField.make cf scope origin true) t) p
 	| _ -> ()
 
-let maybe_display_field ctx c cf p =
-	if is_display_position p then display_field ctx c cf p
+let maybe_display_field ctx origin scope cf p =
+	if is_display_position p then display_field ctx origin scope cf p
 
-let display_enum_field ctx ef p = match ctx.com.display.dms_kind with
+let display_enum_field ctx en ef p = match ctx.com.display.dms_kind with
 	| DMDefinition -> raise_position [ef.ef_name_pos]
 	| DMUsage _ -> reference_position := ef.ef_name_pos
-	| DMHover -> raise_hover (Some (patch_type ctx ef.ef_type)) p ef.ef_doc
+	| DMHover ->
+		let t = patch_type ctx ef.ef_type in
+		raise_hover (make_ci_enum_field (CompletionEnumField.make ef (Self (TEnumDecl en)) true) t) p
 	| _ -> ()
 
 let display_meta com meta p = match com.display.dms_kind with
@@ -101,12 +109,12 @@ let display_meta com meta p = match com.display.dms_kind with
 				if com.json_out = None then
 					raise_metadata ("<metadata>" ^ s ^ "</metadata>")
 				else
-					raise_hover None null_pos (Some s)
+					raise_hover (make_ci_metadata (Meta.to_string meta) (Some s)) p
 		end
 	| DMDefault ->
 		let all,_ = Meta.get_documentation_list() in
 		let all = List.map (fun (s,doc) ->
-			ITMetadata(s,Some doc)
+			make_ci_metadata s (Some doc)
 		) all in
 		raise_fields all CRMetadata (Some p) false
 	| _ ->
@@ -129,7 +137,7 @@ let check_field_modifiers ctx c cf override display_modifier =
 			begin match c.cl_super with
 			| Some(c,tl) ->
 				let _,_,cf = raw_class_field (fun cf -> cf.cf_type) c tl cf.cf_name in
-				display_field ctx (Some c) cf p
+				display_field ctx (Parent(TClassDecl c)) CFSMember cf p
 			| _ ->
 				()
 			end
@@ -138,7 +146,7 @@ let check_field_modifiers ctx c cf override display_modifier =
 			let missing_fields = List.fold_left (fun fields cf -> PMap.remove cf.cf_name fields) all_fields c.cl_ordered_fields in
 			let l = PMap.fold (fun (c,cf) fields ->
 				let origin = Parent (TClassDecl c) in
-				(ITClassField (CompletionClassField.make cf CFSMember origin true)) :: fields
+				make_ci_class_field (CompletionClassField.make cf CFSMember origin true) cf.cf_type :: fields
 			) missing_fields [] in
 			raise_fields l CROverride None false
 		| _ -> ()

+ 13 - 7
src/context/display/displayException.ml

@@ -5,13 +5,18 @@ open CompletionItem
 open Type
 open Genjson
 
+type hover_result = {
+	hitem : CompletionItem.t;
+	hpos : pos;
+}
+
 type kind =
 	| Diagnostics of string
 	| Statistics of string
 	| ModuleSymbols of string
 	| Metadata of string
 	| DisplaySignatures of (tsignature * documentation) list * int * int
-	| DisplayHover of t option * pos * string option
+	| DisplayHover of hover_result
 	| DisplayPosition of pos list
 	| DisplayFields of CompletionItem.t list * CompletionResultKind.t * pos option (* insert pos *) * bool (* sorted? *)
 	| DisplayPackage of string list
@@ -23,13 +28,13 @@ let raise_statistics s = raise (DisplayException(Statistics s))
 let raise_module_symbols s = raise (DisplayException(ModuleSymbols s))
 let raise_metadata s = raise (DisplayException(Metadata s))
 let raise_signatures l isig iarg = raise (DisplayException(DisplaySignatures(l,isig,iarg)))
-let raise_hover t p so = raise (DisplayException(DisplayHover(t,p,so)))
+let raise_hover item p = raise (DisplayException(DisplayHover({hitem = item;hpos = p})))
 let raise_position pl = raise (DisplayException(DisplayPosition pl))
 let raise_fields ckl cr po b = raise (DisplayException(DisplayFields(ckl,cr,po,b)))
 let raise_package sl = raise (DisplayException(DisplayPackage sl))
 
 (* global state *)
-let last_completion_result = ref (Array.make 0 (ITModule ""))
+let last_completion_result = ref (Array.make 0 (CompletionItem.make (ITModule "") None))
 
 let fields_to_json ctx fields kind po sorted =
 	let ja = List.map (CompletionItem.to_json ctx) fields in
@@ -60,11 +65,12 @@ let to_json ctx de =
 			"activeParameter",jint iarg;
 			"signatures",jlist fsig sigs;
 		]
-	| DisplayHover(t,p,doc) ->
+	| DisplayHover hover ->
 		jobject [
-			"documentation",jopt jstring doc;
-			"range",generate_pos_as_range p;
-			"type",jopt (generate_type ctx) t;
+			"documentation",jopt jstring (CompletionItem.get_documentation hover.hitem);
+			"range",generate_pos_as_range hover.hpos;
+			"type",jopt (generate_type ctx) hover.hitem.ci_type; (* TODO: remove *)
+			"item",CompletionItem.to_json ctx hover.hitem;
 		]
 	| DisplayPosition pl ->
 		jarray (List.map generate_pos_as_location pl)

+ 7 - 7
src/context/display/displayFields.ml

@@ -28,7 +28,7 @@ let get_submodule_fields ctx path =
 	let m = Hashtbl.find ctx.g.modules path in
 	let tl = List.filter (fun t -> path <> (t_infos t).mt_path && not (t_infos t).mt_private) m.m_types in
 	let tl = List.map (fun mt ->
-		ITType(CompletionItem.CompletionModuleType.of_module_type mt,ImportStatus.Imported)
+		make_ci_type (CompletionItem.CompletionModuleType.of_module_type mt) ImportStatus.Imported None
 	) tl in
 	tl
 
@@ -71,7 +71,7 @@ let collect_static_extensions ctx items e p =
 								let f = prepare_using_field f in
 								let f = { f with cf_params = []; cf_public = true; cf_type = TFun(args,ret) } in
 								let origin = StaticExtension(TClassDecl c) in
-								let item = ITClassField (CompletionClassField.make f CFSMember origin true) in
+								let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) f.cf_type in
 								PMap.add f.cf_name item acc
 							end
 						with Error (Unify _,_) ->
@@ -114,7 +114,7 @@ let collect ctx e_ast e dk with_type p =
 			PMap.foldi (fun k (c,cf) acc ->
 				if should_access c cf false && is_new_item acc cf.cf_name then begin
 					let origin = if c == c0 then Self(TClassDecl c) else Parent(TClassDecl c) in
-				 	let item = ITClassField (CompletionClassField.make cf CFSMember origin true) in
+				 	let item = make_ci_class_field (CompletionClassField.make cf CFSMember origin true) cf.cf_type in
 					PMap.add k item acc
 				end else
 					acc
@@ -126,7 +126,7 @@ let collect ctx e_ast e dk with_type p =
 					let origin = Self(TAbstractDecl a) in
 					let cf = prepare_using_field cf in
 					let cf = if tl = [] then cf else {cf with cf_type = apply_params a.a_params tl cf.cf_type} in
-					let item = ITClassField (CompletionClassField.make cf CFSMember origin true) in
+					let item = make_ci_class_field (CompletionClassField.make cf CFSMember origin true) cf.cf_type in
 					PMap.add cf.cf_name item acc
 				end else
 					acc
@@ -163,7 +163,7 @@ let collect ctx e_ast e dk with_type p =
 							Self (TAbstractDecl a),check
 						| _ -> AnonymousStructure an,true
 					in
-					if check then PMap.add name (ITClassField (CompletionClassField.make cf CFSMember origin true)) acc
+					if check then PMap.add name (make_ci_class_field (CompletionClassField.make cf CFSMember origin true) cf.cf_type) acc
 					else acc
 				end else
 					acc
@@ -174,7 +174,7 @@ let collect ctx e_ast e dk with_type p =
 				let t = opt_args args ret in
 				let cf = mk_field "bind" (tfun [t] t) p null_pos in
 				cf.cf_kind <- Method MethNormal;
-				let item = ITClassField (CompletionClassField.make cf CFSStatic BuiltIn true) in
+				let item = make_ci_class_field (CompletionClassField.make cf CFSStatic BuiltIn true) t in
 				PMap.add "bind" item items
 			end else
 				items
@@ -187,7 +187,7 @@ let collect ctx e_ast e dk with_type p =
 			let cf = mk_field "code" ctx.t.tint e.epos null_pos in
 			cf.cf_doc <- Some "The character code of this character (inlined at compile-time).";
 			cf.cf_kind <- Var { v_read = AccNormal; v_write = AccNever };
-			let item = ITClassField (CompletionClassField.make cf CFSStatic BuiltIn true) in
+			let item = make_ci_class_field (CompletionClassField.make cf CFSStatic BuiltIn true) cf.cf_type in
 			PMap.add cf.cf_name item PMap.empty
 		| _ ->
 			PMap.empty

+ 2 - 2
src/context/display/displayJson.ml

@@ -53,8 +53,8 @@ let json_of_times root =
 let debug_context_sign = ref None
 let supports_resolve = ref false
 
-let create_json_context () =
-	Genjson.create_context (if !supports_resolve then GMMinimum else GMFull)
+let create_json_context may_resolve =
+	Genjson.create_context (if may_resolve && !supports_resolve then GMMinimum else GMFull)
 
 let parse_input com input report_times pre_compilation did_something =
 	let send_string j = raise (DisplayOutput.Completion j) in

+ 21 - 18
src/context/display/displayToplevel.ml

@@ -136,7 +136,7 @@ let collect ctx only_types with_type =
 					!merge_core_doc_ref ctx c
 				| _ -> ());
                 let is = get_import_status cctx true path in
-				add (ITType(CompletionModuleType.of_module_type mt,is)) (Some (snd path));
+				add (make_ci_type (CompletionModuleType.of_module_type mt) is None) (Some (snd path));
 				add_path cctx path;
 			end
 	in
@@ -155,7 +155,7 @@ let collect ctx only_types with_type =
 				if not (path_exists cctx path) && not is_private then begin
 					add_path cctx path;
 					let is = get_import_status cctx false path in
-					add (ITType(CompletionModuleType.of_type_decl pack name (d,p),is)) None
+					add (make_ci_type (CompletionModuleType.of_type_decl pack name (d,p)) is None) None
 				end
 			with Exit ->
 				()
@@ -170,12 +170,12 @@ let collect ctx only_types with_type =
 		(* locals *)
 		PMap.iter (fun _ v ->
 			if not (is_gen_local v) then
-				add (ITLocal v) (Some v.v_name)
+				add (make_ci_local v v.v_type) (Some v.v_name)
 		) ctx.locals;
 
 		let add_field scope origin cf =
 			let is_qualified = is_qualified cctx cf.cf_name in
-			add (ITClassField(CompletionClassField.make cf scope origin is_qualified)) (Some cf.cf_name)
+			add (make_ci_class_field (CompletionClassField.make cf scope origin is_qualified) cf.cf_type) (Some cf.cf_name)
 		in
 		let maybe_add_field scope origin cf =
 			if not (Meta.has Meta.NoCompletion cf.cf_meta) then add_field scope origin cf
@@ -215,7 +215,8 @@ let collect ctx only_types with_type =
 				add_path cctx a.a_path;
 				List.iter (fun cf ->
 					let ccf = CompletionClassField.make cf CFSMember (Self (TClassDecl c)) true in
-					if (Meta.has Meta.Enum cf.cf_meta) && not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITEnumAbstractField(a,ccf)) (Some cf.cf_name);
+					if (Meta.has Meta.Enum cf.cf_meta) && not (Meta.has Meta.NoCompletion cf.cf_meta) then
+						add (make_ci_enum_abstract_field a ccf cf.cf_type) (Some cf.cf_name);
 				) c.cl_ordered_statics
 			| TTypeDecl t ->
 				begin match follow t.t_type with
@@ -227,7 +228,7 @@ let collect ctx only_types with_type =
 				let origin = Self (TEnumDecl e) in
 				PMap.iter (fun _ ef ->
 					let is_qualified = is_qualified cctx ef.ef_name in
-					add (ITEnumField(CompletionEnumField.make ef origin is_qualified)) (Some ef.ef_name)
+					add (make_ci_enum_field (CompletionEnumField.make ef origin is_qualified) ef.ef_type) (Some ef.ef_name)
 				) e.e_constrs;
 			| _ ->
 				()
@@ -250,7 +251,7 @@ let collect ctx only_types with_type =
 					let cf = PMap.find s c.cl_statics in
 					let cf = if name = cf.cf_name then cf else {cf with cf_name = name} in
 					let origin = StaticImport (TClassDecl c) in
-					add (ITClassField (CompletionClassField.make cf CFSStatic origin is_qualified)) (Some name)
+					add (make_ci_class_field (CompletionClassField.make cf CFSStatic origin is_qualified) cf.cf_type) (Some name)
 				in
 				match resolve_typedef mt with
 					| TClassDecl c -> class_import c;
@@ -258,7 +259,7 @@ let collect ctx only_types with_type =
 						let ef = PMap.find s en.e_constrs in
 						let ef = if name = ef.ef_name then ef else {ef with ef_name = name} in
 						let origin = StaticImport (TEnumDecl en) in
-						add (ITEnumField (CompletionEnumField.make ef origin is_qualified)) (Some s)
+						add (make_ci_enum_field (CompletionEnumField.make ef origin is_qualified) ef.ef_type) (Some s)
 					| TAbstractDecl {a_impl = Some c} -> class_import c;
 					| _ -> raise Not_found
 			with Not_found ->
@@ -266,15 +267,15 @@ let collect ctx only_types with_type =
 		) ctx.m.module_globals;
 
 		(* literals *)
-		add (ITLiteral("null",t_dynamic)) (Some "null");
-		add (ITLiteral("true",ctx.com.basic.tbool)) (Some "true");
-		add (ITLiteral("false",ctx.com.basic.tbool)) (Some "false");
+		add (make_ci_literal "null" t_dynamic) (Some "null");
+		add (make_ci_literal "true" ctx.com.basic.tbool) (Some "true");
+		add (make_ci_literal "false" ctx.com.basic.tbool) (Some "false");
 		begin match ctx.curfun with
 			| FunMember | FunConstructor | FunMemberClassLocal ->
 				let t = TInst(ctx.curclass,List.map snd ctx.curclass.cl_params) in
-				add (ITLiteral("this",t)) (Some "this");
+				add (make_ci_literal "this" t) (Some "this");
 				begin match ctx.curclass.cl_super with
-					| Some(c,tl) -> add (ITLiteral("super",TInst(c,tl))) (Some "super")
+					| Some(c,tl) -> add (make_ci_literal "super" (TInst(c,tl))) (Some "super")
 					| None -> ()
 				end
 			| _ ->
@@ -286,17 +287,17 @@ let collect ctx only_types with_type =
 			Function; Var; If; Else; While; Do; For; Break; Return; Continue; Switch;
 			Try; New; Throw; Untyped; Cast;
 		] in
-		List.iter (fun kwd -> add(ITKeyword(kwd)) (Some (s_keyword kwd))) kwds;
+		List.iter (fun kwd -> add(make_ci_keyword kwd) (Some (s_keyword kwd))) kwds;
 
 		(* builtins *)
-		add (ITLiteral("trace", TFun(["value",false,t_dynamic],ctx.com.basic.tvoid))) (Some "trace")
+		add (make_ci_literal "trace" (TFun(["value",false,t_dynamic],ctx.com.basic.tvoid))) (Some "trace")
 	end;
 
 	(* type params *)
 	List.iter (fun (s,t) -> match follow t with
 		| TInst(c,_) ->
 			(* This is weird, might want to use something else for type parameters *)
-			add (ITType (CompletionModuleType.of_module_type (TClassDecl c),ImportStatus.Imported)) (Some s)
+			add (make_ci_type (CompletionModuleType.of_module_type (TClassDecl c)) ImportStatus.Imported (Some t)) (Some s)
 		| _ -> assert false
 	) ctx.type_params;
 
@@ -345,14 +346,16 @@ let collect ctx only_types with_type =
 	end;
 
 	Hashtbl.iter (fun path _ ->
-		add (ITPackage(path,[])) (Some (snd path))
+		add (make_ci_package path []) (Some (snd path))
 	) packages;
 
 	(* sorting *)
 	let l = DynArray.to_list cctx.items in
 	let l = match with_type with
 		| WithType t ->
-			let rec comp t' =
+			let rec comp t' = match t' with
+				| None -> 9
+				| Some t' ->
 				if type_iseq t' t then 0 (* equal types - perfect *)
 				else if t' == t_dynamic then 5 (* dynamic isn't good, but better than incompatible *)
 				else try Type.unify t' t; 1 (* assignable - great *)

+ 62 - 28
src/core/display/completionItem.ml

@@ -45,6 +45,10 @@ module CompletionModuleType = struct
 		| No
 		| Maybe
 
+	type module_type_source =
+		| Syntax of type_def (* TODO: do we really want to keep this? *)
+		| Typed of module_type
+
 	type t = {
 		pack : string list;
 		name : string;
@@ -57,6 +61,7 @@ module CompletionModuleType = struct
 		is_extern : bool;
 		kind : CompletionModuleKind.t;
 		has_constructor : not_bool;
+		source : module_type_source;
 	}
 
 	let of_type_decl pack module_name (td,p) = match td with
@@ -77,6 +82,7 @@ module CompletionModuleType = struct
 				is_extern = List.mem HExtern d.d_flags;
 				kind = if List.mem HInterface d.d_flags then Interface else Class;
 				has_constructor = ctor;
+				source = Syntax td;
 			}
 		| EEnum d -> {
 				pack = pack;
@@ -90,6 +96,7 @@ module CompletionModuleType = struct
 				is_extern = List.mem EExtern d.d_flags;
 				kind = Enum;
 				has_constructor = No;
+				source = Syntax td;
 			}
 		| ETypedef d ->
 			let kind = match fst d.d_data with CTAnonymous _ -> Struct | _ -> TypeAlias in
@@ -105,6 +112,7 @@ module CompletionModuleType = struct
 				is_extern = List.mem EExtern d.d_flags;
 				kind = kind;
 				has_constructor = if kind = Struct then No else Maybe;
+				source = Syntax td;
 			}
 		| EAbstract d -> {
 				pack = pack;
@@ -118,6 +126,7 @@ module CompletionModuleType = struct
 				is_extern = List.mem AbExtern d.d_flags;
 				kind = if Meta.has Meta.Enum d.d_meta then EnumAbstract else Abstract;
 				has_constructor = if (List.exists (fun cff -> fst cff.cff_name = "new") d.d_data) then Yes else No;
+				source = Syntax td;
 			}
 		| EImport _ | EUsing _ ->
 			raise Exit
@@ -160,6 +169,7 @@ module CompletionModuleType = struct
 			is_extern = is_extern;
 			kind = kind;
 			has_constructor = if has_ctor then Yes else No;
+			source = Typed mt;
 		}
 
 	let get_path cm = (cm.pack,cm.name)
@@ -194,6 +204,7 @@ module ClassFieldOrigin = struct
 		| StaticExtension of module_type
 		| AnonymousStructure of tanon
 		| BuiltIn
+		| Unknown
 
 	let to_json ctx cfo =
 		let i,args = match cfo with
@@ -203,6 +214,7 @@ module ClassFieldOrigin = struct
 		| StaticExtension mt -> 3,if ctx.generation_mode = GMMinimum then None else Some (generate_module_type ctx mt)
 		| AnonymousStructure an -> 4,if ctx.generation_mode = GMMinimum then None else Some (generate_anon ctx an)
 		| BuiltIn -> 5,None
+		| Unknown -> 6,None
 		in
 		jobject (
 			("kind",jint i) :: (match args with None -> [] | Some arg -> ["args",arg])
@@ -253,7 +265,7 @@ open CompletionModuleType
 open CompletionClassField
 open CompletionEnumField
 
-type t =
+type t_kind =
 	| ITLocal of tvar
 	| ITClassField of CompletionClassField.t
 	| ITEnumField of CompletionEnumField.t
@@ -261,14 +273,38 @@ type t =
 	| ITType of CompletionModuleType.t * ImportStatus.t
 	| ITPackage of path * (string * PackageContentKind.t) list
 	| ITModule of string
-	| ITLiteral of string * Type.t
+	| ITLiteral of string
 	| ITTimer of string * string
 	| ITMetadata of string * documentation
 	| ITKeyword of keyword
 	| ITAnonymous of tanon
 	| ITExpression of texpr
 
-let get_index = function
+type t = {
+	ci_kind : t_kind;
+	ci_type : Type.t option;
+}
+
+let make kind t = {
+	ci_kind = kind;
+	ci_type = t;
+}
+
+let make_ci_local v t = make (ITLocal v) (Some t)
+let make_ci_class_field ccf t = make (ITClassField ccf) (Some t)
+let make_ci_enum_abstract_field a ccf t = make (ITEnumAbstractField(a,ccf)) (Some t)
+let make_ci_enum_field cef t = make (ITEnumField cef) (Some t)
+let make_ci_type mt import_status t = make (ITType(mt,import_status)) t
+let make_ci_package path l = make (ITPackage(path,l)) None
+let make_ci_module s = make (ITModule s) None
+let make_ci_literal lit t = make (ITLiteral lit) (Some t)
+let make_ci_timer name value = make (ITTimer(name,value)) None
+let make_ci_metadata s doc = make (ITMetadata(s,doc)) None
+let make_ci_keyword kwd = make (ITKeyword kwd) None
+let make_ci_anon an t = make (ITAnonymous an) (Some t)
+let make_ci_expr e = make (ITExpression e) (Some e.etype)
+
+let get_index item = match item.ci_kind with
 	| ITLocal _ -> 0
 	| ITClassField _ -> 1
 	| ITEnumField _ -> 2
@@ -283,7 +319,7 @@ let get_index = function
 	| ITAnonymous _ -> 11
 	| ITExpression _ -> 12
 
-let get_sort_index = function
+let get_sort_index item = match item.ci_kind with
 	| ITLocal _ -> 0
 	| ITClassField _ -> 0
 	| ITEnumField ef -> ef.efield.ef_index
@@ -298,7 +334,7 @@ let get_sort_index = function
 	| ITAnonymous _ -> 0
 	| ITExpression _ -> 0
 
-let legacy_sort = function
+let legacy_sort item = match item.ci_kind with
 	| ITClassField(cf) | ITEnumAbstractField(_,cf) ->
 		begin match cf.field.cf_kind with
 		| Var _ -> 0,cf.field.cf_name
@@ -316,44 +352,38 @@ let legacy_sort = function
 	| ITMetadata(s,_) -> 5,s
 	| ITTimer(s,_) -> 6,s
 	| ITLocal v -> 7,v.v_name
-	| ITLiteral(s,_) -> 9,s
+	| ITLiteral s -> 9,s
 	| ITKeyword kwd -> 10,s_keyword kwd
 	| ITAnonymous _ -> 11,""
 	| ITExpression _ -> 12,""
 
-let get_name = function
+let get_name item = match item.ci_kind with
 	| ITLocal v -> v.v_name
 	| ITClassField(cf) | ITEnumAbstractField(_,cf) -> cf.field.cf_name
 	| ITEnumField ef -> ef.efield.ef_name
 	| ITType(cm,_) -> cm.name
 	| ITPackage(path,_) -> snd path
 	| ITModule s -> s
-	| ITLiteral(s,_) -> s
+	| ITLiteral s -> s
 	| ITTimer(s,_) -> s
 	| ITMetadata(s,_) -> s
 	| ITKeyword kwd -> s_keyword kwd
 	| ITAnonymous _ -> ""
 	| ITExpression _ -> ""
 
-let get_type = function
-	| ITLocal v -> v.v_type
-	| ITClassField(cf) | ITEnumAbstractField(_,cf) -> cf.field.cf_type
-	| ITEnumField ef -> ef.efield.ef_type
-	| ITType(_,_) -> t_dynamic (* TODO: might want a type here, not sure *)
-	| ITPackage _ -> t_dynamic
-	| ITModule _ -> t_dynamic
-	| ITLiteral(_,t) -> t
-	| ITTimer(_,_) -> t_dynamic
-	| ITMetadata(_,_) -> t_dynamic
-	| ITKeyword _ -> t_dynamic
-	| ITAnonymous an -> TAnon an
-	| ITExpression e -> e.etype
-
-let to_json ctx ck =
-	let kind,data = match ck with
+let get_type item = item.ci_type
+
+let get_documentation item = match item.ci_kind with
+	| ITClassField cf | ITEnumAbstractField(_,cf) -> cf.field.cf_doc
+	| ITEnumField ef -> ef.efield.ef_doc
+	| ITType(mt,_) -> mt.doc
+	| _ -> None
+
+let to_json ctx item =
+	let kind,data = match item.ci_kind with
 		| ITLocal v -> "Local",generate_tvar ctx v
 		| ITClassField(cf) | ITEnumAbstractField(_,cf) ->
-			let name = match ck with
+			let name = match item.ci_kind with
 				| ITClassField _ -> "ClassField"
 				| _ ->  "EnumAbstractField"
 			in
@@ -382,9 +412,9 @@ let to_json ctx ck =
 				"contents",jlist generate_package_content contents;
 			]
 		| ITModule s -> "Module",jstring s
-		| ITLiteral(s,t) -> "Literal",jobject [
+		| ITLiteral s -> "Literal",jobject [
 			"name",jstring s;
-			"type",generate_type ctx t;
+			"type",jopt (generate_type ctx) item.ci_type; (* TODO: remove *)
 		]
 		| ITTimer(s,value) -> "Timer",jobject [
 			"name",jstring s;
@@ -400,4 +430,8 @@ let to_json ctx ck =
 		| ITAnonymous an -> "AnonymousStructure",generate_anon ctx an
 		| ITExpression e -> "Expression",generate_texpr ctx e
 	in
-	generate_adt ctx None kind (Some data)
+	jobject [
+		"kind",jstring kind;
+		"args",data;
+		"type",jopt (generate_type ctx) item.ci_type;
+	]

+ 1 - 1
src/core/displayTypes.ml

@@ -85,7 +85,7 @@ module CompletionResultKind = struct
 			| CRField(item,p) -> 0,Some (jobject [
 				"item",CompletionItem.to_json ctx item;
 				"range",generate_pos_as_range p;
-				"type",generate_type ctx (CompletionItem.get_type item);
+				"type",jopt (generate_type ctx) (CompletionItem.get_type item);
 			])
 			| CRStructureField -> 1,None
 			| CRToplevel -> 2,None

+ 6 - 5
src/typing/typeload.ml

@@ -24,8 +24,9 @@ open Common
 open DisplayTypes.DisplayMode
 open DisplayTypes.CompletionResultKind
 open CompletionItem
-open CompletionItem.CompletionModuleType
-open CompletionItem.CompletionModuleKind
+open CompletionModuleType
+open CompletionModuleKind
+open ClassFieldOrigin
 open DisplayException
 open Type
 open Typecore
@@ -375,7 +376,7 @@ and load_complex_type ctx allow_display p (t,pn) =
 				try
 					load_instance ctx ~allow_display (t,pn) false p
 				with DisplayException(DisplayFields(l,CRTypeHint,p,b)) ->
-					let l = List.filter (function
+					let l = List.filter (fun item -> match item.ci_kind with
 						| ITType({kind = Struct},_) -> true
 						| _ -> false
 					) l in
@@ -473,7 +474,7 @@ and load_complex_type ctx allow_display p (t,pn) =
 			init_meta_overloads ctx None cf;
 			if ctx.is_display_file then begin
 				DisplayEmitter.check_display_metadata ctx cf.cf_meta;
-				DisplayEmitter.maybe_display_field ctx None cf cf.cf_name_pos;
+				DisplayEmitter.maybe_display_field ctx Unknown CFSMember cf cf.cf_name_pos;
 			end;
 			PMap.add n cf acc
 		in
@@ -811,7 +812,7 @@ let handle_path_display ctx path p =
 				| TClassDecl c when snd c.cl_path = st ->
 					ignore(c.cl_build());
 					let cf = PMap.find sf c.cl_statics in
-					DisplayEmitter.display_field ctx (Some c) cf p
+					DisplayEmitter.display_field ctx (Self (TClassDecl c)) CFSStatic cf p
 				| _ ->
 					()
 			) m.m_types;

+ 1 - 1
src/typing/typeloadCheck.ml

@@ -460,7 +460,7 @@ module Inheritance = struct
 				with DisplayException(DisplayFields(l,CRTypeHint,p,b)) ->
 					(* We don't allow `implements` on interfaces. Just raise fields completion with no fields. *)
 					if not is_extends && c.cl_interface then raise_fields [] CRImplements p false;
-					let l = List.filter (function
+					let l = List.filter (fun item -> match item.ci_kind with
 						| ITType({kind = Interface} as cm,_) -> (not is_extends || c.cl_interface) && CompletionModuleType.get_path cm <> c.cl_path
 						| ITType({kind = Class} as cm,_) ->
 							is_extends && not c.cl_interface && CompletionModuleType.get_path cm <> c.cl_path &&

+ 12 - 5
src/typing/typeloadFields.ml

@@ -25,6 +25,7 @@ open Type
 open Typecore
 open Typeload
 open DisplayTypes.DisplayMode
+open CompletionItem.ClassFieldOrigin
 open Common
 open Error
 
@@ -570,6 +571,12 @@ let bind_type (ctx,cctx,fctx) cf r p =
 		end
 	end
 
+let check_field_display ctx fctx c cf =
+	if fctx.is_display_field then begin
+		let scope = if fctx.is_static then CFSStatic else if fctx.field_kind = FKConstructor then CFSConstructor else CFSMember in
+		DisplayEmitter.maybe_display_field ctx (Self (TClassDecl c)) scope cf cf.cf_name_pos
+	end
+
 let bind_var (ctx,cctx,fctx) cf e =
 	let c = cctx.tclass in
 	let p = cf.cf_pos in
@@ -601,7 +608,7 @@ let bind_var (ctx,cctx,fctx) cf e =
 
 	match e with
 	| None ->
-		if fctx.is_display_field then DisplayEmitter.maybe_display_field ctx (Some c) cf cf.cf_name_pos;
+		check_field_display ctx fctx c cf;
 	| Some e ->
 		if requires_value_meta ctx.com (Some c) then cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta);
 		let check_cast e =
@@ -688,7 +695,7 @@ let bind_var (ctx,cctx,fctx) cf e =
 				let e = check_cast e in
 				cf.cf_expr <- Some e;
 				cf.cf_type <- t;
-				if fctx.is_display_field then DisplayEmitter.maybe_display_field ctx (Some c) cf cf.cf_name_pos;
+				check_field_display ctx fctx c cf;
 			end;
 			t
 		) "bind_var" in
@@ -996,13 +1003,13 @@ let create_method (ctx,cctx,fctx) c f fd p =
 						| _ -> c.cl_init <- Some e);
 					cf.cf_expr <- Some (mk (TFunction tf) t p);
 					cf.cf_type <- t;
-				if fctx.is_display_field then DisplayEmitter.maybe_display_field ctx (Some c) cf cf.cf_name_pos
+				check_field_display ctx fctx c cf;
 			end;
 		end;
 		t
 	) "type_fun" in
 	if fctx.do_bind then bind_type (ctx,cctx,fctx) cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos)
-	else if fctx.is_display_field then DisplayEmitter.maybe_display_field ctx (Some c) cf cf.cf_name_pos;
+	else check_field_display ctx fctx c cf;
 	cf
 
 let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
@@ -1092,7 +1099,7 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 	let display_accessor m p =
 		try
 			let cf = match find_accessor m with [_,cf] -> cf | _ -> raise Not_found in
-			DisplayEmitter.display_field ctx (Some c) cf p
+			DisplayEmitter.display_field ctx (Self (TClassDecl c)) (if fctx.is_static then CFSStatic else CFSMember) cf p
 		with Not_found ->
 			()
 	in

+ 0 - 2
src/typing/typeloadFunction.ml

@@ -121,8 +121,6 @@ let type_function ctx args ret fmode f do_display p =
 		with
 		| Parser.TypePath (_,None,_,_) | Exit ->
 			type_expr ctx e NoValue
-		| DisplayException (DisplayHover (Some t,_,_)) when (match follow t with TMono _ -> true | _ -> false) ->
-			type_expr ctx e NoValue
 	end in
 	let e = match e.eexpr with
 		| TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1

+ 1 - 1
src/typing/typeloadModule.ml

@@ -671,7 +671,7 @@ let init_module_type ctx context_init do_init (decl,p) =
 				cf_params = f.ef_params;
 			} in
  			if ctx.is_display_file && Display.is_display_position f.ef_name_pos then
- 				DisplayEmitter.display_enum_field ctx f p;
+ 				DisplayEmitter.display_enum_field ctx e f p;
 			e.e_constrs <- PMap.add f.ef_name f e.e_constrs;
 			fields := PMap.add cf.cf_name cf !fields;
 			incr index;

+ 3 - 2
src/typing/typer.ml

@@ -20,6 +20,7 @@ open Ast
 open DisplayTypes.DisplayMode
 open DisplayException
 open DisplayTypes.CompletionResultKind
+open CompletionItem.ClassFieldOrigin
 open Common
 open Type
 open Typecore
@@ -1657,7 +1658,7 @@ and type_object_decl ctx fl with_type p =
 					| Some t -> t
 					| None ->
 						let cf = PMap.find n field_map in
-						if ctx.in_display && Display.is_display_position pn then DisplayEmitter.display_field ctx None cf pn;
+						if ctx.in_display && Display.is_display_position pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn;
 						cf.cf_type
 				in
 				let e = type_expr ctx e (WithType t) in
@@ -1695,7 +1696,7 @@ and type_object_decl ctx fl with_type p =
 			let e = type_expr ctx e Value in
 			(match follow e.etype with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed in structures" e.epos | _ -> ());
 			let cf = mk_field f e.etype (punion pf e.epos) pf in
-			if ctx.in_display && Display.is_display_position pf then DisplayEmitter.display_field ctx None cf pf;
+			if ctx.in_display && Display.is_display_position pf then DisplayEmitter.display_field ctx Unknown CFSMember cf pf;
 			(((f,pf,qs),e) :: l, if is_valid then begin
 				if String.length f > 0 && f.[0] = '$' then error "Field names starting with a dollar are not allowed" p;
 				PMap.add f cf acc

+ 56 - 60
src/typing/typerDisplay.ml

@@ -25,32 +25,65 @@ let completion_item_of_expr ctx e =
 			false
 	in
 	let of_field e origin cf scope =
-		let is_qualified = retype e cf.cf_name cf.cf_type in
-		ITClassField (CompletionClassField.make cf scope origin is_qualified)
+		let is_qualified = retype e cf.cf_name e.etype in
+		make_ci_class_field (CompletionClassField.make cf scope origin is_qualified) (DisplayEmitter.patch_type ctx e.etype)
 	in
 	let of_enum_field e origin ef =
-		let is_qualified = retype e ef.ef_name ef.ef_type in
-		ITEnumField (CompletionEnumField.make ef origin is_qualified)
+		let is_qualified = retype e ef.ef_name e.etype in
+		make_ci_enum_field (CompletionEnumField.make ef origin is_qualified) (DisplayEmitter.patch_type ctx e.etype)
+	in
+	let itexpr e =
+		let t = DisplayEmitter.patch_type ctx e.etype in
+		make_ci_expr {e with etype = t}
 	in
 	let rec loop e = match e.eexpr with
-		| TLocal v -> ITLocal v
+		| TLocal v | TVar(v,_) -> make_ci_local v (DisplayEmitter.patch_type ctx v.v_type)
 		| TField(_,FStatic(c,cf)) -> of_field e (Self (TClassDecl c)) cf CFSStatic
 		| TField(_,(FInstance(c,_,cf) | FClosure(Some(c,_),cf))) -> of_field e (Self (TClassDecl c)) cf CFSMember
 		| TField(_,FEnum(en,ef)) -> of_enum_field e (Self (TEnumDecl en)) ef
 		| TField(e1,FAnon cf) ->
 			begin match follow e1.etype with
 				| TAnon an -> of_field e (AnonymousStructure an) cf CFSMember
-				| _ -> ITExpression e
+				| _ -> itexpr e
 			end
-		| TTypeExpr mt -> ITType(CompletionModuleType.of_module_type mt,ImportStatus.Imported) (* TODO *)
-		| TConst(ct) -> ITLiteral(s_const ct,e.etype)
+		| TTypeExpr mt -> make_ci_type (CompletionModuleType.of_module_type mt) ImportStatus.Imported (Some e.etype) (* TODO *)
+		| TConst (TThis | TSuper) -> itexpr e (* TODO *)
+		| TConst(ct) -> make_ci_literal (s_const ct) e.etype
 		| TObjectDecl _ ->
 			begin match follow e.etype with
-				| TAnon an -> ITAnonymous an
-				| _ -> ITExpression e
+				| TAnon an -> make_ci_anon an e.etype
+				| _ -> itexpr e
 			end
+		| TNew(c,tl,_) ->
+			(* begin match fst e_ast with
+			| EConst (Regexp (r,opt)) ->
+				let present,absent = List.partition (String.contains opt) ['g';'i';'m';'s';'u'] in
+				let doc flag desc = Printf.sprintf "* %s: %s" (String.make 1 flag) desc in
+				let f c = match c with
+					| 'g' -> doc c "global split and replace"
+					| 'i' -> doc c "case insensitive matching"
+					| 'm' -> doc c "multiline matching"
+					| 's' -> doc c "dot also match newlines"
+					| 'u' -> doc c "use UTF-8 matching"
+					| _ -> assert false
+				in
+				let present = List.map f present in
+				let present = match present with [] -> [] | _ -> "\n\nActive flags:\n\n" :: present in
+				let absent = List.map f absent in
+				let absent = match absent with [] -> [] | _ -> "\n\nInactive flags:\n\n" :: absent in
+				(TInst(c,tl)),Some ("Regular expression\n\n" ^ (String.concat "\n" (present @ absent)))
+			| _ -> *)
+				let t,cf = get_constructor ctx c tl e.epos in
+				let t = match follow t with
+					| TFun(args,_) -> TFun(args,TInst(c,tl))
+					| _ -> t
+				in
+				make_ci_class_field (CompletionClassField.make {cf with cf_type = t} CFSConstructor (Self (TClassDecl c)) true) (DisplayEmitter.patch_type ctx t)
+			(* end *)
+		| TCall({eexpr = TConst TSuper; etype = t} as e1,_) ->
+			itexpr e1 (* TODO *)
 		| TParenthesis e1 | TMeta(_,e1) | TCast(e1,_) -> loop e1
-		| _ -> ITExpression e
+		| _ -> itexpr e
 	in
 	loop e
 
@@ -148,49 +181,8 @@ and display_expr ctx e_ast e dk with_type p =
 	| DMSignature ->
 		handle_signature_display ctx e_ast with_type
 	| DMHover ->
-		let rec loop e = match e.eexpr with
-			| TVar(v,_) -> v.v_type,None
-			| TCall({eexpr = TConst TSuper; etype = t},_) -> t,None
-			| TNew({cl_kind = KAbstractImpl a},tl,_) -> TType(abstract_module_type a tl,[]),None
-			| TNew(c,tl,_) ->
-				begin match fst e_ast with
-				| EConst (Regexp (r,opt)) ->
-					let present,absent = List.partition (String.contains opt) ['g';'i';'m';'s';'u'] in
-					let doc flag desc = Printf.sprintf "* %s: %s" (String.make 1 flag) desc in
-					let f c = match c with
-						| 'g' -> doc c "global split and replace"
-						| 'i' -> doc c "case insensitive matching"
-						| 'm' -> doc c "multiline matching"
-						| 's' -> doc c "dot also match newlines"
-						| 'u' -> doc c "use UTF-8 matching"
-						| _ -> assert false
-					in
-					let present = List.map f present in
-					let present = match present with [] -> [] | _ -> "\n\nActive flags:\n\n" :: present in
-					let absent = List.map f absent in
-					let absent = match absent with [] -> [] | _ -> "\n\nInactive flags:\n\n" :: absent in
-					(TInst(c,tl)),Some ("Regular expression\n\n" ^ (String.concat "\n" (present @ absent)))
-				| _ ->
-					let t,cf = get_constructor ctx c tl p in
-					let t = match follow t with
-						| TFun(args,_) -> TFun(args,TInst(c,tl))
-						| _ -> t
-					in
-					if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c;
-					t,cf.cf_doc
-				end
-			| TTypeExpr (TClassDecl {cl_kind = KAbstractImpl a}) -> TType(abstract_module_type a (List.map snd a.a_params),[]),None
-			| TField(e1,FDynamic "bind") when (match follow e1.etype with TFun _ -> true | _ -> false) -> e1.etype,None
-			| TReturn (Some e1) -> loop e1 (* No point in letting the internal Dynamic surface (issue #5655) *)
-			| TField(_,(FStatic(c,cf) | FInstance(c,_,cf) | FClosure(Some(c,_),cf))) ->
-				if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c;
-				e.etype,cf.cf_doc
-			| TField(_,FEnum(_,ef)) ->
-				e.etype,ef.ef_doc
-			| _ -> e.etype,None
-		in
-		let t,doc = loop e in
-		raise_hover (Some (DisplayEmitter.patch_type ctx t)) p doc
+		let item = completion_item_of_expr ctx e in
+		raise_hover item e.epos
 	| DMUsage _ ->
 		let rec loop e = match e.eexpr with
 		| TField(_,FEnum(_,ef)) ->
@@ -280,11 +272,13 @@ let handle_structure_display ctx e an =
 	| EObjectDecl fl ->
 		let fields = PMap.foldi (fun k cf acc ->
 			if Expr.field_mem_assoc k fl then acc
-			else (ITClassField(CompletionClassField.make cf CFSMember (AnonymousStructure an) true)) :: acc
+			else (make_ci_class_field (CompletionClassField.make cf CFSMember (AnonymousStructure an) true) cf.cf_type) :: acc
 		) an.a_fields [] in
 		raise_fields fields CRStructureField None false
 	| EBlock [] ->
-		let fields = PMap.foldi (fun _ cf acc -> ITClassField(CompletionClassField.make cf CFSMember (AnonymousStructure an) true) :: acc) an.a_fields [] in
+		let fields = PMap.foldi (fun _ cf acc ->
+			make_ci_class_field (CompletionClassField.make cf CFSMember (AnonymousStructure an) true) cf.cf_type :: acc
+		) an.a_fields [] in
 		raise_fields fields CRStructureField None false
 	| _ ->
 		error "Expected object expression" p
@@ -302,7 +296,8 @@ let handle_display ctx e_ast dk with_type =
 		| DMSignature ->
 			raise_signatures [((arg,mono),doc)] 0 0
 		| _ ->
-			raise_hover (Some (TFun(arg,mono))) (pos e_ast) doc
+			let t = TFun(arg,mono) in
+			raise_hover (make_ci_expr (mk (TIdent "trace") t (pos e_ast))) (pos e_ast);
 		end
 	| (EConst (Ident "trace"),_),_ ->
 		let doc = Some "Print given arguments" in
@@ -312,7 +307,8 @@ let handle_display ctx e_ast dk with_type =
 		| DMSignature ->
 			raise_signatures [((arg,ret),doc)] 0 0
 		| _ ->
-			raise_hover (Some (TFun(arg,ret))) (pos e_ast) doc
+			let t = TFun(arg,ret) in
+			raise_hover (make_ci_expr (mk (TIdent "trace") t (pos e_ast))) (pos e_ast);
 		end
 	| (EConst (Ident "_"),p),WithType t ->
 		mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *)
@@ -324,7 +320,7 @@ let handle_display ctx e_ast dk with_type =
 	| Error ((Type_not_found (path,_) | Module_not_found path),_) as err ->
 		if ctx.com.json_out = None then	begin try
 			let s = s_type_path path in
-			raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((ITModule s),p)) None false
+			raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((make_ci_module s),p)) None false
 		with Not_found ->
 			raise err
 		end else
@@ -332,7 +328,7 @@ let handle_display ctx e_ast dk with_type =
 	| DisplayException(DisplayFields(l,CRTypeHint,p,b)) when (match fst e_ast with ENew _ -> true | _ -> false) ->
 		let timer = Timer.timer ["display";"toplevel";"filter ctors"] in
 		ctx.pass <- PBuildClass;
-		let l = List.filter (function
+		let l = List.filter (fun item -> match item.ci_kind with
 			| ITType({kind = (Class | Abstract)} as mt,_) when not mt.is_private ->
 				begin match mt.has_constructor with
 				| Yes -> true