Selaa lähdekoodia

[diagnostics] Add sub errors as related information (#11078)

* [diagnostics] add depth data and keep order of messages

* [tests] update display tests

* [tests] update misc tests

* [tests] update more display tests

* Send missing depth data

* Use located_error from current context

* [diagnostics] add sub errors as related information

* [tests] update tests

* [tests] update test for 10194

* [diagnostics] don't display non top level diagnostics on their own

* cleanup a bit

* Simplify a bit

* Whitespace and comment
Rudy Ges 2 vuotta sitten
vanhempi
commit
f2b013ef51

+ 5 - 5
src/compiler/compiler.ml

@@ -4,16 +4,16 @@ open CompilationContext
 
 let run_or_diagnose ctx f arg =
 	let com = ctx.com in
-	let handle_diagnostics msg kind =
+	let handle_diagnostics ?(depth = 0) msg kind =
 		ctx.has_error <- true;
-		add_diagnostics_message com msg kind Error;
+		add_diagnostics_message ~depth com msg kind Error;
 		DisplayOutput.emit_diagnostics ctx.com
 	in
 	if is_diagnostics com then begin try
 			f arg
 		with
-		| Error.Error(msg,p,_) ->
-			handle_diagnostics (Error.error_msg p msg) DKCompilerMessage
+		| Error.Error(msg,p,depth) ->
+			handle_diagnostics ~depth (Error.error_msg p msg) DKCompilerMessage
 		| Parser.Error(msg,p) ->
 			handle_diagnostics (located (Parser.error_msg msg) p) DKParserError
 		| Lexer.Error(msg,p) ->
@@ -225,8 +225,8 @@ module Setup = struct
 			| WMDisable ->
 				()
 		);
-		com.error <- error ctx;
 		com.located_error <- located_error ctx;
