Browse Source

[php] [as3] support metadata on interfaces (closes #2042)

Simon Krajewski 10 years ago
parent
commit
02b3345a28
4 changed files with 43 additions and 12 deletions
  1. 19 2
      filters.ml
  2. 7 1
      genas3.ml
  3. 17 7
      std/haxe/rtti/Meta.hx
  4. 0 2
      tests/unit/src/unit/issues/Issue2042.hx

+ 19 - 2
filters.ml

@@ -1016,8 +1016,25 @@ let add_meta_field ctx t = match t with
 		| Some e ->
 			let f = mk_field "__meta__" t_dynamic c.cl_pos in
 			f.cf_expr <- Some e;
-			c.cl_ordered_statics <- f :: c.cl_ordered_statics;
-			c.cl_statics <- PMap.add f.cf_name f c.cl_statics)
+			let can_deal_with_interface_metadata () = match ctx.com.platform with
+				| Flash when Common.defined ctx.com Define.As3 -> false
+				| Php -> false
+				| _ -> true
+			in
+			if c.cl_interface && not (can_deal_with_interface_metadata()) then begin
+				(* borrowed from gencommon, but I did wash my hands afterwards *)
+				let path = fst c.cl_path,snd c.cl_path ^ "_HxMeta" in
+				let ncls = mk_class c.cl_module path c.cl_pos in
+				let cf = mk_field "__meta__" e.etype e.epos in
+				cf.cf_expr <- Some e;
+				ncls.cl_statics <- PMap.add "__meta__" cf ncls.cl_statics;
+				ncls.cl_ordered_statics <- cf :: ncls.cl_ordered_statics;
+				ctx.com.types <- (TClassDecl ncls) :: ctx.com.types;
+				c.cl_meta <- (Meta.Custom ":hasMetadata",[],e.epos) :: c.cl_meta
+			end else begin
+				c.cl_ordered_statics <- f :: c.cl_ordered_statics;
+				c.cl_statics <- PMap.add f.cf_name f c.cl_statics
+			end)
 	| _ ->
 		()
 

+ 7 - 1
genas3.ml

@@ -1106,7 +1106,13 @@ let generate_class ctx c =
 	pack();
 	newline ctx;
 	print ctx "}";
-	newline ctx
+	newline ctx;
+	if c.cl_interface && Ast.Meta.has (Ast.Meta.Custom ":hasMetadata") c.cl_meta then begin
+		(* we have to reference the metadata class in order for it to be compiled *)
+		let path = fst c.cl_path,snd c.cl_path ^ "_HxMeta" in
+		spr ctx (Ast.s_type_path path);
+		newline ctx
+	end
 
 let generate_main ctx inits =
 	ctx.curclass <- { null_class with cl_path = [],"__main__" };

+ 17 - 7
std/haxe/rtti/Meta.hx

@@ -34,18 +34,28 @@ class Meta {
 		return (meta == null || meta.obj == null) ? {} : meta.obj;
 	}
 
+	// Could move this to Type.hx?
+	private static function isInterface(t:Dynamic):Bool {
+		#if java
+			return java.Lib.toNativeType(t).isInterface();
+		#elseif cs
+			return cs.Lib.toNativeType(t).IsInterface;
+		#elseif (flash && as3)
+			return untyped flash.Lib.describeType(t).factory.extendsClass.length() == 0;
+		#elseif php
+			return untyped __php__("{0} instanceof _hx_interface", t);
+		#else
+			throw "Something went wrong";
+		#end
+	}
+
 	private static function getMeta(t:Dynamic):Dynamic
 	{
-#if (java || cs)
+#if (java || cs || php || (flash && as3))
 		var ret = Reflect.field(t, "__meta__");
 		if (ret == null && Std.is(t,Class))
 		{
-#if java
-			var interf = java.Lib.toNativeType(t).isInterface();
-#elseif cs
-			var interf = cs.Lib.toNativeType(t).IsInterface;
-#end
-			if (interf)
+			if (isInterface(t))
 			{
 				var name = Type.getClassName(t),
 				    cls = Type.resolveClass(name + '_HxMeta');

+ 0 - 2
tests/unit/src/unit/issues/Issue2042.hx

@@ -4,7 +4,6 @@ class Issue2042 extends Test
 {
 	public function test()
 	{
-		#if (!php && !as3)
 		var m = haxe.rtti.Meta.getType(WithMeta);
 		t(m.someMeta != null);
 		eq(m.someMeta[0],1);
@@ -12,7 +11,6 @@ class Issue2042 extends Test
 		eq(m.otherMeta[0],2);
 		t(haxe.rtti.Meta.getFields(WithMeta).testing != null);
 		eq(haxe.rtti.Meta.getFields(WithMeta).testing.varMeta[0], 3);
-		#end
 	}
 }