Przeglądaj źródła

support proper display on `super()` and `super.method()` (closes #5149)

Simon Krajewski 9 lat temu
rodzic
commit
30a55e9504
3 zmienionych plików z 78 dodań i 3 usunięć
  1. 2 1
      src/syntax/ast.ml
  2. 40 2
      src/typing/typer.ml
  3. 36 0
      tests/display/src/cases/Super.hx

+ 2 - 1
src/syntax/ast.ml

@@ -834,7 +834,8 @@ let s_expr e =
 		| ETernary (e1,e2,e3) -> s_expr_inner tabs e1 ^ " ? " ^ s_expr_inner tabs e2 ^ " : " ^ s_expr_inner tabs e3
 		| ECheckType (e,(t,_)) -> "(" ^ s_expr_inner tabs e ^ " : " ^ s_complex_type tabs t ^ ")"
 		| EMeta (m,e) -> s_metadata tabs m ^ " " ^ s_expr_inner tabs e
-		| _ -> ""
+		| EDisplay (e1,_) -> Printf.sprintf "#DISPLAY(%s)" (s_expr_inner tabs e1)
+		| EDisplayNew tp -> Printf.sprintf "#DISPLAY_NEW(%s)" (s_complex_type_path tabs tp)
 	and s_expr_list tabs el sep =
 		(String.concat sep (List.map (s_expr_inner tabs) el))
 	and s_complex_type_path tabs (t,_) =

+ 40 - 2
src/typing/typer.ml

@@ -3442,7 +3442,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EField(_,n) when n.[0] = '$' ->
 		error "Field names starting with $ are not allowed" p
 	| EConst (Ident s) ->
-		if s = "super" && with_type <> NoValue then error "Cannot use super as value" p;
+		if s = "super" && with_type <> NoValue && not ctx.in_display then error "Cannot use super as value" p;
 		let e = maybe_type_against_enum ctx (fun () -> type_ident ctx s p MGet) with_type p in
 		acc_get ctx e p
 	| EField _
@@ -3778,11 +3778,23 @@ and handle_display ctx e_ast iscall with_type =
 	in
 	ctx.in_display <- fst old;
 	ctx.in_call_args <- snd old;
+	let get_super_constructor () = match ctx.curclass.cl_super with
+		| None -> error "Current class does not have a super" p
+		| Some (c,params) ->
+			let _, f = get_constructor ctx c params p in
+			f
+	in
 	match ctx.com.display with
 	| DMResolve _ ->
 		assert false
 	| DMType ->
-		raise (Display.DisplayType ((match e.eexpr with TVar(v,_) -> v.v_type | _ -> e.etype),p))
+		let t = match e.eexpr with
+			| TVar(v,_) -> v.v_type
+			| TCall({eexpr = TConst TSuper; etype = t},_) -> t
+			| TNew(c,tl,_) -> TInst(c,tl)
+			| _ -> e.etype
+		in
+		raise (Display.DisplayType (t,p))
 	| DMUsage ->
 		let rec loop e = match e.eexpr with
 		| TField(_,FEnum(_,ef)) ->
@@ -3801,6 +3813,18 @@ and handle_display ctx e_ast iscall with_type =
 			with Not_found ->
 				()
 			end
+		| TCall({eexpr = TConst TSuper},_) ->
+			begin try
+				let cf = get_super_constructor() in
+				cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta;
+			with Not_found ->
+				()
+			end
+		| TConst TSuper ->
+			begin match ctx.curclass.cl_super with
+				| None -> ()
+				| Some (c,_) -> c.cl_meta <- (Meta.Usage,[],p) :: c.cl_meta;
+			end
 		| TCall(e1,_) ->
 			loop e1
 		| _ ->
@@ -3821,6 +3845,18 @@ and handle_display ctx e_ast iscall with_type =
 			with Not_found ->
 				[]
 			end
+		| TCall({eexpr = TConst TSuper},_) ->
+			begin try
+				let cf = get_super_constructor() in
+				[cf.cf_pos]
+			with Not_found ->
+				[]
+			end
+		| TConst TSuper ->
+			begin match ctx.curclass.cl_super with
+				| None -> []
+				| Some (c,_) -> [c.cl_pos]
+			end
 		| TCall(e1,_) ->
 			loop e1
 		| _ ->
@@ -4129,6 +4165,8 @@ and type_call ctx e el (with_type:with_type) p =
 			mk (TCall (mk (TLocal v_unprotect) t p,[e])) e.etype e.epos
 		else
 			e
+	| (EDisplay((EConst (Ident "super"),_ as e1),false),_),_ ->
+		handle_display ctx (ECall(e1,el),p) false with_type
 	| (EConst (Ident "super"),sp) , el ->
 		if ctx.curfun <> FunConstructor then error "Cannot call super constructor outside class constructor" p;
 		let el, t = (match ctx.curclass.cl_super with

+ 36 - 0
tests/display/src/cases/Super.hx

@@ -0,0 +1,36 @@
+package cases;
+
+class Super extends DisplayTestCase {
+	/**
+	class Base<T> {
+		public {-1-}function new() { }{-2-}
+	}
+	class Main extends Base<String> {
+		function new() {
+			{-4-}su{-3-}per(){-5-};
+		}
+	}
+	**/
+	function testSuperCall() {
+		eq(range(1, 2), position(pos(3)));
+		eq("cases.Base<String>", type(pos(3)));
+		arrayEq([range(4, 5)], usage(pos(3)));
+	}
+
+	/**
+	{-1-}class{-2-} Base<T> {
+		public {-4-}function test() { }{-5-}
+	}
+	class Main extends Base<String> {
+		override function test() {
+			su{-3-}per.te{-6-}st();
+		}
+	}
+	**/
+	function testSuperField() {
+		eq(range(1, 2), position(pos(3)));
+		eq("cases.Base<String>", type(pos(3)));
+		eq(range(4, 5), position(pos(6)));
+		eq("Void -> Void", type(pos(6)));
+	}
+}