Bläddra i källkod

[display] merge fixes from display branch

closes #7046
closes #7047
closes #7049
closes #7052
closes #7055
Simon Krajewski 7 år sedan
förälder
incheckning
f257a98675

+ 15 - 1
src/compiler/displayOutput.ml

@@ -1,14 +1,17 @@
 open Globals
+open Ast
 open Common
 open Common.CompilationServer
 open Timer
 open DisplayTypes.DisplayMode
+open DisplayTypes.CompletionResultKind
 open CompletionItem
 open DisplayException
 open Type
 open Display
 open DisplayTypes
 open Typecore
+open Genjson
 
 (* Old XML stuff *)
 
@@ -646,4 +649,15 @@ let find_doc t =
 		| _ ->
 			None
 	in
-	doc
+	doc
+
+let handle_syntax_completion com kind p = match com.json_out with
+	| None ->
+		(* Not supported *)
+		()
+	| Some(f,_) ->
+		match kind with
+		| Parser.SCClassHerit ->
+			let l = [ITKeyword Extends;ITKeyword Implements] in
+			let ctx = Genjson.create_context GMFull in
+			f(fields_to_json ctx l CRClassHerit None false)

+ 6 - 2
src/compiler/main.ml

@@ -975,11 +975,13 @@ with
 			| CRImport
 			| CRUsing
 			| CRNew
-			| CRPattern ->
+			| CRPattern
+			| CRClassHerit ->
 				DisplayOutput.print_toplevel fields
 			| CRField
 			| CRStructureField
-			| CRMetadata ->
+			| CRMetadata
+			| CROverride ->
 				DisplayOutput.print_fields fields
 		in
 		raise (DisplayOutput.Completion s)
@@ -1014,6 +1016,8 @@ with
 			| _ -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))
 			end
 		end
+	| Parser.SyntaxCompletion(kind,pos) ->
+		DisplayOutput.handle_syntax_completion com kind pos
 	| DisplayException(ModuleSymbols s | Diagnostics s | Statistics s | Metadata s) ->
 		raise (DisplayOutput.Completion s)
 	| EvalExceptions.Sys_exit i | Hlinterp.Sys_exit i ->

+ 18 - 1
src/context/display/displayEmitter.ml

@@ -120,4 +120,21 @@ let check_display_metadata ctx meta =
 				delay ctx PTypeField (fun _ -> ignore(type_expr ctx e Value));
 			end
 		) args
-	) meta
+	) meta
+
+let check_field_modifiers ctx c cf override display_modifier =
+	match override,display_modifier with
+		| Some p,_ when Display.is_display_position p && ctx.com.display.dms_kind = DMDefinition ->
+			begin match c.cl_super with
+			| Some(c,tl) ->
+				let _,_,cf = raw_class_field (fun cf -> cf.cf_type) c tl cf.cf_name in
+				display_field ctx (Some c) cf p
+			| _ ->
+				()
+			end
+		| _,Some (AOverride,p) when ctx.com.display.dms_kind = DMDefault ->
+			let all_fields = TClass.get_all_super_fields c in
+			let missing_fields = List.fold_left (fun fields cf -> PMap.remove cf.cf_name fields) all_fields c.cl_ordered_fields in
+			let l = PMap.fold (fun cf fields -> (ITClassField(cf,CFSMember)) :: fields) missing_fields [] in
+			raise_fields l CROverride None false
+		| _ -> ()

+ 11 - 8
src/context/display/displayException.ml

@@ -31,6 +31,16 @@ let raise_package sl = raise (DisplayException(DisplayPackage sl))
 (* global state *)
 let last_completion_result = ref (Array.make 0 (ITModule ""))
 