+		com.error <- (fun ?(depth = 0) msg p -> com.located_error ~depth (located msg p));
 		let filter_messages = (fun keep_errors predicate -> (List.filter (fun cm ->
 			(match cm.cm_severity with
 			| MessageSeverity.Error -> keep_errors;

+ 2 - 2
src/compiler/displayProcessing.ml

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

+ 1 - 1
src/compiler/server.ml

@@ -21,7 +21,7 @@ let check_display_flush ctx f_otherwise = match ctx.com.json_out with
 	| None ->
 		if is_diagnostics ctx.com then begin
 			List.iter (fun cm ->
-				add_diagnostics_message ctx.com (located cm.cm_message cm.cm_pos) cm.cm_kind cm.cm_severity
+				add_diagnostics_message ~depth:cm.cm_depth ctx.com (located cm.cm_message cm.cm_pos) cm.cm_kind cm.cm_severity
 			) (List.rev ctx.messages);
 			raise (Completion (Diagnostics.print ctx.com))
 		end else

+ 6 - 9
src/context/common.ml

@@ -233,7 +233,7 @@ class file_keys = object(self)
 end
 
 type shared_display_information = {
-	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t) list;
+	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t * int (* depth *)) list;
 }
 
 type display_information = {
@@ -1229,23 +1229,20 @@ let utf16_to_utf8 str =
 	loop 0;
 	Buffer.contents b
 
-let add_diagnostics_message com msg kind sev =
+let add_diagnostics_message ?(depth = 0) com msg kind sev =
 	if sev = MessageSeverity.Error then com.has_error <- true;
 	let di = com.shared.shared_display_information in
 	match (extract_located msg) with
 	| [] -> ()
 	| (s,p) :: [] ->
-		di.diagnostics_messages <- (s,p,kind,sev) :: di.diagnostics_messages
+		di.diagnostics_messages <- (s,p,kind,sev,depth) :: di.diagnostics_messages
 	| (s,p) :: stack ->
-		(* TODO send full stack data as diagnostics attribute for better handling by editors *)
-		let s = List.fold_left (fun acc (s,p) ->
-			Printf.sprintf "%s%s\n" acc (Lexer.get_error_pos (Printf.sprintf "%s:%d: ") p)
-		) (s ^ "\n") stack in
-		di.diagnostics_messages <- (s,p,kind,sev) :: di.diagnostics_messages
+		let stack_diag = (List.map (fun (s,p) -> (s,p,kind,sev,depth+1)) (List.rev stack)) in
+		di.diagnostics_messages <- stack_diag @ ((s,p,kind,sev,depth) :: di.diagnostics_messages)
 
 let located_display_error com ?(depth = 0) msg =
 	if is_diagnostics com then
-		add_diagnostics_message com msg MessageKind.DKCompilerMessage MessageSeverity.Error
+		add_diagnostics_message ~depth com msg MessageKind.DKCompilerMessage MessageSeverity.Error
 	else
 		com.located_error msg ~depth
 

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

@@ -143,7 +143,7 @@ let prepare com =
 		unresolved_identifiers = [];
 		missing_fields = PMap.empty;
 	} in
-	if not (List.exists (fun (_,_,_,sev) -> sev = MessageSeverity.Error) com.shared.shared_display_information.diagnostics_messages) then
+	if not (List.exists (fun (_,_,_,sev,_) -> sev = MessageSeverity.Error) com.shared.shared_display_information.diagnostics_messages) then
 		collect_diagnostics dctx com;
 	let process_modules com =
 		List.iter (fun m ->

+ 62 - 21
src/context/display/diagnosticsPrinter.ml

@@ -7,7 +7,21 @@ open Type
 open Genjson
 open MessageKind
 
-(* type t = DiagnosticsKind.t * pos *)
+type t = {
+	diag_kind : MessageKind.t;
+	diag_pos : pos;
+	diag_severity : MessageSeverity.t;
+	diag_args : Json.t;
+	mutable diag_related_information : (pos * int * string) list;
+}
+
+let make_diagnostic kd p sev args = {
+	diag_kind = kd;
+	diag_pos = p;
+	diag_severity = sev;
+	diag_args = args;
+	diag_related_information = [];
+}
 
 let is_diagnostics_file com file_key =
 	match com.report_mode with
@@ -30,18 +44,20 @@ open CompletionItem
 open CompletionModuleType
 
 let json_of_diagnostics com dctx =
-	let diag = Hashtbl.create 0 in
-	let add append dk p sev args =
+	let diagnostics = Hashtbl.create 0 in
+	let current = ref None in
+	let add append diag =
+		let p = diag.diag_pos in
 		let file = if p = null_pos then p.pfile else Path.get_real_path p.pfile in
-		let diag = try
-			Hashtbl.find diag file
+		let fdiag = try
+			Hashtbl.find diagnostics file
 		with Not_found ->
-			let d = Hashtbl.create 0 in
-			Hashtbl.add diag file d;
+			let d = [] in
+			Hashtbl.add diagnostics file d;
 			d
 		in
-		if append || not (Hashtbl.mem diag p) then
-			Hashtbl.add diag p (dk,p,sev,args)
+		if append || (List.find_opt (fun diag -> diag.diag_pos = p) fdiag) = None then
+			Hashtbl.replace diagnostics file (diag :: fdiag)
 	in
 	let file_keys = new Common.file_keys in
 	let add dk p sev args =
@@ -57,7 +73,11 @@ let json_of_diagnostics com dctx =
 			| DKMissingFields ->
 				true
 		in
-		if p = null_pos || is_diagnostics_file com (file_keys#get p.pfile) then add append dk p sev args
+		if p = null_pos || is_diagnostics_file com (file_keys#get p.pfile) then begin
+			let diag = make_diagnostic dk p sev args in
+			current := Some diag;
+			add append diag
+		end else current := None
 	in
 	List.iter (fun (s,p,suggestions) ->
 		let suggestions = ExtList.List.filter_map (fun (s,item,r) ->
@@ -79,8 +99,22 @@ let json_of_diagnostics com dctx =
 		) suggestions in
 		add DKUnresolvedIdentifier p MessageSeverity.Error (JArray suggestions);
 	) dctx.unresolved_identifiers;
-	List.iter (fun (s,p,kind,sev) ->
-		add kind p sev (JString s)
+	List.iter (fun (s,p,kind,sev,depth) -> match (depth, !current) with
+		| d, Some diag when d > 0 ->
+			let lines = ExtString.String.nsplit s "\n" in
+			(match lines with
+				| [] -> ()
+				| s :: sub ->
+					let related = List.fold_left (fun acc s -> (p,d,Error.compl_msg s) :: acc) diag.diag_related_information sub in
+					diag.diag_related_information <- (p,d,s) :: related;
+			)
+		| 0, _ ->
+			add kind p sev (JString s)
+		| _ ->
+			(* Do not add errors with depth greater than one as top level diagnostic. *)
+			(* This could happen when running diagnostics for a file that is wentioned in *)
+			(* sub errors of a file not included for diagnostics. *)
+			()
 	) (List.rev dctx.diagnostics_messages);
 	PMap.iter (fun p (mt,mfl) ->
 		let jctx = create_context GMMinimum in
@@ -171,18 +205,25 @@ let json_of_diagnostics com dctx =
 		) ranges
 	) dctx.dead_blocks;
 	let jl = Hashtbl.fold (fun file diag acc ->
-		let jl = Hashtbl.fold (fun _ (dk,p,sev,jargs) acc ->
+		let jl = List.rev_map (fun diag ->
 			(JObject [
-				"kind",JInt (MessageKind.to_int dk);
-				"severity",JInt (MessageSeverity.to_int sev);
-				"range",Genjson.generate_pos_as_range p;
-				"args",jargs
-			]) :: acc
-		) diag [] in
+				"kind",JInt (MessageKind.to_int diag.diag_kind);
+				"severity",JInt (MessageSeverity.to_int diag.diag_severity);
+				"range",Genjson.generate_pos_as_range diag.diag_pos;
+				"args",diag.diag_args;
+				"relatedInformation",JArray (
+					List.rev_map (fun (pos,depth,msg) -> (JObject [
+						"location",Genjson.generate_pos_as_location pos;
+						"depth",JInt depth;
+						"message",JString msg;
+					])) diag.diag_related_information
+				)
+			])
+		) diag in
 		(JObject [
 			"file",if file = "?" then JNull else JString file;
 			"diagnostics",JArray jl
 		]) :: acc
-	) diag [] in
+	) diagnostics [] in
 	let js = JArray jl in
-	js
+	js

+ 4 - 4
src/context/typecore.ml

@@ -422,8 +422,8 @@ let exc_protect ?(force=true) ctx f (where:string) =
 			r := lazy_available t;
 			t
 		with
-			| Error (m,p,nl) ->
-				raise (Fatal_error ((error_msg p m),nl))
+			| Error (m,p,depth) ->
+				raise (Fatal_error ((error_msg p m),depth))
 	);
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r
@@ -860,8 +860,8 @@ let exc_protect ?(force=true) ctx f (where:string) =
 			r := lazy_available t;
 			t
 		with
-			| Error (m,p) ->
-				raise (Fatal_error ((error_msg m),p))
+			| Error (m,p,depth) ->
+				raise (Fatal_error ((error_msg m),p,depth))
 	));
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r

