Forráskód Böngészése

[hl] Fix interface override function resolution (#11723)

* [hl] Fix interface override function resolution

* [tests] add test

* [hl] do not rely on sort_uniq implem keep first element
Yuxiao Mao 1 éve
szülő
commit
3b8f2e04e8
2 módosított fájl, 124 hozzáadás és 2 törlés
  1. 9 2
      src/generators/genhl.ml
  2. 115 0
      tests/unit/src/unit/issues/Issue11723.hx

+ 9 - 2
src/generators/genhl.ml

@@ -570,10 +570,17 @@ and class_type ?(tref=None) ctx c pl statics =
 		let t = HVirtual vp in
 		ctx.cached_types <- PMap.add key_path t ctx.cached_types;
 		let rec loop c =
-			let fields = List.fold_left (fun acc (i,_) -> loop i @ acc) [] c.cl_implements in
-			PMap.fold (fun cf acc -> cfield_type ctx cf :: acc) c.cl_fields fields
+			let rec concat_uniq fields pfields =
+				match pfields with
+				| (n,_,_) as pf::pfl -> if List.exists (fun (n1,_,_) -> n1 = n) fields then concat_uniq fields pfl else concat_uniq (pf::fields) pfl
+				| [] -> fields
+			in
+			let pfields = List.fold_left (fun acc (i,_) -> loop i @ acc) [] c.cl_implements in
+			let fields = PMap.fold (fun cf acc -> cfield_type ctx cf :: acc) c.cl_fields [] in
+			concat_uniq fields pfields
 		in
 		let fields = loop c in
+		let fields = List.sort (fun (n1,_,_) (n2,_,_) -> compare n1 n2) fields in
 		vp.vfields <- Array.of_list fields;
 		Array.iteri (fun i (n,_,_) -> vp.vindex <- PMap.add n i vp.vindex) vp.vfields;
 		t

+ 115 - 0
tests/unit/src/unit/issues/Issue11723.hx

@@ -0,0 +1,115 @@
+package unit.issues;
+
+@:keep
+private interface IEntity {
+	var id:Int;
+	function getVariable(varName:String):IVariable;
+	function containsVariable(varName:String):Bool;
+}
+
+@:keep
+private interface IUser extends IEntity {
+	var id:Int;
+	var name:String;
+	function getVariable(name:String):IUserVariable;
+	function setVariable(userVariable:IUserVariable):Void;
+}
+
+private class BasicUser implements IUser {
+	public var id:Int;
+	public var name:String;
+
+	private var _variables:haxe.ds.StringMap<IUserVariable>;
+
+	public function new(id:Int, name:String) {
+		this.id = id;
+		this.name = name;
+		_variables = new haxe.ds.StringMap();
+	}
+
+	public function getVariable(name:String):IUserVariable {
+		var get = _variables.get(name);
+		return cast(get, IUserVariable);
+	}
+
+	public function containsVariable(name:String):Bool {
+		var get = _variables.get(name);
+		return get != null;
+	}
+
+	public function setVariable(userVariable:IUserVariable):Void {
+		if (userVariable != null) {
+			_variables.set(userVariable.name, userVariable);
+		}
+	}
+}
+
+@:keep
+private interface IVariable {
+	var name:String;
+	var type:String;
+	function getValue():Dynamic;
+	function getIntValue():Int;
+	function getStringValue():String;
+}
+
+@:keep
+private interface IUserVariable extends IVariable {
+	var isPrivate:Bool;
+}
+
+private class BaseVariable implements IVariable {
+	public var name:String;
+	public var type:String;
+
+	private var _value:Any;
+
+	public function new(name:String, value:Any, type:String) {
+		this.name = name;
+		this.type = type;
+		_value = value;
+	}
+
+	public function getValue():Dynamic {
+		return _value;
+	}
+
+	public function getIntValue():Int {
+		return cast(_value, Int);
+	}
+
+	public function getStringValue():String {
+		return cast(_value, String);
+	}
+}
+
+private class BasicUserVariable extends BaseVariable implements IUserVariable {
+	public var isPrivate:Bool;
+
+	public function new(name:String, value:Any, type:String) {
+		super(name, value, type);
+	}
+}
+
+class Issue11723 extends Test {
+	public function test() {
+		var varname = "TestVar";
+		var myVariable = new BasicUserVariable(varname, "Testvalue", "String");
+		eq("Testvalue", myVariable.getStringValue());
+
+		var myUser = new BasicUser(1, "myUser");
+		myUser.setVariable(myVariable);
+		var formUser = myUser.getVariable(varname);
+		eq("Testvalue", formUser.getStringValue());
+
+		var bareEntity:IEntity = myUser;
+		var fromBareEntity = bareEntity.getVariable(varname);
+		eq("Testvalue", fromBareEntity.getStringValue());
+		t(bareEntity.containsVariable(varname));
+
+		var bareUser:IUser = myUser;
+		var fromBareUser = bareUser.getVariable(varname);
+		eq("Testvalue", fromBareUser.getStringValue());
+		t(bareUser.containsVariable(varname));
+	}
+}