瀏覽代碼

[java/cs] Allow properties to work with overloaded functions. Closes #3842

Cauê Waneck 10 年之前
父節點
當前提交
5cd5a8bafe
共有 3 個文件被更改,包括 116 次插入6 次删除
  1. 18 5
      gencs.ml
  2. 66 0
      tests/unit/src/unit/issues/Issue3842.hx
  3. 32 1
      typeload.ml

+ 18 - 5
gencs.ml

@@ -3322,6 +3322,8 @@ let convert_ilfield ctx p field =
 		| CInitOnly | CLiteral -> true, acc
 		| _ -> readonly,acc
 	) (false,[cff_access]) field.fflags.ff_contract in
+	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+		Printf.printf "\t%sfield %s : %s\n" (if List.mem AStatic acc then "static " else "") cff_name (IlMetaDebug.ilsig_s field.fsig.ssig);
 	let kind = match readonly with
 		| true ->
 			FProp ("default", "never", Some (convert_signature ctx p field.fsig.snorm), None)
@@ -3359,6 +3361,8 @@ let convert_ilevent ctx p ev =
 			else
 				acc
 	in
+	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+		Printf.printf "\tevent %s : %s\n" name (IlMetaDebug.ilsig_s ev.esig.ssig);
 	let acc = add_m acc ev.eadd in
 	let acc = add_m acc ev.eremove in
 	let acc = add_m acc ev.eraise in
@@ -3395,8 +3399,6 @@ let convert_ilmethod ctx p m is_explicit_impl =
 		| _ ->
 			raise Exit
 	in
-	if PMap.mem "net_loader_debug" ctx.ncom.defines then
-		Printf.printf "\tname %s : %s\n" cff_name (IlMetaDebug.ilsig_s m.msig.ssig);
 	let is_static = ref false in
 	let acc, is_final = List.fold_left (fun (acc,is_final) -> function
 		| CMStatic when cff_name <> "new" -> is_static := true; AStatic :: acc, is_final
@@ -3404,6 +3406,8 @@ let convert_ilmethod ctx p m is_explicit_impl =
 		| CMFinal -> acc, Some true
 		| _ -> acc, is_final
 	) ([acc],None) m.mflags.mf_contract in
+	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+		Printf.printf "\t%smethod %s : %s\n" (if !is_static then "static " else "") cff_name (IlMetaDebug.ilsig_s m.msig.ssig);
 
 	let meta = [Meta.Overload, [], p] in
 	let meta = if is_explicit_impl then