+ 1 - 1
src/core/displayTypes.ml

@@ -332,7 +332,7 @@ type diagnostics_context = {
 	mutable import_positions : (pos,bool ref) PMap.t;
 	mutable dead_blocks : (Path.UniqueKey.t,(pos * expr) list) Hashtbl.t;
 	mutable unresolved_identifiers : (string * pos * (string * CompletionItem.t * int) list) list;
-	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t) list;
+	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t * int (* depth *)) list;
 	mutable missing_fields : (pos,(module_type * (missing_fields_diagnostics list ref))) PMap.t;
 }
 

+ 4 - 4
src/typing/callUnification.ml

@@ -398,7 +398,7 @@ let unify_field_call ctx fa el_typed el p inline =
 					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;
-				typing_error "End of overload failure reasons" p
+				typing_error ~depth:1 "End of overload failure reasons" p
 			end
 		in
 		if overload_kind = OverloadProper then begin match Overloads.Resolution.reduce_compatible candidates with
@@ -477,16 +477,16 @@ object(self)
 		ctx.macro_depth <- ctx.macro_depth - 1;
 		ctx.with_type_stack <- List.tl ctx.with_type_stack;
 		let old = ctx.com.located_error in
-		ctx.com.located_error <- (fun ?(depth=0) msg ->
+		ctx.com.located_error <- (fun ?(depth = 0) msg ->
 			let ep = extract_located_pos msg in
 			(* 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
 				locate_macro_error := false;
-				old (if ep = null_pos then (relocate msg p) else msg);
+				old ~depth (if ep = null_pos then (relocate msg p) else msg);
 				locate_macro_error := true;
 				if ep <> null_pos then old ~depth:(depth+1) (located (compl_msg "Called from macro here") p);
 			end else
-				old msg;
+				old ~depth msg;
 		);
 		let e = try
 			f()

+ 2 - 2
src/typing/macroContext.ml

@@ -537,10 +537,10 @@ let create_macro_interp ctx mctx =
 			mint, (fun() -> ())
 	) in
 	let on_error = com2.located_error in
-	com2.located_error <- (fun ?depth msg ->
+	com2.located_error <- (fun ?(depth = 0) msg ->
 		Interp.set_error (Interp.get_ctx()) true;
 		macro_interp_cache := None;
-		on_error msg
+		on_error ~depth msg
 	);
 	let macro = ((fun() -> Interp.select mint), mctx) in
 	ctx.g.macros <- Some macro;

+ 4 - 4
src/typing/operators.ml

@@ -9,11 +9,11 @@ open Calls
 open Fields
 open FieldAccess
 
-let check_error ctx err p = match err with
+let check_error ctx err p depth = match err with
 	| Module_not_found ([],name) when Diagnostics.error_in_diagnostics_run ctx.com p ->
 		DisplayToplevel.handle_unresolved_identifier ctx name p true
 	| _ ->
-		Common.located_display_error ctx.com (error_msg p err)
+		Common.located_display_error ~depth ctx.com (error_msg p err)
 
 module BinopResult = struct
 
@@ -555,8 +555,8 @@ let type_assign ctx e1 e2 with_type p =
 	let e1 = !type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type in
 	let type_rhs with_type = try
 		type_expr ctx e2 with_type
-	with Error(e,p,_) ->
-		check_error ctx e p;
+	with Error(e,p,depth) ->
+		check_error ctx e p depth;
 		Texpr.Builder.make_null t_dynamic (pos e2)
 	in
 	let assign_to e1 =

+ 2 - 2
src/typing/typeload.ml

@@ -286,9 +286,9 @@ let check_param_constraints ctx t map c p =
 			let ti = map ti in
 			try
 				unify_raise t ti p
-			with Error(Unify l,p,n) ->
+			with Error(Unify l,p,depth) ->
 				let fail() =
-					if not ctx.untyped then located_display_error ctx.com (error_msg p (Unify (Constraint_failure (s_type_path c.cl_path) :: l)));
+					if not ctx.untyped then located_display_error ~depth ctx.com (error_msg p (Unify (Constraint_failure (s_type_path c.cl_path) :: l)));
 				in
 				match follow t with
 				| TInst({cl_kind = KExpr e},_) ->

+ 7 - 7
src/typing/typer.ml

@@ -711,8 +711,8 @@ and type_vars ctx vl p =
 				DisplayEmitter.display_variable ctx v pv;
 			v,e
 		with
-			Error (e,p,_) ->
-				check_error ctx e p;
+			Error (e,p,depth) ->
+				check_error ctx e p depth;
 				add_local ctx VGenerated n t_dynamic pv, None (* TODO: What to do with this... *)
 	) vl in
 	List.iter (fun (v,_) ->
@@ -838,7 +838,7 @@ and type_block ctx el with_type p =
 	let rec loop acc = function
 		| [] -> List.rev acc
 		| 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,depth) -> check_error ctx e p depth; acc in
 			loop acc l
 	in
 	let l = loop [] el in
@@ -1584,8 +1584,8 @@ and type_return ?(implicit=false) ctx e with_type p =
 					]) t e.epos;
 				| _ ->
 					mk (TReturn (Some e)) (mono_or_dynamic ctx with_type p) p