+let fields_to_json ctx fields kind po sorted =
+	let ja = List.map (CompletionItem.to_json ctx) fields in
+	last_completion_result := Array.of_list fields;
+	let fl =
+		("items",jarray ja) ::
+		("kind",jint (Obj.magic kind)) ::
+		("sorted",jbool sorted) ::
+		(match po with None -> [] | Some p -> ["replaceRange",generate_pos_as_range p]) in
+	jobject fl
+
 let to_json ctx de =
 	match de with
 	| Diagnostics _
@@ -59,13 +69,6 @@ let to_json ctx de =
 	| DisplayPosition pl ->
 		jarray (List.map generate_pos_as_location pl)
 	| DisplayFields(fields,kind,po,sorted) ->
-		let ja = List.map (CompletionItem.to_json ctx) fields in
-		last_completion_result := Array.of_list fields;
-		let fl =
-			("items",jarray ja) ::
-			("kind",jint (Obj.magic kind)) ::
-			("sorted",jbool sorted) ::
-			(match po with None -> [] | Some p -> ["replaceRange",generate_pos_as_range p]) in
-		jobject fl
+		fields_to_json ctx fields kind po sorted
 	| DisplayPackage pack ->
 		jarray (List.map jstring pack)

+ 6 - 1
src/context/display/displayToplevel.ml

@@ -321,7 +321,12 @@ let collect ctx only_types with_type =
 					| _ ->
 						6 (* incompatible type - probably useless *)
 			in
-			let l = List.map (fun ck -> ck,(comp (get_type ck),get_name ck)) l in
+			let l = List.map (fun ck ->
+				let s1 = comp (get_type ck) in
+				let s2 = get_sort_index ck in
+				let s3 = get_name ck in
+				ck,(s1,s2,s3)
+			) l in
 			let l = List.sort (fun (_,i1) (_,i2) -> compare i1 i2) l in
 			List.map fst l
 		| _ -> l

+ 26 - 0
src/core/display/completionItem.ml

@@ -194,6 +194,32 @@ type t =
 	| ITMetadata of string * documentation
 	| ITKeyword of keyword
 
+let get_index = function
+	| ITLocal _ -> 0
+	| ITClassField _ -> 1
+	| ITEnumField _ -> 2
+	| ITEnumAbstractField _ -> 3
+	| ITType _ -> 4
+	| ITPackage _ -> 5
+	| ITModule _ -> 6
+	| ITLiteral _ -> 7
+	| ITTimer _ -> 8
+	| ITMetadata _ -> 9
+	| ITKeyword _ -> 10
+
+let get_sort_index = function
+	| ITLocal _ -> 0
+	| ITClassField _ -> 0
+	| ITEnumField(_,ef) -> ef.ef_index
+	| ITEnumAbstractField _ -> 0
+	| ITType _ -> 0
+	| ITPackage _ -> 0
+	| ITModule _ -> 0
+	| ITLiteral _ -> 0
+	| ITTimer _ -> 0
+	| ITMetadata _ -> 0
+	| ITKeyword _ -> 0
+
 let legacy_sort = function
 	| ITClassField(cf,_) | ITEnumAbstractField(_,cf) ->
 		begin match cf.cf_kind with

+ 2 - 0
src/core/displayTypes.ml

@@ -77,6 +77,8 @@ module CompletionResultKind = struct
 		| CRUsing
 		| CRNew
 		| CRPattern
+		| CROverride
+		| CRClassHerit
 end
 
 module DisplayMode = struct

+ 2 - 2
src/core/json/genjson.ml

@@ -159,9 +159,9 @@ let rec generate_type ctx t =
 			| Some t -> loop t
 			end
 		| TLazy f ->
-			return_partial_type := true;
+			(* return_partial_type := true; *)
 			let t = lazy_type f in
-			return_partial_type := false;
+			(* return_partial_type := false; *)
 			loop t
 		| TDynamic t -> "TDynamic",Some (if t == t_dynamic then jnull else generate_type ctx t)
 		| TInst(c,tl) -> "TInst",Some (generate_path_with_params ctx c.cl_path tl)

