Просмотр исходного кода

Alternative message reporting modes (#10863)

* Avoid some 'Called from macro here' errors

* Add nesting level data to errors

* Add verbose error reporting

* Use ExtString.String.starts_with

* Rename to pretty-errors

* Some cleanup

* Expose nesting level parameter to message emiting API

* Better handling of invalid positions

* Rewrite into generic -D message-reporting=[format] feature

Also add logging capabilities with -D messages-log-file=[path]

* Handle non-ascii characters in sources

* Implement -D message-reporting=diagnostics

* Add Info prefix to info messages

* Properly close log file

* Only add 'Info : ' prefix in diagnostics mode

* Error handling and directory creation for log file

* Whitespace

* Error reporting specific defines shouldn't trigger new context

* Rename indented message display mode

* [tests] Add pretty test output for 6065

* Avoid adding useless whitespace on empty lines

* Cleanup source resolution, fix files not ending with empty line

* [tests] Add pretty test output for 5644

* Avoid adding useless whitespace with multiline positions

* [tests] Add pretty test output for 6584

* [tests] Add pretty test output for 6790

* [tests] Add pretty test output for 6796

* [tests] Add pretty test output for 7968

* Fix indent reporting mode, add error message

* [tests] Add indent test output for 6065

* [tests] Add pretty and indent test output for 5949

* Improve conditions for displaying error headings

* [tests] Add pretty test output for 8471

* Indent message reporting: indent su errors instead of prefixing with ...

* [tests] Add pretty and indent tests output for 6810

* [tests] Add pretty and indent tests output for 10844

* [tests] Update indent test output for 6065

* [test] remove haxe -version output check

* Also remove '...' prefixes to single line errors in indent mode

* Carry position with compiler errors

Takes care of pretty printing Stack errors, including call stack

Commit this ugly thing while it works, cleanup tomorrow

* [tests] Add pretty and indent tests output for 8303

* Position marker for single char positions

* Don't nest first element of Stack errors

* [tests] update pretty/indent tests

* nesting_level -> depth

* A bit of cleanup

* Cleanup typing_error

* Cleanup display_error

* Add std path resolution to misc tests output checks

* More nesting level -> depth changes

* [tests] only normalize root of std path

* Fix missing depth

* Update doc

* Add another test for 4803

* Internal errors handling

* [tests] don't resolve real path of std root since eval doesn't

* [tests] remove test with different outcome on all platforms

* [ci] use predictable std path for misc tests

* [tests] No need for Context

* [tests] add log file tests

* Handle stack in located_typing_error

* Reduce diff

* Whitespace

* Add comment

* Reduce diff

* Change compiler_message from tuple to record

* [tests] Add missing test output for 10844

(needed std path being exposed to misc tests)

* [skip ci] add comments
Rudy Ges 2 лет назад
Родитель
Сommit
17e6b0c88c
100 измененных файлов с 1093 добавлено и 307 удалено
  1. 2 0
      .github/workflows/main.yml
  2. 2 0
      extra/github-actions/workflows/main.yml
  3. 22 0
      src-json/define.json
  4. 1 1
      src/codegen/gencommon/gencommon.ml
  5. 7 3
      src/compiler/compilationContext.ml
  6. 24 18
      src/compiler/compiler.ml
  7. 2 2
      src/compiler/displayProcessing.ml
  8. 1 1
      src/compiler/retyper.ml
  9. 355 27
      src/compiler/server.ml
  10. 6 6
      src/context/abstractCast.ml
  11. 16 11
      src/context/common.ml
  12. 2 2
      src/context/display/diagnostics.ml
  13. 1 1
      src/context/display/displayFields.ml
  14. 14 10
      src/context/typecore.ml
  15. 1 0
      src/core/define.ml
  16. 34 22
      src/core/error.ml
  17. 32 3
      src/core/globals.ml
  18. 1 1
      src/core/texpr.ml
  19. 1 1
      src/filters/filters.ml
  20. 8 5
      src/macro/eval/evalExceptions.ml
  21. 2 2
      src/macro/eval/evalLuv.ml
  22. 4 2
      src/macro/eval/evalMain.ml
  23. 22 17
      src/macro/macroApi.ml
  24. 1 1
      src/optimization/analyzerTexpr.ml
  25. 1 1
      src/optimization/inlineConstructors.ml
  26. 2 2
      src/optimization/optimizer.ml
  27. 32 32
      src/typing/callUnification.ml
  28. 1 1
      src/typing/calls.ml
  29. 3 3
      src/typing/fields.ml
  30. 5 5
      src/typing/forLoop.ml
  31. 7 7
      src/typing/generic.ml
  32. 13 13
      src/typing/macroContext.ml
  33. 1 1
      src/typing/magicTypes.ml
  34. 1 1
      src/typing/matcher.ml
  35. 6 6
      src/typing/operators.ml
  36. 15 15
      src/typing/typeload.ml
  37. 8 8
      src/typing/typeloadCheck.ml
  38. 12 12
      src/typing/typeloadFields.ml
  39. 4 4
      src/typing/typeloadModule.ml
  40. 1 1
      src/typing/typeloadParse.ml
  41. 24 24
      src/typing/typer.ml
  42. 7 7
      src/typing/typerDisplay.ml
  43. 1 1
      src/typing/typerDotPath.ml
  44. 12 12
      std/haxe/macro/Context.hx
  45. 2 0
      tests/misc/projects/Issue10623/indent-fail.hxml
  46. 2 0
      tests/misc/projects/Issue10623/indent-fail.hxml.stderr
  47. 3 0
      tests/misc/projects/Issue10623/pretty-fail.hxml
  48. 10 0
      tests/misc/projects/Issue10623/pretty-fail.hxml.stderr
  49. 3 0
      tests/misc/projects/Issue10844/user-defined-define-json-fail.hxml.stderr
  50. 2 0
      tests/misc/projects/Issue10844/user-defined-meta-indent-fail.hxml
  51. 2 0
      tests/misc/projects/Issue10844/user-defined-meta-indent-fail.hxml.stderr
  52. 3 0
      tests/misc/projects/Issue10844/user-defined-meta-json-fail.hxml.stderr
  53. 2 0
      tests/misc/projects/Issue10844/user-defined-meta-json-indent-fail.hxml
  54. 3 0
      tests/misc/projects/Issue10844/user-defined-meta-json-indent-fail.hxml.stderr
  55. 4 0
      tests/misc/projects/Issue10844/user-defined-meta-json-pretty-fail.hxml
  56. 12 0
      tests/misc/projects/Issue10844/user-defined-meta-json-pretty-fail.hxml.stderr
  57. 4 0
      tests/misc/projects/Issue10844/user-defined-meta-pretty-fail.hxml
  58. 5 0
      tests/misc/projects/Issue10844/user-defined-meta-pretty-fail.hxml.stderr
  59. 3 0
      tests/misc/projects/Issue10863/logmode-fail.hxml
  60. 1 0
      tests/misc/projects/Issue10863/logmode-fail.hxml.stderr
  61. 2 0
      tests/misc/projects/Issue10863/reporting-fail.hxml
  62. 1 0
      tests/misc/projects/Issue10863/reporting-fail.hxml.stderr
  63. 8 0
      tests/misc/projects/Issue4803/Main2.hx
  64. 3 0
      tests/misc/projects/Issue4803/compile2-fail.hxml
  65. 2 0
      tests/misc/projects/Issue4803/compile2-fail.hxml.stderr
  66. 3 0
      tests/misc/projects/Issue5644/pretty-fail.hxml
  67. 6 0
      tests/misc/projects/Issue5644/pretty-fail.hxml.stderr
  68. 2 0
      tests/misc/projects/Issue5949/indent-fail.hxml
  69. 2 0
      tests/misc/projects/Issue5949/indent-fail.hxml.stderr
  70. 3 0
      tests/misc/projects/Issue5949/pretty-fail.hxml
  71. 10 0
      tests/misc/projects/Issue5949/pretty-fail.hxml.stderr
  72. 2 0
      tests/misc/projects/Issue6065/indent-fail.hxml
  73. 14 0
      tests/misc/projects/Issue6065/indent-fail.hxml.stderr
  74. 3 0
      tests/misc/projects/Issue6065/pretty-fail.hxml
  75. 40 0
      tests/misc/projects/Issue6065/pretty-fail.hxml.stderr
  76. 3 0
      tests/misc/projects/Issue6584/pretty-fail.hxml
  77. 14 0
      tests/misc/projects/Issue6584/pretty-fail.hxml.stderr
  78. 3 0
      tests/misc/projects/Issue6790/pretty-fail.hxml
  79. 7 0
      tests/misc/projects/Issue6790/pretty-fail.hxml.stderr
  80. 3 0
      tests/misc/projects/Issue6796/pretty-fail.hxml
  81. 7 0
      tests/misc/projects/Issue6796/pretty-fail.hxml.stderr
  82. 3 0
      tests/misc/projects/Issue6810/.gitignore
  83. 2 0
      tests/misc/projects/Issue6810/indent-fail.hxml
  84. 8 0
      tests/misc/projects/Issue6810/indent-fail.hxml.stderr
  85. 2 0
      tests/misc/projects/Issue6810/logfile-01-fail.hxml
  86. 4 0
      tests/misc/projects/Issue6810/logfile-02-fail.hxml
  87. 4 0
      tests/misc/projects/Issue6810/logfile-03-fail.hxml
  88. 1 0
      tests/misc/projects/Issue6810/logfile-04-fail.hxml
  89. 3 0
      tests/misc/projects/Issue6810/pretty-fail.hxml
  90. 18 0
      tests/misc/projects/Issue6810/pretty-fail.hxml.stderr
  91. 3 0
      tests/misc/projects/Issue7968/pretty-fail.hxml
  92. 10 0
      tests/misc/projects/Issue7968/pretty-fail.hxml.stderr
  93. 2 0
      tests/misc/projects/Issue8303/indent-fail.hxml
  94. 21 0
      tests/misc/projects/Issue8303/indent-fail.hxml.stderr
  95. 3 0
      tests/misc/projects/Issue8303/pretty-fail.hxml
  96. 54 0
      tests/misc/projects/Issue8303/pretty-fail.hxml.stderr
  97. 3 0
      tests/misc/projects/Issue8471/compile2-pretty.hxml
  98. 22 0
      tests/misc/projects/Issue8471/compile2-pretty.hxml.stderr
  99. 7 14
      tests/misc/projects/issue5002/compile2-fail.hxml.stderr
  100. 7 1
      tests/misc/src/Main.hx

+ 2 - 0
.github/workflows/main.yml

@@ -347,6 +347,7 @@ jobs:
       PLATFORM: linux64
       PLATFORM: linux64
       TEST: ${{matrix.target}}
       TEST: ${{matrix.target}}
       HXCPP_COMPILE_CACHE: ~/hxcache
       HXCPP_COMPILE_CACHE: ~/hxcache
+      HAXE_STD_PATH: /usr/local/share/haxe/std
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
@@ -852,6 +853,7 @@ jobs:
       PLATFORM: mac
       PLATFORM: mac
       TEST: ${{matrix.target}}
       TEST: ${{matrix.target}}
       HXCPP_COMPILE_CACHE: ~/hxcache
       HXCPP_COMPILE_CACHE: ~/hxcache
+      HAXE_STD_PATH: /usr/local/share/haxe/std
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:

+ 2 - 0
extra/github-actions/workflows/main.yml

@@ -157,6 +157,7 @@ jobs:
       PLATFORM: linux64
       PLATFORM: linux64
       TEST: ${{matrix.target}}
       TEST: ${{matrix.target}}
       HXCPP_COMPILE_CACHE: ~/hxcache
       HXCPP_COMPILE_CACHE: ~/hxcache
+      HAXE_STD_PATH: /usr/local/share/haxe/std
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
@@ -406,6 +407,7 @@ jobs:
       PLATFORM: mac
       PLATFORM: mac
       TEST: ${{matrix.target}}
       TEST: ${{matrix.target}}
       HXCPP_COMPILE_CACHE: ~/hxcache
       HXCPP_COMPILE_CACHE: ~/hxcache
+      HAXE_STD_PATH: /usr/local/share/haxe/std
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:

+ 22 - 0
src-json/define.json

@@ -718,5 +718,27 @@
 		"name": "NoTre",
 		"name": "NoTre",
 		"define": "no-tre",
 		"define": "no-tre",
 		"doc": "Disable tail recursion elimination."
 		"doc": "Disable tail recursion elimination."
+	},
+	{
+		"name": "MessageReporting",
+		"define": "message-reporting",
+		"doc": "Select message reporting mode for compiler output. (default: classic)",
+		"params": ["mode: classic | pretty | indent"]
+	},
+	{
+		"name": "NoColor",
+		"define": "no-color",
+		"doc": "Disable ANSI color codes when using rich output."
+	},
+	{
+		"name": "MessagesLogFile",
+		"define": "messages-log-file",
+		"doc": "Path to a text file to write messages log to, in addition to regular output."
+	},
+	{
+		"name": "MessagesLogFormat",
+		"define": "messages-log-format",
+		"doc": "Select message reporting mode for messages log output. (default: indent)",
+		"params": ["format: classic | pretty | indent"]
 	}
 	}
 ]
 ]

+ 1 - 1
src/codegen/gencommon/gencommon.ml

@@ -732,7 +732,7 @@ let run_filters_from gen t filters =
 let run_filters gen =
 let run_filters gen =
 	let last_error = gen.gcon.error in
 	let last_error = gen.gcon.error in
 	let has_errors = ref false in
 	let has_errors = ref false in