-		with Error(err,p,_) ->
-			check_error ctx err p;
+		with Error(err,p,depth) ->
+			check_error ctx err p depth;
 			(* 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). *)
 			let e_null = mk (TConst TNull) (mk_mono()) p in
@@ -2011,8 +2011,8 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 	| EThrow e ->
 		let e = try
 			type_expr ctx e WithType.value
-		with Error(e,p',_) ->
-			check_error ctx e p';
+		with Error(e,p',depth) ->
+			check_error ctx e p' depth;
 			Texpr.Builder.make_null t_dynamic p
 		in
 		mk (TThrow e) (mono_or_dynamic ctx with_type p) p

+ 8 - 0
tests/display/src/Diagnostic.hx

@@ -1,4 +1,5 @@
 // from vshaxe
+import haxe.display.Position.Location;
 import haxe.display.Position.Range;
 import haxe.display.JsonModuleTypes;
 
@@ -66,4 +67,11 @@ typedef Diagnostic<T> = {
 	var range:Range;
 	var severity:DiagnosticSeverity;
 	var args:T;
+	var relatedInformation:Array<DiagnosticRelatedInformation>;
+}
+
+typedef DiagnosticRelatedInformation = {
+	var location:Location;
+	var message:String;
+	var depth:Int;
 }

+ 1 - 0
tests/display/src/cases/Issue10194.hx

@@ -15,6 +15,7 @@ class Issue10194 extends DisplayTestCase {
 				kind: DKCompilerError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "String should be Int\nFor function argument 'a'"
 			}
 		], diagnostics());

