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 years ago
parent
commit
dca81bddf5
5 changed files with 83 additions and 34 deletions
  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
 	| IAsName of string
 	| IAll
 	| IAll
 
 
-type import = (string * pos) list * import_mode
+type import = placed_name list * import_mode
 
 
 type type_def =
 type type_def =
 	| EClass of (class_flag, class_field list) definition
 	| EClass of (class_flag, class_field list) definition
@@ -463,7 +463,7 @@ type type_def =
 	| ETypedef of (enum_flag, type_hint) definition
 	| ETypedef of (enum_flag, type_hint) definition
 	| EAbstract of (abstract_flag, class_field list) definition
 	| EAbstract of (abstract_flag, class_field list) definition
 	| EImport of import
 	| EImport of import
-	| EUsing of placed_type_path
+	| EUsing of placed_name list
 
 
 type type_decl = type_def * pos
 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 =
 and parse_type_decl s =
 	match s with parser
 	match s with parser
 	| [< '(Kwd Import,p1) >] -> parse_import s p1
 	| [< '(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 >] ->
 	| [< doc = get_doc; meta = parse_meta; c = parse_common_flags; s >] ->
 		match s with parser
 		match s with parser
 		| [< n , p1 = parse_enum_flags; name = type_name; tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] ->
 		| [< 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
 	) in
 	(EImport (path,mode),punion p1 p2)
 	(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 =
 and parse_abstract_relations s =
 	match s with parser
 	match s with parser
 	| [< '(Const (Ident "to"),_); t = parse_complex_type >] -> AToType t
 	| [< '(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;
 	List.iter (check_module_types ctx m p) m.m_types;
 	Hashtbl.add ctx.g.modules m.m_path m
 	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
 	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
 	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
 	match decl with
 	| EImport (path,mode) ->
 	| EImport (path,mode) ->
 		ctx.m.module_imports <- (path,mode) :: ctx.m.module_imports;
 		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
 		let rec loop acc = function
 			| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 			| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 			| rest -> List.rev acc, rest
 			| 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
 						error "No statics to import from this type" p
 				) :: !context_init
 				) :: !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 *)
 		(* do the import first *)
 		let types = (match t.tsub with
 		let types = (match t.tsub with
 			| None ->
 			| None ->

+ 4 - 1
src/typing/typer.ml

@@ -4767,7 +4767,10 @@ let make_macro_api ctx p =
 			) types in
 			) types in
 			let pos = (match types with [] -> Ast.null_pos | (_,p) :: _ -> p) 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 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 types = imports @ usings @ types in
 			let mpath = Ast.parse_path m in
 			let mpath = Ast.parse_path m in
 			begin try
 			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)));
 		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.
 		// 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.
+	}
 }
 }