-	gen.gcon.error <- (fun msg pos -> has_errors := true; last_error msg pos);
+	gen.gcon.error <- (fun ?(depth=0) msg pos -> has_errors := true; last_error ~depth msg pos);
 	(* first of all, we have to make sure that the filters won't trigger a major Gc collection *)
 	(* first of all, we have to make sure that the filters won't trigger a major Gc collection *)
 	let t = Timer.timer ["gencommon_filters"] in
 	let t = Timer.timer ["gencommon_filters"] in
 	(if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false);
 	(if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false);

+ 7 - 3
src/compiler/compilationContext.ml

@@ -64,6 +64,10 @@ type server_api = {
 let message ctx msg =
 let message ctx msg =
 	ctx.messages <- msg :: ctx.messages
 	ctx.messages <- msg :: ctx.messages
 
 
-let error ctx msg p =
-	message ctx (msg,p,DKCompilerMessage,Error);
-	ctx.has_error <- true
+let error ctx ?(depth=0) msg p =
+	message ctx (make_compiler_message msg p depth DKCompilerMessage Error);
+	ctx.has_error <- true
+
+let located_error ctx ?(depth=0) msg =
+	message ctx (make_compiler_message (extract_located_msg msg) (extract_located_pos msg) depth DKCompilerMessage Error);
+	ctx.has_error <- true

+ 24 - 18
src/compiler/compiler.ml

@@ -4,20 +4,20 @@ open CompilationContext
 
 
 let run_or_diagnose ctx f arg =
 let run_or_diagnose ctx f arg =
 	let com = ctx.com in
 	let com = ctx.com in
-	let handle_diagnostics msg p kind =
+	let handle_diagnostics msg kind =
 		ctx.has_error <- true;
 		ctx.has_error <- true;
-		add_diagnostics_message com msg p kind Error;
+		add_diagnostics_message com msg kind Error;
 		DisplayOutput.emit_diagnostics ctx.com
 		DisplayOutput.emit_diagnostics ctx.com
 	in
 	in
 	if is_diagnostics com then begin try
 	if is_diagnostics com then begin try
 			f arg
 			f arg
 		with
 		with
-		| Error.Error(msg,p) ->
-			handle_diagnostics (Error.error_msg msg) p DKCompilerMessage
+		| Error.Error(msg,p,_) ->
+			handle_diagnostics (Error.error_msg p msg) DKCompilerMessage
 		| Parser.Error(msg,p) ->
 		| Parser.Error(msg,p) ->
-			handle_diagnostics (Parser.error_msg msg) p DKParserError
+			handle_diagnostics (located (Parser.error_msg msg) p) DKParserError
 		| Lexer.Error(msg,p) ->
 		| Lexer.Error(msg,p) ->
-			handle_diagnostics (Lexer.error_msg msg) p DKParserError
+			handle_diagnostics (located (Lexer.error_msg msg) p) DKParserError
 		end
 		end
 	else
 	else
 		f arg
 		f arg
@@ -211,8 +211,8 @@ module Setup = struct
 		Common.define_value com Define.Haxe s_version;
 		Common.define_value com Define.Haxe s_version;
 		Common.raw_define com "true";
 		Common.raw_define com "true";
 		Common.define_value com Define.Dce "std";
 		Common.define_value com Define.Dce "std";
-		com.info <- (fun msg p -> message ctx (msg,p,DKCompilerMessage,Information));
-		com.warning <- (fun w options msg p ->
+		com.info <- (fun ?(depth=0) msg p -> message ctx (make_compiler_message msg p depth DKCompilerMessage Information));
+		com.warning <- (fun ?(depth=0) w options msg p ->
 			match Warning.get_mode w (com.warning_options @ options) with
 			match Warning.get_mode w (com.warning_options @ options) with
 			| WMEnable ->
 			| WMEnable ->
 				let wobj = Warning.warning_obj w in
 				let wobj = Warning.warning_obj w in
@@ -221,18 +221,18 @@ module Setup = struct
 				else
 				else
 					Printf.sprintf "(%s) %s" wobj.w_name msg
 					Printf.sprintf "(%s) %s" wobj.w_name msg
 				in
 				in
-				message ctx (msg,p,DKCompilerMessage,Warning)
+				message ctx (make_compiler_message msg p depth DKCompilerMessage Warning)
 			| WMDisable ->
 			| WMDisable ->
 				()
 				()
 		);
 		);
 		com.error <- error ctx;
 		com.error <- error ctx;
-		let filter_messages = (fun keep_errors predicate -> (List.filter (fun ((_,_,_,sev) as cm) ->
-			(match sev with
+		let filter_messages = (fun keep_errors predicate -> (List.filter (fun cm ->
+			(match cm.cm_severity with
 			| MessageSeverity.Error -> keep_errors;
 			| MessageSeverity.Error -> keep_errors;
 			| Information | Warning | Hint -> predicate cm;)
 			| Information | Warning | Hint -> predicate cm;)
 		) (List.rev ctx.messages))) in
 		) (List.rev ctx.messages))) in
-		com.get_messages <- (fun () -> (List.map (fun ((_,_,_,sev) as cm) ->
-			(match sev with
+		com.get_messages <- (fun () -> (List.map (fun cm ->
+			(match cm.cm_severity with
 			| MessageSeverity.Error -> die "" __LOC__;
 			| MessageSeverity.Error -> die "" __LOC__;
 			| Information | Warning | Hint -> cm;)
 			| Information | Warning | Hint -> cm;)
 		) (filter_messages false (fun _ -> true))));
 		) (filter_messages false (fun _ -> true))));
@@ -334,8 +334,8 @@ try
 with
 with
 	| Abort ->
 	| Abort ->
 		()
 		()
-	| Error.Fatal_error (m,p) ->
-		error ctx m p
+	| Error.Fatal_error (m,depth) ->
+		located_error ~depth ctx m
 	| Common.Abort (m,p) ->
 	| Common.Abort (m,p) ->
 		error ctx m p
 		error ctx m p
 	| Lexer.Error (m,p) ->
 	| Lexer.Error (m,p) ->
@@ -348,10 +348,16 @@ with
 			ctx.messages <- [];
 			ctx.messages <- [];
 		end else begin
 		end else begin
 			error ctx (Printf.sprintf "You cannot access the %s package while %s (for %s)" pack (if pf = "macro" then "in a macro" else "targeting " ^ pf) (s_type_path m) ) p;
 			error ctx (Printf.sprintf "You cannot access the %s package while %s (for %s)" pack (if pf = "macro" then "in a macro" else "targeting " ^ pf) (s_type_path m) ) p;
-			List.iter (error ctx (Error.compl_msg "referenced here")) (List.rev pl);
+			List.iter (error ~depth:1 ctx (Error.compl_msg "referenced here")) (List.rev pl);
 		end
 		end
-	| Error.Error (m,p) ->
-		error ctx (Error.error_msg m) p
+	| Error.Error (Stack stack,_,depth) -> (match stack with
+		| [] -> ()
+		| (e,p) :: stack -> begin
+			located_error ~depth ctx (Error.error_msg p e);
+			List.iter (fun (e,p) -> located_error ~depth:(depth+1) ctx (Error.error_msg p e)) stack;
+		end)
+	| Error.Error (m,p,depth) ->
+		located_error ~depth ctx (Error.error_msg p m)
 	| Generic.Generic_Exception(m,p) ->
 	| Generic.Generic_Exception(m,p) ->
 		error ctx m p
 		error ctx m p
 	| Arg.Bad msg ->
 	| Arg.Bad msg ->

+ 2 - 2
src/compiler/displayProcessing.ml

@@ -92,10 +92,10 @@ let process_display_arg ctx actx =
 let process_display_configuration ctx =
 let process_display_configuration ctx =
 	let com = ctx.com in
 	let com = ctx.com in
 	if is_diagnostics com then begin
 	if is_diagnostics com then begin
-		com.warning <- (fun w options s p ->
+		com.warning <- (fun ?depth w options s p ->
 			match Warning.get_mode w (com.warning_options @ options) with
 			match Warning.get_mode w (com.warning_options @ options) with
 			| WMEnable ->
 			| WMEnable ->
-				add_diagnostics_message com s p DKCompilerMessage Warning
+				add_diagnostics_message com (located s p) DKCompilerMessage Warning
 			| WMDisable ->
 			| WMDisable ->
 				()
 				()
 		);
 		);

+ 1 - 1
src/compiler/retyper.ml

@@ -21,7 +21,7 @@ let disable_typeloading rctx ctx f =
 	ctx.g.load_only_cached_modules <- true;
 	ctx.g.load_only_cached_modules <- true;
 	try
 	try
 		Std.finally (fun () -> ctx.g.load_only_cached_modules <- old) f ()
 		Std.finally (fun () -> ctx.g.load_only_cached_modules <- old) f ()
-	with (Error.Error (Module_not_found path,_)) ->
+	with (Error.Error (Module_not_found path,_,_)) ->
 		fail rctx (Printf.sprintf "Could not load [Module %s]" (s_type_path path))
 		fail rctx (Printf.sprintf "Could not load [Module %s]" (s_type_path path))
 
 
 let pair_type th t = match th with
 let pair_type th t = match th with

+ 355 - 27
src/compiler/server.ml

@@ -1,3 +1,4 @@
+open Extlib_leftovers
 open Printf
 open Printf
 open Globals
 open Globals
 open Ast
 open Ast
@@ -19,19 +20,19 @@ let has_error ctx =
 let check_display_flush ctx f_otherwise = match ctx.com.json_out with
 let check_display_flush ctx f_otherwise = match ctx.com.json_out with
 	| None ->
 	| None ->
 		if is_diagnostics ctx.com then begin
 		if is_diagnostics ctx.com then begin
-			List.iter (fun (msg,p,kind,sev) ->
-				add_diagnostics_message ctx.com msg p kind sev
+			List.iter (fun cm ->
+				add_diagnostics_message ctx.com (located cm.cm_message cm.cm_pos) cm.cm_kind cm.cm_severity
 			) (List.rev ctx.messages);
 			) (List.rev ctx.messages);
 			raise (Completion (Diagnostics.print ctx.com))
 			raise (Completion (Diagnostics.print ctx.com))
 		end else
 		end else
 			f_otherwise ()
 			f_otherwise ()
 	| Some api ->
 	| Some api ->
 		if has_error ctx then begin
 		if has_error ctx then begin
-			let errors = List.map (fun (msg,p,_,sev) ->
+			let errors = List.map (fun cm ->
 				JObject [
 				JObject [
-					"severity",JInt (MessageSeverity.to_int sev);
-					"location",Genjson.generate_pos_as_location p;
-					"message",JString msg;
+					"severity",JInt (MessageSeverity.to_int cm.cm_severity);
+					"location",Genjson.generate_pos_as_location cm.cm_pos;
+					"message",JString cm.cm_message;
 				]
 				]
 			) (List.rev ctx.messages) in
 			) (List.rev ctx.messages) in
 			api.send_error errors
 			api.send_error errors
@@ -86,17 +87,248 @@ let parse_file cs com file p =
 open ServerCompilationContext
 open ServerCompilationContext
 
 
 module Communication = struct
 module Communication = struct
+	type error_context = {
+		mutable last_positions : pos IntMap.t;
+		mutable max_lines : int IntMap.t;
+		mutable gutter : int IntMap.t;
+		mutable previous : (pos * MessageSeverity.t * int) option;
+	}
+
+	let create_error_context () = {
+		last_positions = IntMap.empty;
+		max_lines = IntMap.empty;
+		gutter = IntMap.empty;
+		previous = None;
+	}
+
+	let error_printer file line = Printf.sprintf "%s:%d:" file line
+
+	let resolve_source file l1 p1 l2 p2 =
+		let ch = open_in_bin file in
+		let curline = ref 1 in
+		let lines = ref [] in
+		let rec loop p line =
+			let inc i line =
+				if (!curline >= l1) && (!curline <= l2) then lines := (!curline, line) :: !lines;
+				curline := !curline + 1;
+				(i, "")
+			in
+
+			let input_char_or_done ch line =
+				try input_char ch with End_of_file -> begin
+					ignore(inc 0 line);
+					raise End_of_file
+				end
+			in
+
+			try
+				let read_char line = match input_char_or_done ch line with
+					| '\n' -> inc 1 line
+					| '\r' ->
+						ignore(input_char_or_done ch line);
+						inc 2 line
+					| c -> begin
+						let line = ref (line ^ (String.make 1 c)) in
+						let rec skip n =
+							if n > 0 then begin
+								let c = input_char_or_done ch !line in
+								line := !line ^ (String.make 1 c);
+								skip (n - 1)
+							end
+						in
+
+						let code = int_of_char c in
+						if code < 0xC0 then ()
+						else if code < 0xE0 then skip 1
+						else if code < 0xF0 then skip 2
+						else skip 3;
+
+						(1, !line)
+					end
+				in
+
+				let (delta, line) = read_char line in
+				loop (p + delta) line
+			with End_of_file ->
+				close_in ch;
+		in
+
+		loop 0 "";
+		List.rev !lines
+
+	let compiler_pretty_message_string ctx ectx cm =
+		match cm.cm_message with
+		(* Filter some messages that don't add much when using this message renderer *)
+		| "End of overload failure reasons" -> None
+		| _ -> begin
+			ectx.last_positions <- (IntMap.add cm.cm_depth cm.cm_pos ectx.last_positions);
+			let is_null_pos = cm.cm_pos = null_pos || cm.cm_pos.pmin = -1 in
+			let is_unknown_file f = f = "" || f = "?" in
+
+			(* Extract informations from position *)
+			let l1, p1, l2, p2, epos, lines =
+				if is_null_pos then begin
+					let epos = if is_unknown_file cm.cm_pos.pfile then "(unknown position)" else cm.cm_pos.pfile in
+					(-1, -1, -1, -1, epos, [])
+				end else begin
+					let f =
+						try Common.find_file ctx.com cm.cm_pos.pfile
+						with Not_found -> failwith ("File not found '" ^ cm.cm_pos.pfile ^ "'")
+						in
+
+					let l1, p1, l2, p2 = Lexer.get_pos_coords cm.cm_pos in
+					let lines = resolve_source f l1 p1 l2 p2 in
+					let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+					(l1, p1, l2, p2, epos, lines)
+				end in
+
+			(* If 4 lines or less, display all; if more, crop the middle *)
+			let lines = match lines with
+				| _ :: (_ :: (_ :: (_ :: []))) -> lines
+				| hd :: (_ :: (_ :: (_ :: l))) ->
+					let _,line = hd in
+					let indent = ref 0 in
+					let found = ref false in
+
+					while (not !found) && (!indent < (String.length line - 1)) do
+						found := not (Lexer.is_whitespace (String.unsafe_get line !indent));
+						indent := !indent + 1
+					done;
+
+					[hd; (0, (String.make (!indent+1) ' ') ^ "[...]"); List.hd (List.rev l)]
+				| _ -> lines
+			in
+
+			let parent_pos =
+				if cm.cm_depth = 0 then null_pos
+				else (try IntMap.find (cm.cm_depth-1) ectx.last_positions with Not_found -> null_pos)
+			in
+
+			let prev_pos,prev_sev,prev_nl = match ectx.previous with
+				| None -> (None, None, 0)
+				| Some (p, sev, depth) -> (Some p, Some sev, depth)
+			in
+
+			let sev_changed = prev_sev = None || Some cm.cm_severity <> prev_sev in
+			let pos_changed = (prev_pos = None || cm.cm_pos <> Option.get prev_pos || (cm.cm_depth <> prev_nl && cm.cm_depth <> prev_nl + 1)) && (parent_pos = null_pos || cm.cm_pos <> parent_pos) in
+			let file_changed = prev_pos = None || (pos_changed && match (cm.cm_pos.pfile, (Option.get prev_pos).pfile) with
+				| (f1, f2) when (is_unknown_file f1) && (is_unknown_file f2) -> false
+				| (f1, f2) -> f1 <> f2
+			) in
+
+			let display_heading = cm.cm_depth = 0 || sev_changed || file_changed in
+			let display_source = cm.cm_depth = 0 || sev_changed || pos_changed in
+			let display_pos_marker = (not is_null_pos) && (cm.cm_depth = 0 || sev_changed || pos_changed) in
+
+			let gutter_len = (try String.length (Printf.sprintf "%d" (IntMap.find cm.cm_depth ectx.max_lines)) with Not_found -> 0) + 2 in
+
+			let no_color = Define.defined ctx.com.defines Define.NoColor in
+			let c_reset = if no_color then "" else "\x1b[0m" in
+			let c_bold = if no_color then "" else "\x1b[1m" in
+			let c_dim = if no_color then "" else "\x1b[2m" in
+
+			let (c_sev, c_sev_bg) = if no_color then ("", "") else match cm.cm_severity with
+				| MessageSeverity.Warning -> ("\x1b[33m", "\x1b[30;43m")
+				| Information | Hint -> ("\x1b[34m", "\x1b[30;44m")
+				| Error -> ("\x1b[31m", "\x1b[30;41m")
+			in
+
+			let sev_label = if cm.cm_depth > 0 then " -> " else Printf.sprintf
+				(if no_color then "[%s]" else " %s ")
+				(match cm.cm_severity with
+					| MessageSeverity.Warning -> "WARNING"
+					| Information -> "INFO"
+					| Hint -> "HINT"
+					| Error -> "ERROR"
+				) in
+
+			let out = ref "" in
+
+			if display_heading then
+				out := Printf.sprintf "%s%s\n\n"
+					(* Severity heading *)
+					(c_sev_bg ^ sev_label ^ c_reset ^ " ")
+					(* File + line pointer *)
+					epos;
+
+			(* Error source *)
+			if display_source then out := List.fold_left (fun out (l, line) ->
+				let nb_len = String.length (string_of_int l) in
+
+				(* Replace tabs with 1 space to avoid column misalignments *)
+				let line = String.concat " " (ExtString.String.nsplit line "\t") in
+				let len = String.length line in
 
 
-	let compiler_message_string (str,p,_,sev) =
-		let str = match sev with
-			| MessageSeverity.Warning -> "Warning : " ^ str
-			| Information | Error | Hint -> str
+				out ^ Printf.sprintf "%s%s | %s\n"
+					(* left-padded line number *)
+					(String.make (gutter_len-nb_len-1) ' ')
+					(if l = 0 then "-" else Printf.sprintf "%d" l)
+					(* Source code at that line *)
+					(
+						if l = 0 then
+							c_dim ^ line ^ c_reset
+						else if l1 = l2 then
+							(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
+							^ c_reset ^ c_bold ^ (String.sub line (p1-1) (p2-p1))
+							^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len - p2 + 1))
+							^ c_reset
+						else begin
+							(if (l = l1) then
+								(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
+								^ c_reset ^ c_bold ^ (String.sub line (p1-1) (len-p1+1))
+								^ c_reset
+							else if (l = l2) then
+								(if p2 > 1 then c_bold ^ (String.sub line 0 (p2-1)) else "")
+								^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len-p2+1))
+								^ c_reset
+							else c_bold ^ line ^ c_reset)
+						end
+					)
+			) !out lines;
+
+			(* Error position marker *)
+			if display_pos_marker then
+				out := Printf.sprintf "%s%s|%s\n"
+					!out
+					(String.make gutter_len ' ')
+					(if l1 = l2 then String.make p1 ' ' ^ c_sev ^ String.make (if p1 = p2 then 1 else p2-p1) '^' ^ c_reset else "");
+
+			(* Error message *)
+			out := List.fold_left (fun out str -> Printf.sprintf "%s%s| %s\n"
+				out
+				(String.make gutter_len ' ')
+				(* Remove "... " prefix *)
+				(if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str)
+			) !out (ExtString.String.nsplit cm.cm_message "\n");
+
+			ectx.previous <- Some ((if is_null_pos then null_pos else cm.cm_pos), cm.cm_severity, cm.cm_depth);
+			ectx.gutter <- (IntMap.add cm.cm_depth gutter_len ectx.gutter);
+
+			(* Indent sub errors *)
+			let rec indent ?(acc=0) depth =
+				if depth = 0 then acc
+				else indent ~acc:(acc + try IntMap.find (depth-1) ectx.gutter with Not_found -> 3) (depth-1)
+			in
+
+			Some (
+				if cm.cm_depth > 0 then String.concat "\n" (List.map (fun str -> match str with
+					| "" -> ""
+					| _ -> (String.make (indent cm.cm_depth) ' ') ^ str
+				) (ExtString.String.nsplit !out "\n"))
+				else !out
+			)
+		end
+
+	let compiler_message_string ctx ectx cm =
+		let str = match cm.cm_severity with
+			| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
+			| Information | Error | Hint -> cm.cm_message
 		in
 		in
-		if p = null_pos then
-			str
+
+		if cm.cm_pos = null_pos then
+			Some str
 		else begin
 		else begin
-			let error_printer file line = Printf.sprintf "%s:%d:" file line in
-			let epos = Lexer.get_error_pos error_printer p in
+			let epos = Lexer.get_error_pos error_printer cm.cm_pos in
 			let str =
 			let str =
 				let lines =
 				let lines =
 					match (ExtString.String.nsplit str "\n") with
 					match (ExtString.String.nsplit str "\n") with
@@ -105,9 +337,105 @@ module Communication = struct
 				in
 				in
 				String.concat ("\n" ^ epos ^ " : ") lines
 				String.concat ("\n" ^ epos ^ " : ") lines
 			in
 			in
-			Printf.sprintf "%s : %s" epos str
+			Some (Printf.sprintf "%s : %s" epos str)
 		end
 		end
 
 
+	let compiler_indented_message_string ctx ectx cm =
+		match cm.cm_message with
+		(* Filter some messages that don't add much when using this message renderer *)
+		| "End of overload failure reasons" -> None
+		| _ ->
+			let str = match cm.cm_severity with
+				| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
+				| Information -> "Info : " ^ cm.cm_message
+				| Error | Hint -> cm.cm_message
+			in
+
+			if cm.cm_pos = null_pos then
+				Some str
+			else begin
+				let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+				let lines =
+					match (ExtString.String.nsplit str "\n") with
+					| first :: rest -> (cm.cm_depth, first) :: List.map (fun msg -> (cm.cm_depth+1, msg)) rest
+					| l -> [(cm.cm_depth, List.hd l)]
+				in
+				let rm_prefix str = if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str in
+				Some (String.concat "\n" (List.map (fun (depth, msg) -> (String.make (depth*2) ' ') ^ epos ^ " : " ^ (rm_prefix msg)) lines))
+			end
+
+	let get_max_line max_lines messages =
+		List.fold_left (fun max_lines cm ->
+			let _,_,l2,_ = Lexer.get_pos_coords cm.cm_pos in
+			let old = try IntMap.find cm.cm_depth max_lines with Not_found -> 0 in
+
+			if l2 > old then IntMap.add cm.cm_depth l2 max_lines
+			else max_lines
+		) max_lines messages
+
+	let display_messages ctx on_message = begin
+		let ectx = create_error_context () in
+		ectx.max_lines <- get_max_line ectx.max_lines ctx.messages;
+
+		let get_formatter def default =
+			let format_mode = Define.defined_value_safe ~default ctx.com.defines def in
+			match format_mode with
+				| "pretty" -> compiler_pretty_message_string ctx ectx
+				| "indent" -> compiler_indented_message_string ctx ectx
+				| "classic" -> compiler_message_string ctx ectx
+				| m -> begin
+					let def = Define.get_define_key def in
+					error ctx (Printf.sprintf "Invalid message reporting mode: \"%s\", expected classic | pretty | indent (for -D %s)." m def) null_pos;
+					compiler_message_string ctx ectx
+				end
+			in
+
+		let message_formatter = get_formatter Define.MessageReporting "classic" in
+		let log_formatter = get_formatter Define.MessagesLogFormat "indent" in
+
+		let log_messages = ref (Define.defined ctx.com.defines Define.MessagesLogFile) in
+		let log_message = ref None in
+		let close_logs = ref None in
+
+		if !log_messages then begin
+			try begin
+				let buf = Rbuffer.create 16000 in
+
+				let file = Define.defined_value ctx.com.defines Define.MessagesLogFile in
+				let chan =
+					Path.mkdir_from_path file;
+					open_out_bin file
+				in
+
+				log_message := (Some (fun msg ->
+					match (log_formatter msg) with
+						| None -> ()
+						| Some str -> Rbuffer.add_string buf (str ^ "\n")));
+
+				close_logs := (Some (fun () ->
+					Rbuffer.output_buffer chan buf;
+					Rbuffer.clear buf;
+					close_out chan
+				));
+			end with
+				| Failure e | Sys_error e -> begin
+					let def = Define.get_define_key Define.MessagesLogFile in
+					error ctx (Printf.sprintf "Error opening log file: %s. Logging to file disabled (-D %s)" e def) null_pos;
+					log_messages := false;
+				end
+		end;
+
+		List.iter (fun cm ->
+			if !log_messages then (Option.get !log_message) cm;
+
+			match (message_formatter cm) with
+				| None -> ()
+				| Some str -> on_message cm.cm_severity str
+		) (List.rev ctx.messages);
+
+		if !log_messages then (Option.get !close_logs) ();
+	end
+
 	let create_stdio () =
 	let create_stdio () =
 		let rec self = {
 		let rec self = {
 			write_out = (fun s ->
 			write_out = (fun s ->
@@ -118,10 +446,12 @@ module Communication = struct
 				prerr_string s;
 				prerr_string s;
 			);
 			);
 			flush = (fun ctx ->
 			flush = (fun ctx ->
-				List.iter (fun ((_,_,_,sev) as cm) -> match sev with
-					| MessageSeverity.Information -> print_endline (compiler_message_string cm)
-					| Warning | Error | Hint -> prerr_endline (compiler_message_string cm)
-				) (List.rev ctx.messages);
+				display_messages ctx (fun sev output ->
+					match sev with
+						| MessageSeverity.Information -> print_endline output
+						| Warning | Error | Hint -> prerr_endline output
+				);
+
 				if has_error ctx && !Helper.prompt then begin
 				if has_error ctx && !Helper.prompt then begin
 					print_endline "Press enter to exit...";
 					print_endline "Press enter to exit...";
 					ignore(read_line());
 					ignore(read_line());
@@ -148,13 +478,11 @@ module Communication = struct
 		);
 		);
 		flush = (fun ctx ->
 		flush = (fun ctx ->
 			check_display_flush ctx (fun () ->
 			check_display_flush ctx (fun () ->
-				List.iter
-					(fun msg ->
-						let s = compiler_message_string msg in
-						write (s ^ "\n");
-						ServerMessage.message s;
-					)
-					(List.rev ctx.messages);
+				display_messages ctx (fun _ output ->
+					write (output ^ "\n");
+					ServerMessage.message output;
+				);
+
 				sctx.was_compilation <- ctx.com.display.dms_full_typing;
 				sctx.was_compilation <- ctx.com.display.dms_full_typing;
 				if has_error ctx then begin
 				if has_error ctx then begin
 					measure_times := false;
 					measure_times := false;
@@ -766,4 +1094,4 @@ and init_wait_socket host port =
 		let close() = Unix.close sin in
 		let close() = Unix.close sin in
 		false, read, write, close
 		false, read, write, close
 	) in
 	) in
-	accept
+	accept

+ 6 - 6
src/context/abstractCast.ml

@@ -19,7 +19,7 @@ let rec make_static_call ctx c cf a pl args t p =
 					| None ->  type_expr ctx (EConst (Ident "null"),p) WithType.value
 					| None ->  type_expr ctx (EConst (Ident "null"),p) WithType.value
 				in
 				in
 				ctx.with_type_stack <- List.tl ctx.with_type_stack;
 				ctx.with_type_stack <- List.tl ctx.with_type_stack;
-				let e = try cast_or_unify_raise ctx t e p with Error(Unify _,_) -> raise Not_found in
+				let e = try cast_or_unify_raise ctx t e p with Error(Unify _,_,_) -> raise Not_found in
 				f();
 				f();
 				e
 				e
 			| _ -> die "" __LOC__
 			| _ -> die "" __LOC__
@@ -38,7 +38,7 @@ and do_check_cast ctx uctx tleft eright p =
 				(try
 				(try
 					Type.unify_custom uctx eright.etype tleft;
 					Type.unify_custom uctx eright.etype tleft;
 				with Unify_error l ->
 				with Unify_error l ->
-					raise (Error (Unify l, eright.epos)))
+					raise (Error (Unify l, eright.epos,0)))
 			| _ -> ()
 			| _ -> ()
 		end;
 		end;
 		if cf == ctx.curfield || rec_stack_memq cf cast_stack then typing_error "Recursive implicit cast" p;
 		if cf == ctx.curfield || rec_stack_memq cf cast_stack then typing_error "Recursive implicit cast" p;
@@ -108,7 +108,7 @@ and cast_or_unify_raise ctx ?(uctx=None) tleft eright p =
 and cast_or_unify ctx tleft eright p =
 and cast_or_unify ctx tleft eright p =
 	try
 	try
 		cast_or_unify_raise ctx tleft eright p
 		cast_or_unify_raise ctx tleft eright p
-	with Error (Unify l,p) ->
+	with Error (Unify l,p,_) ->
 		raise_or_display ctx l p;
 		raise_or_display ctx l p;
 		eright
 		eright
 
 
@@ -142,7 +142,7 @@ let find_array_read_access_raise ctx a pl e1 p =
 					let e1 = cast_or_unify_raise ctx ta1 e1 p in
 					let e1 = cast_or_unify_raise ctx ta1 e1 p in
 					check_constraints();
 					check_constraints();
 					cf,tf,r,e1
 					cf,tf,r,e1
-				with Unify_error _ | Error (Unify _,_) ->
+				with Unify_error _ | Error (Unify _,_,_) ->
 					loop cfl
 					loop cfl
 				end
 				end
 			| _ -> loop cfl
 			| _ -> loop cfl
@@ -163,7 +163,7 @@ let find_array_write_access_raise ctx a pl e1 e2  p =
 					let e2 = cast_or_unify_raise ctx ta2 e2 p in
 					let e2 = cast_or_unify_raise ctx ta2 e2 p in
 					check_constraints();
 					check_constraints();
 					cf,tf,r,e1,e2
 					cf,tf,r,e1,e2
-				with Unify_error _ | Error (Unify _,_) ->
+				with Unify_error _ | Error (Unify _,_,_) ->
 					loop cfl
 					loop cfl
 				end
 				end
 			| _ -> loop cfl
 			| _ -> loop cfl
@@ -345,4 +345,4 @@ let handle_abstract_casts ctx e =
 	in
 	in
 	loop ctx e
 	loop ctx e
 ;;
 ;;
-Typecore.cast_or_unify_raise_ref := cast_or_unify_raise
+Typecore.cast_or_unify_raise_ref := cast_or_unify_raise

+ 16 - 11
src/context/common.ml

@@ -353,9 +353,9 @@ type context = {
 	mutable report_mode : report_mode;
 	mutable report_mode : report_mode;
 	(* communication *)
 	(* communication *)
 	mutable print : string -> unit;
 	mutable print : string -> unit;
-	mutable error : string -> pos -> unit;
-	mutable info : string -> pos -> unit;
-	mutable warning : warning -> Warning.warning_option list list -> string -> pos -> unit;
+	mutable error : ?depth:int -> string -> pos -> unit;
+	mutable info : ?depth:int -> string -> pos -> unit;
+	mutable warning : ?depth:int -> warning -> Warning.warning_option list list -> string -> pos -> unit;
 	mutable warning_options : Warning.warning_option list list;
 	mutable warning_options : Warning.warning_option list list;
 	mutable get_messages : unit -> compiler_message list;
 	mutable get_messages : unit -> compiler_message list;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
@@ -822,10 +822,10 @@ let create compilation_step cs version args =
 		user_defines = Hashtbl.create 0;
 		user_defines = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		get_macros = (fun() -> None);
 		get_macros = (fun() -> None);
-		info = (fun _ _ -> die "" __LOC__);
-		warning = (fun _ _ _ -> die "" __LOC__);
+		info = (fun ?depth _ _ -> die "" __LOC__);
+		warning = (fun ?depth _ _ _ -> die "" __LOC__);
 		warning_options = [];
 		warning_options = [];
-		error = (fun _ _ -> die "" __LOC__);
+		error = (fun ?depth _ _ -> die "" __LOC__);
 		get_messages = (fun() -> []);
 		get_messages = (fun() -> []);
 		filter_messages = (fun _ -> ());
 		filter_messages = (fun _ -> ());
 		pass_debug_messages = DynArray.create();
 		pass_debug_messages = DynArray.create();
@@ -1013,7 +1013,7 @@ let allow_package ctx s =
 	with Not_found ->
 	with Not_found ->
 		()
 		()
 
 
-let abort msg p = raise (Abort (msg,p))
+let abort ?depth msg p = raise (Abort (msg,p))
 
 
 let platform ctx p = ctx.platform = p
 let platform ctx p = ctx.platform = p
 
 
@@ -1217,16 +1217,21 @@ let utf16_to_utf8 str =
 	loop 0;
 	loop 0;
 	Buffer.contents b
 	Buffer.contents b
 
 
-let add_diagnostics_message com s p kind sev =
+let add_diagnostics_message com msg kind sev =
+	let p = Globals.extract_located_pos msg in
+	let s = Globals.extract_located_msg msg in
 	if sev = MessageSeverity.Error then com.has_error <- true;
 	if sev = MessageSeverity.Error then com.has_error <- true;
 	let di = com.shared.shared_display_information in
 	let di = com.shared.shared_display_information in
 	di.diagnostics_messages <- (s,p,kind,sev) :: di.diagnostics_messages
 	di.diagnostics_messages <- (s,p,kind,sev) :: di.diagnostics_messages
 
 
-let display_error com msg p =
+let located_display_error com ?(depth = 0) msg =
 	if is_diagnostics com then
 	if is_diagnostics com then
-		add_diagnostics_message com msg p MessageKind.DKCompilerMessage MessageSeverity.Error
+		add_diagnostics_message com msg MessageKind.DKCompilerMessage MessageSeverity.Error
 	else
 	else
-		com.error msg p
+		com.error (Globals.extract_located_msg msg) (Globals.extract_located_pos msg) ~depth
+
+let display_error com ?(depth = 0) msg p =
+	located_display_error com ~depth (Globals.located msg p)
 
 
 open Printer
 open Printer
 
 

+ 2 - 2
src/context/display/diagnostics.ml

@@ -43,10 +43,10 @@ let find_unused_variables com e =
 let check_other_things com e =
 let check_other_things com e =
 	let had_effect = ref false in
 	let had_effect = ref false in
 	let no_effect p =
 	let no_effect p =
-		add_diagnostics_message com "This code has no effect" p DKCompilerMessage Warning;
+		add_diagnostics_message com (located "This code has no effect" p) DKCompilerMessage Warning;
 	in
 	in
 	let pointless_compound s p =
 	let pointless_compound s p =
-		add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DKCompilerMessage Warning;
+		add_diagnostics_message com (located (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p) DKCompilerMessage Warning;
 	in
 	in
 	let rec compound s el p =
 	let rec compound s el p =
 		let old = !had_effect in
 		let old = !had_effect in

+ 1 - 1
src/context/display/displayFields.ml

@@ -75,7 +75,7 @@ let collect_static_extensions ctx items e p =
 					let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) (f.cf_type,ct) in
 					let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) (f.cf_type,ct) in
 					PMap.add f.cf_name item acc
 					PMap.add f.cf_name item acc
 				end
 				end
-			with Error (Unify _,_) | Unify_error _ ->
+			with Error (Unify _,_,_) | Unify_error _ ->
 				acc
 				acc
 			end
 			end
 		| _ ->
 		| _ ->

+ 14 - 10
src/context/typecore.ml

@@ -197,7 +197,7 @@ type dot_path_part = {
 
 
 exception Forbid_package of (string * path * pos) * pos list * string
 exception Forbid_package of (string * path * pos) * pos list * string
 
 
-exception WithTypeError of error_msg * pos
+exception WithTypeError of error_msg * pos * int (* depth *)
 
 
 let memory_marker = [|Unix.time()|]
 let memory_marker = [|Unix.time()|]
 
 
@@ -221,9 +221,9 @@ let pass_name = function
 	| PForce -> "force"
 	| PForce -> "force"
 	| PFinal -> "final"
 	| PFinal -> "final"
 
 
-let warning ctx w msg p =
+let warning ?(depth=0) ctx w msg p =
 	let options = (Warning.from_meta ctx.curclass.cl_meta) @ (Warning.from_meta ctx.curfield.cf_meta) in
 	let options = (Warning.from_meta ctx.curclass.cl_meta) @ (Warning.from_meta ctx.curfield.cf_meta) in
-	ctx.com.warning w options msg p
+	ctx.com.warning ~depth w options msg p
 
 
 let make_call ctx e el t p = (!make_call_ref) ctx e el t p
 let make_call ctx e el t p = (!make_call_ref) ctx e el t p
 
 
@@ -256,11 +256,11 @@ let make_static_call ctx c cf map args t p =
 
 
 let raise_or_display ctx l p =
 let raise_or_display ctx l p =
 	if ctx.untyped then ()
 	if ctx.untyped then ()
-	else if ctx.in_call_args then raise (WithTypeError(Unify l,p))
-	else display_error ctx.com (error_msg (Unify l)) p
+	else if ctx.in_call_args then raise (WithTypeError(Unify l,p,0))
+	else located_display_error ctx.com (error_msg p (Unify l))
 
 
 let raise_or_display_message ctx msg p =
 let raise_or_display_message ctx msg p =
-	if ctx.in_call_args then raise (WithTypeError (Custom msg,p))
+	if ctx.in_call_args then raise (WithTypeError (Custom msg,p,0))
 	else display_error ctx.com msg p
 	else display_error ctx.com msg p
 
 
 let unify ctx t1 t2 p =
 let unify ctx t1 t2 p =
@@ -276,7 +276,7 @@ let unify_raise_custom uctx t1 t2 p =
 	with
 	with
 		Unify_error l ->
 		Unify_error l ->
 			(* no untyped check *)
 			(* no untyped check *)
-			raise (Error (Unify l,p))
+			raise (Error (Unify l,p,0))
 
 
 let unify_raise = unify_raise_custom default_unification_context
 let unify_raise = unify_raise_custom default_unification_context
 
 
@@ -294,7 +294,7 @@ let add_local ctx k n t p =
 				(* ignore std lib *)
 				(* ignore std lib *)
 				if not (List.exists (ExtLib.String.starts_with p.pfile) ctx.com.std_path) then begin
 				if not (List.exists (ExtLib.String.starts_with p.pfile) ctx.com.std_path) then begin
 					warning ctx WVarShadow "This variable shadows a previously declared variable" p;
 					warning ctx WVarShadow "This variable shadows a previously declared variable" p;
-					warning ctx WVarShadow (compl_msg "Previous variable was here") v'.v_pos
+					warning ~depth:1 ctx WVarShadow (compl_msg "Previous variable was here") v'.v_pos
 				end
 				end
 			with Not_found ->
 			with Not_found ->
 				()
 				()
@@ -420,8 +420,8 @@ let exc_protect ?(force=true) ctx f (where:string) =
 			r := lazy_available t;
 			r := lazy_available t;
 			t
 			t
 		with
 		with
-			| Error (m,p) ->
-				raise (Fatal_error ((error_msg m),p))
+			| Error (m,p,nl) ->
+				raise (Fatal_error ((error_msg p m),nl))
 	);
 	);
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r
 	r
@@ -795,6 +795,10 @@ let display_error ctx.com msg p =
 	debug ctx ("ERROR " ^ msg);
 	debug ctx ("ERROR " ^ msg);
 	display_error ctx.com msg p
 	display_error ctx.com msg p
 
 
+let located_display_error ctx.com msg =
+	debug ctx ("ERROR " ^ msg);
+	located_display_error ctx.com msg
+
 let make_pass ?inf ctx f =
 let make_pass ?inf ctx f =
 	let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
 	let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
 	(fun v ->
 	(fun v ->

+ 1 - 0
src/core/define.ml

@@ -117,6 +117,7 @@ let get_signature def =
 			   Note that we should removed flags like use_rtti_doc here.
 			   Note that we should removed flags like use_rtti_doc here.
 			*)
 			*)
 			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin"
 			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin"
+			| "message_reporting" | "messages_log_file" | "messages_log_format" | "no_color"
 			| "dump" | "dump_dependencies" | "dump_ignore_var_ids" -> acc
 			| "dump" | "dump_dependencies" | "dump_ignore_var_ids" -> acc
 			| _ -> (k ^ "=" ^ v) :: acc
 			| _ -> (k ^ "=" ^ v) :: acc
 		) def.values [] in
 		) def.values [] in

+ 34 - 22
src/core/error.ml

@@ -17,7 +17,7 @@ and error_msg =
 	| Unify of unify_error list
 	| Unify of unify_error list
 	| Custom of string
 	| Custom of string
 	| Unknown_ident of string
 	| Unknown_ident of string
-	| Stack of error_msg * error_msg
+	| Stack of (error_msg * Globals.pos) list
 	| Call_error of call_error
 	| Call_error of call_error
 	| No_constructor of module_type
 	| No_constructor of module_type
 	| Abstract_class of module_type
 	| Abstract_class of module_type
@@ -26,8 +26,8 @@ and type_not_found_reason =
 	| Private_type
 	| Private_type
 	| Not_defined
 	| Not_defined
 
 
-exception Fatal_error of string * Globals.pos
-exception Error of error_msg * Globals.pos
+exception Fatal_error of Globals.located * int (* depth *)
+exception Error of error_msg * Globals.pos * int (* depth *)
 
 
 let string_source t = match follow t with
 let string_source t = match follow t with
 	| TInst(c,tl) -> PMap.foldi (fun s _ acc -> s :: acc) (TClass.get_all_fields c tl) []
 	| TInst(c,tl) -> PMap.foldi (fun s _ acc -> s :: acc) (TClass.get_all_fields c tl) []
@@ -43,6 +43,9 @@ let short_type ctx t =
 	Should be called for each complementary error message.
 	Should be called for each complementary error message.
 *)
 *)
 let compl_msg s = "... " ^ s
 let compl_msg s = "... " ^ s
+let rec compl_located_msg = function
+	 | Message (s,p) -> Message (compl_msg s,p)
+	 | Stack stack -> Stack (List.map compl_located_msg stack)
 
 
 let unify_error_msg ctx err = match err with
 let unify_error_msg ctx err = match err with
 	| Cannot_unify (t1,t2) ->
 	| Cannot_unify (t1,t2) ->
@@ -270,29 +273,38 @@ module BetterErrors = struct
 			Printf.sprintf "error: %s\nhave: %s\nwant: %s" (Buffer.contents message_buffer) slhs srhs
 			Printf.sprintf "error: %s\nhave: %s\nwant: %s" (Buffer.contents message_buffer) slhs srhs
 end
 end
 
 
-let rec error_msg = function
-	| Module_not_found m -> "Type not found : " ^ s_type_path m
-	| Type_not_found (m,t,Private_type) -> "Cannot access private type " ^ t ^ " in module " ^ s_type_path m
-	| Type_not_found (m,t,Not_defined) -> "Module " ^ s_type_path m ^ " does not define type " ^ t
-	| Unify l -> BetterErrors.better_error_message l
-	| Unknown_ident s -> "Unknown identifier : " ^ s
-	| Custom s -> s
-	| Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
-	| Call_error err -> s_call_error err
-	| No_constructor mt -> (s_type_path (t_infos mt).mt_path ^ " does not have a constructor")
-	| Abstract_class mt -> (s_type_path (t_infos mt).mt_path) ^ " is abstract and cannot be constructed"
+let rec error_msg p = function
+	| Module_not_found m -> located ("Type not found : " ^ s_type_path m) p
+	| Type_not_found (m,t,Private_type) -> located ("Cannot access private type " ^ t ^ " in module " ^ s_type_path m) p
+	| Type_not_found (m,t,Not_defined) -> located ("Module " ^ s_type_path m ^ " does not define type " ^ t) p
+	| Unify l -> located (BetterErrors.better_error_message l) p
+	| Unknown_ident s -> located ("Unknown identifier : " ^ s) p
+	| Custom s -> located s p
+	| Stack stack -> located_stack (List.map (fun (e,p) -> error_msg p e) stack)
+	| Call_error err -> s_call_error p err
+	| No_constructor mt -> located (s_type_path (t_infos mt).mt_path ^ " does not have a constructor") p
+	| Abstract_class mt -> located (s_type_path (t_infos mt).mt_path ^ " is abstract and cannot be constructed") p
 
 
-and s_call_error = function
+and s_call_error p = function
 	| Not_enough_arguments tl ->
 	| Not_enough_arguments tl ->
 		let pctx = print_context() in
 		let pctx = print_context() in
-		"Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl))
-	| Too_many_arguments -> "Too many arguments"
-	| Could_not_unify err -> error_msg err
-	| Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s
+		located ("Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl))) p
+	| Too_many_arguments -> located "Too many arguments" p
+	| Could_not_unify err -> error_msg p err
+	| Cannot_skip_non_nullable s -> located ("Cannot skip non-nullable argument " ^ s) p
 
 
-let typing_error msg p = raise (Error (Custom msg,p))
+let typing_error ?(depth=0) msg p = raise (Error (Custom msg,p,depth))
+let located_typing_error ?(depth=0) msg =
+	let err = match msg with
+		| Message (msg,p) -> Custom msg
+		| Stack stack -> Stack (List.map (fun msg -> (Custom (extract_located_msg msg),(extract_located_pos msg))) stack)
+	in
+	raise (Error (err,(extract_located_pos msg),depth))
+
+let call_stack_error ?(depth=0) msg stack p =
+	raise (Error (Stack (((Custom ("Uncaught exception " ^ msg)),p) :: (List.map (fun p -> ((Custom "Called from here"),p)) stack)),p,depth))
 
 
-let raise_typing_error err p = raise (Error(err,p))
+let raise_typing_error ?(depth=0) err p = raise (Error(err,p,depth))
 
 
 let error_require r p =
 let error_require r p =
 	if r = "" then
 	if r = "" then
@@ -309,4 +321,4 @@ let error_require r p =
 	in
 	in
 	typing_error ("Accessing this field requires " ^ r) p
 	typing_error ("Accessing this field requires " ^ r) p
 
 
-let invalid_assign p = typing_error "Invalid assign" p
+let invalid_assign p = typing_error "Invalid assign" p

+ 32 - 3
src/core/globals.ml

@@ -5,6 +5,9 @@ type pos = {
 }
 }
 
 
 type path = string list * string
 type path = string list * string
+type located =
+	| Message of string * pos
+	| Stack of located list
 
 
 module IntMap = Ptmap
 module IntMap = Ptmap
 module StringMap = Map.Make(struct type t = string let compare = String.compare end)
 module StringMap = Map.Make(struct type t = string let compare = String.compare end)
@@ -30,6 +33,20 @@ let version_minor = (version mod 1000) / 100
 let version_revision = (version mod 100)
 let version_revision = (version mod 100)
 let version_pre = Some "rc.1"
 let version_pre = Some "rc.1"
 
 
+let null_pos = { pfile = "?"; pmin = -1; pmax = -1 }
+
+let located msg p = Message (msg,p)
+let located_stack stack = Stack stack
+
+let rec extract_located_msg = function
+	 | Message (msg,p) -> msg
+	 | Stack stack -> String.concat "\n" (List.map extract_located_msg stack)
+
+let rec extract_located_pos = function
+	 | Message (_,p) -> p
+	 | Stack [] -> null_pos
+	 | Stack (hd :: _) -> extract_located_pos hd
+
 let macro_platform = ref Neko
 let macro_platform = ref Neko
 
 
 let return_partial_type = ref false
 let return_partial_type = ref false
@@ -85,8 +102,6 @@ let platform_list_help = function
 	| [p] -> " (" ^ platform_name p ^ " only)"
 	| [p] -> " (" ^ platform_name p ^ " only)"
 	| pl -> " (for " ^ String.concat "," (List.map platform_name pl) ^ ")"
 	| pl -> " (for " ^ String.concat "," (List.map platform_name pl) ^ ")"
 
 
-let null_pos = { pfile = "?"; pmin = -1; pmax = -1 }
-
 let mk_zero_range_pos p = { p with pmax = p.pmin }
 let mk_zero_range_pos p = { p with pmax = p.pmin }
 
 
 let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s
 let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s
@@ -171,6 +186,20 @@ module MessageKind = struct
 		| DKMissingFields -> 7
 		| DKMissingFields -> 7
 end
 end
 
 
-type compiler_message = string * pos * MessageKind.t * MessageSeverity.t
+type compiler_message = {
+	cm_message : string;
+	cm_pos : pos;
+	cm_depth : int;
+	cm_kind : MessageKind.t;
+	cm_severity : MessageSeverity.t;
+}
+
+let make_compiler_message msg p depth kind sev = {
+		cm_message = msg;
+		cm_pos = p;
+		cm_depth = depth;
+		cm_kind = kind;
+		cm_severity = sev;
+}
 
 
 let i32_31 = Int32.of_int 31
 let i32_31 = Int32.of_int 31

+ 1 - 1
src/core/texpr.ml

@@ -597,7 +597,7 @@ let rec type_constant_value basic (e,p) =
 		typing_error "Constant value expected" p
 		typing_error "Constant value expected" p
 
 
 let is_constant_value basic e =
 let is_constant_value basic e =
-	try (ignore (type_constant_value basic e); true) with Error (Custom _,_) -> false
+	try (ignore (type_constant_value basic e); true) with Error (Custom _,_,_) -> false
 
 
 let for_remap basic v e1 e2 p =
 let for_remap basic v e1 e2 p =
 	let v' = alloc_var v.v_kind v.v_name e1.etype e1.epos in
 	let v' = alloc_var v.v_kind v.v_name e1.etype e1.epos in

+ 1 - 1
src/filters/filters.ml

@@ -72,7 +72,7 @@ module LocalStatic = struct
 		begin try
 		begin try
 			let cf = PMap.find name ctx.curclass.cl_statics in
 			let cf = PMap.find name ctx.curclass.cl_statics in
 			display_error ctx.com (Printf.sprintf "The expanded name of this local (%s) conflicts with another static field" name) v.v_pos;
 			display_error ctx.com (Printf.sprintf "The expanded name of this local (%s) conflicts with another static field" name) v.v_pos;
-			typing_error "Conflicting field was found here" cf.cf_name_pos;
+			typing_error ~depth:1 "Conflicting field was found here" cf.cf_name_pos;
 		with Not_found ->
 		with Not_found ->
 			let cf = mk_field name ~static:true v.v_type v.v_pos v.v_pos in
 			let cf = mk_field name ~static:true v.v_type v.v_pos v.v_pos in
 			begin match eo with
 			begin match eo with

+ 8 - 5
src/macro/eval/evalExceptions.ml

@@ -67,9 +67,12 @@ let format_pos p =
 let uncaught_exception_string v p extra =
 let uncaught_exception_string v p extra =
 	(Printf.sprintf "%s : Uncaught exception %s%s" (format_pos p) (value_string v) extra)
 	(Printf.sprintf "%s : Uncaught exception %s%s" (format_pos p) (value_string v) extra)
 
 
-let get_exc_error_message ctx v stack p =
+let get_exc_error_stack ctx stack =
 	let pl = List.map (fun env -> {pfile = rev_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax}) stack in
 	let pl = List.map (fun env -> {pfile = rev_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax}) stack in
-	let pl = List.filter (fun p -> p <> null_pos) pl in
+	List.filter (fun p -> p <> null_pos) pl
+
+let get_exc_error_message ctx v stack p =
+	let pl = get_exc_error_stack ctx stack in
 	match pl with
 	match pl with
 	| [] ->
 	| [] ->
 		uncaught_exception_string v p ""
 		uncaught_exception_string v p ""
@@ -143,7 +146,7 @@ let catch_exceptions ctx ?(final=(fun() -> ())) f p =
 							)
 							)
 						| _ -> null_pos
 						| _ -> null_pos
 					in
 					in
