Browse Source

add Compiler.addGlobalMetadata

Simon Krajewski 11 years ago
parent
commit
9713f35f16
30 changed files with 141 additions and 74 deletions
  1. 9 0
      interp.ml
  2. 4 73
      std/haxe/macro/Compiler.hx
  3. 11 0
      tests/misc/projects/Issue3102/Main.hx
  4. 8 0
      tests/misc/projects/Issue3102/Main2.hx
  5. 3 0
      tests/misc/projects/Issue3102/compile-each.hxml
  6. 3 0
      tests/misc/projects/Issue3102/compile2-each.hxml
  7. 2 0
      tests/misc/projects/Issue3102/keep-field-not-rec.hxml
  8. 2 0
      tests/misc/projects/Issue3102/keep-field.hxml
  9. 3 0
      tests/misc/projects/Issue3102/keep-field2.hxml
  10. 2 0
      tests/misc/projects/Issue3102/keep-module-not-rec-fail.hxml
  11. 2 0
      tests/misc/projects/Issue3102/keep-module.hxml
  12. 2 0
      tests/misc/projects/Issue3102/keep-module2.hxml
  13. 2 0
      tests/misc/projects/Issue3102/keep-pack1-not-rec-fail.hxml
  14. 2 0
      tests/misc/projects/Issue3102/keep-pack1.hxml
  15. 2 0
      tests/misc/projects/Issue3102/keep-pack2-not-rec.hxml
  16. 2 0
      tests/misc/projects/Issue3102/keep-pack2.hxml
  17. 2 0
      tests/misc/projects/Issue3102/keep-pack3-fail.hxml
  18. 2 0
      tests/misc/projects/Issue3102/keep-pack4-fail.hxml
  19. 2 0
      tests/misc/projects/Issue3102/keep-type-not-rec.hxml
  20. 2 0
      tests/misc/projects/Issue3102/keep-type.hxml
  21. 8 0
      tests/misc/projects/Issue3102/pack1/pack2/Test.hx
  22. BIN
      tests/misc/projects/Issue3102/test.n
  23. 13 0
      tests/misc/projects/Issue3129/Build.hx
  24. 10 0
      tests/misc/projects/Issue3129/Main.hx
  25. 3 0
      tests/misc/projects/Issue3129/compile.hxml
  26. BIN
      tests/misc/projects/Issue3129/test.n
  27. 1 1
      tests/misc/src/Main.hx
  28. 1 0
      typecore.ml
  29. 28 0
      typeload.ml
  30. 10 0
      typer.ml

+ 9 - 0
interp.ml

@@ -124,6 +124,7 @@ type extern_api = {
 	use_cache : unit -> bool;
 	use_cache : unit -> bool;
 	format_string : string -> Ast.pos -> Ast.expr;
 	format_string : string -> Ast.pos -> Ast.expr;
 	cast_or_unify : Type.t -> texpr -> Ast.pos -> Type.texpr;
 	cast_or_unify : Type.t -> texpr -> Ast.pos -> Type.texpr;
+	add_global_metadata : string -> string -> (bool * bool * bool) -> unit;
 }
 }
 
 
 type callstack = {
 type callstack = {
@@ -2401,6 +2402,14 @@ let macro_lib =
 			| _ -> error());
 			| _ -> error());
 			VNull
 			VNull
 		);
 		);
