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

support some display stuff on imports

Simon Krajewski 9 жил өмнө
parent
commit
9aea259cdb

+ 38 - 1
src/display/display.ml

@@ -284,4 +284,41 @@ let print_module_symbols (pack,decls) =
 	let js = JArray jl in
 	let b = Buffer.create 0 in
 	write_json (Buffer.add_string b) js;
-	Buffer.contents b
+	Buffer.contents b
+
+type import_display_kind =
+	| IDKPackage of string list
+	| IDKModule of string list * string
+	| IDKSubType of string list * string * string
+	| IDKModuleField of string list * string * string
+	| IDKSubTypeField of string list * string * string * string
+	| IDK
+
+let convert_import_to_something_usable path =
+	let rec loop pack m t = function
+		| (s,p) :: l ->
+			let is_lower = is_lower_ident s in
+			let is_display_pos = encloses_position !Parser.resume_display p in
+			begin match is_lower,m,t with
+				| _,None,Some _ | false,Some _,Some _ ->
+					assert false (* impossible, I think *)
+				| true,Some m,None ->
+					if is_display_pos then IDKModuleField(List.rev pack,m,s)
+					else IDK (* assume that we're done *)
+				| true,Some m,Some t ->
+					if is_display_pos then IDKSubTypeField(List.rev pack,m,t,s)
+					else IDK
+				| true,None,None ->
+					if is_display_pos then IDKPackage (List.rev (s :: pack))
+					else loop (s :: pack) m t l
+				| false,Some sm,None ->
+					if is_display_pos then IDKSubType (List.rev pack,sm,s)
+					else loop pack m (Some s) l
+				| false,None,None ->
+					if is_display_pos then IDKModule (List.rev pack,s)
+					else loop pack (Some s) None l
+			end
+		| [] ->
+			IDK
+	in
+	loop [] None None path

+ 36 - 6
src/typing/typeload.ml

@@ -345,6 +345,11 @@ let rec load_type_def ctx p t =
 			with
 				Exit -> next()
 
+let resolve_position_by_path ctx path p =
+	let mt = load_type_def ctx p path in
+	let p = (t_infos mt).mt_pos in
+	raise (Display.DisplayPosition [p])
+
 let check_param_constraints ctx types t pl c p =
 	match follow t with
 	| TMono _ -> ()
@@ -1875,12 +1880,8 @@ let build_module_def ctx mt meta fvars context_init fbuild =
 
 let is_display_file ctx p = match ctx.com.display with
 	| DMNone -> false
-	| DMResolve s ->
-		let mt = load_type_def ctx p {tname = s; tpackage = []; tsub = None; tparams = []} in
-		let p = (t_infos mt).mt_pos in
-		raise (Display.DisplayPosition [p]);
-	| _ ->
-		Display.is_display_file p
+	| DMResolve s -> resolve_position_by_path ctx {tname = s; tpackage = []; tsub = None; tparams = []} p
+	| _ -> Display.is_display_file p
 
 module ClassInitializer = struct
 	type class_init_ctx = {
@@ -2848,6 +2849,35 @@ 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 begin match Display.convert_import_to_something_usable path,ctx.com.display with
+			| Display.IDKPackage sl,_ ->
+				raise (Parser.TypePath(sl,None,true))
+			| Display.IDKModule(sl,s),DMPosition ->
+				(* We assume that we want to go to the module file, not a specific type
+				   which might not even exist anyway. *)
+				let mt = ctx.g.do_load_module ctx (sl,s) p in
+				let p = { pfile = mt.m_extra.m_file; pmin = 0; pmax = 0} in
+				raise (Display.DisplayPosition [p])
+			| Display.IDKModule(sl,s),_ ->
+				(* TODO: wait till nadako requests @type display for these, then implement it somehow *)
+				raise (Parser.TypePath(sl,Some(s,false),true))
+			| Display.IDKSubType(sl,sm,st),DMPosition ->
+				resolve_position_by_path ctx { tpackage = sl; tname = sm; tparams = []; tsub = Some st} p
+			| Display.IDKSubType(sl,sm,st),_ ->
+				raise (Parser.TypePath(sl @ [sm],Some(st,false),true))
+			| (Display.IDKSubTypeField(sl,sm,st,sf) | Display.IDKModuleField(sl,(sm as st),sf)),_ ->
+				let m = ctx.g.do_load_module ctx (sl,sm) p in
+				List.iter (fun t -> match t with
+					| TClassDecl c when snd c.cl_path = st ->
+						ignore(c.cl_build());
+						let cf = PMap.find sf c.cl_statics in
+						Display.display_field ctx.com.display cf p
+					| _ ->
+						()
+				) m.m_types;
+			| Display.IDK,_ ->
+				()
+		end;
 		let rec loop acc = function
 			| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 			| rest -> List.rev acc, rest

+ 12 - 0
tests/display/src/DisplayTestCase.hx

@@ -1,3 +1,7 @@
+import Types;
+
+using Lambda;
+
 @:autoBuild(Macro.buildTestCase())
 class DisplayTestCase {
 	var ctx:DisplayTestContext;
@@ -45,6 +49,14 @@ class DisplayTestCase {
 		}
 	}
 
+	function hasField(a:Array<FieldElement>, name:String, type:String):Bool {
+		return a.exists(function(t) return t.type == type && t.name == name);
+	}
+
+	function hasPath(a:Array<FieldElement>, name:String):Bool {
+		return a.exists(function(t) return t.name == name);
+	}
+
 	function report(message, pos:haxe.PosInfos) {
 		haxe.Log.trace(message, pos);
 	}

+ 0 - 11
tests/display/src/cases/Completion.hx

@@ -1,8 +1,5 @@
 package cases;
 
-import Types;
-using Lambda;
-
 class Completion extends DisplayTestCase {
 	/**
 	var s = { foo: 1 };
@@ -48,12 +45,4 @@ class Completion extends DisplayTestCase {
 	@:funcCode function testHaxeUnitPort5() {
 		eq(true, hasPath(fields(pos(1)), "ExprDef"));
 	}
-
-	static function hasField(a:Array<FieldElement>, name:String, type:String):Bool {
-		return a.exists(function(t) return t.type == type && t.name == name);
-	}
-
-	static function hasPath(a:Array<FieldElement>, name:String):Bool {
-		return a.exists(function(t) return t.name == name);
-	}
 }

+ 18 - 0
tests/display/src/cases/IImport.hx

@@ -0,0 +1,18 @@
+package cases;
+
+import Types;
+using Lambda;
+
+class IImport extends DisplayTestCase {
+	/**
+	import ha{-1-}xe.ma{-2-}cro.Exp{-3-}rTools.Expr{-4-}ArrayTools.it{-5-}er;
+	**/
+	function testImport1() {
+		eq(true, hasPath(fields(pos(1)), "Serializer"));
+		eq(true, hasPath(fields(pos(2)), "ExprTools"));
+		eq(true, hasPath(fields(pos(3)), "ExprArrayTools"));
+		eq(true, hasField(fields(pos(4)), "iter", "el : Array<haxe.macro.Expr> -> f : (haxe.macro.Expr -> Void) -> Void"));
+		eq("el : Array<haxe.macro.Expr> -> f : (haxe.macro.Expr -> Void) -> Void", type(pos(5)));
+		// TODO: test @position display. A bit annoying because it actually ends up in other files and we can't use markers.
+	}
+}