Преглед изворни кода

Implement @:assemblyMeta and @:assemblyStrict (#8360)

* [WIP] Implement @:assemblyMeta and @:assemblyStrict

* [cs] Implement @:assemblyStrict and handle more assembly-related errors

* Add descriptions to @:assemblyMeta and @:assemblyStrict metas

* Move test project to misc/cs/projects

* Use @:cs.assemblyMeta and @:cs.assemblyStruct

* Fix gencs.ml
Rudy Ges пре 5 година
родитељ
комит
2c5cad3f05

+ 14 - 0
src-json/meta.json

@@ -52,6 +52,20 @@
 		"targets": ["TAbstract", "TAbstractField"],
 		"links": ["https://haxe.org/manual/types-abstract-array-access.html"]
 	},
+	{
+		"name": "AssemblyMeta",
+		"metadata": ":cs.assemblyMeta",
+		"doc": "Used to declare a native C# assembly attribute",
+		"platforms": ["cs"],
+		"targets": ["TClass"]
+	},
+	{
+		"name": "AssemblyStrict",
+		"metadata": ":cs.assemblyStrict",
+		"doc": "Used to declare a native C# assembly attribute; is type checked",
+		"platforms": ["cs"],
+		"targets": ["TClass"]
+	},
 	{
 		"name": "Ast",
 		"metadata": ":ast",

+ 43 - 6
src/generators/gencs.ml

@@ -1878,6 +1878,22 @@ let generate con =
 				gen.gcon.error "Invalid expression inside @:meta metadata" p
 		in
 
+		let gen_assembly_attributes w metadata =
+			List.iter (function
+				| Meta.AssemblyMeta, [EConst(String(s,_)), _], _ ->
+					write w "[assembly:";
+					write w s;
+					write w "]";
+					newline w
+				| Meta.AssemblyMeta, [meta], _ ->
+					write w "[assembly:";
+					gen_spart w meta;
+					write w "]";
+					newline w
+				| _ -> ()
+			) metadata
+		in
+
 		let gen_attributes w metadata =
 			List.iter (function
 				| Meta.Meta, [EConst(String(s,_)), _], _ ->
@@ -2522,12 +2538,28 @@ let generate con =
 			end
 		in
 
-		let gen_class w cl =
+		let gen_class w cl is_first_type =
+			if (is_first_type == false) then begin
+				if Meta.has Meta.AssemblyStrict cl.cl_meta then
+					gen.gcon.error "@:cs.assemblyStrict can only be used on the first class of a module" cl.cl_pos
+				else if Meta.has Meta.AssemblyMeta cl.cl_meta then
+					gen.gcon.error "@:cs.assemblyMeta can only be used on the first class of a module" cl.cl_pos;
+			end;
+
 			write w "#pragma warning disable 109, 114, 219, 429, 168, 162";
 			newline w;
 			let should_close = match change_ns (TClassDecl cl) (fst (cl.cl_path)) with
-				| [] -> false
+				| [] ->
+					(* Should the assembly annotations be added to the class in this case? *)
+
+					if Meta.has Meta.AssemblyStrict cl.cl_meta then
+						gen.gcon.error "@:cs.assemblyStrict cannot be used on top level modules" cl.cl_pos
+					else if Meta.has Meta.AssemblyMeta cl.cl_meta then
+						gen.gcon.error "@:cs.assemblyMeta cannot be used on top level modules" cl.cl_pos;
+
+					false
 				| ns ->
+					gen_assembly_attributes w cl.cl_meta;
 					print w "namespace %s " (String.concat "." ns);
 					begin_block w;
 					true
@@ -2782,7 +2814,7 @@ let generate con =
 			if should_close then end_block w
 		in
 
-		let module_type_gen w md_tp =
+		let module_type_gen w md_tp is_first_type =
 			let file_start = len w = 0 in
 			let requires_root = no_root && file_start in
 			if file_start then
@@ -2792,9 +2824,10 @@ let generate con =
 				| TClassDecl cl ->
 					if not cl.cl_extern then begin
 						(if requires_root then write w "using haxe.root;\n"; newline w;);
+
 						(if (Meta.has Meta.CsUsing cl.cl_meta) then
 							match (Meta.get Meta.CsUsing cl.cl_meta) with
-								| _,_,p when not file_start ->
+								| _,_,p when not !is_first_type ->
 									gen.gcon.error "@:cs.using can only be used on the first type of a module" p
 								| _,[],p ->
 									gen.gcon.error "One or several string constants expected" p
@@ -2806,7 +2839,9 @@ let generate con =
 									) e);
 									newline w
 						);
-						gen_class w cl;
+
+						gen_class w cl !is_first_type;
+						is_first_type := false;
 						newline w;
 						newline w
 					end;