+		"add_global_metadata", Fun5 (fun v1 v2 v3 v4 v5 ->
+			match v1,v2,v3,v4,v5 with
+				| VString s1,VString s2,VBool b1,VBool b2,VBool b3 ->
+					(get_ctx()).curapi.add_global_metadata s1 s2 (b1,b2,b3);
+					VNull
+				| _ ->
+					error()
+		);
 		"custom_js", Fun1 (fun f ->
 		"custom_js", Fun1 (fun f ->
 			match f with
 			match f with
 			| VFunction (Fun1 _) ->
 			| VFunction (Fun1 _) ->

+ 4 - 73
std/haxe/macro/Compiler.hx

@@ -270,87 +270,18 @@ class Compiler {
 		@param paths An Array of package, module or sub-type dot paths to keep.
 		@param paths An Array of package, module or sub-type dot paths to keep.
 		@param recursive If true, recurses into sub-packages for package paths.
 		@param recursive If true, recurses into sub-packages for package paths.
 	**/
 	**/
-	public static function keep(?path : String, ?paths : Array<String>, ?recursive:Bool = true)
-	{
+	public static function keep(?path : String, ?paths : Array<String>, ?recursive:Bool = true) {
 		if (null == paths)
 		if (null == paths)
 			paths = [];
 			paths = [];
 		if (null != path)
 		if (null != path)
 			paths.push(path);
 			paths.push(path);
 		for (path in paths) {
 		for (path in paths) {
-			var found:Bool = false;
-			var moduleFirstCharacter:String = ((path.indexOf(".") < 0)?path:path.substring(path.lastIndexOf(".")+1)).charAt(0);
-			var startsWithUpperCase:Bool = (moduleFirstCharacter == moduleFirstCharacter.toUpperCase());//needed because FileSystem is not case sensitive
-			var moduleRoot = (path.indexOf(".") < 0)?"":path.substring(0, path.lastIndexOf("."));
-			var moduleRootFirstCharacter:String = ((moduleRoot.indexOf(".") < 0)?moduleRoot:moduleRoot.substring(moduleRoot.lastIndexOf(".")+1)).charAt(0);
-			var rootStartsWithUpperCase:Bool = (moduleRootFirstCharacter == moduleRootFirstCharacter.toUpperCase());//needed because FileSystem is not case sensitive
-			for ( classPath in Context.getClassPath() ) {
-				var moduleRootPath = (moduleRoot == "")?"":(classPath + moduleRoot.split(".").join("/") + ".hx");
-				var fullPath = classPath + path.split(".").join("/");
-				var isValidModule:Bool = startsWithUpperCase && sys.FileSystem.exists(fullPath + ".hx");
-				var isValidSubType:Bool = !isValidModule && moduleRootPath != "" && rootStartsWithUpperCase && sys.FileSystem.exists(moduleRootPath);
-				var isValidDirectory:Bool = !isValidSubType && sys.FileSystem.exists(fullPath) && sys.FileSystem.isDirectory(fullPath);
-				if ( !isValidDirectory && !isValidModule && !isValidSubType)
-					continue;
-				else
-					found = true;
-
-				if(isValidDirectory) {
-					for( file in sys.FileSystem.readDirectory(fullPath) ) {
-						if( StringTools.endsWith(file, ".hx") ) {
-							var module = path + "." + file.substr(0, file.length - 3);
-							keepModule(module);
-						} else if( recursive && sys.FileSystem.isDirectory(fullPath + "/" + file) )
-							keep(path + "." + file, true);
-					}
-				} else if(isValidModule){
-					keepModule(path);
-				} else if(isValidSubType){
-					keepSubType(path);
-				}
-			}
-
-			if (!found)
-				Context.warning("file or directory not found, can't keep: "+path, Context.currentPos());
-		}
-	}
-
-	private static function keepSubType( path : String )
-	{
-		var module = path.substring(0, path.lastIndexOf("."));
-		var typeName = path.substring(path.lastIndexOf(".") + 1);
-		var subType:Type.BaseType = null;
-		for (type in Context.getModule(module)) {
-			switch(type) {
-				case TInst(_.get() => cls, _) if (cls.name == typeName):
-					subType = cls;
-					break;
-				case TEnum(_.get() => en, _) if (en.name == typeName):
-					subType = en;
-					break;
-				default:
-					//
-			}
+			addGlobalMetadata(path, "@:keep", recursive, true, true);
 		}
 		}
-
-		if (subType == null)
-			Context.warning('Cannot keep $path: type not found or is not a class or enum', Context.currentPos());
-		else
-			subType.meta.add(":keep", [], subType.pos);
 	}
 	}
 
 
-	private static function keepModule( path : String )
-	{
-		var types = Context.getModule(path);
-		for (type in types) {
-			switch(type) {
-				case TInst(_.get() => cls, _) if (!cls.kind.match(KAbstractImpl(_))):
-					cls.meta.add(":keep", [], cls.pos);
-				case TEnum(_.get() => en, _):
-					en.meta.add(":keep", [], en.pos);
-				default:
-					//
-			}
-		}
+	public static function addGlobalMetadata(pathFilter:String, meta:String, ?recursive:Bool = true, ?toTypes:Bool = true, ?toFields:Bool = false) {
+		untyped load("add_global_metadata",5)(untyped pathFilter.__s, meta.__s, recursive, toTypes, toFields);
 	}
 	}
 
 
 	/**
 	/**

+ 11 - 0
tests/misc/projects/Issue3102/Main.hx

@@ -0,0 +1,11 @@
+class Main {
+	static function main() {
+		var test:Dynamic = new Test();
+		test.get12();
+	}
+}
+
+class Test {
+	public function new() { }
+	public function get12() return 12;
+}

+ 8 - 0
tests/misc/projects/Issue3102/Main2.hx

@@ -0,0 +1,8 @@
+import pack1.pack2.Test;
+
+class Main2 {
+	static function main() {
+		var test = Type.createInstance(Type.resolveClass("pack1.pack2.Test"), []);
+		test.get12();
+	}
+}

+ 3 - 0
tests/misc/projects/Issue3102/compile-each.hxml

@@ -0,0 +1,3 @@
+-dce full
+-main Main
+-x test

+ 3 - 0
tests/misc/projects/Issue3102/compile2-each.hxml

@@ -0,0 +1,3 @@
+-dce full
+-main Main2
+-x test

+ 2 - 0
tests/misc/projects/Issue3102/keep-field-not-rec.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+--macro keep('Main.Test.get12', false)

+ 2 - 0
tests/misc/projects/Issue3102/keep-field.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+--macro keep('Main.Test.get12')

+ 3 - 0
tests/misc/projects/Issue3102/keep-field2.hxml

@@ -0,0 +1,3 @@
+compile2-each.hxml
+--macro keep('pack1.pack2.Test.get12')
+--macro keep('pack1.pack2.Test.new')

+ 2 - 0
tests/misc/projects/Issue3102/keep-module-not-rec-fail.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+--macro keep('Main', false)

+ 2 - 0
tests/misc/projects/Issue3102/keep-module.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+--macro keep('Main')

+ 2 - 0
tests/misc/projects/Issue3102/keep-module2.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1.pack2.Test')

+ 2 - 0
tests/misc/projects/Issue3102/keep-pack1-not-rec-fail.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1', false)

+ 2 - 0
tests/misc/projects/Issue3102/keep-pack1.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1')

+ 2 - 0
tests/misc/projects/Issue3102/keep-pack2-not-rec.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1.pack2', false)

+ 2 - 0
tests/misc/projects/Issue3102/keep-pack2.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1.pack2')

+ 2 - 0
tests/misc/projects/Issue3102/keep-pack3-fail.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1.pack3')

+ 2 - 0
tests/misc/projects/Issue3102/keep-pack4-fail.hxml

@@ -0,0 +1,2 @@
+compile2-each.hxml
+--macro keep('pack1.pack2.pack3')

+ 2 - 0
tests/misc/projects/Issue3102/keep-type-not-rec.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+--macro keep('Main.Test', false)

+ 2 - 0
tests/misc/projects/Issue3102/keep-type.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+--macro keep('Main.Test')

+ 8 - 0
tests/misc/projects/Issue3102/pack1/pack2/Test.hx

@@ -0,0 +1,8 @@
+package pack1.pack2;
+
+class Test {
+	public function new() { }
+	public function get12() {
+		return 12;
+	}
+}

BIN
tests/misc/projects/Issue3102/test.n


+ 13 - 0
tests/misc/projects/Issue3129/Build.hx

@@ -0,0 +1,13 @@
+import haxe.macro.Expr;
+import haxe.macro.Context;
+
+class Build {
+	macro static public function build():Array<Field> {
+		var field = (macro class X {
+			public function test() { }
+		}).fields[0];
+		var fields = Context.getBuildFields();
+		fields.push(field);
+		return fields;
+	}
+}

+ 10 - 0
tests/misc/projects/Issue3129/Main.hx

@@ -0,0 +1,10 @@
+class Main {
+
+	static function main() {
+		var m = new Main();
+		m.test();
+	}
+
+	public function new() { }
+
+}

+ 3 - 0
tests/misc/projects/Issue3129/compile.hxml

@@ -0,0 +1,3 @@
+--macro addGlobalMetadata('Main', '@:build(Build.build())')
+-main Main
+-x test

BIN
tests/misc/projects/Issue3129/test.n


+ 1 - 1
tests/misc/src/Main.hx

@@ -73,7 +73,6 @@ class Main {
 
 
 	static function runCommand(command:String, args:Array<String>, expectFailure:Bool, expectStderr:String) {
 	static function runCommand(command:String, args:Array<String>, expectFailure:Bool, expectStderr:String) {
 		var proc = new sys.io.Process(command, args);
 		var proc = new sys.io.Process(command, args);
-		var stderr = proc.stderr.readAll().toString();
 		proc.stdout.readAll();
 		proc.stdout.readAll();
 		var exit = proc.exitCode();
 		var exit = proc.exitCode();
 		var success = exit == 0;
 		var success = exit == 0;
@@ -86,6 +85,7 @@ class Main {
 			case [false, true]:
 			case [false, true]:
 				true;
 				true;
 			case [false, false]:
 			case [false, false]:
+				var stderr = proc.stderr.readAll().toString();
 				Sys.print(stderr);
 				Sys.print(stderr);
 				false;
 				false;
 		}
 		}

+ 1 - 0
typecore.ml

@@ -68,6 +68,7 @@ type typer_globals = {
 	mutable std : module_def;
 	mutable std : module_def;
 	mutable hook_generate : (unit -> unit) list;
 	mutable hook_generate : (unit -> unit) list;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
+	mutable global_metadata : (string list * Ast.metadata_entry * (bool * bool * bool)) list;
 	mutable get_build_infos : unit -> (module_type * t list * Ast.class_field list) option;
 	mutable get_build_infos : unit -> (module_type * t list * Ast.class_field list) option;
 	delayed_macros : (unit -> unit) DynArray.t;
 	delayed_macros : (unit -> unit) DynArray.t;
 	mutable global_using : tclass list;
 	mutable global_using : tclass list;

+ 28 - 0
typeload.ml

@@ -1466,6 +1466,31 @@ let init_core_api ctx c =
 	| None, Some { cf_public = false } -> ()
 	| None, Some { cf_public = false } -> ()
 	| _ -> error "Constructor differs from core type" c.cl_pos)
 	| _ -> error "Constructor differs from core type" c.cl_pos)
 
 
+let check_global_metadata ctx mpath tpath so =
+	let sl1 = if mpath = tpath then
+		(fst tpath) @ [snd tpath]
+	else
+		(fst mpath) @ [snd mpath;snd tpath]
+	in
+	let sl1,field_mode = match so with None -> sl1,false | Some s -> sl1 @ [s],true in
+	List.fold_left (fun acc (sl2,m,(recursive,to_types,to_fields)) ->
+		let rec loop sl1 sl2 = match sl1,sl2 with
+			| [],[] ->
+				true
+			(* always recurse into types of package paths *)
+			| (s1 :: s11 :: _),[s2] when is_lower_ident s2 && not (is_lower_ident s11)->
+				s1 = s2
+			| _,[] ->
+				recursive
+			| [],_ ->
+				false
+			| (s1 :: sl1),(s2 :: sl2) ->
+				s1 = s2 && loop sl1 sl2
+		in
+		let add = ((field_mode && to_fields) || (not field_mode && to_types)) && (sl2 = [""] || loop sl1 sl2) in
+		if add then (m :: acc) else acc
+	) [] ctx.g.global_metadata
+
 let patch_class ctx c fields =
 let patch_class ctx c fields =
 	let h = (try Some (Hashtbl.find ctx.g.type_patches c.cl_path) with Not_found -> None) in
 	let h = (try Some (Hashtbl.find ctx.g.type_patches c.cl_path) with Not_found -> None) in
 	match h with
 	match h with
@@ -1787,6 +1812,7 @@ let init_class ctx c p context_init herits fields =
 
 
 	let loop_cf f =
 	let loop_cf f =
 		let name = f.cff_name in
 		let name = f.cff_name in
+		f.cff_meta <- f.cff_meta @ (check_global_metadata ctx c.cl_module.m_path c.cl_path (Some name));
 		let p = f.cff_pos in
 		let p = f.cff_pos in
 		if name.[0] = '$' && ctx.com.display = DMNone then error "Field names starting with a dollar are not allowed" p;
 		if name.[0] = '$' && ctx.com.display = DMNone then error "Field names starting with a dollar are not allowed" p;
 		let stat = List.mem AStatic f.cff_access in
 		let stat = List.mem AStatic f.cff_access in
@@ -2441,6 +2467,7 @@ let rec init_module_type ctx context_init do_init (decl,p) =
 		context_init := (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using) :: !context_init
 		context_init := (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using) :: !context_init
 	| EClass d ->
 	| EClass d ->
 		let c = (match get_type d.d_name with TClassDecl c -> c | _ -> assert false) in
 		let c = (match get_type d.d_name with TClassDecl c -> c | _ -> assert false) in
+		c.cl_meta <- c.cl_meta @ check_global_metadata ctx c.cl_module.m_path c.cl_path None;
 		let herits = d.d_flags in
 		let herits = d.d_flags in
 		if Meta.has Meta.Generic c.cl_meta && c.cl_params <> [] then c.cl_kind <- KGeneric;
 		if Meta.has Meta.Generic c.cl_meta && c.cl_params <> [] then c.cl_kind <- KGeneric;
 		if Meta.has Meta.GenericBuild c.cl_meta then c.cl_kind <- KGenericBuild d.d_data;
 		if Meta.has Meta.GenericBuild c.cl_meta then c.cl_kind <- KGenericBuild d.d_data;
@@ -2462,6 +2489,7 @@ let rec init_module_type ctx context_init do_init (decl,p) =
 		let e = (match get_type d.d_name with TEnumDecl e -> e | _ -> assert false) in
 		let e = (match get_type d.d_name with TEnumDecl e -> e | _ -> assert false) in
 		let ctx = { ctx with type_params = e.e_params } in
 		let ctx = { ctx with type_params = e.e_params } in
 		let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in
 		let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in
+		e.e_meta <- e.e_meta @ check_global_metadata ctx e.e_module.m_path e.e_path None;
 		(match h with
 		(match h with
 		| None -> ()
 		| None -> ()
 		| Some (h,hcl) ->
 		| Some (h,hcl) ->

+ 10 - 0
typer.ml

@@ -4371,6 +4371,15 @@ let make_macro_api ctx p =
 		Interp.cast_or_unify = (fun t e p ->
 		Interp.cast_or_unify = (fun t e p ->
 			Codegen.AbstractCast.cast_or_unify_raise ctx t e p
 			Codegen.AbstractCast.cast_or_unify_raise ctx t e p
 		);
 		);
+		Interp.add_global_metadata = (fun s1 s2 config ->
+			let meta = (match parse_string ctx.com (s2 ^ " typedef T = T") null_pos false with
+				| _,[ETypedef t,_] -> t.d_meta
+				| _ -> assert false
+			) in
+			List.iter (fun m ->
+				ctx.g.global_metadata <- (ExtString.String.nsplit s1 ".",m,config) :: ctx.g.global_metadata;
+			) meta;
+		);
 	}
 	}
 
 
 let rec init_macro_interp ctx mctx mint =
 let rec init_macro_interp ctx mctx mint =
@@ -4702,6 +4711,7 @@ let rec create com =
 			modules = Hashtbl.create 0;
 			modules = Hashtbl.create 0;
 			types_module = Hashtbl.create 0;
 			types_module = Hashtbl.create 0;
 			type_patches = Hashtbl.create 0;
 			type_patches = Hashtbl.create 0;
+			global_metadata = [];
 			delayed = [];
 			delayed = [];
 			debug_delayed = [];
 			debug_delayed = [];
 			delayed_macros = DynArray.create();
 			delayed_macros = DynArray.create();