Browse Source

Context messages API (#8471)

* Add Context warning API

* Add tests for Context warning API

* Ensure order of warnings is consistent

* Only manipulate warnings, not all messages

* Update std too...

* Fix filter_warnings; do not break on CMInfo

* ... and keep CMInfo when filtering warnings

* Remove unneeded parens

* Rework Context messages API

* Fix rebase
Rudy Ges 6 years ago
parent
commit
f11267be46

+ 11 - 0
src/compiler/main.ml

@@ -490,6 +490,17 @@ try
 	com.info <- (fun msg p -> message ctx (CMInfo(msg,p)));
 	com.warning <- (fun msg p -> message ctx (CMWarning(msg,p)));
 	com.error <- error ctx;
+	let filter_messages = (fun keep_errors predicate -> (List.filter (fun msg ->
+		(match msg with
+		| CMError(_,_) -> keep_errors;
+		| CMInfo(_,_) | CMWarning(_,_) -> predicate msg;)
+	) (List.rev ctx.messages))) in
+	com.get_messages <- (fun () -> (List.map (fun msg ->
+		(match msg with
+		| CMError(_,_) -> assert false;
+		| CMInfo(_,_) | CMWarning(_,_) -> msg;)
+	) (filter_messages false (fun _ -> true))));
+	com.filter_messages <- (fun predicate -> (ctx.messages <- (List.rev (filter_messages true predicate))));
 	if CompilationServer.runs() then com.run_command <- run_command ctx;
 	com.class_path <- get_std_class_paths ();
 	com.std_path <- List.filter (fun p -> ExtString.String.ends_with p "std/" || ExtString.String.ends_with p "std\\") com.class_path;

+ 4 - 0
src/context/common.ml

@@ -180,6 +180,8 @@ type context = {
 	mutable error : string -> pos -> unit;
 	mutable info : string -> pos -> unit;
 	mutable warning : string -> pos -> unit;
+	mutable get_messages : unit -> compiler_message list;
+	mutable filter_messages : (compiler_message -> bool) -> unit;
 	mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *)
 	callbacks : compiler_callbacks;
 	defines : Define.define;
@@ -452,6 +454,8 @@ let create version s_version args =
 		info = (fun _ _ -> assert false);
 		warning = (fun _ _ -> assert false);
 		error = (fun _ _ -> assert false);
+		get_messages = (fun() -> []);
+		filter_messages = (fun _ -> ());
 		pass_debug_messages = DynArray.create();
 		basic = {
 			tvoid = m;

+ 2 - 1
src/macro/eval/evalEncode.ml

@@ -158,6 +158,7 @@ let encode_enum i pos index pl =
 		| IImportMode -> key_haxe_macro_ImportMode
 		| IQuoteStatus -> key_haxe_macro_QuoteStatus
 		| IDisplayKind -> key_haxe_macro_DisplayKind
+		| IMessage -> key_haxe_macro_Message
 	in
 	encode_enum_value key index (Array.of_list pl) pos
 
@@ -286,4 +287,4 @@ let encode_lazy f =
 		r := (fun () -> v);
 		v
 	) in
-	VLazy r
+	VLazy r

+ 2 - 1
src/macro/eval/evalHash.ml

@@ -104,6 +104,7 @@ let key_haxe_macro_AnonStatus = hash "haxe.macro.AnonStatus"
 let key_haxe_macro_ImportMode = hash "haxe.macro.ImportMode"
 let key_haxe_macro_QuoteStatus = hash "haxe.macro.QuoteStatus"
 let key_haxe_macro_DisplayKind = hash "haxe.macro.DisplayKind"
+let key_haxe_macro_Message = hash "haxe.macro.Message"
 let key_haxe_CallStack = hash "haxe.CallStack"
 let key___init__ = hash "__init__"
 let key_new = hash "new"
@@ -126,4 +127,4 @@ let key_haxe_iterators_map_key_value_iterator = hash "haxe.iterators.MapKeyValue
 let key_sys_net_Mutex = hash "sys.thread.Mutex"
 let key_sys_net_Lock = hash "sys.thread.Lock"
 let key_sys_net_Tls = hash "sys.thread.Tls"
-let key_sys_net_Deque = hash "sys.thread.Deque"
+let key_sys_net_Deque = hash "sys.thread.Deque"

+ 20 - 0
src/macro/macroApi.ml

@@ -76,6 +76,7 @@ type enum_type =
 	| IQuoteStatus
 	| IImportMode
 	| IDisplayKind
+	| IMessage
 
 (**
 	Our access to the interpreter from the macro api
@@ -170,6 +171,7 @@ let enum_name = function
 	| IImportMode -> "ImportMode"
 	| IQuoteStatus -> "QuoteStatus"
 	| IDisplayKind -> "DisplayKind"
+	| IMessage -> "Message"
 
 let all_enums =
 	let last = IImportMode in
@@ -390,6 +392,14 @@ and encode_display_kind dk =
 	in
 	encode_enum ~pos:None IDisplayKind tag pl
 
+and encode_message msg =
+	let tag, pl = match msg with
+		| CMInfo(msg,p) -> 0, [(encode_string msg); (encode_pos p)]
+		| CMWarning(msg,p) -> 1, [(encode_string msg); (encode_pos p)]
+		| CMError(_,_) -> assert false
+	in
+	encode_enum ~pos:None IMessage tag pl
+
 and encode_expr e =
 	let rec loop (e,p) =
 		let tag, pl = match e with
@@ -1502,6 +1512,16 @@ let macro_api ccom get_api =
 			(ccom()).info msg p;
 			vnull
 		);
+		"get_messages", vfun0 (fun() ->
+			encode_array (List.map (fun msg -> encode_message msg) ((ccom()).get_messages()));
+		);
+		"filter_messages", vfun1 (fun predicate ->
+			let predicate = prepare_callback predicate 2 in
+			(ccom()).filter_messages (fun msg -> (
+				decode_bool (predicate [encode_message msg])
+			));
+			vnull
+		);
 		"class_path", vfun0 (fun() ->
 			encode_array (List.map encode_string (ccom()).class_path);
 		);

+ 20 - 0
std/haxe/macro/Context.hx

@@ -25,6 +25,11 @@ package haxe.macro;
 import haxe.macro.Expr;
 import haxe.macro.Type.TypedExpr;
 
+enum Message {
+	Info(msg:String, pos:Position);
+	Warning(msg:String, pos:Position);
+}
+
 /**
 	Context provides an API for macro programming.
 
@@ -68,6 +73,21 @@ class Context {
 		load("info", 2)(msg, pos);
 	}
 
+	/**
+		Gets a list of all current compilation info/warning messages.
+	**/
+	public static function getMessages() : Array<Message> {
+		return load("get_messages",0)();
+	}
+
+	/**
+		Filters all current info/warning messages. Filtered out messages will
+		not be displayed by the compiler.
+	**/
+	public static function filterMessages( predicate : Message -> Bool ) {
+		load("filter_messages",1)(predicate);
+	}
+
 	/**
 		Resolves a file name `file` based on the current class paths.
 

+ 27 - 0
tests/misc/projects/Issue8471/Macro.hx

@@ -0,0 +1,27 @@
+import haxe.macro.Context;
+
+class Macro {
+	public static function init() {
+		Context.warning("This warning will disappear", Context.currentPos());
+
+		Context.onAfterTyping(afterTyping);
+		Context.onAfterGenerate(afterGenerate);
+	}
+
+	static function afterTyping(_) {
+		var nbMessages = Context.getMessages().length;
+		Context.filterMessages(_ -> false);
+		Context.warning('There were $nbMessages messages on after typing', Context.currentPos());
+		Context.warning("This warning will not disappear", Context.currentPos());
+		Context.warning("This warning will disappear too", Context.currentPos());
+	}
+
+	static function afterGenerate() {
+		var nbMessages = Context.getMessages().length;
+		Context.warning('There were $nbMessages messages on after generate', Context.currentPos());
+		Context.filterMessages(msg -> switch msg {
+			case Warning(w, _): w != "This warning will disappear too";
+			case Info(_, _): true;
+		});
+	}
+}

+ 35 - 0
tests/misc/projects/Issue8471/Macro2.hx

@@ -0,0 +1,35 @@
+import haxe.macro.Context;
+
+@:deprecated
+typedef DeprecatedType = String;
+
+class Macro2 {
+	public static function init() {
+		Context.onAfterTyping(afterTyping);
+	}
+
+	static function afterTyping(_) {
+		Context.warning(("1" :DeprecatedType), Context.currentPos());
+		Context.warning("2", Context.currentPos());
+		Context.warning("3", Context.currentPos());
+
+		var messages = Context.getMessages();
+		var order = Lambda.fold(messages, (msg, acc) -> switch msg {
+			case Warning(w, _) if (w.length == 1): acc + w;
+			case Info(_, _): acc + 'i';
+			case _: acc;
+		}, "") + "|";
+
+		Context.filterMessages(function(msg) {
+			switch msg {
+				case Warning(w, _) if (w.length == 1): order += w;
+				case Info(_, _): order += 'i';
+				case _:
+			}
+
+			return true;
+		});
+
+		Context.warning(order, Context.currentPos());
+	}
+}

+ 2 - 0
tests/misc/projects/Issue8471/compile.hxml

@@ -0,0 +1,2 @@
+--version
+--macro Macro.init()

+ 3 - 0
tests/misc/projects/Issue8471/compile.hxml.stderr

@@ -0,0 +1,3 @@
+Warning : There were 2 messages on after typing
+Warning : This warning will not disappear
+Warning : There were 3 messages on after generate

+ 2 - 0
tests/misc/projects/Issue8471/compile2.hxml

@@ -0,0 +1,2 @@
+--version
+--macro Macro2.init()

+ 5 - 0
tests/misc/projects/Issue8471/compile2.hxml.stderr

@@ -0,0 +1,5 @@
+Macro2.hx:12: characters 25-39 : Warning : This typedef is deprecated in favor of String
+Warning : 1
+Warning : 2
+Warning : 3
+Warning : i123|i123