Browse Source

[macro] Build order vs inheritance (#11582)

* [macro] more predictable build macro order

* [tests] add macro build order test

* [tests] Run our build macro before utest build macro
Rudy Ges 1 year ago
parent
commit
539601b839

+ 1 - 1
src/typing/typeloadCheck.ml

@@ -513,7 +513,7 @@ module Inheritance = struct
 				match m with
 				| Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,{ c.cl_pos with pmax = c.cl_pos.pmin }(* prevent display metadata *)) :: m :: c.cl_meta
 				| _ -> ()
-			) csup.cl_meta;
+			) (List.rev csup.cl_meta);
 			if has_class_flag csup CFinal && not (((has_class_flag csup CExtern) && Meta.has Meta.Hack c.cl_meta) || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then
 				raise_typing_error ("Cannot extend a final " ^ if (has_class_flag c CInterface) then "interface" else "class") p;
 		in

+ 27 - 0
tests/misc/projects/Issue11582/Macro.macro.hx

@@ -0,0 +1,27 @@
+class Macro {
+	static var id = 0;
+	static function build(i:String) {
+		if (haxe.macro.Context.getLocalClass().get().isInterface) return null;
+
+		var hasMacros = false;
+		var fields = haxe.macro.Context.getBuildFields();
+		for (f in fields) {
+			if (f.name == "macros") {
+				hasMacros = true;
+				break;
+			}
+		}
+
+		if (!hasMacros)
+			fields = (macro class A {
+				public static var macros = [];
+			}).fields.concat(fields);
+
+		var id = '_' + id++;
+		fields.push((macro class A {
+			 static var $id = {macros.push($v{i}); 0;};
+		}).fields[0]);
+
+		return fields;
+	}
+}

+ 51 - 0
tests/misc/projects/Issue11582/Main.hx

@@ -0,0 +1,51 @@
+class Main {
+	static function main() {
+		trace("Foo");
+		trace(Foo1.macros);
+		trace(Foo2.macros);
+		trace(Foo3.macros);
+		trace(Foo4.macros);
+
+		trace("Bar");
+		trace(Bar1.macros);
+		trace(Bar2.macros);
+		trace(Bar3.macros);
+
+		trace("Baz");
+		trace(Baz1.macros);
+		trace(Baz2.macros);
+		trace(Baz3.macros);
+	}
+}
+
+@:autoBuild(Macro.build("I1"))
+interface I1 {}
+
+@:autoBuild(Macro.build("I2"))
+interface I2 {}
+
+@:autoBuild(Macro.build("auto Foo1 (1)"))
+@:autoBuild(Macro.build("auto Foo1 (2)"))
+@:build(Macro.build("Foo1"))
+class Foo1 implements I1 implements I2 {}
+
+@:build(Macro.build("Foo2"))
+class Foo2 extends Foo1 {}
+
+@:build(Macro.build("Foo3 (1)"))
+@:build(Macro.build("Foo3 (2)"))
+class Foo3 extends Foo2 {}
+
+@:build(Macro.build("Foo4"))
+class Foo4 extends Foo3 {}
+
+class Bar1 implements I2 implements I1 {}
+class Bar2 extends Bar1 {}
+class Bar3 extends Bar2 {}
+
+@:autoBuild(Macro.build("I3"))
+interface I3 extends I1 {}
+
+class Baz1 implements I3 implements I2 {}
+class Baz2 extends Baz1 {}
+class Baz3 extends Baz2 {}

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

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

+ 13 - 0
tests/misc/projects/Issue11582/compile.hxml.stdout

@@ -0,0 +1,13 @@
+Main.hx:3: Foo
+Main.hx:4: [I2,I1,Foo1]
+Main.hx:5: [I2,I1,auto Foo1 (1),auto Foo1 (2),Foo2]
+Main.hx:6: [I2,I1,auto Foo1 (1),auto Foo1 (2),Foo3 (1),Foo3 (2)]
+Main.hx:7: [I2,I1,auto Foo1 (1),auto Foo1 (2),Foo4]
+Main.hx:9: Bar
+Main.hx:10: [I1,I2]
+Main.hx:11: [I1,I2]
+Main.hx:12: [I1,I2]
+Main.hx:14: Baz
+Main.hx:15: [I2,I1,I3]
+Main.hx:16: [I2,I1,I3]
+Main.hx:17: [I2,I1,I3]

+ 3 - 1
tests/server/src/TestCase.hx

@@ -18,7 +18,9 @@ using StringTools;
 using Lambda;
 
 @:autoBuild(utils.macro.BuildHub.build())
-class TestCase implements ITest {
+interface ITestCase {}
+
+class TestCase implements ITest implements ITestCase {
 	static public var debugLastResult:{
 		hasError:Bool,
 		stdout:String,