+ 18 - 1
src/core/type.ml

@@ -2757,4 +2757,21 @@ let abstract_module_type a tl = {
 	t_private = true;
 	t_params = [];
 	t_meta = no_meta;
-}
+}
+
+module TClass = struct
+	let get_all_super_fields c =
+		let rec loop acc c tl =
+			let maybe_add acc cf = match cf.cf_kind with
+				| Method MethNormal when not (PMap.mem cf.cf_name acc) -> PMap.add cf.cf_name cf acc
+				| _ -> acc
+			in
+			let acc = List.fold_left maybe_add acc c.cl_ordered_fields in
+			match c.cl_super with
+			| Some(c,tl) -> loop acc c tl
+			| None -> acc
+		in
+		match c.cl_super with
+			| Some(c,tl) -> loop PMap.empty c tl
+			| None -> PMap.empty
+end

+ 62 - 14
src/syntax/grammar.mly

@@ -157,8 +157,28 @@ and parse_type_decl s =
 					d_data = l
 				}, punion p1 p2)
 			end
-		| [< n , p1 = parse_class_flags; name = type_name; tl = parse_constraint_params; hl = plist parse_class_herit; >] ->
-			expect_unless_resume bropen s;
+		| [< n , p1 = parse_class_flags; name = type_name; tl = parse_constraint_params >] ->
+			let rec loop had_display p0 acc = match s with parser
+				| [< '(Kwd Extends,p1); t,b = parse_type_path_or_resume p1 >] ->
+					if not had_display && encloses_resume {p1 with pmin = p0.pmax; pmax = p1.pmin} then
+						syntax_completion SCClassHerit p0;
+					loop (had_display || b) (pos t) ((HExtends t) :: acc)
+				| [< '(Kwd Implements,p1); t,b = parse_type_path_or_resume p1 >] ->
+					if not had_display && encloses_resume {p1 with pmin = p0.pmax; pmax = p1.pmin} then
+						syntax_completion SCClassHerit p0;
+					loop (had_display || b) (pos t) ((HImplements t) :: acc)
+				| [< '(BrOpen,p1) >] ->
+					if not had_display && encloses_resume {p1 with pmin = p0.pmax; pmax = p1.pmin} then
+						syntax_completion SCClassHerit p0;
+					List.rev acc
+				| [< >] ->
+					if not (do_resume()) then serror() else begin
+						if not had_display && encloses_resume {p1 with pmin = p0.pmax; pmax = (next_pos s).pmax} then
+							syntax_completion SCClassHerit p0;
+						List.rev acc
+					end
+			in
+			let hl = loop false (last_pos s) [] in
 			let fl, p2 = parse_class_fields false p1 s in
 			(EClass {
 				d_name = name;
@@ -540,18 +560,34 @@ and parse_type_path_or_const = parser
 	| [< e = expr >] -> TPExpr e
 	| [< >] -> serror()
 
-and parse_complex_type_next (t : type_hint) = parser
-	| [< '(Arrow,_); t2,p2 = parse_complex_type >] ->
-		(match t2 with
+and parse_complex_type_next (t : type_hint) s =
+	let make_fun t2 p2 = match t2 with
 		| CTFunction (args,r) ->
 			CTFunction (t :: args,r),punion (pos t) p2
 		| _ ->
-			CTFunction ([t] , (t2,p2)),punion (pos t) p2)
+			CTFunction ([t] , (t2,p2)),punion (pos t) p2
+	in
+	match s with parser
+	| [< '(Arrow,pa); s >] ->
+		begin match s with parser
+		| [< t2,p2 = parse_complex_type >] -> make_fun t2 p2
+		| [< >] ->
+			if would_skip_resume pa s then begin
+				let ct = CTPath magic_type_path in
+				make_fun ct null_pos
+			end else serror()
+		end
 	| [< >] -> t
 
 and parse_function_type_next tl p1 = parser
-	| [< '(Arrow,_); tret = parse_complex_type_inner false >] ->
-		CTFunction (tl,tret), punion p1 (snd tret)
+	| [< '(Arrow,pa); s >] ->
+		begin match s with parser
+		| [< tret = parse_complex_type_inner false >] -> CTFunction (tl,tret), punion p1 (snd tret)
+		| [< >] -> if would_skip_resume pa s then begin
+				let ct = (CTPath magic_type_path),null_pos in
+				CTFunction (tl,ct), punion p1 pa
+			end else serror()
+		end
 	| [< >] -> serror ()
 
 and parse_type_anonymous opt = parser
@@ -656,7 +692,19 @@ and parse_class_field s =
 		| [< f = parse_function_field doc meta al >] ->
 			f
 		| [< >] ->
-			if al = [] then raise Stream.Failure else serror()
+			begin match List.rev al with
+				| [] -> raise Stream.Failure
+				| (AOverride,po) :: _ when would_skip_resume po s ->
+					let f = {
+						f_params = [];
+						f_args = [];
+						f_type = None;
+						f_expr = None
+					} in
+					let _,p2 = next_token s in
+					(magic_display_field_name,p2),punion po p2,FFun f,al
+				| _ -> serror()
+			end
 		) in
 		let pos = match al with
 			| [] -> pos
@@ -724,12 +772,12 @@ and parse_constraint_param = parser
 		}
 
 and parse_type_path_or_resume p1 s = match s with parser
-	| [< t = parse_type_path >] -> t
-	| [< >] -> if would_skip_resume p1 s then { tpackage = []; tname = ""; tparams = []; tsub = None },punion_next p1 s else raise Stream.Failure
+	| [< t = parse_type_path >] -> t,false
+	| [< >] -> if would_skip_resume p1 s then (magic_type_path,punion_next p1 s),true else raise Stream.Failure
 
 and parse_class_herit = parser
-	| [< '(Kwd Extends,p1); t = parse_type_path_or_resume p1 >] -> HExtends t
-	| [< '(Kwd Implements,p1); t = parse_type_path_or_resume p1 >] -> HImplements t
+	| [< '(Kwd Extends,p1); t,_ = parse_type_path_or_resume p1 >] -> HExtends t
+	| [< '(Kwd Implements,p1); t,_ = parse_type_path_or_resume p1 >] -> HImplements t
 
 and block1 = parser
 	| [< name,p = dollar_ident; s >] -> block2 (name,p,NoQuotes) (Ident name) p s
@@ -1005,7 +1053,7 @@ and expr = parser
 			| [< >] -> serror())
 		| [< e = secure_expr >] -> expr_next (ECast (e,None),punion p1 (pos e)) s)
 	| [< '(Kwd Throw,p); e = expr >] -> (EThrow e,p)
-	| [< '(Kwd New,p1); t = parse_type_path_or_resume p1; s >] ->
+	| [< '(Kwd New,p1); t,_ = parse_type_path_or_resume p1; s >] ->
 		begin match s with parser
 		| [< '(POpen,po); e = parse_call_params (fun el p2 -> (ENew(t,el)),punion p1 p2) po >] -> expr_next e s
 		| [< >] ->

+ 12 - 0
src/syntax/parser.ml

@@ -31,9 +31,13 @@ type error_msg =
 	| Missing_type
 	| Custom of string
 
+type syntax_completion =
+	| SCClassHerit
+
 exception Error of error_msg * pos
 exception TypePath of string list * (string * bool) option * bool (* in import *)
 exception Display of expr
+exception SyntaxCompletion of syntax_completion * pos
 
 let error_msg = function
 	| Unexpected t -> "Unexpected "^(s_token t)
@@ -44,6 +48,9 @@ let error_msg = function
 	| Missing_type -> "Missing type declaration"
 	| Custom s -> s
 
+let syntax_completion kind p =
+	raise (SyntaxCompletion(kind,p))
+
 let error m p = raise (Error (m,p))
 let display_error : (error_msg -> pos -> unit) ref = ref (fun _ _ -> assert false)
 
@@ -96,6 +103,8 @@ let last_token s =
 	let n = Stream.count s in
 	TokenCache.get (if n = 0 then 0 else n - 1)
 
+let last_pos s = pos (last_token s)
+
 let get_doc s =
 	(* do the peek first to make sure we fetch the doc *)
 	match Stream.peek s with
@@ -113,6 +122,9 @@ let do_resume() = !resume_display <> null_pos
 
 let display e = raise (Display e)
 
+let magic_display_field_name = " - display - "
+let magic_type_path = { tpackage = []; tname = ""; tparams = []; tsub = None }
+
 let type_path sl in_import = match sl with
 	| n :: l when n.[0] >= 'A' && n.[0] <= 'Z' -> raise (TypePath (List.rev l,Some (n,false),in_import));
 	| _ -> raise (TypePath (List.rev sl,None,in_import))

+ 49 - 24
src/typing/typeload.ml

@@ -36,28 +36,46 @@ let build_count = ref 0
 
 let type_function_params_rec = ref (fun _ _ _ _ -> assert false)
 
-let check_field_access ctx acc =
-	ignore(List.fold_left (fun acc (access,p1) ->
-		try
-			let _,p2 = List.find (fun (access',_) -> access = access') acc in
-			if p1 <> null_pos && p2 <> null_pos then begin
-				display_error ctx (Printf.sprintf "Duplicate access modifier %s" (Ast.s_access access)) p1;
-				display_error ctx "Previously defined here" p2;
-			end;
-			acc
-		with Not_found -> match access with
-			| APublic | APrivate ->
-				begin try
-					let _,p2 = List.find (fun (access',_) -> match access' with APublic | APrivate -> true | _ -> false) acc in
-					display_error ctx (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
-					display_error ctx "Conflicts with this" p2;
-					acc
-				with Not_found ->
-					(access,p1) :: acc
-				end
-			| _ ->
-				(access,p1) :: acc
-	) [] acc)
+let check_field_access ctx cff =
+	let display_access = ref None in
+	let rec loop p0 acc l =
+		let check_display p1 =
+			let pmid = {p0 with pmin = p0.pmax; pmax = p1.pmin} in
+			if Display.is_display_position pmid then match acc with
+			| access :: _ -> display_access := Some access;
+			| [] -> ()
+		in
+		match l with
+		| [] ->
+			(* This is a bit dodgy. Ideally we would use the position of the `function` keyword, but we don't have that...
+			   Using the name means this is going to complete within the `function` keyword too. Not sure what we
+			   can do about it. *)
+			check_display (pos (cff.cff_name))
+		| (access,p1) :: l ->
+			check_display p1;
+			try
+				let _,p2 = List.find (fun (access',_) -> access = access') acc in
+				if p1 <> null_pos && p2 <> null_pos then begin
+					display_error ctx (Printf.sprintf "Duplicate access modifier %s" (Ast.s_access access)) p1;
+					display_error ctx "Previously defined here" p2;
+				end;
+				loop p1 acc l
+			with Not_found -> match access with
+				| APublic | APrivate ->
+					begin try
+						let _,p2 = List.find (fun (access',_) -> match access' with APublic | APrivate -> true | _ -> false) acc in
+						display_error ctx (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
+						display_error ctx "Conflicts with this" p2;
+						loop p1 acc l
+					with Not_found ->
+						loop p1 ((access,p1) :: acc) l
+					end
+				| _ ->
+					loop p1 ((access,p1) :: acc) l
+	in
+	let pmin = {cff.cff_pos with pmax = cff.cff_pos.pmin} in
+	loop pmin [] cff.cff_access;
+	!display_access
 
 (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **)
 
@@ -391,7 +409,7 @@ and load_complex_type ctx allow_display p (t,pn) =
 			let dyn = ref false in
 			let params = ref [] in
 			let final = ref false in
-			check_field_access ctx f.cff_access;
+			ignore(check_field_access ctx f); (* TODO: do we want to do anything with this? *)
 			List.iter (fun a ->
 				match fst a with
 				| APublic -> ()
@@ -758,8 +776,15 @@ let handle_path_display ctx path p =
 			let mt = ctx.g.do_load_module ctx (sl,s) p in
 			let p = { pfile = mt.m_extra.m_file; pmin = 0; pmax = 0} in
 			DisplayException.raise_position [p]
+		| (IDKModule(sl,s),_),DMHover ->
+			let m = ctx.g.do_load_module ctx (sl,s) p in
+			begin try
+				let mt = List.find (fun mt -> snd (t_infos mt).mt_path = s) m.m_types in
+				DisplayEmitter.display_module_type ctx mt p;
+			with Not_found ->
+				()
+			end
 		| (IDKModule(sl,s),_),_ ->
-			(* TODO: wait till nadako requests @type display for these, then implement it somehow *)
 			raise (Parser.TypePath(sl,Some(s,false),true))
 		| (IDKSubType(sl,sm,st),p),DMDefinition ->
 			resolve_position_by_path ctx { tpackage = sl; tname = sm; tparams = []; tsub = Some st} p

+ 4 - 12
src/typing/typeloadFields.ml

@@ -59,6 +59,7 @@ type field_init_ctx = {
 	is_display_field : bool;
 	is_field_debug : bool;
 	field_kind : field_kind;
+	display_modifier : placed_access option;
 	mutable do_bind : bool;
 	mutable do_add : bool;
 	(* If true, cf_expr = None makes a difference in the logic. We insert a dummy expression in
@@ -413,7 +414,7 @@ let create_field_context (ctx,cctx) c cff =
 		ctx with
 		pass = PBuildClass; (* will be set later to PTypeExpr *)
 	} in
-	Typeload.check_field_access ctx cff.cff_access;
+	let display_modifier = Typeload.check_field_access ctx cff in
 	let is_static = List.mem_assoc AStatic cff.cff_access in
 	let is_extern = List.mem_assoc AExtern cff.cff_access in
 	let is_extern = if Meta.has Meta.Extern cff.cff_meta then begin
@@ -444,6 +445,7 @@ let create_field_context (ctx,cctx) c cff =
 		is_final = List.mem_assoc AFinal cff.cff_access;
 		is_display_field = ctx.is_display_file && Display.is_display_position cff.cff_pos;
 		is_field_debug = cctx.is_class_debug;
+		display_modifier = display_modifier;
 		is_abstract_member = cctx.abstract <> None && Meta.has Meta.Impl cff.cff_meta;
 		field_kind = field_kind;
 		do_bind = (((not c.cl_extern || is_inline) && not c.cl_interface) || field_kind = FKInit);
@@ -973,17 +975,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
 					cf.cf_expr <- None;
 					cf.cf_type <- t
 				| _ ->
-					if ctx.is_display_file && ctx.com.display.dms_kind = DMDefinition then begin match fctx.override with
-						| Some p when Display.is_display_position p ->
-							begin match c.cl_super with
-							| Some(c,tl) ->
-								let _,_,cf = raw_class_field (fun cf -> cf.cf_type) c tl cf.cf_name in
-								DisplayEmitter.display_field ctx (Some c) cf p
-							| _ ->
-								()
-							end
-						| _ -> ()
-					end;
+					if ctx.is_display_file then DisplayEmitter.check_field_modifiers ctx c cf fctx.override fctx.display_modifier;
 					let e , fargs = TypeloadFunction.type_function ctx args ret fmode fd fctx.is_display_field p in
 					begin match fctx.field_kind with
 					| FKNormal when not fctx.is_static -> TypeloadCheck.check_overriding ctx c cf

+ 1 - 1
src/typing/typeloadModule.ml

@@ -383,7 +383,7 @@ let init_module_type ctx context_init do_init (decl,p) =
 				(* create a temp private typedef, does not register it in module *)
 				let mt = TTypeDecl {
 					t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name);
-					t_module = md;
+					t_module = ctx.m.curmod;
 					t_pos = p;
 					t_name_pos = p;
 					t_private = true;

+ 2 - 1
tests/display/build.hxml

@@ -1,4 +1,5 @@
 -p src
 --main Main
 --interp
--D use-rtti-doc
+-D use-rtti-doc
+#-D test=Issue7046

+ 12 - 0
tests/display/src/cases/Issue7046.hx

@@ -0,0 +1,12 @@
+package cases;
+
+class Issue7046 extends DisplayTestCase {
+	/**
+	import Ar{-1-}ray;
+	using Ar{-2-}ray;
+	**/
+	function test() {
+		eq("Array<Array.T>", type(pos(1)));
+		eq("Array<Array.T>", type(pos(2)));
+	}
+}

+ 14 - 0
tests/display/src/cases/Issue7047.hx

@@ -0,0 +1,14 @@
+package cases;
+
+class Issue7047 extends DisplayTestCase {
+	/**
+	class Main {
+		var f:Void->{-1-}
+
+		static function main() {}
+	}
+	**/
+	function test() {
+		eq(true, hasToplevel(toplevel(pos(1)), "type", "Array"));
+	}
+}

+ 35 - 0
tests/display/src/cases/Issue7055.hx

@@ -0,0 +1,35 @@
+package cases;
+
+class Issue7055 extends DisplayTestCase {
+	/**
+	enum TestEnum {
+		Some;
+		Random;
+		Enum;
+		Constructors;
+		For;
+		Testing;
+	}
+
+	class Main {
+		static function main() {
+			switch ((null:TestEnum)) {
+				case {-1-}
+			}
+		}
+	}
+	**/
+	function test() {
+		var results = toplevel(pos(1));
+		var i = 0;
+		function nextIs(name, ?pos) {
+			eq(results[i++].name, name, pos);
+		}
+		nextIs("Some");
+		nextIs("Random");
+		nextIs("Enum");
+		nextIs("Constructors");
+		nextIs("For");
+		nextIs("Testing");
+	}
+}

+ 56 - 0
tests/display/src/cases/Override.hx

@@ -0,0 +1,56 @@
+package cases;
+
+class Override extends DisplayTestCase {
+	/**
+	class Super {
+		public function test1() return 12;
+		public function test2() return 12;
+	}
+
+	class Main extends Super {
+		override function test1() { return 12; }
+		override {-1-}function x() { }
+	}
+	**/
+	function test1() {
+		var fields = fields(pos(1));
+		eq(true, hasField(fields, "test2", "Void -> Int"));
+		eq(false, hasField(fields, "test1", "Void -> Int"));
+	}
+
+	/**
+	class Super {
+		public function test1() return 12;
+		public function test2() return 12;
+	}
+
+	class Main extends Super {
+		override {-1-}function x() { }
+		override function test1() { return 12; }
+	}
+	**/
+	function test2() {
+		var fields = fields(pos(1));
+		eq(true, hasField(fields, "test2", "Void -> Int"));
+		eq(false, hasField(fields, "test1", "Void -> Int"));
+	}
+
+	/**
+	class SuperSuper {
+		public function test1() return 12;
+		public function test2() return 12;
+	}
+
+	class Super extends SuperSuper { }
+
+	class Main extends Super {
+		override function test1() { return 12; }
+		override {-1-}function x() { }
+	}
+	**/
+	function test3() {
+		var fields = fields(pos(1));
+		eq(true, hasField(fields, "test2", "Void -> Int"));
+		eq(false, hasField(fields, "test1", "Void -> Int"));
+	}
+}