+ 8 - 6
tests/display/src/cases/Issue5306.hx

@@ -20,17 +20,19 @@ class Issue5306 extends DisplayTestCase {
 			// 	severity: Warning,
 			// 	args: []
 			// },
-			{
-				kind: DKCompilerError,
-				range: diagnosticsRange(pos(3), pos(4)),
-				severity: Error,
-				args: "Type not found : InvalidType"
-			},
 			{
 				kind: DKParserError,
 				range: diagnosticsRange(pos(5), pos(6)),
 				severity: Error,
+				relatedInformation: [],
 				args: "Missing ;"
+			},
+			{
+				kind: DKCompilerError,
+				range: diagnosticsRange(pos(3), pos(4)),
+				severity: Error,
+				relatedInformation: [],
+				args: "Type not found : InvalidType"
 			}
 		];
 		arrayEq(expected, diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7777.hx

@@ -19,6 +19,7 @@ class Issue7777 extends DisplayTestCase {
 				kind: DKUnusedImport,
 				severity: Warning,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: []
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7932.hx

@@ -12,6 +12,7 @@ class Issue7932 extends DisplayTestCase {
 				kind: DKParserError,
 				range: diagnosticsRange(pos(1), pos(2)),
 				severity: Error,
+				relatedInformation: [],
 				args: "Expected type parameter"
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7935.hx

@@ -40,6 +40,7 @@ class Issue7935 extends DisplayTestCase {
 				kind: DKParserError,
 				range: diagnosticsRange(pos(1), pos(2)),
 				severity: Error,
+				relatedInformation: [],
 				args: message
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7938.hx

@@ -12,6 +12,7 @@ class Issue7938 extends DisplayTestCase {
 				kind: DKParserError,
 				range: diagnosticsRange(pos(1), pos(2)),
 				severity: Error,
+				relatedInformation: [],
 				args: "Unexpected fuction"
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7939.hx

@@ -10,6 +10,7 @@ class Issue7939 extends DisplayTestCase {
 				kind: DKParserError,
 				range: diagnosticsRange(pos(1), pos(2)),
 				severity: Error,
+				relatedInformation: [],
 				args: "Unexpected {"
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7940.hx

@@ -14,6 +14,7 @@ class Issue7940 extends DisplayTestCase {
 				kind: DKParserError,
 				range: diagnosticsRange(pos(1), pos(1)),
 				severity: Error,
+				relatedInformation: [],
 				args: "Unterminated string"
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7943.hx

@@ -14,6 +14,7 @@ class Issue7943 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(3), pos(4)),
+				relatedInformation: [],
 				args: "Missing ;"
 			}
 		], diagnostics());

+ 1 - 0
tests/display/src/cases/Issue7944.hx

@@ -14,6 +14,7 @@ class Issue7944 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Unexpected fun"
 			}
 		], diagnostics());

+ 2 - 0
tests/display/src/cases/Issue7945.hx

@@ -10,6 +10,7 @@ class Issue7945 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Expected { or to or from"
 			}
 		], diagnostics());
@@ -24,6 +25,7 @@ class Issue7945 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Expected extends or implements or {"
 			}
 		], diagnostics());

+ 2 - 0
tests/display/src/cases/Issue7946.hx

@@ -10,6 +10,7 @@ class Issue7946 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Unexpected open"
 			}
 		], diagnostics());
@@ -24,6 +25,7 @@ class Issue7946 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Unexpected clas"
 			}
 		], diagnostics());

+ 2 - 0
tests/display/src/cases/Issue7947.hx

@@ -22,6 +22,7 @@ class Issue7947 extends DisplayTestCase {
 				kind: DKCompilerError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Void should be Bool"
 			}
 		], diagnostics());
@@ -48,6 +49,7 @@ class Issue7947 extends DisplayTestCase {
 				kind: DKCompilerError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Bool should be Void"
 			}
 		], diagnostics());