-					raise (Error.Error (Error.Custom s.sstring,p))
+					raise (Error.Error (Error.Custom s.sstring,p,0))
 				| _ ->
 				| _ ->
 					Error.typing_error "Something went wrong" null_pos
 					Error.typing_error "Something went wrong" null_pos
 		end else begin
 		end else begin
@@ -153,10 +156,10 @@ let catch_exceptions ctx ?(final=(fun() -> ())) f p =
 				| l when p' = null_pos -> l (* If the exception position is null_pos, we're "probably" in a built-in function. *)
 				| l when p' = null_pos -> l (* If the exception position is null_pos, we're "probably" in a built-in function. *)
 				| _ :: l -> l (* Otherwise, ignore topmost frame position. *)
 				| _ :: l -> l (* Otherwise, ignore topmost frame position. *)
 			in
 			in
-			let msg = get_exc_error_message ctx v stack (if p' = null_pos then p else p') in
+			let stack = get_exc_error_stack ctx stack in
 			reset_ctx();
 			reset_ctx();
 			final();
 			final();
-			Error.typing_error msg null_pos
+			Error.call_stack_error (value_string v) stack (if p' = null_pos then p else p')
 		end
 		end
 	| MacroApi.Abort ->
 	| MacroApi.Abort ->
 		final();
 		final();