@@ -2815,6 +2850,7 @@ let generate con =
 					if not e.e_extern && not (Meta.has Meta.Class e.e_meta) then begin
 						(if requires_root then write w "using haxe.root;\n"; newline w;);
 						gen_enum w e;
+						is_first_type := false;
 						newline w;
 						newline w
 					end;
@@ -3439,7 +3475,8 @@ let generate con =
 		List.iter (fun md_def ->
 			let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in
 			let w = SourceWriter.new_source_writer() in
-			let should_write = List.fold_left (fun should md -> module_type_gen w md || should) false md_def.m_types in
+			let is_first_type = ref true in
+			let should_write = List.fold_left (fun should md -> module_type_gen w md is_first_type || should) false md_def.m_types in
 			if should_write then begin
 				let path = path_of_md_def md_def in
 				write_file gen w source_dir path "cs" out_files

+ 6 - 3
src/typing/typeloadModule.ml

@@ -131,7 +131,7 @@ module StrictMeta = struct
 			| _ ->
 				display_error ctx "Unexpected expression" texpr.epos; assert false
 
-	let get_strict_meta ctx params pos =
+	let get_strict_meta ctx meta params pos =
 		let pf = ctx.com.platform in
 		let changed_expr, fields_to_check, ctype = match params with
 			| [ECall(ef, el),p] ->
@@ -166,7 +166,7 @@ module StrictMeta = struct
 		let texpr = type_expr ctx changed_expr NoValue in
 		let with_type_expr = (ECheckType( (EConst (Ident "null"), pos), (ctype,null_pos) ), pos) in
 		let extra = handle_fields ctx fields_to_check with_type_expr in
-		Meta.Meta, [make_meta ctx texpr extra], pos
+		meta, [make_meta ctx texpr extra], pos
 
 	let check_strict_meta ctx metas =
 		let pf = ctx.com.platform in
@@ -174,8 +174,11 @@ module StrictMeta = struct
 			| Cs | Java ->
 				let ret = ref [] in
 				List.iter (function
+					| Meta.AssemblyStrict,params,pos -> (try
+						ret := get_strict_meta ctx Meta.AssemblyMeta params pos :: !ret
+					with | Exit -> ())
 					| Meta.Strict,params,pos -> (try
-						ret := get_strict_meta ctx params pos :: !ret
+						ret := get_strict_meta ctx Meta.Meta params pos :: !ret
 					with | Exit -> ())
 					| _ -> ()
 				) metas;

+ 2 - 0
tests/misc/cs/projects/Issue8347/.gitignore

@@ -0,0 +1,2 @@
+cs
+cs-fail

+ 7 - 0
tests/misc/cs/projects/Issue8347/Main.hx

@@ -0,0 +1,7 @@
+import cs.system.reflection.AssemblyDelaySignAttribute;
+
+@:cs.assemblyMeta(Test)
+class Main {}
+
+@:cs.assemblyStrict(cs.system.reflection.AssemblyDelaySignAttribute(true))
+class Main2 {}

+ 5 - 0
tests/misc/cs/projects/Issue8347/compile-fail.hxml

@@ -0,0 +1,5 @@
+-cp src
+Main
+fail.NotFirstType
+-cs cs-fail
+-D no-compilation

+ 4 - 0
tests/misc/cs/projects/Issue8347/compile-fail.hxml.stderr

@@ -0,0 +1,4 @@
+src/fail/NotFirstType.hx:8: characters 1-22 : @:cs.assemblyStrict can only be used on the first class of a module
+Main.hx:4: characters 1-14 : @:cs.assemblyMeta cannot be used on top level modules
+Main.hx:7: characters 1-15 : @:cs.assemblyStrict can only be used on the first class of a module
+Main.hx:7: characters 1-15 : @:cs.assemblyStrict cannot be used on top level modules

+ 3 - 0
tests/misc/cs/projects/Issue8347/compile.hxml

@@ -0,0 +1,3 @@
+-cp src
+pack.Main
+-cs bin

+ 9 - 0
tests/misc/cs/projects/Issue8347/src/fail/NotFirstType.hx

@@ -0,0 +1,9 @@
+package fail;
+
+import cs.system.reflection.AssemblyDelaySignAttribute;
+
+enum SomeEnum {}
+
+@:cs.assemblyStrict(cs.system.reflection.AssemblyDelaySignAttribute(true))
+class NotFirstType {}
+

+ 7 - 0
tests/misc/cs/projects/Issue8347/src/pack/Main.hx

@@ -0,0 +1,7 @@
+package pack;
+
+import cs.system.reflection.AssemblyDelaySignAttribute;
+
+@:cs.assemblyMeta(System.Reflection.AssemblyDefaultAliasAttribute("test"))
+@:cs.assemblyStrict(cs.system.reflection.AssemblyDelaySignAttribute(true))
+class Main {}