Browse Source

rework EUsing to be position-aware as well

I hope I didn't miss anything in the parser or elsewhere...
Simon Krajewski 9 năm trước cách đây
mục cha
commit
dca81bddf5
5 tập tin đã thay đổi với 83 bổ sung34 xóa
  1. 2 2
      src/syntax/ast.ml
  2. 24 1
      src/syntax/parser.ml
  3. 42 30
      src/typing/typeload.ml
  4. 4 1
      src/typing/typer.ml
  5. 11 0
      tests/display/src/cases/IImport.hx

+ 2 - 2
src/syntax/ast.ml

@@ -455,7 +455,7 @@ type import_mode =
 	| IAsName of string
 	| IAll
 
-type import = (string * pos) list * import_mode
+type import = placed_name list * import_mode
 
 type type_def =
 	| EClass of (class_flag, class_field list) definition
@@ -463,7 +463,7 @@ type type_def =
 	| ETypedef of (enum_flag, type_hint) definition
 	| EAbstract of (abstract_flag, class_field list) definition
 	| EImport of import
-	| EUsing of placed_type_path
+	| EUsing of placed_name list
 
 type type_decl = type_def * pos
 

+ 24 - 1
src/syntax/parser.ml

@@ -594,7 +594,7 @@ and parse_type_decls pack acc s =
 and parse_type_decl s =
 	match s with parser
 	| [< '(Kwd Import,p1) >] -> parse_import s p1
-	| [< '(Kwd Using,p1); t = parse_type_path; p2 = semicolon >] -> EUsing t, punion p1 p2
+	| [< '(Kwd Using,p1) >] -> parse_using s p1
 	| [< doc = get_doc; meta = parse_meta; c = parse_common_flags; s >] ->
 		match s with parser
 		| [< n , p1 = parse_enum_flags; name = type_name; tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] ->
@@ -689,6 +689,29 @@ and parse_import s p1 =
 	) in
 	(EImport (path,mode),punion p1 p2)
 
+and parse_using s p1 =
+	let rec loop acc =
+		match s with parser
+		| [< '(Dot,p) >] ->
+			begin match s with parser
+			| [< '(Const (Ident k),p) >] ->
+				loop ((k,p) :: acc)
+			| [< '(Kwd Macro,p) >] ->
+				loop (("macro",p) :: acc)
+			| [< '(Kwd Extern,p) >] ->
+				loop (("extern",p) :: acc)
+			| [< >] ->
+				serror()
+			end
+		| [< '(Semicolon,p2) >] ->
+			p2,List.rev acc
+	in
+	let p2, path = (match s with parser
+		| [< '(Const (Ident name),p) >] -> loop [name,p]
+		| [< >] -> serror()
+	) in
+	(EUsing path,punion p1 p2)
+
 and parse_abstract_relations s =
 	match s with parser
 	| [< '(Const (Ident "to"),_); t = parse_complex_type >] -> AToType t

+ 42 - 30
src/typing/typeload.ml

@@ -2837,6 +2837,36 @@ let add_module ctx m p =
 	List.iter (check_module_types ctx m p) m.m_types;
 	Hashtbl.add ctx.g.modules m.m_path m
 
+let handle_path_display ctx path p =
+	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,_ ->
+			()
+
 (*
 	In this pass, we can access load and access other modules types, but we cannot follow them or access their structure
 	since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate
@@ -2849,35 +2879,7 @@ 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;
+		if Display.is_display_file p then handle_path_display ctx path p;
 		let rec loop acc = function
 			| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 			| rest -> List.rev acc, rest
@@ -2989,7 +2991,17 @@ let init_module_type ctx context_init do_init (decl,p) =
 						error "No statics to import from this type" p
 				) :: !context_init
 			))
-	| EUsing (t,_) ->
+	| EUsing path ->
+		if Display.is_display_file p then handle_path_display ctx path p;
+		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 = [] }
+				else { tpackage = List.rev (List.map fst sl); tname = s2; tsub = Some s1; tparams = [] }
+			| (s1,_) :: sl ->
+				{ tpackage = List.rev (List.map fst sl); tname = s1; tsub = None; tparams = [] }
+			| [] ->
+				assert false
+		in
 		(* do the import first *)
 		let types = (match t.tsub with
 			| None ->

+ 4 - 1
src/typing/typer.ml

@@ -4767,7 +4767,10 @@ let make_macro_api ctx p =
 			) types in
 			let pos = (match types with [] -> Ast.null_pos | (_,p) :: _ -> p) in
 			let imports = List.map (fun (il,ik) -> EImport(il,ik),pos) imports in
-			let usings = List.map (fun tp -> EUsing (tp,null_pos),pos) usings in
+			let usings = List.map (fun tp ->
+				let sl = tp.tpackage @ [tp.tname] @ (match tp.tsub with None -> [] | Some s -> [s]) in
+				EUsing (List.map (fun s -> s,null_pos) sl),pos
+			) usings in
 			let types = imports @ usings @ types in
 			let mpath = Ast.parse_path m in
 			begin try

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

@@ -15,4 +15,15 @@ class IImport extends DisplayTestCase {
 		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.
 	}
+
+	/**
+	using ha{-1-}xe.ma{-2-}cro.Exp{-3-}rTools.Expr{-4-}ArrayTools;
+	**/
+	function testUsing1() {
+		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"));
+		// TODO: test @position display. A bit annoying because it actually ends up in other files and we can't use markers.
+	}
 }