+ 2 - 2
src/macro/eval/evalLuv.ml

@@ -546,11 +546,11 @@ let uv_error_fields = [
 		Error.set_on_unhandled_exception (fun ex ->
 		Error.set_on_unhandled_exception (fun ex ->
 			let msg =
 			let msg =
 				match ex with
 				match ex with
-				| HaxeError.Error (Custom msg,_) ->
+				| HaxeError.Error (Custom msg,_,_) ->
 					(* Eval interpreter rethrows runtime exceptions as `Custom "Exception message\nException stack"` *)
 					(* Eval interpreter rethrows runtime exceptions as `Custom "Exception message\nException stack"` *)
 					(try fst (ExtString.String.split msg "\n")
 					(try fst (ExtString.String.split msg "\n")
 					with _ -> msg)
 					with _ -> msg)
-				| HaxeError.Error (err,_) -> HaxeError.error_msg err
+				| HaxeError.Error (err,p,_) -> extract_located_msg (HaxeError.error_msg p err)
 				| _ -> Printexc.to_string ex
 				| _ -> Printexc.to_string ex
 			in
 			in
 			let e = create_haxe_exception ~stack:(get_ctx()).exception_stack msg in
 			let e = create_haxe_exception ~stack:(get_ctx()).exception_stack msg in

+ 4 - 2
src/macro/eval/evalMain.ml

@@ -151,7 +151,7 @@ let create com api is_macro =
 		| _ ->
 		| _ ->
 			let msg =
 			let msg =
 				match ex with
 				match ex with
-				| Error.Error (err,_) -> Error.error_msg err
+				| Error.Error (err,p,_) -> extract_located_msg (Error.error_msg p err)
 				| _ -> Printexc.to_string ex
 				| _ -> Printexc.to_string ex
 			in
 			in
 			Printf.eprintf "%s\n" msg;
 			Printf.eprintf "%s\n" msg;
@@ -401,7 +401,9 @@ let set_error ctx b =
 let add_types ctx types ready =
 let add_types ctx types ready =
 	if not ctx.had_error then ignore(catch_exceptions ctx (fun () -> ignore(add_types ctx types ready)) null_pos)
 	if not ctx.had_error then ignore(catch_exceptions ctx (fun () -> ignore(add_types ctx types ready)) null_pos)
 
 
-let compiler_error msg pos =
+let compiler_error msg =
+	let pos = extract_located_pos msg in
+	let msg = extract_located_msg msg in
 	let vi = encode_instance key_haxe_macro_Error in
 	let vi = encode_instance key_haxe_macro_Error in
 	match vi with
 	match vi with
 	| VInstance i ->
 	| VInstance i ->

+ 22 - 17
src/macro/macroApi.ml

@@ -61,10 +61,10 @@ type 'value compiler_api = {
 	encode_ctype : Ast.type_hint -> 'value;
 	encode_ctype : Ast.type_hint -> 'value;
 	decode_type : 'value -> t;
 	decode_type : 'value -> t;
 	flush_context : (unit -> t) -> t;
 	flush_context : (unit -> t) -> t;
-	display_error : (string -> pos -> unit);
+	display_error : ?depth:int -> (string -> pos -> unit);
 	with_imports : 'a . import list -> placed_name list list -> (unit -> 'a) -> 'a;
 	with_imports : 'a . import list -> placed_name list list -> (unit -> 'a) -> 'a;
 	with_options : 'a . compiler_options -> (unit -> 'a) -> 'a;
 	with_options : 'a . compiler_options -> (unit -> 'a) -> 'a;
-	warning : Warning.warning -> string -> pos -> unit;
+	warning : ?depth:int -> Warning.warning -> string -> pos -> unit;
 }
 }
 
 
 
 
@@ -152,7 +152,7 @@ module type InterpApi = sig
 	val encode_ref : 'a -> ('a -> value) -> (unit -> string) -> value
 	val encode_ref : 'a -> ('a -> value) -> (unit -> string) -> value
 	val decode_ref : value -> 'a
 	val decode_ref : value -> 'a
 
 
-	val compiler_error : string -> Globals.pos -> 'a
+	val compiler_error : Globals.located -> 'a
 	val error_message : string -> 'a
 	val error_message : string -> 'a
 	val value_to_expr : value -> Globals.pos -> Ast.expr
 	val value_to_expr : value -> Globals.pos -> Ast.expr
 	val value_signature : value -> string
 	val value_signature : value -> string
@@ -493,10 +493,10 @@ and encode_package_rule pr =
 	in
 	in
 	encode_enum ~pos:None IPackageRule tag pl
 	encode_enum ~pos:None IPackageRule tag pl
 
 
-and encode_message (msg,p,_,sev) =
-	let tag, pl = match sev with
-		| Globals.MessageSeverity.Information -> 0, [(encode_string msg); (encode_pos p)]
-		| Warning | Hint -> 1, [(encode_string msg); (encode_pos p)]
+and encode_message cm =
+	let tag, pl = match cm.cm_severity with
+		| Globals.MessageSeverity.Information -> 0, [(encode_string cm.cm_message); (encode_pos cm.cm_pos)]
+		| Warning | Hint -> 1, [(encode_string cm.cm_message); (encode_pos cm.cm_pos)]
 		| Error -> Globals.die "" __LOC__
 		| Error -> Globals.die "" __LOC__
 	in
 	in
 	encode_enum ~pos:None IMessage tag pl
 	encode_enum ~pos:None IMessage tag pl
@@ -1689,33 +1689,38 @@ let macro_api ccom get_api =
 		"current_pos", vfun0 (fun() ->
 		"current_pos", vfun0 (fun() ->
 			encode_pos (get_api()).pos
 			encode_pos (get_api()).pos
 		);
 		);
-		"error", vfun2 (fun msg p ->
+		"error", vfun3 (fun msg p depth ->
 			let msg = decode_string msg in
 			let msg = decode_string msg in
 			let p = decode_pos p in
 			let p = decode_pos p in
-			(ccom()).error msg p;
+			let depth = decode_int depth in
+			(ccom()).error ~depth msg p;
 			raise Abort
 			raise Abort
 		);
 		);
-		"fatal_error", vfun2 (fun msg p ->
+		"fatal_error", vfun3 (fun msg p depth ->
 			let msg = decode_string msg in
 			let msg = decode_string msg in
 			let p = decode_pos p in
 			let p = decode_pos p in
-			raise (Error.Fatal_error (msg,p))
+			let depth = decode_int depth in
+			raise (Error.Fatal_error ((Globals.located msg p),depth))
 		);
 		);
-		"report_error", vfun2 (fun msg p ->
+		"report_error", vfun3 (fun msg p depth ->
 			let msg = decode_string msg in
 			let msg = decode_string msg in
 			let p = decode_pos p in
 			let p = decode_pos p in
-			(get_api()).display_error msg p;
+			let depth = decode_int depth in
+			(get_api()).display_error ~depth msg p;
 			vnull
 			vnull
 		);
 		);
-		"warning", vfun2 (fun msg p ->
+		"warning", vfun3 (fun msg p depth ->
 			let msg = decode_string msg in
 			let msg = decode_string msg in
 			let p = decode_pos p in
 			let p = decode_pos p in
-			(get_api()).warning WUser msg p;
+			let depth = decode_int depth in
+			(get_api()).warning ~depth WUser msg p;
 			vnull
 			vnull
 		);
 		);
-		"info", vfun2 (fun msg p ->
+		"info", vfun3 (fun msg p depth ->
 			let msg = decode_string msg in
 			let msg = decode_string msg in
 			let p = decode_pos p in
 			let p = decode_pos p in
-			(ccom()).info msg p;
+			let depth = decode_int depth in
+			(ccom()).info ~depth msg p;
 			vnull
 			vnull
 		);
 		);
 		"get_messages", vfun0 (fun() ->
 		"get_messages", vfun0 (fun() ->

+ 1 - 1
src/optimization/analyzerTexpr.ml

@@ -1208,7 +1208,7 @@ module Purity = struct
 					apply_to_class com c
 					apply_to_class com c
 				with Purity_conflict(impure,p) ->
 				with Purity_conflict(impure,p) ->
 					com.error "Impure field overrides/implements field which was explicitly marked as @:pure" impure.pn_field.cf_pos;
 					com.error "Impure field overrides/implements field which was explicitly marked as @:pure" impure.pn_field.cf_pos;
-					Error.typing_error (Error.compl_msg "Pure field is here") p;
+					Error.typing_error ~depth:1 (Error.compl_msg "Pure field is here") p;
 				end
 				end
 			| _ -> ()
 			| _ -> ()
 		) com.types;
 		) com.types;

+ 1 - 1
src/optimization/inlineConstructors.ml

@@ -123,7 +123,7 @@ let inline_constructors ctx original_e =
 				List.iter (fun v -> if v.v_id < 0 then cancel_v v p) io.io_dependent_vars;
 				List.iter (fun v -> if v.v_id < 0 then cancel_v v p) io.io_dependent_vars;
 				if ioc.ioc_forced then begin
 				if ioc.ioc_forced then begin
 					display_error ctx.com "Forced inline constructor could not be inlined" io.io_pos;
 					display_error ctx.com "Forced inline constructor could not be inlined" io.io_pos;
-					display_error ctx.com (compl_msg "Cancellation happened here") p;
+					display_error ~depth:1 ctx.com (compl_msg "Cancellation happened here") p;
 				end
 				end
 			| _ -> ()
 			| _ -> ()
 		end
 		end

+ 2 - 2
src/optimization/optimizer.ml

@@ -345,7 +345,7 @@ let rec reduce_loop ctx e =
 				let cf = mk_field "" ef.etype e.epos null_pos in
 				let cf = mk_field "" ef.etype e.epos null_pos in
 				let ethis = mk (TConst TThis) t_dynamic e.epos in
 				let ethis = mk (TConst TThis) t_dynamic e.epos in
 				let rt = (match follow ef.etype with TFun (_,rt) -> rt | _ -> die "" __LOC__) in
 				let rt = (match follow ef.etype with TFun (_,rt) -> rt | _ -> die "" __LOC__) in
-				let inl = (try type_inline ctx cf func ethis el rt None e.epos ~self_calling_closure:true false with Error (Custom _,_) -> None) in
+				let inl = (try type_inline ctx cf func ethis el rt None e.epos ~self_calling_closure:true false with Error (Custom _,_,_) -> None) in
 				(match inl with
 				(match inl with
 				| None -> reduce_expr ctx e
 				| None -> reduce_expr ctx e
 				| Some e -> reduce_loop ctx e)
 				| Some e -> reduce_loop ctx e)
@@ -354,7 +354,7 @@ let rec reduce_loop ctx e =
 				| Some {eexpr = TFunction tf} ->
 				| Some {eexpr = TFunction tf} ->
 					let config = inline_config (Some cl) cf el e.etype in
 					let config = inline_config (Some cl) cf el e.etype in
 					let rt = (match follow e1.etype with TFun (_,rt) -> rt | _ -> die "" __LOC__) in
 					let rt = (match follow e1.etype with TFun (_,rt) -> rt | _ -> die "" __LOC__) in
-					let inl = (try type_inline ctx cf tf ef el rt config e.epos false with Error (Custom _,_) -> None) in
+					let inl = (try type_inline ctx cf tf ef el rt config e.epos false with Error (Custom _,_,_) -> None) in
 					(match inl with
 					(match inl with
 					| None -> reduce_expr ctx e
 					| None -> reduce_expr ctx e
 					| Some e ->
 					| Some e ->

+ 32 - 32
src/typing/callUnification.ml

@@ -15,10 +15,10 @@ let is_forced_inline c cf =
 
 
 let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 	let call_error err p =
 	let call_error err p =
-		raise (Error (Call_error err,p))
+		raise (Error (Call_error err,p,0))
 	in
 	in
 	let arg_error ul name opt p =
 	let arg_error ul name opt p =
-		let err = Stack (ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in
+		let err = Stack [(ul,p); (Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'"), p)] in
 		call_error (Could_not_unify err) p
 		call_error (Could_not_unify err) p
 	in
 	in
 	let mk_pos_infos t =
 	let mk_pos_infos t =
@@ -42,8 +42,8 @@ let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 	let handle_errors fn =
 	let handle_errors fn =
 		try
 		try
 			fn()
 			fn()
-		with Error(l,p) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) ->
-			raise (WithTypeError (l,p))
+		with Error(l,p,nl) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) ->
+			raise (WithTypeError (l,p,nl))
 	in
 	in
 	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, (has_class_flag c CExtern) | _ -> false, false in *)
 	(* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, (has_class_flag c CExtern) | _ -> false, false in *)
 	let type_against name t e =
 	let type_against name t e =
@@ -61,7 +61,7 @@ let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 			[]
 			[]
 		| _,[name,false,TAbstract({ a_path = ["cpp"],"Rest" },[t])] ->
 		| _,[name,false,TAbstract({ a_path = ["cpp"],"Rest" },[t])] ->
 			(try List.map (fun e -> type_against name t e) el
 			(try List.map (fun e -> type_against name t e) el
-			with WithTypeError(ul,p) -> arg_error ul name false p)
+			with WithTypeError(ul,p,_) -> arg_error ul name false p)
 		| _,[name,false,t] when ExtType.is_rest (follow t) ->
 		| _,[name,false,t] when ExtType.is_rest (follow t) ->
 			begin match follow t with
 			begin match follow t with
 				| TAbstract({a_path=(["haxe"],"Rest")},[arg_t]) ->
 				| TAbstract({a_path=(["haxe"],"Rest")},[arg_t]) ->
@@ -80,28 +80,28 @@ let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 						match el with
 						match el with
 						| [(EUnop (Spread,Prefix,e),p)] ->
 						| [(EUnop (Spread,Prefix,e),p)] ->
 							(try [mk (TUnop (Spread, Prefix, type_against name t e)) t p]
 							(try [mk (TUnop (Spread, Prefix, type_against name t e)) t p]
-							with WithTypeError(ul,p) -> arg_error ul name false p)
+							with WithTypeError(ul,p,_) -> arg_error ul name false p)
 						| _ when ExtType.is_mono (follow arg_t) ->
 						| _ when ExtType.is_mono (follow arg_t) ->
 							(try
 							(try
 								let el = type_rest mk_mono in
 								let el = type_rest mk_mono in
 								unify ctx (unify_min ctx el) arg_t (punion_el callp el);
 								unify ctx (unify_min ctx el) arg_t (punion_el callp el);
 								el
 								el
-							with WithTypeError(ul,p) ->
+							with WithTypeError(ul,p,_) ->
 								arg_error ul name false p)
 								arg_error ul name false p)
 						| _ ->
 						| _ ->
 							(try
 							(try
 								type_rest (fun() -> arg_t)
 								type_rest (fun() -> arg_t)
-							with WithTypeError(ul,p) ->
+							with WithTypeError(ul,p,_) ->
 								arg_error ul name false p)
 								arg_error ul name false p)
 					(* for other platforms make sure rest arguments are wrapped in an array *)
 					(* for other platforms make sure rest arguments are wrapped in an array *)
 					else begin
 					else begin
 						match el with
 						match el with
 						| [(EUnop (Spread,Prefix,e),p)] ->
 						| [(EUnop (Spread,Prefix,e),p)] ->
 							(try [type_against name t e]
 							(try [type_against name t e]
-							with WithTypeError(ul,p) -> arg_error ul name false p)
+							with WithTypeError(ul,p,_) -> arg_error ul name false p)
 						| [] ->
 						| [] ->
 							(try [type_against name t (EArrayDecl [],callp)]
 							(try [type_against name t (EArrayDecl [],callp)]
-							with WithTypeError(ul,p) -> arg_error ul name false p)
+							with WithTypeError(ul,p,_) -> arg_error ul name false p)
 						| (_,p1) :: _ ->
 						| (_,p1) :: _ ->
 							let p =
 							let p =
 								List.fold_left (fun p (e1,p2) ->
 								List.fold_left (fun p (e1,p2) ->
@@ -121,7 +121,7 @@ let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 									do_type (ECheckType(e,(CTPath tp, p)),p) (* ([arg1, arg2...]:Array<Dynamic>) *)
 									do_type (ECheckType(e,(CTPath tp, p)),p) (* ([arg1, arg2...]:Array<Dynamic>) *)
 								end else
 								end else
 									do_type e
 									do_type e
-							with WithTypeError(ul,p) ->
+							with WithTypeError(ul,p,_) ->
 								arg_error ul name false p
 								arg_error ul name false p
 							)
 							)
 					end
 					end
@@ -158,7 +158,7 @@ let rec unify_call_args ctx el args r callp inline force_inline in_overload =
 				let e = type_against name t e in
 				let e = type_against name t e in
 				e :: loop el args
 				e :: loop el args
 			with
 			with
-				WithTypeError (ul,p)->
+				WithTypeError (ul,p,_)->
 					if opt && might_skip then
 					if opt && might_skip then
 						let e_def = skip name ul t p in
 						let e_def = skip name ul t p in
 						e_def :: loop (e :: el) args
 						e_def :: loop (e :: el) args
@@ -199,15 +199,15 @@ let unify_typed_args ctx tmap args el_typed call_pos =
 		match args,el with
 		match args,el with
 		| [], _ :: _ ->
 		| [], _ :: _ ->
 			let call_error = Call_error(Too_many_arguments) in
 			let call_error = Call_error(Too_many_arguments) in
-			raise(Error(call_error,call_pos))
+			raise(Error(call_error,call_pos,0))
 		| _, [] ->
 		| _, [] ->
 			List.rev acc_args,args
 			List.rev acc_args,args
 		| ((_,opt,t0) as arg) :: args,e :: el ->
 		| ((_,opt,t0) as arg) :: args,e :: el ->
 			begin try
 			begin try
 				unify_raise (tmap e.etype) t0 e.epos;
 				unify_raise (tmap e.etype) t0 e.epos;
-			with Error(Unify _ as msg,p) ->
+			with Error(Unify _ as msg,p,nl) ->
 				let call_error = Call_error(Could_not_unify msg) in
 				let call_error = Call_error(Could_not_unify msg) in
-				raise(Error(call_error,p))
+				raise(Error(call_error,p,nl))
 			end;
 			end;
 			loop (arg :: acc_args) (fun t -> t) args el
 			loop (arg :: acc_args) (fun t -> t) args el
 	in
 	in
@@ -310,13 +310,13 @@ let unify_field_call ctx fa el_typed el p inline =
 			typing_error (s_type (print_context()) t ^ " cannot be called") p
 			typing_error (s_type (print_context()) t ^ " cannot be called") p
 	in
 	in
 	let maybe_raise_unknown_ident cerr p =
 	let maybe_raise_unknown_ident cerr p =
-		let rec loop err =
+		let rec loop err p =
 			match err with
 			match err with
-			| Unknown_ident _ -> typing_error (error_msg err) p
-			| Stack (e1,e2) -> (loop e1; loop e2)
+			| Unknown_ident _ -> located_typing_error (error_msg p err)
+			| Stack stack -> List.iter (fun (e,p) -> loop e p) stack
 			| _ -> ()
 			| _ -> ()
 		in
 		in
-		match cerr with Could_not_unify err -> loop err | _ -> ()
+		match cerr with Could_not_unify err -> loop err p | _ -> ()
 	in
 	in
 	let attempt_calls candidates =
 	let attempt_calls candidates =
 		let rec loop candidates = match candidates with
 		let rec loop candidates = match candidates with
@@ -334,7 +334,7 @@ let unify_field_call ctx fa el_typed el p inline =
 						candidate :: candidates,failures
 						candidate :: candidates,failures
 					end else
 					end else
 						[candidate],[]
 						[candidate],[]
-				with Error ((Call_error cerr as err),p) ->
+				with Error ((Call_error cerr as err),p,_) ->
 					List.iter (fun (m,t,constr) ->
 					List.iter (fun (m,t,constr) ->
 						if t != m.tm_type then m.tm_type <- t;
 						if t != m.tm_type then m.tm_type <- t;
 						if constr != m.tm_down_constraints then m.tm_down_constraints <- constr;
 						if constr != m.tm_down_constraints then m.tm_down_constraints <- constr;
@@ -380,17 +380,17 @@ let unify_field_call ctx fa el_typed el p inline =
 				Option.may (fun de ->
 				Option.may (fun de ->
 					raise_augmented_display_exception cf de;
 					raise_augmented_display_exception cf de;
 				) delayed_display;
 				) delayed_display;
-				cf,error_msg err,p
+				cf,error_msg p err
 			) failures in
 			) failures in
-			let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in
+			let failures = remove_duplicates (fun (_,msg1) (_,msg2) -> msg1 <> msg2) failures in
 			begin match failures with
 			begin match failures with
-			| [_,msg,p] ->
-				typing_error msg p
+			| [_,msg] ->
+				located_typing_error msg
 			| _ ->
 			| _ ->
 				display_error ctx.com "Could not find a suitable overload, reasons follow" p;
 				display_error ctx.com "Could not find a suitable overload, reasons follow" p;
-				List.iter (fun (cf,msg,p2) ->
-					display_error ctx.com ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p;
-					display_error ctx.com msg p2;
+				List.iter (fun (cf,msg) ->
+					display_error ~depth:1 ctx.com ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p;
+					located_display_error ~depth:2 ctx.com msg;
 				) failures;
 				) failures;
 				typing_error "End of overload failure reasons" p
 				typing_error "End of overload failure reasons" p
 			end
 			end
@@ -404,7 +404,7 @@ let unify_field_call ctx fa el_typed el p inline =
 				display_error ctx.com "Ambiguous overload, candidates follow" p;
 				display_error ctx.com "Ambiguous overload, candidates follow" p;
 				let st = s_type (print_context()) in
 				let st = s_type (print_context()) in
 				List.iter (fun fcc ->
 				List.iter (fun fcc ->
-					display_error ctx.com (Printf.sprintf "... %s" (st fcc.fc_type)) fcc.fc_field.cf_name_pos;
+					display_error ~depth:1 ctx.com (compl_msg (st fcc.fc_type)) fcc.fc_field.cf_name_pos;
 				) (fcc :: l);
 				) (fcc :: l);
 				commit_delayed_display fcc
 				commit_delayed_display fcc
 		end else begin match List.rev candidates with
 		end else begin match List.rev candidates with
@@ -471,13 +471,13 @@ object(self)
 		ctx.macro_depth <- ctx.macro_depth - 1;
 		ctx.macro_depth <- ctx.macro_depth - 1;
 		ctx.with_type_stack <- List.tl ctx.with_type_stack;
 		ctx.with_type_stack <- List.tl ctx.with_type_stack;
 		let old = ctx.com.error in
 		let old = ctx.com.error in
-		ctx.com.error <- (fun msg ep ->
+		ctx.com.error <- (fun ?(depth=0) msg ep ->
 			(* display additional info in the case the error is not part of our original call *)
 			(* display additional info in the case the error is not part of our original call *)
 			if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then begin
 			if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then begin
 				locate_macro_error := false;
 				locate_macro_error := false;
-				old msg ep;
+				old msg (if ep = null_pos then p else ep);
 				locate_macro_error := true;
 				locate_macro_error := true;
-				old (compl_msg "Called from macro here") p;
+				if ep <> null_pos then old ~depth:(depth+1) (compl_msg "Called from macro here") p;
 			end else
 			end else
 				old msg ep;
 				old msg ep;
 		);
 		);
@@ -619,4 +619,4 @@ let maybe_reapply_overload_call ctx e =
 				e
 				e
 			end
 			end
 		| _ ->
 		| _ ->
-			e
+			e

+ 1 - 1
src/typing/calls.ml

@@ -485,7 +485,7 @@ let array_access ctx e1 e2 mode p =
 				let t = ctx.t.tarray pt in
 				let t = ctx.t.tarray pt in
 				begin try
 				begin try
 					unify_raise et t p
 					unify_raise et t p
-				with Error(Unify _,_) ->
+				with Error(Unify _,_,_) ->
 					if not ctx.untyped then begin
 					if not ctx.untyped then begin
 						let msg = if !has_abstract_array_access then
 						let msg = if !has_abstract_array_access then
 							"No @:arrayAccess function accepts an argument of " ^ (s_type (print_context()) e2.etype)
 							"No @:arrayAccess function accepts an argument of " ^ (s_type (print_context()) e2.etype)

+ 3 - 3
src/typing/fields.ml

@@ -76,7 +76,7 @@ let no_abstract_constructor c p =
 	if has_class_flag c CAbstract then raise_typing_error (Abstract_class (TClassDecl c)) p
 	if has_class_flag c CAbstract then raise_typing_error (Abstract_class (TClassDecl c)) p
 
 
 let check_constructor_access ctx c f p =
 let check_constructor_access ctx c f p =
-	if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx.com (error_msg (No_constructor (TClassDecl c))) p;
+	if (Meta.has Meta.CompilerGenerated f.cf_meta) then located_display_error ctx.com (error_msg p (No_constructor (TClassDecl c)));
 	if not (can_access ctx c f true || extends ctx.curclass c) && not ctx.untyped then display_error ctx.com (Printf.sprintf "Cannot access private constructor of %s" (s_class_path c)) p
 	if not (can_access ctx c f true || extends ctx.curclass c) && not ctx.untyped then display_error ctx.com (Printf.sprintf "Cannot access private constructor of %s" (s_class_path c)) p
 
 
 let check_no_closure_meta ctx cf fa mode p =
 let check_no_closure_meta ctx cf fa mode p =
@@ -438,7 +438,7 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 							end
 							end
 						| _ ->
 						| _ ->
 							check()
 							check()
-					with Unify_error el | Error (Unify el,_) ->
+					with Unify_error el | Error (Unify el,_,_) ->
 						check_constant_struct := !check_constant_struct || List.exists (function
 						check_constant_struct := !check_constant_struct || List.exists (function
 							| Has_extra_field _ -> true
 							| Has_extra_field _ -> true
 							| _ -> false
 							| _ -> false
@@ -629,4 +629,4 @@ let get_struct_init_anon_fields c tl =
 			PMap.add cf.cf_name cf fields
 			PMap.add cf.cf_name cf fields
 		| _ ->
 		| _ ->
 			fields
 			fields
-	) c.cl_fields PMap.empty
+	) c.cl_fields PMap.empty

+ 5 - 5
src/typing/forLoop.ml

@@ -92,9 +92,9 @@ module IterationKind = struct
 			| TDynamic _ | TMono _ ->
 			| TDynamic _ | TMono _ ->
 				(* try to find something better than a dynamic value to iterate on *)
 				(* try to find something better than a dynamic value to iterate on *)
 				dynamic_iterator := Some e;
 				dynamic_iterator := Some e;
-				raise (Error (Unify [Unify_custom "Avoid iterating on a dynamic value"], p))
+				raise (Error (Unify [Unify_custom "Avoid iterating on a dynamic value"], p, 0))
 			| _ -> e
 			| _ -> e
-		with Error (Unify _,_) ->
+		with Error (Unify _,_,depth) ->
 			let try_last_resort after =
 			let try_last_resort after =
 				try
 				try
 					match last_resort with
 					match last_resort with
@@ -108,14 +108,14 @@ module IterationKind = struct
 				try
 				try
 					unify_raise acc_expr.etype t acc_expr.epos;
 					unify_raise acc_expr.etype t acc_expr.epos;
 					acc_expr
 					acc_expr
-				with Error (Unify(l),p) ->
+				with Error (Unify(l),p,n) ->
 					try_last_resort (fun () ->
 					try_last_resort (fun () ->
 						match !dynamic_iterator with
 						match !dynamic_iterator with
 						| Some e -> e
 						| Some e -> e
 						| None ->
 						| None ->
 							if resume then raise Not_found;
 							if resume then raise Not_found;
-							display_error ctx.com "Field iterator has an invalid type" acc_expr.epos;
-							display_error ctx.com (error_msg (Unify l)) p;
+							display_error ~depth ctx.com "Field iterator has an invalid type" acc_expr.epos;
+							located_display_error ~depth:(depth+1) ctx.com (error_msg p (Unify l));
 							mk (TConst TNull) t_dynamic p
 							mk (TConst TNull) t_dynamic p
 					)
 					)
 			in
 			in

+ 7 - 7
src/typing/generic.ml

@@ -156,7 +156,7 @@ let static_method_container gctx c cf p =
 		match t with
 		match t with
 		| TInst(cg,_) -> cg
 		| TInst(cg,_) -> cg
 		| _ -> typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
 		| _ -> typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
-	with Error(Module_not_found path,_) when path = (pack,name) ->
+	with Error(Module_not_found path,_,_) when path = (pack,name) ->
 		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
 		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
 		let mg = {
 		let mg = {
 			m_id = alloc_mid();
 			m_id = alloc_mid();
@@ -233,7 +233,7 @@ let rec build_generic_class ctx c p tl =
 		match t with
 		match t with
 		| TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t
 		| TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t
 		| _ -> typing_error ("Cannot specialize @:generic because the generated type name is already used: " ^ name) p
 		| _ -> typing_error ("Cannot specialize @:generic because the generated type name is already used: " ^ name) p
-	with Error(Module_not_found path,_) when path = (pack,name) ->
+	with Error(Module_not_found path,_,_) when path = (pack,name) ->
 		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
 		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
 		ignore(c.cl_build()); (* make sure the super class is already setup *)
 		ignore(c.cl_build()); (* make sure the super class is already setup *)
 		let mg = {
 		let mg = {
@@ -300,7 +300,7 @@ let rec build_generic_class ctx c p tl =
 					| Some e ->
 					| Some e ->
 						cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
 						cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
 				) with Unify_error l ->
 				) with Unify_error l ->
-					typing_error (error_msg (Unify l)) cf_new.cf_pos
+					located_typing_error (error_msg cf_new.cf_pos (Unify l))
 				end;
 				end;
 				t
 				t
 			in
 			in
@@ -383,9 +383,9 @@ let type_generic_function ctx fa fcc with_type p =
 		let name = cf.cf_name ^ "_" ^ gctx.name in
 		let name = cf.cf_name ^ "_" ^ gctx.name in
 		let unify_existing_field tcf pcf = try
 		let unify_existing_field tcf pcf = try
 			unify_raise tcf fcc.fc_type p
 			unify_raise tcf fcc.fc_type p
-		with Error(Unify _,_) as err ->
-			display_error ctx.com ("Cannot create field " ^ name ^ " due to type mismatch") p;
-			display_error ctx.com (compl_msg "Conflicting field was defined here") pcf;
+		with Error(Unify _,_,depth) as err ->
+			display_error ~depth ctx.com ("Cannot create field " ^ name ^ " due to type mismatch") p;
+			display_error ~depth:(depth+1) ctx.com (compl_msg "Conflicting field was defined here") pcf;
 			raise err
 			raise err
 		in
 		in
 		let fa = try
 		let fa = try
@@ -472,4 +472,4 @@ let type_generic_function ctx fa fcc with_type p =
 		typing_error msg p)
 		typing_error msg p)
 
 
 ;;
 ;;
-Typecore.type_generic_function_ref := type_generic_function
+Typecore.type_generic_function_ref := type_generic_function

+ 13 - 13
src/typing/macroContext.ml

@@ -88,7 +88,7 @@ let typing_timer ctx need_type f =
 		disable resumable errors... unless we are in display mode (we want to reach point of completion)
 		disable resumable errors... unless we are in display mode (we want to reach point of completion)
 	*)
 	*)
 	(*if ctx.com.display = DMNone then ctx.com.error <- (fun e p -> raise (Error(Custom e,p)));*) (* TODO: review this... *)
 	(*if ctx.com.display = DMNone then ctx.com.error <- (fun e p -> raise (Error(Custom e,p)));*) (* TODO: review this... *)