+ 2 - 0
tests/display/src/cases/Issue7948.hx

@@ -14,6 +14,7 @@ class Issue7948 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: 'Unexpected keyword "class"'
 			}
 		], diagnostics());
@@ -32,6 +33,7 @@ class Issue7948 extends DisplayTestCase {
 				kind: DKParserError,
 				severity: Error,
 				range: diagnosticsRange(pos(1), pos(2)),
+				relatedInformation: [],
 				args: "Unexpected }"
 			}
 		], diagnostics());

+ 1 - 1
tests/misc/projects/Issue11020/compile.hxml.stderr

@@ -1 +1 @@
-[{"file":"$$normPath(::cwd::/,true)Main.hx","diagnostics":[{"kind":2,"severity":3,"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":19}},"args":"Context.info"},{"kind":2,"severity":2,"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":19}},"args":"Context.warning"},{"kind":2,"severity":1,"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":19}},"args":"Context.error"},{"kind":2,"severity":1,"range":{"start":{"line":0,"character":11},"end":{"line":0,"character":18}},"args":"Build failure"}]}]
+[{"file":"$$normPath(::cwd::/,true)Main.hx","diagnostics":[{"kind":2,"severity":3,"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":19}},"args":"Context.info","relatedInformation":[]},{"kind":2,"severity":2,"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":19}},"args":"Context.warning","relatedInformation":[]},{"kind":2,"severity":1,"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":19}},"args":"Context.error","relatedInformation":[]},{"kind":2,"severity":1,"range":{"start":{"line":0,"character":11},"end":{"line":0,"character":18}},"args":"Build failure","relatedInformation":[]}]}]

+ 1 - 1
tests/misc/projects/Issue6794/compile.hxml.stderr

@@ -1 +1 @@
-[{"file":"$$normPath(::cwd::/,true)Main.hx","diagnostics":[{"kind":2,"severity":2,"range":{"start":{"line":13,"character":42},"end":{"line":13,"character":43}},"args":"foo"}]}]
+[{"file":"$$normPath(::cwd::/,true)Main.hx","diagnostics":[{"kind":2,"severity":2,"range":{"start":{"line":13,"character":42},"end":{"line":13,"character":43}},"args":"foo","relatedInformation":[]}]}]

+ 1 - 1
tests/misc/projects/Issue9676/compile1D.hxml.stderr

@@ -1 +1 @@
-[{"file":"$$normPath(::cwd::/,true)MainField.hx","diagnostics":[{"kind":4,"severity":1,"range":{"start":{"line":1,"character":8},"end":{"line":1,"character":17}},"args":"`final var` is not supported, use `final` instead"}]}]
+[{"file":"$$normPath(::cwd::/,true)MainField.hx","diagnostics":[{"kind":4,"severity":1,"range":{"start":{"line":1,"character":8},"end":{"line":1,"character":17}},"args":"`final var` is not supported, use `final` instead","relatedInformation":[]}]}]

+ 1 - 1
tests/misc/projects/Issue9676/compile2D.hxml.stderr

@@ -1 +1 @@
-[{"file":"$$normPath(::cwd::/,true)MainExpr.hx","diagnostics":[{"kind":4,"severity":1,"range":{"start":{"line":1,"character":1},"end":{"line":1,"character":10}},"args":"`final var` is not supported, use `final` instead"}]}]
+[{"file":"$$normPath(::cwd::/,true)MainExpr.hx","diagnostics":[{"kind":4,"severity":1,"range":{"start":{"line":1,"character":1},"end":{"line":1,"character":10}},"args":"`final var` is not supported, use `final` instead","relatedInformation":[]}]}]

+ 1 - 1
tests/misc/projects/Issue9676/compile3D.hxml.stderr

@@ -1 +1 @@
-[{"file":"$$normPath(::cwd::/,true)MainMacro.hx","diagnostics":[{"kind":4,"severity":1,"range":{"start":{"line":1,"character":7},"end":{"line":1,"character":16}},"args":"`final var` is not supported, use `final` instead"}]}]
+[{"file":"$$normPath(::cwd::/,true)MainMacro.hx","diagnostics":[{"kind":4,"severity":1,"range":{"start":{"line":1,"character":7},"end":{"line":1,"character":16}},"args":"`final var` is not supported, use `final` instead","relatedInformation":[]}]}]