فهرست منبع

fix #5145, use interface list in TDClass to allow multiple extends (#5213)

* use interface list for TDClass isInterface to allow multiple extends, issue 5145

* add HExtends to extended interface list

* add test for #5154

* add test for backwards compatible behavior, and get the issue # right

* actually add test for backwards compatible behavior

* - fixed interface reification syntax for multiple extends
- fixed building of typedefinition object for reified interfaces with multiple extends
- added test for reified interface with multiple extends
ousado 9 سال پیش
والد
کامیت
0be79b9f85
4فایلهای تغییر یافته به همراه88 افزوده شده و 5 حذف شده
  1. 10 3
      src/macro/interp.ml
  2. 7 2
      src/syntax/parser.ml
  3. 69 0
      tests/misc/projects/Issue5145/Main.hx
  4. 2 0
      tests/misc/projects/Issue5145/compile.hxml

+ 10 - 3
src/macro/interp.ml

@@ -5110,9 +5110,16 @@ let decode_type_def v =
 		ETypedef (mk (if isExtern then [EExtern] else []) (CTAnonymous fields,Globals.null_pos))
 		ETypedef (mk (if isExtern then [EExtern] else []) (CTAnonymous fields,Globals.null_pos))
 	| 2, [ext;impl;interf] ->
 	| 2, [ext;impl;interf] ->
 		let flags = if isExtern then [HExtern] else [] in
 		let flags = if isExtern then [HExtern] else [] in
-		let flags = (match interf with VNull | VBool false -> flags | VBool true -> HInterface :: flags | _ -> raise Invalid_expr) in
+		let is_interface = (match interf with VNull | VBool false -> false | VBool true -> true | _ -> raise Invalid_expr ) in
+		let interfaces = (match opt (fun v -> List.map decode_path (dec_array v)) impl with Some l -> l | _ -> [] ) in
 		let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in
 		let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in
-		let flags = (match opt (fun v -> List.map decode_path (dec_array v)) impl with None -> flags | Some l -> List.map (fun t -> HImplements t) l @ flags) in
+		let flags = if is_interface then begin
+				let flags = HInterface :: flags in
+				List.map (fun t -> HExtends t) interfaces @ flags
+			end else begin
+				List.map (fun t -> HImplements t) interfaces @ flags
+			end
+		in
 		EClass (mk flags fields)
 		EClass (mk flags fields)
 	| 3, [t] ->
 	| 3, [t] ->
 		ETypedef (mk (if isExtern then [EExtern] else []) (decode_ctype t))
 		ETypedef (mk (if isExtern then [EExtern] else []) (decode_ctype t))
@@ -5179,4 +5186,4 @@ encode_import_ref := encode_import;
 decode_import_ref := decode_import;
 decode_import_ref := decode_import;
 eval_expr_ref := eval_expr;
 eval_expr_ref := eval_expr;
 encode_import_ref := encode_import;
 encode_import_ref := encode_import;
-encode_module_type_ref := encode_module_type;
+encode_module_type_ref := encode_module_type;

+ 7 - 2
src/syntax/parser.ml

@@ -505,7 +505,12 @@ let reify in_macro =
 			List.iter (function
 			List.iter (function
 				| HExtern | HPrivate -> ()
 				| HExtern | HPrivate -> ()
 				| HInterface -> interf := true;
 				| HInterface -> interf := true;
-				| HExtends t -> ext := Some (to_tpath t p)
+				| HExtends t -> ext := (match !ext with
+					| None -> Some (to_tpath t p)
+					| Some _ -> begin
+						impl := (to_tpath t p) :: !impl;
+						!ext
+					  end)
 				| HImplements i-> impl := (to_tpath i p) :: !impl
 				| HImplements i-> impl := (to_tpath i p) :: !impl
 			) d.d_flags;
 			) d.d_flags;
 			to_obj [
 			to_obj [
@@ -681,7 +686,7 @@ and parse_type_decl s =
 and parse_class doc meta cflags need_name s =
 and parse_class doc meta cflags need_name s =
 	let opt_name = if need_name then type_name else (fun s -> match popt type_name s with None -> "",null_pos | Some n -> n) in
 	let opt_name = if need_name then type_name else (fun s -> match popt type_name s with None -> "",null_pos | Some n -> n) in
 	match s with parser
 	match s with parser
-	| [< n , p1 = parse_class_flags; name = opt_name; tl = parse_constraint_params; hl = psep Comma parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields (not need_name) p1 >] ->
+	| [< n , p1 = parse_class_flags; name = opt_name; tl = parse_constraint_params; hl = plist parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields (not need_name) p1 >] ->
 		(EClass {
 		(EClass {
 			d_name = name;
 			d_name = name;
 			d_doc = doc;
 			d_doc = doc;

+ 69 - 0
tests/misc/projects/Issue5145/Main.hx

@@ -0,0 +1,69 @@
+import haxe.macro.Context;
+import haxe.macro.Type;
+import haxe.macro.Expr;
+using haxe.macro.Tools;
+
+interface IA {}
+interface IB {}
+interface IC extends IA extends IB {}
+
+class Main {
+
+    static function main() test();
+
+    macro static function test() {
+
+        function get_type_path(ct:ComplexType) return switch ct {
+            case TPath(tp):tp;
+            case _:throw("bad");
+        };
+
+        var td = macro class ID {};
+        var ia = macro : Main.IA;
+        var ib = macro : Main.IB;
+        var ic = macro : Main.IC;
+        td.kind = TDClass(null,[ia,ib,ic].map(get_type_path),true);
+        Context.defineType(td);
+        var t = Context.getType("ID");
+        switch t {
+            case TInst(_.get()=>tt,_):
+                if (tt.interfaces.length != 3)
+                    Context.error("Number of extended interfaces must be 3",Context.currentPos());
+            case _:
+        }
+
+        var td = macro class IE {};
+        var ia = macro : Main.IA;
+        var ib = macro : Main.IB;
+        var ic = macro : Main.IC;
+
+        var ia_tpath = switch ia {
+            case TPath(tp):tp;
+            case _:Context.error("must be TPath",Context.currentPos());
+        }
+        td.kind = TDClass(ia_tpath,[ib,ic].map(get_type_path),true);
+        Context.defineType(td);
+
+        var t = Context.getType("IE");
+        switch t {
+            case TInst(_.get()=>tt,_):
+                if (tt.interfaces.length != 3)
+                    Context.error("Number of extended interfaces must be 3",Context.currentPos());
+            case _:
+        }
+
+        var reification = macro interface IF extends Main.IA extends Main.IB {
+
+        };
+        Context.defineType(reification);
+        var t = Context.getType("IF");
+        switch t {
+            case TInst(_.get()=>tt,_):
+                if (tt.interfaces.length != 2){
+                    Context.error("Number of extended interfaces must be 2",Context.currentPos());
+                }
+            case _:
+        }
+        return macro null;
+    }
+}

+ 2 - 0
tests/misc/projects/Issue5145/compile.hxml

@@ -0,0 +1,2 @@
+
+-main Main