-	ctx.com.error <- (fun e p -> raise (Error(Custom e,p)));
+	ctx.com.error <- (fun ?(depth=0) e p -> raise (Error(Custom e,p,depth)));
 	if need_type && ctx.pass < PTypeField then begin
 	if need_type && ctx.pass < PTypeField then begin
 		ctx.pass <- PTypeField;
 		ctx.pass <- PTypeField;
 		flush_pass ctx PBuildClass "typing_timer";
 		flush_pass ctx PBuildClass "typing_timer";
@@ -103,12 +103,12 @@ let typing_timer ctx need_type f =
 		let r = f() in
 		let r = f() in
 		exit();
 		exit();
 		r
 		r
-	with Error (ekind,p) ->
+	with Error (ekind,p,_) ->
 			exit();
 			exit();
-			Interp.compiler_error (error_msg ekind) p
-		| WithTypeError (l,p) ->
+			Interp.compiler_error (error_msg p ekind)
+		| WithTypeError (l,p,_) ->
 			exit();
 			exit();
-			Interp.compiler_error (error_msg l) p
+			Interp.compiler_error (error_msg p l)
 		| e ->
 		| e ->
 			exit();
 			exit();
 			raise e
 			raise e
@@ -146,7 +146,7 @@ let make_macro_api ctx p =
 				try
 				try
 					let m = Some (Typeload.load_instance ctx (tp,p) true) in
 					let m = Some (Typeload.load_instance ctx (tp,p) true) in
 					m
 					m
-				with Error (Module_not_found _,p2) when p == p2 ->
+				with Error (Module_not_found _,p2,_) when p == p2 ->
 					None
 					None
 			)
 			)
 		);
 		);
@@ -352,7 +352,7 @@ let make_macro_api ctx p =
 				try
 				try
 					ignore(AbstractCast.cast_or_unify_raise ctx t e p);
 					ignore(AbstractCast.cast_or_unify_raise ctx t e p);
 					true
 					true
-				with Error (Unify _,_) ->
+				with Error (Unify _,_,_) ->
 					false
 					false
 			)
 			)
 		);
 		);
@@ -422,8 +422,8 @@ let make_macro_api ctx p =
 			in
 			in
 			Std.finally restore f ()
 			Std.finally restore f ()
 		);
 		);
-		MacroApi.warning = (fun w msg p ->
-			warning ctx w msg p
+		MacroApi.warning = (fun ?(depth=0) w msg p ->
+			warning ~depth ctx w msg p
 		);
 		);
 	}
 	}
 
 
@@ -493,7 +493,7 @@ and flush_macro_context mint ctx =
 		List.iter (fun f -> f t) type_filters
 		List.iter (fun f -> f t) type_filters
 	in
 	in
 	(try Interp.add_types mint types ready
 	(try Interp.add_types mint types ready
-	with Error (e,p) -> t(); raise (Fatal_error(error_msg e,p)));
+	with Error (e,p,n) -> t(); raise (Fatal_error(error_msg p e,n)));
 	t()
 	t()
 
 
 let create_macro_interp ctx mctx =
 let create_macro_interp ctx mctx =
@@ -508,7 +508,7 @@ let create_macro_interp ctx mctx =
 			mint, (fun() -> ())
 			mint, (fun() -> ())
 	) in
 	) in
 	let on_error = com2.error in
 	let on_error = com2.error in