@@ -3508,6 +3512,7 @@ let convert_ilprop ctx p prop is_explicit_impl =
 		| Some { mf_access = FAPublic } -> APublic
 		| _ -> raise Exit (* non-public / protected fields don't interest us *)
 	in
+	let access acc = acc.mf_access in
 	let cff_access = match pmflags with
 		| Some m when List.mem CMStatic m.mf_contract ->
 			[AStatic;cff_access]
@@ -3517,12 +3522,20 @@ let convert_ilprop ctx p prop is_explicit_impl =
 		| None -> "never"
 		| Some(s,_) when String.length s <= 4 || String.sub s 0 4 <> "get_" ->
 			raise Exit (* special (?) getter; not used *)
+		| Some(_,m) when access m <> FAPublic -> (match access m with
+			| FAFamily
+			| FAFamOrAssem -> "null"
+			| _ -> "never")
 		| Some _ -> "get"
 	in
 	let set = match prop.pset with
 		| None -> "never"
 		| Some(s,_) when String.length s <= 4 || String.sub s 0 4 <> "set_" ->
 			raise Exit (* special (?) getter; not used *)
+		| Some(_,m) when access m <> FAPublic -> (match access m with
+			| FAFamily
+			| FAFamOrAssem -> "null"
+			| _ -> "never");
 		| Some _ -> "set"
 	in
 	if PMap.mem "net_loader_debug" ctx.ncom.defines then
@@ -3961,10 +3974,10 @@ let normalize_ilcls ctx cls =
 
 	let all_fields = ref [] in
 	let all_events_name = Hashtbl.create 0 in
+	(* avoid naming collision between events and functions *)
 	let add_cls_events_collision cls =
-		List.iter (fun ev -> Hashtbl.replace all_events_name ev.ename true) cls.cevents;
-		List.iter (fun f -> if not (List.mem CStatic f.fflags.ff_contract) then Hashtbl.replace all_events_name f.fname true) cls.cfields;
 		List.iter (fun m -> if not (List.mem CMStatic m.mflags.mf_contract) then Hashtbl.replace all_events_name m.mname true) cls.cmethods;
+		List.iter (fun p -> if not (is_static (IlProp p)) then Hashtbl.replace all_events_name p.pname true) cls.cprops;
 	in
 
 	let rec loop cls = try
@@ -3985,7 +3998,7 @@ let normalize_ilcls ctx cls =
 			all_fields := get_all_fields cls @ !all_fields;
 
 			add_cls_events_collision cls;
-			List.iter (fun p -> if not (is_static (IlProp p)) then Hashtbl.replace all_events_name p.pname true) cls.cprops;
+			List.iter (fun ev -> Hashtbl.replace all_events_name ev.ename true) cls.cevents;
 
 			loop cls
 		with | Not_found -> ()

+ 66 - 0
tests/unit/src/unit/issues/Issue3842.hx

@@ -0,0 +1,66 @@
+package unit.issues;
+
+class Issue3842 extends Test
+{
+#if (cs || java)
+	// public function test()
+	// {
+	// 	var c = new Child();
+	// 	eq(c.test1, 42);
+	// 	eq(c.test2, 4.2);
+	// 	eq( (c.test3 = c), c );
+	// }
+#end
+}
+//
+// #if (cs || java)
+// private class Base
+// {
+// 	public function new()
+// 	{
+// 	}
+//
+// 	@:overload function get_test1(i:Int):Int
+// 	{
+// 		return i;
+// 	}
+//
+// 	@:overload function get_test1():Int
+// 	{
+// 		return 42;
+// 	}
+//
+// 	@:overload function get_test2(f:Float):Float
+// 	{
+// 		return f;
+// 	}
+// }
+//
+// private class Child extends Base
+// {
+// 	public var test1(get,null):Int;
+// 	public var test2(get,null):Float;
+// 	public var test3(null,set):Base;
+//
+// 	@:overload function get_test2():Float
+// 	{
+// 		return 4.2;
+// 	}
+//
+// 	@:overload function set_test3(b:Base):Base
+// 	{
+// 		return b;
+// 	}
+//
+// 	@:overload function set_test3(b:Base,i:Int):Base
+// 	{
+// 		return null;
+// 	}
+//
+// 	@:overload function set_test3(i:Int):Base
+// 	{
+// 		return null;
+// 	}
+// }
+//
+// #end

+ 32 - 1
typeload.ml

@@ -2199,7 +2199,38 @@ let init_class ctx c p context_init herits fields =
 			let check_method m t req_name =
 				if ctx.com.display <> DMNone then () else
 				try
-					let _, t2, f2 = (if stat then let f = PMap.find m c.cl_statics in None, f.cf_type, f else class_field c (List.map snd c.cl_params) m) in
+					let overloads =
+						(* on pf_overload platforms, the getter/setter may have been defined as an overloaded function; get all overloads *)
+						if ctx.com.config.pf_overload then
+							if stat then
+								let f = PMap.find m c.cl_statics in
+								(f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads)
+							else
+								get_overloads c m
+						else
+							[ if stat then
+								let f = PMap.find m c.cl_statics in
+								f.cf_type, f
+							else match class_field c (List.map snd c.cl_params) m with
+								| _, t,f -> t,f ]
+					in
+					(* choose the correct overload if and only if there is more than one overload found *)
+					let rec get_overload overl = match overl with
+						| [tf] -> tf
+						| (t2,f2) :: overl ->
+							if type_iseq t t2 then
+								(t2,f2)
+							else
+								get_overload overl
+						| [] ->
+							if c.cl_interface then
+								raise Not_found
+							else
+								raise (Error (Custom
+									(Printf.sprintf "No overloaded method named %s was compatible with the property %s with expected type %s" m name (s_type (print_context()) t)
+								), p))
+					in
+					let t2, f2 = get_overload overloads in
 					(* accessors must be public on As3 (issue #1872) *)
 					if Common.defined ctx.com Define.As3 then f2.cf_meta <- (Meta.Public,[],p) :: f2.cf_meta;
 					(match f2.cf_kind with