-	com2.error <- (fun e p ->
+	com2.error <- (fun ?depth e p ->
 		Interp.set_error (Interp.get_ctx()) true;
 		Interp.set_error (Interp.get_ctx()) true;
 		macro_interp_cache := None;
 		macro_interp_cache := None;
 		on_error e p
 		on_error e p
@@ -664,7 +664,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 			unify_raise mret ttype mpos;
 			unify_raise mret ttype mpos;
 			(* TODO: enable this again in the future *)
 			(* TODO: enable this again in the future *)
 			(* warning ctx WDeprecated "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *)
 			(* warning ctx WDeprecated "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *)
-		with Error (Unify _,_) ->
+		with Error (Unify _,_,_) ->
 			let cttype = mk_type_path ~sub:"ComplexType" (["haxe";"macro"],"Expr") in
 			let cttype = mk_type_path ~sub:"ComplexType" (["haxe";"macro"],"Expr") in
 			let ttype = Typeload.load_instance mctx (cttype,p) false in
 			let ttype = Typeload.load_instance mctx (cttype,p) false in
 			unify_raise mret ttype mpos;
 			unify_raise mret ttype mpos;
@@ -699,7 +699,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 		*)
 		*)
 		let eargs = List.map (fun (n,o,t) ->
 		let eargs = List.map (fun (n,o,t) ->
 			try unify_raise t expr p; (n, o, t_dynamic), MAExpr
 			try unify_raise t expr p; (n, o, t_dynamic), MAExpr
-			with Error (Unify _,_) -> match follow t with
+			with Error (Unify _,_,_) -> match follow t with
 				| TFun _ ->
 				| TFun _ ->
 					(n,o,t), MAFunction
 					(n,o,t), MAFunction
 				| _ ->
 				| _ ->

+ 1 - 1
src/typing/magicTypes.ml

@@ -22,7 +22,7 @@ let extend_remoting ctx c t p async prot =
 	let t = (try
 	let t = (try
 		load_type_def ctx p (mk_type_path (fst path,new_name))
 		load_type_def ctx p (mk_type_path (fst path,new_name))
 	with
 	with
-		Error (Module_not_found _,p2) when p == p2 ->
+		Error (Module_not_found _,p2,_) when p == p2 ->
 	(* build it *)
 	(* build it *)
 	Common.log ctx.com ("Building proxy for " ^ s_type_path path);
 	Common.log ctx.com ("Building proxy for " ^ s_type_path path);
 	let file, decls = (try
 	let file, decls = (try

+ 1 - 1
src/typing/matcher.ml

@@ -271,7 +271,7 @@ module Pattern = struct
 		let catch_errors () =
 		let catch_errors () =
 			let old = ctx.com.error in
 			let old = ctx.com.error in
 			let restore_report_mode = disable_report_mode ctx.com in
 			let restore_report_mode = disable_report_mode ctx.com in
-			ctx.com.error <- (fun _ _ ->
+			ctx.com.error <- (fun ?depth _ _ ->
 				raise Exit
 				raise Exit
 			);
 			);
 			(fun () ->
 			(fun () ->

+ 6 - 6
src/typing/operators.ml

@@ -203,7 +203,7 @@ let make_binop ctx op e1 e2 is_assign_op with_type p =
 			| KAbstract (a,tl) ->
 			| KAbstract (a,tl) ->
 				try
 				try
 					AbstractCast.cast_or_unify_raise ctx tstring e p
 					AbstractCast.cast_or_unify_raise ctx tstring e p
-				with Error (Unify _,_) ->
+				with Error (Unify _,_,_) ->
 					loop (Abstract.get_underlying_type a tl)
 					loop (Abstract.get_underlying_type a tl)
 		in
 		in
 		loop e.etype
 		loop e.etype
@@ -330,7 +330,7 @@ let make_binop ctx op e1 e2 is_assign_op with_type p =
 			(* we only have to check one type here, because unification fails if one is Void and the other is not *)
 			(* we only have to check one type here, because unification fails if one is Void and the other is not *)
 			(match follow e2.etype with TAbstract({a_path=[],"Void"},_) -> typing_error "Cannot compare Void" p | _ -> ());
 			(match follow e2.etype with TAbstract({a_path=[],"Void"},_) -> typing_error "Cannot compare Void" p | _ -> ());
 			AbstractCast.cast_or_unify_raise ctx e2.etype e1 p,e2
 			AbstractCast.cast_or_unify_raise ctx e2.etype e1 p,e2
-		with Error (Unify _,_) ->
+		with Error (Unify _,_,_) ->
 			e1,AbstractCast.cast_or_unify ctx e1.etype e2 p
 			e1,AbstractCast.cast_or_unify ctx e1.etype e2 p
 		in
 		in
 		if not ctx.com.config.pf_supports_function_equality then begin match e1.eexpr, e2.eexpr with
 		if not ctx.com.config.pf_supports_function_equality then begin match e1.eexpr, e2.eexpr with
@@ -410,13 +410,13 @@ let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op with_type
 				let t_expected = BinopResult.get_type result in
 				let t_expected = BinopResult.get_type result in
 				begin try
 				begin try
 					unify_raise tret t_expected p
 					unify_raise tret t_expected p
-				with Error (Unify _,_) ->
+				with Error (Unify _,_,depth) ->
 					match follow tret with
 					match follow tret with
 						| TAbstract(a,tl) when type_iseq (Abstract.get_underlying_type a tl) t_expected ->
 						| TAbstract(a,tl) when type_iseq (Abstract.get_underlying_type a tl) t_expected ->
 							()
 							()
 						| _ ->
 						| _ ->
 							let st = s_type (print_context()) in
 							let st = s_type (print_context()) in
-							typing_error (Printf.sprintf "The result of this operation (%s) is not compatible with declared return type %s" (st t_expected) (st tret)) p
+							typing_error ~depth (Printf.sprintf "The result of this operation (%s) is not compatible with declared return type %s" (st t_expected) (st tret)) p
 				end;
 				end;
 			end;
 			end;
 			(*
 			(*
@@ -490,10 +490,10 @@ let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op with_type
 					in
 					in
 					begin try
 					begin try
 						check e1 e2 false
 						check e1 e2 false
-					with Error (Unify _,_) | Unify_error _ -> try
+					with Error (Unify _,_,_) | Unify_error _ -> try
 						if not (Meta.has Meta.Commutative cf.cf_meta) then raise Not_found;
 						if not (Meta.has Meta.Commutative cf.cf_meta) then raise Not_found;
 						check e2 e1 true
 						check e2 e1 true
-					with Not_found | Error (Unify _,_) | Unify_error _ ->
+					with Not_found | Error (Unify _,_,_) | Unify_error _ ->
 						loop find_op ol
 						loop find_op ol
 					end
 					end
 				| _ ->
 				| _ ->

+ 15 - 15
src/typing/typeload.ml

@@ -59,7 +59,7 @@ let check_field_access ctx cff =
 				let _,p2 = List.find (fun (access',_) -> access = access') acc in
 				let _,p2 = List.find (fun (access',_) -> access = access') acc in
 				if p1 <> null_pos && p2 <> null_pos then begin
 				if p1 <> null_pos && p2 <> null_pos then begin
 					display_error ctx.com (Printf.sprintf "Duplicate access modifier %s" (Ast.s_access access)) p1;
 					display_error ctx.com (Printf.sprintf "Duplicate access modifier %s" (Ast.s_access access)) p1;
-					display_error ctx.com (compl_msg "Previously defined here") p2;
+					display_error ~depth:1 ctx.com (compl_msg "Previously defined here") p2;
 				end;
 				end;
 				loop p1 acc l
 				loop p1 acc l
 			with Not_found -> match access with
 			with Not_found -> match access with
@@ -67,7 +67,7 @@ let check_field_access ctx cff =
 					begin try
 					begin try
 						let _,p2 = List.find (fun (access',_) -> match access' with APublic | APrivate -> true | _ -> false) acc in
 						let _,p2 = List.find (fun (access',_) -> match access' with APublic | APrivate -> true | _ -> false) acc in
 						display_error ctx.com (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
 						display_error ctx.com (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
-						display_error ctx.com (compl_msg "Conflicts with this") p2;
+						display_error ~depth:1 ctx.com (compl_msg "Conflicts with this") p2;
 						loop p1 acc l
 						loop p1 acc l
 					with Not_found ->
 					with Not_found ->
 						loop p1 ((access,p1) :: acc) l
 						loop p1 ((access,p1) :: acc) l
@@ -109,7 +109,7 @@ let load_type_raise ctx mpath tname p =
 (* raises Not_found *)
 (* raises Not_found *)
 let load_type ctx mpath tname p = try
 let load_type ctx mpath tname p = try
 	load_type_raise ctx mpath tname p
 	load_type_raise ctx mpath tname p
-with Error((Module_not_found _ | Type_not_found _),p2) when p = p2 ->
+with Error((Module_not_found _ | Type_not_found _),p2,_) when p = p2 ->
 	raise Not_found
 	raise Not_found
 
 
 (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **)
 (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **)
@@ -142,7 +142,7 @@ let find_in_wildcard_imports ctx mname p f =
 				let m =
 				let m =
 					try
 					try
 						ctx.g.do_load_module ctx path p
 						ctx.g.do_load_module ctx path p
-					with Error (Module_not_found mpath,_) when mpath = path ->
+					with Error (Module_not_found mpath,_,_) when mpath = path ->
 						raise Not_found
 						raise Not_found
 				in
 				in
 				let r = f m ~resume:true in
 				let r = f m ~resume:true in
@@ -163,7 +163,7 @@ let find_in_modules_starting_from_current_package ~resume ctx mname p f =
 			let m =
 			let m =
 				try
 				try
 					ctx.g.do_load_module ctx path p
 					ctx.g.do_load_module ctx path p
-				with Error (Module_not_found mpath,_) when resume && mpath = path ->
+				with Error (Module_not_found mpath,_,_) when resume && mpath = path ->
 					raise Not_found
 					raise Not_found
 			in
 			in
 			f m ~resume:resume
 			f m ~resume:resume
@@ -172,7 +172,7 @@ let find_in_modules_starting_from_current_package ~resume ctx mname p f =
 				let m =
 				let m =
 					try
 					try
 						ctx.g.do_load_module ctx path p
 						ctx.g.do_load_module ctx path p
-					with Error (Module_not_found mpath,_) when mpath = path ->
+					with Error (Module_not_found mpath,_,_) when mpath = path ->
 						raise Not_found
 						raise Not_found
 					in
 					in
 				f m ~resume:true;
 				f m ~resume:true;
@@ -200,7 +200,7 @@ let load_unqualified_type_def ctx mname tname p =
 let load_module ctx path p =
 let load_module ctx path p =
 	try
 	try
 		ctx.g.do_load_module ctx path p
 		ctx.g.do_load_module ctx path p
-	with Error (Module_not_found mpath,_) as exc when mpath = path ->
+	with Error (Module_not_found mpath,_,_) as exc when mpath = path ->
 		match path with
 		match path with
 		| ("std" :: pack, name) ->
 		| ("std" :: pack, name) ->
 			ctx.g.do_load_module ctx (pack,name) p
 			ctx.g.do_load_module ctx (pack,name) p
@@ -286,15 +286,15 @@ let check_param_constraints ctx t map c p =
 			let ti = map ti in
 			let ti = map ti in
 			try
 			try
 				unify_raise t ti p
 				unify_raise t ti p
-			with Error(Unify l,p) ->
+			with Error(Unify l,p,n) ->
 				let fail() =
 				let fail() =
-					if not ctx.untyped then display_error ctx.com (error_msg (Unify (Constraint_failure (s_type_path c.cl_path) :: l))) p;
+					if not ctx.untyped then located_display_error ctx.com (error_msg p (Unify (Constraint_failure (s_type_path c.cl_path) :: l)));
 				in
 				in
 				match follow t with
 				match follow t with
 				| TInst({cl_kind = KExpr e},_) ->
 				| TInst({cl_kind = KExpr e},_) ->
 					let e = type_expr {ctx with locals = PMap.empty} e (WithType.with_type ti) in
 					let e = type_expr {ctx with locals = PMap.empty} e (WithType.with_type ti) in
 					begin try unify_raise e.etype ti p
 					begin try unify_raise e.etype ti p
-					with Error (Unify _,_) -> fail() end
+					with Error (Unify _,_,_) -> fail() end
 				| _ ->
 				| _ ->
 					fail()
 					fail()
 
 
@@ -437,7 +437,7 @@ and load_instance ctx ?(allow_display=false) ((_,pn) as tp) allow_no_params =
 		let t = load_instance' ctx tp allow_no_params in
 		let t = load_instance' ctx tp allow_no_params in
 		if allow_display then DisplayEmitter.check_display_type ctx t tp;
 		if allow_display then DisplayEmitter.check_display_type ctx t tp;
 		t
 		t
-	with Error (Module_not_found path,_) when ctx.macro_depth <= 0 && (ctx.com.display.dms_kind = DMDefault) && DisplayPosition.display_position#enclosed_in pn ->
+	with Error (Module_not_found path,_,_) when ctx.macro_depth <= 0 && (ctx.com.display.dms_kind = DMDefault) && DisplayPosition.display_position#enclosed_in pn ->
 		let s = s_type_path path in
 		let s = s_type_path path in
 		DisplayToplevel.collect_and_raise ctx TKType NoValue CRTypeHint (s,pn) (patch_string_pos pn s)
 		DisplayToplevel.collect_and_raise ctx TKType NoValue CRTypeHint (s,pn) (patch_string_pos pn s)
 
 
@@ -627,7 +627,7 @@ and load_complex_type' ctx allow_display (t,p) =
 and load_complex_type ctx allow_display (t,pn) =
 and load_complex_type ctx allow_display (t,pn) =
 	try
 	try
 		load_complex_type' ctx allow_display (t,pn)
 		load_complex_type' ctx allow_display (t,pn)
-	with Error(Module_not_found(([],name)),p) as exc ->
+	with Error(Module_not_found(([],name)),p,_) as exc ->
 		if Diagnostics.error_in_diagnostics_run ctx.com p then begin
 		if Diagnostics.error_in_diagnostics_run ctx.com p then begin
 			delay ctx PForce (fun () -> DisplayToplevel.handle_unresolved_identifier ctx name p true);
 			delay ctx PForce (fun () -> DisplayToplevel.handle_unresolved_identifier ctx name p true);
 			t_dynamic
 			t_dynamic
@@ -862,7 +862,7 @@ let init_core_api ctx c =
 						typing_error "Type parameters must have the same number of constraints as core type" c.cl_pos
 						typing_error "Type parameters must have the same number of constraints as core type" c.cl_pos
 					| Unify_error l ->
 					| Unify_error l ->
 						display_error ctx.com ("Type parameter " ^ tp2.ttp_name ^ " has different constraint than in core type") c.cl_pos;
 						display_error ctx.com ("Type parameter " ^ tp2.ttp_name ^ " has different constraint than in core type") c.cl_pos;
-						display_error ctx.com (error_msg (Unify l)) c.cl_pos
+						located_display_error ctx.com (error_msg c.cl_pos (Unify l));
 				end
 				end
 			| t1,t2 ->
 			| t1,t2 ->
 				Printf.printf "%s %s" (s_type (print_context()) t1) (s_type (print_context()) t2);
 				Printf.printf "%s %s" (s_type (print_context()) t1) (s_type (print_context()) t2);
@@ -880,7 +880,7 @@ let init_core_api ctx c =
 			type_eq EqCoreType (apply_params ccore.cl_params (extract_param_types c.cl_params) f.cf_type) f2.cf_type
 			type_eq EqCoreType (apply_params ccore.cl_params (extract_param_types c.cl_params) f.cf_type) f2.cf_type
 		with Unify_error l ->
 		with Unify_error l ->
 			display_error ctx.com ("Field " ^ f.cf_name ^ " has different type than in core type") p;
 			display_error ctx.com ("Field " ^ f.cf_name ^ " has different type than in core type") p;
-			display_error ctx.com (error_msg (Unify l)) p);
+			located_display_error ctx.com (error_msg p (Unify l)));
 		if (has_class_field_flag f2 CfPublic) <> (has_class_field_flag f CfPublic) then typing_error ("Field " ^ f.cf_name ^ " has different visibility than core type") p;
 		if (has_class_field_flag f2 CfPublic) <> (has_class_field_flag f CfPublic) then typing_error ("Field " ^ f.cf_name ^ " has different visibility than core type") p;
 		(match f2.cf_doc with
 		(match f2.cf_doc with
 		| None -> f2.cf_doc <- f.cf_doc
 		| None -> f2.cf_doc <- f.cf_doc
@@ -922,4 +922,4 @@ let init_core_api ctx c =
 
 
 let string_list_of_expr_path (e,p) =
 let string_list_of_expr_path (e,p) =
 	try string_list_of_expr_path_raise (e,p)
 	try string_list_of_expr_path_raise (e,p)
-	with Exit -> typing_error "Invalid path" p
+	with Exit -> typing_error "Invalid path" p

+ 8 - 8
src/typing/typeloadCheck.ml

@@ -153,7 +153,7 @@ let get_native_name meta =
 let check_native_name_override ctx child base =
 let check_native_name_override ctx child base =
 	let error base_pos child_pos =
 	let error base_pos child_pos =
 		display_error ctx.com ("Field " ^ child.cf_name ^ " has different @:native value than in superclass") child_pos;
 		display_error ctx.com ("Field " ^ child.cf_name ^ " has different @:native value than in superclass") child_pos;
-		display_error ctx.com (compl_msg "Base field is defined here") base_pos
+		display_error ~depth:1 ctx.com (compl_msg "Base field is defined here") base_pos
 	in
 	in
 	try
 	try
 		let child_name, child_pos = get_native_name child.cf_meta in
 		let child_name, child_pos = get_native_name child.cf_meta in
@@ -212,8 +212,8 @@ let check_overriding ctx c f =
 			with
 			with
 				Unify_error l ->
 				Unify_error l ->
 					display_error ctx.com ("Field " ^ i ^ " overrides parent class with different or incomplete type") p;
 					display_error ctx.com ("Field " ^ i ^ " overrides parent class with different or incomplete type") p;
-					display_error ctx.com (compl_msg "Base field is defined here") f2.cf_name_pos;
-					display_error ctx.com (compl_msg (error_msg (Unify l))) p;
+					display_error ~depth:1 ctx.com (compl_msg "Base field is defined here") f2.cf_name_pos;
+					located_display_error ~depth:1 ctx.com (compl_located_msg (error_msg p (Unify l)));
 		with
 		with
 			Not_found ->
 			Not_found ->
 				if has_class_field_flag f CfOverride then
 				if has_class_field_flag f CfOverride then
@@ -397,8 +397,8 @@ module Inheritance = struct
 						Unify_error l ->
 						Unify_error l ->
 							if not (Meta.has Meta.CsNative c.cl_meta && (has_class_flag c CExtern)) then begin
 							if not (Meta.has Meta.CsNative c.cl_meta && (has_class_flag c CExtern)) then begin
 								display_error ctx.com ("Field " ^ f.cf_name ^ " has different type than in " ^ s_type_path intf.cl_path) p;
 								display_error ctx.com ("Field " ^ f.cf_name ^ " has different type than in " ^ s_type_path intf.cl_path) p;
-								display_error ctx.com (compl_msg "Interface field is defined here") f.cf_pos;
-								display_error ctx.com (compl_msg (error_msg (Unify l))) p;
+								display_error ~depth:1 ctx.com (compl_msg "Interface field is defined here") f.cf_pos;
+								located_display_error ~depth:1 ctx.com (compl_located_msg (error_msg p (Unify l)));
 							end
 							end
 				)
 				)
 			with Not_found ->
 			with Not_found ->
@@ -498,7 +498,7 @@ module Inheritance = struct
 					| t ->
 					| t ->
 						s_type pctx t
 						s_type pctx t
 				in
 				in
-				display_error ctx.com (Printf.sprintf "... %s(%s)" cf.cf_name s) cf.cf_name_pos
+				display_error ~depth:1 ctx.com (compl_msg (Printf.sprintf "%s(%s)" cf.cf_name s)) cf.cf_name_pos
 			) (List.rev !missing)
 			) (List.rev !missing)
 
 
 	let set_heritance ctx c herits p =
 	let set_heritance ctx c herits p =
@@ -627,7 +627,7 @@ module Inheritance = struct
 					raise_fields l (if is_extends then CRExtends else CRImplements) r.fsubject
 					raise_fields l (if is_extends then CRExtends else CRImplements) r.fsubject
 				in
 				in
 				Some (check_herit t is_extends p)
 				Some (check_herit t is_extends p)
-			with Error(Module_not_found(([],name)),p) when ctx.com.display.dms_kind <> DMNone ->
+			with Error(Module_not_found(([],name)),p,_) when ctx.com.display.dms_kind <> DMNone ->
 				if Diagnostics.error_in_diagnostics_run ctx.com p then DisplayToplevel.handle_unresolved_identifier ctx name p true;
 				if Diagnostics.error_in_diagnostics_run ctx.com p then DisplayToplevel.handle_unresolved_identifier ctx name p true;
 				None
 				None
 		) herits in
 		) herits in
@@ -654,4 +654,4 @@ let check_final_vars ctx e =
 		Hashtbl.iter (fun _ cf ->
 		Hashtbl.iter (fun _ cf ->
 			display_error ctx.com ("final field " ^ cf.cf_name ^ " must be initialized immediately or in the constructor") cf.cf_pos;
 			display_error ctx.com ("final field " ^ cf.cf_name ^ " must be initialized immediately or in the constructor") cf.cf_pos;
 		) final_vars
 		) final_vars
-	end
+	end

+ 12 - 12
src/typing/typeloadFields.ml

@@ -418,7 +418,7 @@ let build_enum_abstract ctx c a fields p =
 					()
 					()
 				| VPublic(access,p2) | VPrivate(access,p2) ->
 				| VPublic(access,p2) | VPrivate(access,p2) ->
 					display_error ctx.com (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
 					display_error ctx.com (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
-					display_error ctx.com "Conflicts with this" p2;
+					display_error ~depth:1 ctx.com "Conflicts with this" p2;
 			in
 			in
 			let rec loop visibility acc = match acc with
 			let rec loop visibility acc = match acc with
 				| (AExtern,p) :: acc ->
 				| (AExtern,p) :: acc ->
@@ -486,7 +486,7 @@ let build_module_def ctx mt meta fvars context_init fbuild =
 					| [ECall (epath,el),p] -> epath, el
 					| [ECall (epath,el),p] -> epath, el
 					| _ -> typing_error "Invalid build parameters" p
 					| _ -> typing_error "Invalid build parameters" p
 				) in
 				) in
-				let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error (_,p) -> typing_error "Build call parameter must be a class path" p in
+				let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error (_,p,depth) -> typing_error ~depth "Build call parameter must be a class path" p in
 				if ctx.com.is_macro_context then typing_error "You cannot use @:build inside a macro : make sure that your type is not used in macro" p;
 				if ctx.com.is_macro_context then typing_error "You cannot use @:build inside a macro : make sure that your type is not used in macro" p;
 				let old = ctx.get_build_infos in
 				let old = ctx.get_build_infos in
 				ctx.get_build_infos <- (fun() -> Some (mt, extract_param_types (t_infos mt).mt_params, fvars()));
 				ctx.get_build_infos <- (fun() -> Some (mt, extract_param_types (t_infos mt).mt_params, fvars()));
@@ -1066,7 +1066,7 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 					let r = exc_protect ctx (fun r ->
 					let r = exc_protect ctx (fun r ->
 						r := lazy_processing (fun () -> t);
 						r := lazy_processing (fun () -> t);
 						(* the return type of a from-function must be the abstract, not the underlying type *)
 						(* the return type of a from-function must be the abstract, not the underlying type *)
-						if not fctx.is_macro then (try type_eq EqStrict ret ta with Unify_error l -> typing_error (error_msg (Unify l)) p);
+						if not fctx.is_macro then (try type_eq EqStrict ret ta with Unify_error l -> located_typing_error (error_msg p (Unify l)));
 						match t with
 						match t with
 							| TFun([_,_,t],_) -> t
 							| TFun([_,_,t],_) -> t
 							| TFun([(_,_,t1);(_,true,t2)],_) when is_pos_infos t2 -> t1
 							| TFun([(_,_,t1);(_,true,t2)],_) when is_pos_infos t2 -> t1
@@ -1095,7 +1095,7 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 					(* TODO: this doesn't seem quite right... *)
 					(* TODO: this doesn't seem quite right... *)
 					if not (has_class_field_flag cf CfImpl) then add_class_field_flag cf CfImpl;
 					if not (has_class_field_flag cf CfImpl) then add_class_field_flag cf CfImpl;
 					let resolve_m args =
 					let resolve_m args =
-						(try unify_raise t (tfun (tthis :: args) m) cf.cf_pos with Error (Unify l,p) -> typing_error (error_msg (Unify l)) p);
+						(try unify_raise t (tfun (tthis :: args) m) cf.cf_pos with Error (Unify l,p,depth) -> located_typing_error ~depth (error_msg p (Unify l)));
 						match follow m with
 						match follow m with
 							| TMono _ when (match t with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic
 							| TMono _ when (match t with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic
 							| m -> m
 							| m -> m
@@ -1159,7 +1159,7 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 				| (Meta.Op,[EUnop(op,flag,_),_],_) :: _ ->
 				| (Meta.Op,[EUnop(op,flag,_),_],_) :: _ ->
 					if fctx.is_macro then invalid_modifier ctx.com fctx "macro" "operator function" p;
 					if fctx.is_macro then invalid_modifier ctx.com fctx "macro" "operator function" p;
 					let targ = if fctx.is_abstract_member then tthis else ta in
 					let targ = if fctx.is_abstract_member then tthis else ta in
-					(try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos)));
+					(try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos,0)));
 					a.a_unops <- (op,flag,cf) :: a.a_unops;
 					a.a_unops <- (op,flag,cf) :: a.a_unops;
 					allow_no_expr();
 					allow_no_expr();
 				| (Meta.Op,[ECall _,_],_) :: _ ->
 				| (Meta.Op,[ECall _,_],_) :: _ ->
@@ -1501,13 +1501,13 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 					(match f2.cf_kind with
 					(match f2.cf_kind with
 						| Method MethMacro ->
 						| Method MethMacro ->
 							display_error ctx.com (f2.cf_name ^ ": Macro methods cannot be used as property accessor") p;
 							display_error ctx.com (f2.cf_name ^ ": Macro methods cannot be used as property accessor") p;
-							display_error ctx.com (compl_msg (f2.cf_name ^ ": Accessor method is here")) f2.cf_pos;
+							display_error ~depth:1 ctx.com (compl_msg (f2.cf_name ^ ": Accessor method is here")) f2.cf_pos;
 						| _ -> ());
 						| _ -> ());
 					unify_raise t2 t f2.cf_pos;
 					unify_raise t2 t f2.cf_pos;
 					if (fctx.is_abstract_member && not (has_class_field_flag f2 CfImpl)) || (has_class_field_flag f2 CfImpl && not (fctx.is_abstract_member)) then
 					if (fctx.is_abstract_member && not (has_class_field_flag f2 CfImpl)) || (has_class_field_flag f2 CfImpl && not (fctx.is_abstract_member)) then
 						display_error ctx.com "Mixing abstract implementation and static properties/accessors is not allowed" f2.cf_pos;
 						display_error ctx.com "Mixing abstract implementation and static properties/accessors is not allowed" f2.cf_pos;
-				with Error (Unify l,p) ->
-					raise (Error (Stack (Custom ("In method " ^ m ^ " required by property " ^ name),Unify l),p))
+				with Error (Unify l,p,depth) ->
+					raise (Error (Stack [(Custom ("In method " ^ m ^ " required by property " ^ name),p);(Unify l,p)],p,depth+1))
 			)
 			)
 		with
 		with
 			| Not_found ->
 			| Not_found ->
@@ -1659,7 +1659,7 @@ let check_overload ctx f fs =
 			) fs
 			) fs
 		in
 		in
 		display_error ctx.com ("Another overloaded field of same signature was already declared : " ^ f.cf_name) f.cf_pos;
 		display_error ctx.com ("Another overloaded field of same signature was already declared : " ^ f.cf_name) f.cf_pos;
-		display_error ctx.com (compl_msg "The second field is declared here") f2.cf_pos;
+		display_error ~depth:1 ctx.com (compl_msg "The second field is declared here") f2.cf_pos;
 		false
 		false
 	with Not_found -> try
 	with Not_found -> try
 		(* OVERLOADTODO: generalize this and respect whether or not we actually generate the functions *)
 		(* OVERLOADTODO: generalize this and respect whether or not we actually generate the functions *)
@@ -1676,7 +1676,7 @@ let check_overload ctx f fs =
 			f.cf_name ^
 			f.cf_name ^
 			"\nThe signatures are different in Haxe, but not in the target language"
 			"\nThe signatures are different in Haxe, but not in the target language"
 		) f.cf_pos;
 		) f.cf_pos;
-		display_error ctx.com (compl_msg "The second field is declared here") f2.cf_pos;
+		display_error ~depth:1 ctx.com (compl_msg "The second field is declared here") f2.cf_pos;
 		false
 		false
 	with Not_found ->
 	with Not_found ->
 		true
 		true
@@ -1825,8 +1825,8 @@ let init_class ctx c p context_init herits fields =
 				else
 				else
 				if fctx.do_add then TClass.add_field c cf
 				if fctx.do_add then TClass.add_field c cf
 			end
 			end
-		with Error (Custom str,p2) when p = p2 ->
-			display_error ctx.com str p
+		with Error (Custom str,p2,depth) when p = p2 ->
+			display_error ~depth ctx.com str p
 	) fields;
 	) fields;
 	(match cctx.abstract with
 	(match cctx.abstract with
 	| Some a ->
 	| Some a ->

+ 4 - 4
src/typing/typeloadModule.ml

@@ -70,7 +70,7 @@ module ModuleLevel = struct
 			DeprecationCheck.check_is com name meta p;
 			DeprecationCheck.check_is com name meta p;
 			let error prev_pos =
 			let error prev_pos =
 				display_error ctx.com ("Name " ^ name ^ " is already defined in this module") p;
 				display_error ctx.com ("Name " ^ name ^ " is already defined in this module") p;
-				typing_error (compl_msg "Previous declaration here") prev_pos;
+				typing_error ~depth:1 (compl_msg "Previous declaration here") prev_pos;
 			in
 			in
 			List.iter (fun (t2,(_,p2)) ->
 			List.iter (fun (t2,(_,p2)) ->
 				if snd (t_path t2) = name then error (t_infos t2).mt_name_pos
 				if snd (t_path t2) = name then error (t_infos t2).mt_name_pos
@@ -677,8 +677,8 @@ module TypeLevel = struct
 				check_path_display path p;
 				check_path_display path p;
 				ImportHandling.init_import ctx context_init path mode p;
 				ImportHandling.init_import ctx context_init path mode p;
 				ImportHandling.commit_import ctx path mode p;
 				ImportHandling.commit_import ctx path mode p;
-			with Error(err,p) ->
-				display_error ctx.com (Error.error_msg err) p
+			with Error(err,p,depth) ->
+				located_display_error ~depth ctx.com (Error.error_msg p err)
 			end
 			end
 		| EUsing path ->
 		| EUsing path ->
 			check_path_display path p;
 			check_path_display path p;
@@ -797,7 +797,7 @@ let load_module' ctx g m p =
 			m
 			m
 		| None ->
 		| None ->
 			let raise_not_found () =
 			let raise_not_found () =
-				raise (Error (Module_not_found m,p))
+				raise (Error (Module_not_found m,p,0))
 			in
 			in
 			if ctx.com.module_nonexistent_lut#mem m then raise_not_found();
 			if ctx.com.module_nonexistent_lut#mem m then raise_not_found();
 			if ctx.g.load_only_cached_modules then raise_not_found();
 			if ctx.g.load_only_cached_modules then raise_not_found();

+ 1 - 1
src/typing/typeloadParse.ml

@@ -270,7 +270,7 @@ let handle_parser_result com p result =
 		let msg = Parser.error_msg msg in
 		let msg = Parser.error_msg msg in
 		match com.display.dms_error_policy with
 		match com.display.dms_error_policy with
 			| EPShow ->
 			| EPShow ->
-				if is_diagnostics com then add_diagnostics_message com msg p DKParserError Error
+				if is_diagnostics com then add_diagnostics_message com (located msg p) DKParserError Error
 				else typing_error msg p
 				else typing_error msg p
 			| EPIgnore ->
 			| EPIgnore ->
 				com.has_error <- true
 				com.has_error <- true

+ 24 - 24
src/typing/typer.ml

@@ -97,7 +97,7 @@ let maybe_type_against_enum ctx f with_type iscall p =
 			let e = try
 			let e = try
 				f()
 				f()
 			with
 			with
-			| Error (Unknown_ident n,_) ->
+			| Error (Unknown_ident n,_,_) ->
 				restore();
 				restore();
 				raise_or_display_message ctx (StringError.string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p;
 				raise_or_display_message ctx (StringError.string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p;
 				AKExpr (mk (TConst TNull) (mk_mono()) p)
 				AKExpr (mk (TConst TNull) (mk_mono()) p)
@@ -128,7 +128,7 @@ let check_error ctx err p = match err with
 	| Module_not_found ([],name) when Diagnostics.error_in_diagnostics_run ctx.com p ->
 	| Module_not_found ([],name) when Diagnostics.error_in_diagnostics_run ctx.com p ->
 		DisplayToplevel.handle_unresolved_identifier ctx name p true
 		DisplayToplevel.handle_unresolved_identifier ctx name p true
 	| _ ->
 	| _ ->
-		display_error ctx.com (error_msg err) p
+		located_display_error ctx.com (error_msg p err)
 
 
 (* ---------------------------------------------------------------------- *)
 (* ---------------------------------------------------------------------- *)
 (* PASS 3 : type expression & check structure *)
 (* PASS 3 : type expression & check structure *)
@@ -254,8 +254,8 @@ let rec unify_min_raise ctx (el:texpr list) : t =
 
 
 let unify_min ctx el =
 let unify_min ctx el =
 	try unify_min_raise ctx el
 	try unify_min_raise ctx el
-	with Error (Unify l,p) ->
-		if not ctx.untyped then display_error ctx.com (error_msg (Unify l)) p;
+	with Error (Unify l,p,depth) ->
+		if not ctx.untyped then located_display_error ~depth ctx.com (error_msg p (Unify l));
 		(List.hd el).etype
 		(List.hd el).etype
 
 
 let unify_min_for_type_source ctx el src =
 let unify_min_for_type_source ctx el src =
@@ -471,7 +471,7 @@ and type_ident ctx i p mode with_type =
 	with Not_found -> try
 	with Not_found -> try
 		(* lookup type *)
 		(* lookup type *)
 		if is_lower_ident i p then raise Not_found;
 		if is_lower_ident i p then raise Not_found;
-		let e = (try type_type ctx ([],i) p with Error (Module_not_found ([],name),_) when name = i -> raise Not_found) in
+		let e = (try type_type ctx ([],i) p with Error (Module_not_found ([],name),_,_) when name = i -> raise Not_found) in
 		AKExpr e
 		AKExpr e
 	with Not_found ->
 	with Not_found ->
 		let resolved_to_type_parameter = ref false in
 		let resolved_to_type_parameter = ref false in
@@ -499,7 +499,7 @@ and type_ident ctx i p mode with_type =
 				end else begin
 				end else begin
 					let err = Unknown_ident i in
 					let err = Unknown_ident i in
 					if ctx.in_display then begin
 					if ctx.in_display then begin
-						raise (Error (err,p))
+						raise (Error (err,p,0))
 					end;
 					end;
 					if Diagnostics.error_in_diagnostics_run ctx.com p then begin
 					if Diagnostics.error_in_diagnostics_run ctx.com p then begin
 						DisplayToplevel.handle_unresolved_identifier ctx i p false;
 						DisplayToplevel.handle_unresolved_identifier ctx i p false;
@@ -508,9 +508,9 @@ and type_ident ctx i p mode with_type =
 						AKExpr (mk (TIdent i) t p)
 						AKExpr (mk (TIdent i) t p)
 					end else match ctx.com.display.dms_kind with
 					end else match ctx.com.display.dms_kind with
 						| DMNone ->
 						| DMNone ->
-							raise (Error(err,p))
+							raise (Error(err,p,0))
 						| _ ->
 						| _ ->
-							display_error ctx.com (error_msg err) p;
+							located_display_error ctx.com (error_msg p err);
 							let t = mk_mono() in
 							let t = mk_mono() in
 							(* Add a fake local for #8751. *)
 							(* Add a fake local for #8751. *)
 							if !ServerConfig.legacy_completion then
 							if !ServerConfig.legacy_completion then
@@ -539,7 +539,7 @@ and handle_efield ctx e p0 mode with_type =
 				try
 				try
 					(* TODO: we don't really want to do full type_ident again, just the second part of it *)
 					(* TODO: we don't really want to do full type_ident again, just the second part of it *)
 					field_chain ctx pnext (type_ident ctx name p MGet WithType.value)
 					field_chain ctx pnext (type_ident ctx name p MGet WithType.value)
-				with Error (Unknown_ident _,p2) as e when p = p2 ->
+				with Error (Unknown_ident _,p2,_) as e when p = p2 ->
 					try
 					try
 						(* try raising a more sensible error if there was an uppercase-first (module name) part *)
 						(* try raising a more sensible error if there was an uppercase-first (module name) part *)
 						begin
 						begin
@@ -563,9 +563,9 @@ and handle_efield ctx e p0 mode with_type =
 							let mpath = (pack,name) in
 							let mpath = (pack,name) in
 							if ctx.com.module_lut#mem mpath then
 							if ctx.com.module_lut#mem mpath then
 								let tname = Option.default name sub in
 								let tname = Option.default name sub in
-								raise (Error (Type_not_found (mpath,tname,Not_defined),p))
+								raise (Error (Type_not_found (mpath,tname,Not_defined),p,0))
 							else
 							else
-								raise (Error (Module_not_found mpath,p))
+								raise (Error (Module_not_found mpath,p,0))
 						end
 						end
 					with Not_found ->
 					with Not_found ->
 						(* if there was no module name part, last guess is that we're trying to get package completion *)
 						(* if there was no module name part, last guess is that we're trying to get package completion *)
@@ -713,7 +713,7 @@ and type_vars ctx vl p =
 				DisplayEmitter.display_variable ctx v pv;
 				DisplayEmitter.display_variable ctx v pv;
 			v,e
 			v,e
 		with
 		with
-			Error (e,p) ->
+			Error (e,p,_) ->
 				check_error ctx e p;
 				check_error ctx e p;
 				add_local ctx VGenerated n t_dynamic pv, None (* TODO: What to do with this... *)
 				add_local ctx VGenerated n t_dynamic pv, None (* TODO: What to do with this... *)
 	) vl in
 	) vl in
@@ -840,7 +840,7 @@ and type_block ctx el with_type p =
 	let rec loop acc = function
 	let rec loop acc = function
 		| [] -> List.rev acc
 		| [] -> List.rev acc
 		| e :: l ->
 		| e :: l ->
-			let acc = try merge acc (type_expr ctx e (if l = [] then with_type else WithType.no_value)) with Error (e,p) -> check_error ctx e p; acc in
+			let acc = try merge acc (type_expr ctx e (if l = [] then with_type else WithType.no_value)) with Error (e,p,_) -> check_error ctx e p; acc in
 			loop acc l
 			loop acc l
 	in
 	in
 	let l = loop [] el in
 	let l = loop [] el in
@@ -926,7 +926,7 @@ and type_object_decl ctx fl with_type p =
 			(match PMap.foldi (fun n cf acc -> if not (Meta.has Meta.Optional cf.cf_meta) && not (PMap.mem n !fields) then n :: acc else acc) field_map [] with
 			(match PMap.foldi (fun n cf acc -> if not (Meta.has Meta.Optional cf.cf_meta) && not (PMap.mem n !fields) then n :: acc else acc) field_map [] with
 				| [] -> ()
 				| [] -> ()
 				| [n] -> raise_or_display ctx [Unify_custom ("Object requires field " ^ n)] p
 				| [n] -> raise_or_display ctx [Unify_custom ("Object requires field " ^ n)] p
-				| nl -> raise_or_display ctx [Unify_custom ("Object requires fields: " ^ (String.concat ", " nl))] p);
+				| depth -> raise_or_display ctx [Unify_custom ("Object requires fields: " ^ (String.concat ", " depth))] p);
 			(match !extra_fields with
 			(match !extra_fields with
 			| [] -> ()
 			| [] -> ()
 			| _ -> raise_or_display ctx (List.map (fun n -> has_extra_field t n) !extra_fields) p);
 			| _ -> raise_or_display ctx (List.map (fun n -> has_extra_field t n) !extra_fields) p);
@@ -1030,8 +1030,8 @@ and type_new ctx path el with_type force_inline p =
 			let fcc = unify_field_call ctx fa [] el p fa.fa_inline in
 			let fcc = unify_field_call ctx fa [] el p fa.fa_inline in
 			check_constructor_access ctx c fcc.fc_field p;
 			check_constructor_access ctx c fcc.fc_field p;
 			fcc
 			fcc
-		with Error (e,p) ->
-			typing_error (error_msg e) p;
+		with Error (e,p,depth) ->
+			located_typing_error ~depth (error_msg p e);
 	in
 	in
 	let display_position_in_el () =
 	let display_position_in_el () =
 		List.exists (fun e -> DisplayPosition.display_position#enclosed_in (pos e)) el
 		List.exists (fun e -> DisplayPosition.display_position#enclosed_in (pos e)) el
@@ -1115,8 +1115,8 @@ and type_new ctx path el with_type force_inline p =
 		mk (TNew (c,params,el)) t p
 		mk (TNew (c,params,el)) t p
 	| _ ->
 	| _ ->
 		typing_error (s_type (print_context()) t ^ " cannot be constructed") p
 		typing_error (s_type (print_context()) t ^ " cannot be constructed") p
-	end with Error(No_constructor _ as err,p) when ctx.com.display.dms_kind <> DMNone ->
-		display_error ctx.com (error_msg err) p;
+	end with Error(No_constructor _ as err,p,depth) when ctx.com.display.dms_kind <> DMNone ->
+		located_display_error ~depth ctx.com (error_msg p err);
 		Diagnostics.secure_generated_code ctx (mk (TConst TNull) t p)
 		Diagnostics.secure_generated_code ctx (mk (TConst TNull) t p)
 
 
 and type_try ctx e1 catches with_type p =
 and type_try ctx e1 catches with_type p =
@@ -1215,7 +1215,7 @@ and type_map_declaration ctx e1 el with_type p =
 		try
 		try
 			let p = Hashtbl.find keys e_key.eexpr in
 			let p = Hashtbl.find keys e_key.eexpr in
 			display_error ctx.com "Duplicate key" e_key.epos;
 			display_error ctx.com "Duplicate key" e_key.epos;
-			typing_error (compl_msg "Previously defined here") p
+			typing_error ~depth:1 (compl_msg "Previously defined here") p
 		with Not_found ->
 		with Not_found ->
 			begin match e_key.eexpr with
 			begin match e_key.eexpr with
 			| TConst _ -> Hashtbl.add keys e_key.eexpr e_key.epos;
 			| TConst _ -> Hashtbl.add keys e_key.eexpr e_key.epos;
@@ -1464,12 +1464,12 @@ and type_array_decl ctx el with_type p =
 		let el = List.map (fun e -> type_expr ctx e WithType.value) el in
 		let el = List.map (fun e -> type_expr ctx e WithType.value) el in
 		let t = try
 		let t = try
 			unify_min_raise ctx el
 			unify_min_raise ctx el
-		with Error (Unify l,p) ->
+		with Error (Unify l,p,n) ->
 			if !allow_array_dynamic || ctx.untyped || ignore_error ctx.com then
 			if !allow_array_dynamic || ctx.untyped || ignore_error ctx.com then
 				t_dynamic
 				t_dynamic
 			else begin
 			else begin
 				display_error ctx.com "Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>" p;
 				display_error ctx.com "Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>" p;
-				raise (Error (Unify l, p))
+				raise (Error (Unify l, p,n))
 			end
 			end
 		in
 		in
 		mk (TArrayDecl el) (ctx.t.tarray t) p
 		mk (TArrayDecl el) (ctx.t.tarray t) p
@@ -1563,7 +1563,7 @@ and type_return ?(implicit=false) ctx e with_type p =
 					]) t e.epos;
 					]) t e.epos;
 				| _ ->
 				| _ ->
 					mk (TReturn (Some e)) (mono_or_dynamic ctx with_type p) p
 					mk (TReturn (Some e)) (mono_or_dynamic ctx with_type p) p
-		with Error(err,p) ->
+		with Error(err,p,_) ->
 			check_error ctx err p;
 			check_error ctx err p;
 			(* If we have a bad return, let's generate a return null expression at least. This surpresses various
 			(* If we have a bad return, let's generate a return null expression at least. This surpresses various
 				follow-up errors that come from the fact that the function no longer has a return expression (issue #6445). *)
 				follow-up errors that come from the fact that the function no longer has a return expression (issue #6445). *)
@@ -1800,7 +1800,7 @@ and type_call_builtin ctx e el mode with_type p =
 			let cf = fa.fa_field in
 			let cf = fa.fa_field in
 			let t = TInst (c,params) in
 			let t = TInst (c,params) in
 			let e = mk (TConst TSuper) t sp in
 			let e = mk (TConst TSuper) t sp in
-			if (Meta.has Meta.CompilerGenerated cf.cf_meta) then display_error ctx.com (error_msg (No_constructor (TClassDecl c))) p;
+			if (Meta.has Meta.CompilerGenerated cf.cf_meta) then located_display_error ctx.com (error_msg p (No_constructor (TClassDecl c)));
 			let fa = FieldAccess.create e cf (FHInstance(c,params)) false p in
 			let fa = FieldAccess.create e cf (FHInstance(c,params)) false p in
 			let fcc = unify_field_call ctx fa [] el p false in
 			let fcc = unify_field_call ctx fa [] el p false in
 			let el = fcc.fc_args in
 			let el = fcc.fc_args in
@@ -2113,7 +2113,7 @@ let rec create com =
 	ctx.g.std <- (try
 	ctx.g.std <- (try
 		TypeloadModule.load_module ctx ([],"StdTypes") null_pos
 		TypeloadModule.load_module ctx ([],"StdTypes") null_pos
 	with
 	with
-		Error (Module_not_found ([],"StdTypes"),_) ->
+		Error (Module_not_found ([],"StdTypes"),_,_) ->
 			try
 			try
 				let std_path = Sys.getenv "HAXE_STD_PATH" in
 				let std_path = Sys.getenv "HAXE_STD_PATH" in
 				typing_error ("Standard library not found. Please check your `HAXE_STD_PATH` environment variable (current value: \"" ^ std_path ^ "\")") null_pos
 				typing_error ("Standard library not found. Please check your `HAXE_STD_PATH` environment variable (current value: \"" ^ std_path ^ "\")") null_pos

+ 7 - 7
src/typing/typerDisplay.ml

@@ -212,7 +212,7 @@ let rec handle_signature_display ctx e_ast with_type =
 						let _ = unify_call_args ctx el args r p false false false in
 						let _ = unify_call_args ctx el args r p false false false in
 						true
 						true
 					with
 					with
-					| Error(Call_error (Not_enough_arguments _),_) -> true
+					| Error(Call_error (Not_enough_arguments _),_,_) -> true
 					| _ -> false
 					| _ -> false
 					end
 					end
 				in
 				in
@@ -263,10 +263,10 @@ let rec handle_signature_display ctx e_ast with_type =
 				try
 				try
 					acc_get ctx (!type_call_target_ref ctx e1 el with_type None)
 					acc_get ctx (!type_call_target_ref ctx e1 el with_type None)
 				with
 				with
-				| Error (Unknown_ident "trace",_) ->
+				| Error (Unknown_ident "trace",_,_) ->
 					let e = expr_of_type_path (["haxe";"Log"],"trace") p in
 					let e = expr_of_type_path (["haxe";"Log"],"trace") p in
 					type_expr ctx e WithType.value
 					type_expr ctx e WithType.value
-				| Error (Unknown_ident "$type",p) ->
+				| Error (Unknown_ident "$type",p,_) ->
 					display_dollar_type ctx p (fun t -> t,(CompletionType.from_type (get_import_status ctx) t))
 					display_dollar_type ctx p (fun t -> t,(CompletionType.from_type (get_import_status ctx) t))
 			in
 			in
 			let e1 = match e1 with
 			let e1 = match e1 with
@@ -536,10 +536,10 @@ let handle_display ctx e_ast dk mode with_type =
 		mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *)
 		mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *)
 	| (_,p),_ -> try
 	| (_,p),_ -> try
 		type_expr ~mode ctx e_ast with_type
 		type_expr ~mode ctx e_ast with_type
-	with Error (Unknown_ident n,_) when ctx.com.display.dms_kind = DMDefault ->
+	with Error (Unknown_ident n,_,_) when ctx.com.display.dms_kind = DMDefault ->
         if dk = DKDot && is_legacy_completion ctx.com then raise (Parser.TypePath ([n],None,false,p))
         if dk = DKDot && is_legacy_completion ctx.com then raise (Parser.TypePath ([n],None,false,p))
 		else raise_toplevel ctx dk with_type (n,p)
 		else raise_toplevel ctx dk with_type (n,p)
-	| Error ((Type_not_found (path,_,_) | Module_not_found path),_) as err when ctx.com.display.dms_kind = DMDefault ->
+	| Error ((Type_not_found (path,_,_) | Module_not_found path),_,_) as err when ctx.com.display.dms_kind = DMDefault ->
 		if is_legacy_completion ctx.com then begin try
 		if is_legacy_completion ctx.com then begin try
 			raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((make_ci_module path),p,None,None)) (make_subject None (pos e_ast))
 			raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((make_ci_module path),p,None,None)) (make_subject None (pos e_ast))
 		with Not_found ->
 		with Not_found ->
@@ -615,7 +615,7 @@ let handle_display ctx e_ast dk mode with_type =
 		| WithType.WithType(t,_) ->
 		| WithType.WithType(t,_) ->
 			(* We don't want to actually use the transformed expression which may have inserted implicit cast calls.
 			(* We don't want to actually use the transformed expression which may have inserted implicit cast calls.
 			   It only matters that unification takes place. *)
 			   It only matters that unification takes place. *)
-			(try ignore(AbstractCast.cast_or_unify_raise ctx t e e.epos) with Error (Unify l,p) -> ());
+			(try ignore(AbstractCast.cast_or_unify_raise ctx t e e.epos) with Error (Unify l,p,_) -> ());
 		| _ ->
 		| _ ->
 			()
 			()
 	end;
 	end;
@@ -721,4 +721,4 @@ let handle_edisplay ctx e dk mode with_type =
 		with DisplayException(DisplayFields ({fkind = CRToplevel _} as r)) ->
 		with DisplayException(DisplayFields ({fkind = CRToplevel _} as r)) ->
 			raise_fields r.fitems (CRPattern ((get_expected_type ctx with_type),outermost)) r.fsubject
 			raise_fields r.fitems (CRPattern ((get_expected_type ctx with_type),outermost)) r.fsubject
 		end
 		end
-	| _ -> handle_display ctx e dk with_type
+	| _ -> handle_display ctx e dk with_type

+ 1 - 1
src/typing/typerDotPath.ml

@@ -74,7 +74,7 @@ let resolve_qualified ctx pack name next_path p mode with_type =
 	try
 	try
 		let m = Typeload.load_module ctx (pack,name) p in
 		let m = Typeload.load_module ctx (pack,name) p in
 		resolve_in_module ctx m next_path p mode with_type
 		resolve_in_module ctx m next_path p mode with_type
-	with Error (Module_not_found mpath,_) when mpath = (pack,name) ->
+	with Error (Module_not_found mpath,_,_) when mpath = (pack,name) ->
 		(* might be an instance of https://github.com/HaxeFoundation/haxe/issues/9150
 		(* might be an instance of https://github.com/HaxeFoundation/haxe/issues/9150
 		   so let's also check (pack,name) of a TYPE in the current module context ¯\_(ツ)_/¯ *)
 		   so let's also check (pack,name) of a TYPE in the current module context ¯\_(ツ)_/¯ *)
 		let t = Typeload.find_type_in_current_module_context ctx pack name in (* raises Not_found *)
 		let t = Typeload.find_type_in_current_module_context ctx pack name in (* raises Not_found *)

+ 12 - 12
std/haxe/macro/Context.hx

@@ -47,38 +47,38 @@ class Context {
 		Displays a compilation error `msg` at the given `Position` `pos`
 		Displays a compilation error `msg` at the given `Position` `pos`
 		and aborts the current macro call.
 		and aborts the current macro call.
 	**/
 	**/
-	public static function error(msg:String, pos:Position):Dynamic {
-		return load("error", 2)(msg, pos);
+	public static function error(msg:String, pos:Position, ?depth:Int = 0):Dynamic {
+		return load("error", 2)(msg, pos, depth);
 	}
 	}
 
 
 	/**
 	/**
 		Displays a compilation error `msg` at the given `Position` `pos`
 		Displays a compilation error `msg` at the given `Position` `pos`
 		and aborts the compilation.
 		and aborts the compilation.
 	**/
 	**/
-	public static function fatalError(msg:String, pos:Position):Dynamic {
-		return load("fatal_error", 2)(msg, pos);
+	public static function fatalError(msg:String, pos:Position, ?depth:Int = 0):Dynamic {
+		return load("fatal_error", 2)(msg, pos, depth);
 	}
 	}
 
 
 	/**
 	/**
 		Displays a compilation error `msg` at the given `Position` `pos`
 		Displays a compilation error `msg` at the given `Position` `pos`
 		without aborting the current macro call.
 		without aborting the current macro call.
 	**/
 	**/
-	public static function reportError(msg:String, pos:Position):Void {
-		load("report_error", 2)(msg, pos);
+	public static function reportError(msg:String, pos:Position, ?depth:Int = 0):Void {
+		load("report_error", 2)(msg, pos, depth);
 	}
 	}
 
 
 	/**
 	/**
 		Displays a compilation warning `msg` at the given `Position` `pos`.
 		Displays a compilation warning `msg` at the given `Position` `pos`.
 	**/
 	**/
-	public static function warning(msg:String, pos:Position) {
-		load("warning", 2)(msg, pos);
+	public static function warning(msg:String, pos:Position, ?depth:Int = 0) {
+		load("warning", 2)(msg, pos, depth);
 	}
 	}
 
 
 	/**
 	/**
 		Displays a compilation info `msg` at the given `Position` `pos`.
 		Displays a compilation info `msg` at the given `Position` `pos`.
 	**/
 	**/
-	public static function info(msg:String, pos:Position) {
-		load("info", 2)(msg, pos);
+	public static function info(msg:String, pos:Position, ?depth:Int = 0) {
+		load("info", 2)(msg, pos, depth);
 	}
 	}
 
 
 	/**
 	/**
@@ -311,7 +311,7 @@ class Context {
 
 
 	/**
 	/**
 		Returns the typed expression of the call to the main function.
 		Returns the typed expression of the call to the main function.
-		
+
 		This function will only work in the generation phase. Any calls
 		This function will only work in the generation phase. Any calls
 		made outside a function passed to `haxe.macro.Context.onGenerate`
 		made outside a function passed to `haxe.macro.Context.onGenerate`
 		or `haxe.macro.Context.onAfterGenerate` will return `null`.
 		or `haxe.macro.Context.onAfterGenerate` will return `null`.
@@ -322,7 +322,7 @@ class Context {
 
 
 	/**
 	/**
 		Returns an array of module types to be generated in the output.
 		Returns an array of module types to be generated in the output.
-		
+
 		This list may change depending on the phase of compilation and
 		This list may change depending on the phase of compilation and
 		should not be treated as conclusive until the generation phase.
 		should not be treated as conclusive until the generation phase.
 
 

+ 2 - 0
tests/misc/projects/Issue10623/indent-fail.hxml

@@ -0,0 +1,2 @@
+compile-fail.hxml
+-D message-reporting=indent

+ 2 - 0
tests/misc/projects/Issue10623/indent-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Uncaught exception Invalid string
+  Main.hx:5: characters 3-18 : Called from here

+ 3 - 0
tests/misc/projects/Issue10623/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 10 - 0
tests/misc/projects/Issue10623/pretty-fail.hxml.stderr

@@ -0,0 +1,10 @@
+[ERROR] (unknown position)
+
+   | Uncaught exception Invalid string
+
+    ->  Main.hx:5: characters 3-18
+
+    5 |   data.toString().substr(0);
+      |   ^^^^^^^^^^^^^^^
+      | Called from here
+

+ 3 - 0
tests/misc/projects/Issue10844/user-defined-define-json-fail.hxml.stderr

@@ -0,0 +1,3 @@
+(unknown) : Uncaught exception Could not read file define.jsno
+$$normPath(::std::)/haxe/macro/Compiler.hx:482: characters 11-39 : Called from here
+(unknown) : Called from here

+ 2 - 0
tests/misc/projects/Issue10844/user-defined-meta-indent-fail.hxml

@@ -0,0 +1,2 @@
+user-defined-meta-fail.hxml
+-D message-reporting=indent

+ 2 - 0
tests/misc/projects/Issue10844/user-defined-meta-indent-fail.hxml.stderr

@@ -0,0 +1,2 @@
+(unknown) : Object requires field metadata
+  (unknown) : For function argument 'meta'

+ 3 - 0
tests/misc/projects/Issue10844/user-defined-meta-json-fail.hxml.stderr

@@ -0,0 +1,3 @@
+(unknown) : Uncaught exception Could not read file meta.jsno
+$$normPath(::std::)/haxe/macro/Compiler.hx:472: characters 11-39 : Called from here
+(unknown) : Called from here

+ 2 - 0
tests/misc/projects/Issue10844/user-defined-meta-json-indent-fail.hxml

@@ -0,0 +1,2 @@
+user-defined-meta-json-fail.hxml
+-D message-reporting=indent

+ 3 - 0
tests/misc/projects/Issue10844/user-defined-meta-json-indent-fail.hxml.stderr

@@ -0,0 +1,3 @@
+(unknown) : Uncaught exception Could not read file meta.jsno
+  $$normPath(::std::)/haxe/macro/Compiler.hx:472: characters 11-39 : Called from here
+  (unknown) : Called from here

+ 4 - 0
tests/misc/projects/Issue10844/user-defined-meta-json-pretty-fail.hxml

@@ -0,0 +1,4 @@
+user-defined-meta-json-fail.hxml
+-D message-reporting=pretty
+-D no-color
+

+ 12 - 0
tests/misc/projects/Issue10844/user-defined-meta-json-pretty-fail.hxml.stderr

@@ -0,0 +1,12 @@
+[ERROR] --macro haxe.macro.Compiler.registerMetadataDescriptionFile('meta.jsno', 'myapp')
+
+   | Uncaught exception Could not read file meta.jsno
+
+    ->  $$normPath(::std::)/haxe/macro/Compiler.hx:472: characters 11-39
+
+    472 |   var f = sys.io.File.getContent(path);
+        |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        | Called from here
+
+        | Called from here
+

+ 4 - 0
tests/misc/projects/Issue10844/user-defined-meta-pretty-fail.hxml

@@ -0,0 +1,4 @@
+user-defined-meta-fail.hxml
+-D message-reporting=pretty
+-D no-color
+

+ 5 - 0
tests/misc/projects/Issue10844/user-defined-meta-pretty-fail.hxml.stderr

@@ -0,0 +1,5 @@
+[ERROR] --macro haxe.macro.Compiler.registerCustomMetadata({metdata: ':zzz', doc: 'something'}, 'myapp')
+
+   | Object requires field metadata
+   | For function argument 'meta'
+

+ 3 - 0
tests/misc/projects/Issue10863/logmode-fail.hxml

@@ -0,0 +1,3 @@
+Any
+-D messages-log-file=error.log
+-D messages-log-format=awesome

+ 1 - 0
tests/misc/projects/Issue10863/logmode-fail.hxml.stderr

@@ -0,0 +1 @@
+Invalid message reporting mode: "awesome", expected classic | pretty | indent (for -D messages_log_format).

+ 2 - 0
tests/misc/projects/Issue10863/reporting-fail.hxml

@@ -0,0 +1,2 @@
+Any
+-D message-reporting=awesome

+ 1 - 0
tests/misc/projects/Issue10863/reporting-fail.hxml.stderr

@@ -0,0 +1 @@
+Invalid message reporting mode: "awesome", expected classic | pretty | indent (for -D message_reporting).

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

@@ -0,0 +1,8 @@
+extern inline overload function test(a:String) {}
+extern inline overload function test(a:Int) {}
+
+function main() {
+	test(function() {
+		var x:String = 1;
+	});
+}

+ 3 - 0
tests/misc/projects/Issue4803/compile2-fail.hxml

@@ -0,0 +1,3 @@
+--main Main2
+-js js.js
+--no-output

+ 2 - 0
tests/misc/projects/Issue4803/compile2-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main2.hx:6: characters 3-20 : Int should be String
+Main2.hx:6: characters 3-20 : ... For function argument 'a'

+ 3 - 0
tests/misc/projects/Issue5644/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 6 - 0
tests/misc/projects/Issue5644/pretty-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] User.hx:1: characters 20-47
+
+ 1 | class User extends ThisObviouslyDoesntExist<T> {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | Type not found : ThisObviouslyDoesntExist
+

+ 2 - 0
tests/misc/projects/Issue5949/indent-fail.hxml

@@ -0,0 +1,2 @@
+compile-fail.hxml
+-D message-reporting=indent

+ 2 - 0
tests/misc/projects/Issue5949/indent-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main.hx:11: characters 11-14 : Field a has different @:native value than in superclass
+  Main.hx:6: characters 18-19 : Base field is defined here

+ 3 - 0
tests/misc/projects/Issue5949/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 10 - 0
tests/misc/projects/Issue5949/pretty-fail.hxml.stderr

@@ -0,0 +1,10 @@
+[ERROR] Main.hx:11: characters 11-14
+
+ 11 |  @:native("z") override public function a() {}
+    |           ^^^
+    | Field a has different @:native value than in superclass
+
+     6 |  public function a() {}
+       |                  ^
+       | Base field is defined here
+

+ 2 - 0
tests/misc/projects/Issue6065/indent-fail.hxml

@@ -0,0 +1,2 @@
+compile-fail.hxml
+-D message-reporting=indent

+ 14 - 0
tests/misc/projects/Issue6065/indent-fail.hxml.stderr

@@ -0,0 +1,14 @@
+Main.hx:8: characters 9-18 : Could not find a suitable overload, reasons follow
+  Main.hx:8: characters 9-18 : Overload resolution failed for () -> Void
+    Main.hx:8: characters 13-17 : Too many arguments
+  Main.hx:8: characters 9-18 : Overload resolution failed for (t : f.T) -> Void
+    Main.hx:8: characters 13-17 : Constraint check failure for f.T
+      Main.hx:8: characters 13-17 : String should be Int
+      Main.hx:8: characters 13-17 : For function argument 't'
+Main.hx:9: characters 9-16 : Could not find a suitable overload, reasons follow
+  Main.hx:9: characters 9-16 : Overload resolution failed for () -> Void
+    Main.hx:9: characters 13-15 : Too many arguments
+  Main.hx:9: characters 9-16 : Overload resolution failed for (t : f.T) -> Void
+    Main.hx:9: characters 13-15 : Constraint check failure for f.T
+      Main.hx:9: characters 13-15 : { } should be Int
+      Main.hx:9: characters 13-15 : For function argument 't'

+ 3 - 0
tests/misc/projects/Issue6065/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 40 - 0
tests/misc/projects/Issue6065/pretty-fail.hxml.stderr

@@ -0,0 +1,40 @@
+[ERROR] Main.hx:8: characters 9-18
+
+ 8 |         C.f("hi");
+   |         ^^^^^^^^^
+   | Could not find a suitable overload, reasons follow
+
+      | Overload resolution failed for () -> Void
+
+       8 |         C.f("hi");
+         |             ^^^^
+         | Too many arguments
+
+      | Overload resolution failed for (t : f.T) -> Void
+
+       8 |         C.f("hi");
+         |             ^^^^
+         | Constraint check failure for f.T
+         | String should be Int
+         | For function argument 't'
+
+[ERROR] Main.hx:9: characters 9-16
+
+ 9 |         C.f({});
+   |         ^^^^^^^
+   | Could not find a suitable overload, reasons follow
+
+      | Overload resolution failed for () -> Void
+
+       9 |         C.f({});
+         |             ^^
+         | Too many arguments
+
+      | Overload resolution failed for (t : f.T) -> Void
+
+       9 |         C.f({});
+         |             ^^
+         | Constraint check failure for f.T
+         | { } should be Int
+         | For function argument 't'
+

+ 3 - 0
tests/misc/projects/Issue6584/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile5-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 14 - 0
tests/misc/projects/Issue6584/pretty-fail.hxml.stderr

@@ -0,0 +1,14 @@
+[ERROR] Main5.hx:1: lines 1-6
+
+ 1 | class Main {
+ - |   [...]
+ 6 | }
+   |
+   | This class has uninitialized final vars, which requires a constructor
+
+[ERROR] Main5.hx:2: characters 8-9
+
+ 2 |  final v:Int;
+   |        ^
+   | Example of an uninitialized final var
+

+ 3 - 0
tests/misc/projects/Issue6790/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 7 - 0
tests/misc/projects/Issue6790/pretty-fail.hxml.stderr

@@ -0,0 +1,7 @@
+[ERROR] Mismatch.hx:6: characters 19-26
+
+ 6 |   p.then(x -> 10, e -> "");
+   |                   ^^^^^^^
+   | (e : Unknown<0>) -> String should be Null<js.lib.PromiseHandler<Dynamic, Int>>
+   | For optional function argument 'onRejected'
+

+ 3 - 0
tests/misc/projects/Issue6796/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 7 - 0
tests/misc/projects/Issue6796/pretty-fail.hxml.stderr

@@ -0,0 +1,7 @@
+[ERROR] Main.hx:3: characters 21-25
+
+ 3 |         Sys.println(main["foo"]);
+   |                     ^^^^
+   | Array access is not allowed on () -> Unknown<0>
+   | For function argument 'v'
+

+ 3 - 0
tests/misc/projects/Issue6810/.gitignore

@@ -0,0 +1,3 @@
+logfile-02-fail.hxml.stderr
+logfile-03-fail.hxml.stderr
+logfile-04-fail.hxml.stderr

+ 2 - 0
tests/misc/projects/Issue6810/indent-fail.hxml

@@ -0,0 +1,2 @@
+compile-fail.hxml
+-D message-reporting=indent

+ 8 - 0
tests/misc/projects/Issue6810/indent-fail.hxml.stderr

@@ -0,0 +1,8 @@
+Fail.hx:7: characters 8-12 : error: Void should be haxe.NotVoid
+  Fail.hx:7: characters 8-12 : have: (...) -> Void
+  Fail.hx:7: characters 8-12 : want: (...) -> haxe.NotVoid
+  Fail.hx:7: characters 8-12 : For function argument 'f'
+Fail.hx:8: characters 8-16 : error: FakeVoid should be haxe.NotVoid
+  Fail.hx:8: characters 8-16 : have: (...) -> FakeVoid
+  Fail.hx:8: characters 8-16 : want: (...) -> haxe.NotVoid
+  Fail.hx:8: characters 8-16 : For function argument 'f'

+ 2 - 0
tests/misc/projects/Issue6810/logfile-01-fail.hxml

@@ -0,0 +1,2 @@
+-D messages-log-file=logfile-02-fail.hxml.stderr
+compile-fail.hxml

+ 4 - 0
tests/misc/projects/Issue6810/logfile-02-fail.hxml

@@ -0,0 +1,4 @@
+-D messages-log-file=logfile-03-fail.hxml.stderr
+-D messages-log-format=pretty
+-D message-reporting=indent
+compile-fail.hxml

+ 4 - 0
tests/misc/projects/Issue6810/logfile-03-fail.hxml

@@ -0,0 +1,4 @@
+-D messages-log-file=logfile-04-fail.hxml.stderr
+-D messages-log-format=classic
+-D message-reporting=pretty
+compile-fail.hxml

+ 1 - 0
tests/misc/projects/Issue6810/logfile-04-fail.hxml

@@ -0,0 +1 @@
+compile-fail.hxml

+ 3 - 0
tests/misc/projects/Issue6810/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 18 - 0
tests/misc/projects/Issue6810/pretty-fail.hxml.stderr

@@ -0,0 +1,18 @@
+[ERROR] Fail.hx:7: characters 8-12
+
+ 7 |   test(void);
+   |        ^^^^
+   | error: Void should be haxe.NotVoid
+   | have: (...) -> Void
+   | want: (...) -> haxe.NotVoid
+   | For function argument 'f'
+
+[ERROR] Fail.hx:8: characters 8-16
+
+ 8 |   test(fakeVoid);
+   |        ^^^^^^^^
+   | error: FakeVoid should be haxe.NotVoid
+   | have: (...) -> FakeVoid
+   | want: (...) -> haxe.NotVoid
+   | For function argument 'f'
+

+ 3 - 0
tests/misc/projects/Issue7968/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 10 - 0
tests/misc/projects/Issue7968/pretty-fail.hxml.stderr

@@ -0,0 +1,10 @@
+[ERROR] Foo.hx:2: characters 1-18
+
+ 2 | typedef A = Float;
+   | ^^^^^^^^^^^^^^^^^
+   | Name A is already defined in this module
+
+    1 | typedef A = Int;
+      |         ^
+      | Previous declaration here
+

+ 2 - 0
tests/misc/projects/Issue8303/indent-fail.hxml

@@ -0,0 +1,2 @@
+compile-fail.hxml
+-D message-reporting=indent

+ 21 - 0
tests/misc/projects/Issue8303/indent-fail.hxml.stderr

@@ -0,0 +1,21 @@
+Uncaught exception Stack overflow
+  Main.hx:1: character 1 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:8: characters 4-9 : Called from here
+  Main.hx:10: characters 3-8 : Called from here
+  Main.hx:3: characters 3-9 : Called from here

+ 3 - 0
tests/misc/projects/Issue8303/pretty-fail.hxml

@@ -0,0 +1,3 @@
+compile-fail.hxml
+-D message-reporting=pretty
+-D no-color

+ 54 - 0
tests/misc/projects/Issue8303/pretty-fail.hxml.stderr

@@ -0,0 +1,54 @@
+[ERROR] (unknown position)
+
+   | Uncaught exception Stack overflow
+
+    ->  Main.hx:1: character 1
+
+     1 | class Main {
+       | ^
+       | Called from here
+
+     8 |    log();
+       |    ^^^^^
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+       | Called from here
+
+    10 |   log();
+       |   ^^^^^
+       | Called from here
+
+     3 |   test();
+       |   ^^^^^^
+       | Called from here
+

+ 3 - 0
tests/misc/projects/Issue8471/compile2-pretty.hxml

@@ -0,0 +1,3 @@
+compile2.hxml
+-D message-reporting=pretty
+-D no-color

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

@@ -0,0 +1,22 @@
+[WARNING] Macro2.hx:12: characters 25-39
+
+ 12 |   Context.warning(("1" :DeprecatedType), Context.currentPos());
+    |                         ^^^^^^^^^^^^^^
+    | (WDeprecated) This typedef is deprecated in favor of String
+
+[WARNING] (unknown position)
+
+    | 1
+
+[WARNING] (unknown position)
+
+    | 2
+
+[WARNING] (unknown position)
+
+    | 3
+
+[WARNING] (unknown position)
+
+    | i123|i123
+

+ 7 - 14
tests/misc/projects/issue5002/compile2-fail.hxml.stderr

@@ -1,17 +1,10 @@
-"0_variable" is not a valid variable name.
-Main2.hx:6: characters 3-32 : ... Called from macro here
-"var" is not a valid variable name.
-Main2.hx:7: characters 3-25 : ... Called from macro here
-"new" is not a valid variable name.
-Main2.hx:8: characters 3-25 : ... Called from macro here
-"foo \"\t\n" is not a valid variable name.
-Main2.hx:9: characters 3-32 : ... Called from macro here
-"0_catchVariable" is not a valid catch variable name.
-Main2.hx:10: characters 3-25 : ... Called from macro here
-"0_function" is not a valid function name.
-Main2.hx:11: characters 3-24 : ... Called from macro here
-"0_argument" is not a valid function argument name.
-Main2.hx:12: characters 3-32 : ... Called from macro here
+Main2.hx:6: characters 3-32 : "0_variable" is not a valid variable name.
+Main2.hx:7: characters 3-25 : "var" is not a valid variable name.
+Main2.hx:8: characters 3-25 : "new" is not a valid variable name.
+Main2.hx:9: characters 3-32 : "foo \"\t\n" is not a valid variable name.
+Main2.hx:10: characters 3-25 : "0_catchVariable" is not a valid catch variable name.
+Main2.hx:11: characters 3-24 : "0_function" is not a valid function name.
+Main2.hx:12: characters 3-32 : "0_argument" is not a valid function argument name.
 Main2.hx:13: characters 3-27 : Unknown identifier : 0_patternVariable, pattern variables must be lower-case or with `var ` prefix
 Main2.hx:13: characters 3-27 : Unknown identifier : 0_patternVariable, pattern variables must be lower-case or with `var ` prefix
 Main2.hx:14: characters 3-23 : "0_forVariable" is not a valid for variable name.
 Main2.hx:14: characters 3-23 : "0_forVariable" is not a valid for variable name.
 Main2.hx:15: characters 3-31 : "0_forVariableKey" is not a valid for variable name.
 Main2.hx:15: characters 3-31 : "0_forVariableKey" is not a valid for variable name.

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

@@ -69,8 +69,9 @@ class Main {
 		s = s.replace("\r\n", "\n"); // get rid of windows newlines
 		s = s.replace("\r\n", "\n"); // get rid of windows newlines
 
 
 		var cwd = Path.removeTrailingSlashes(FileSystem.fullPath(Sys.getCwd()));
 		var cwd = Path.removeTrailingSlashes(FileSystem.fullPath(Sys.getCwd()));
+		var std = Path.removeTrailingSlashes(getStd());
 
 
-		var context = {cwd: cwd};
+		var context = {cwd: cwd, std: std};
 		var macros = {normPath: normPath};
 		var macros = {normPath: normPath};
 
 
 		return new haxe.Template(s).execute(context, macros);
 		return new haxe.Template(s).execute(context, macros);
@@ -165,4 +166,9 @@ class Main {
 
 
 		return true;
 		return true;
 	}
 	}
+
+	static macro function getStd() {
+		var std = Compiler.getConfiguration().stdPath;
+		return macro $v{std.shift()};
+	}
 }
 }