소스 검색

[parser] handle object declaration display differently

closes #7074
Simon Krajewski 7 년 전
부모
커밋
a5a4552c44
4개의 변경된 파일75개의 추가작업 그리고 33개의 파일을 삭제
  1. 5 0
      src/context/display/display.ml
  2. 2 1
      src/core/ast.ml
  3. 24 32
      src/syntax/grammar.mly
  4. 44 0
      tests/display/src/cases/StructureCompletion.hx

+ 5 - 0
src/context/display/display.ml

@@ -58,6 +58,9 @@ module ExprPreprocessing = struct
 					e
 			| EBlock [] when is_annotated (pos e) ->
 				annotate e DKStructure
+			| EBlock [EDisplay((EConst(Ident s),pn),DKMarked),_] when is_completion ->
+				let e = EObjectDecl [(s,pn,NoQuotes),(EConst (Ident "null"),null_pos)],(pos e) in
+				annotate e DKStructure
 			| EBlock el when is_annotated (pos e) && is_completion ->
 				let el = loop_el el in
 				EBlock el,(pos e)
@@ -74,6 +77,8 @@ module ExprPreprocessing = struct
 			| EArrayDecl el when is_annotated (pos e) && is_completion ->
 				let el = loop_el el in
 				EArrayDecl el,(pos e)
+			| EObjectDecl fl when is_annotated (pos e) && is_completion ->
+				annotate e DKStructure
 			| EDisplay _ ->
 				raise Exit
 			| EConst (String _) when (not (Lexer.is_fmt_string (pos e)) || !Parser.was_auto_triggered) && is_annotated (pos e) && is_completion ->

+ 2 - 1
src/core/ast.ml

@@ -934,7 +934,8 @@ module Expr = struct
 			| EObjectDecl fl ->
 				add "EObjectDecl";
 				List.iter (fun ((n,p,_),e1) ->
-					loop' (Printf.sprintf "%s  %s" tabs n) e1
+					Buffer.add_string buf (Printf.sprintf "%4i-%4i %s%s\n" p.pmin p.pmax tabs n);
+					loop e1
 				) fl;
 			| EArrayDecl el ->
 				add "EArrayDecl";

+ 24 - 32
src/syntax/grammar.mly

@@ -852,46 +852,32 @@ and parse_block_elt = parser
 	| [< e = expr; _ = semicolon >] -> e
 
 and parse_obj_decl name e p0 s =
-	let has_resume = ref false in
 	let make_obj_decl el p1 =
 		EObjectDecl (List.rev el),punion p0 p1
 	in
 	let rec loop p_end acc = match s with parser
 		| [< '(Comma,p1); s >] ->
-			if is_resuming p1 then has_resume := true;
+			let next_expr key =
+				let e = secure_expr s in
+				loop (pos e) ((key,e) :: acc)
+			in
 			let next key = match s with parser
 				| [< '(DblDot,_) >] ->
-					let e = try
-						secure_expr s
-					with Display e ->
-						let acc = (key,e) :: acc in
-						let e = make_obj_decl acc (pos e) in
-						display e
-					in
-					loop (pos e) ((key,e) :: acc)
-				| [< >] -> serror()
+					next_expr key
+				| [< >] ->
+					if do_resume() then next_expr key
+					else serror()
 			in
 			begin match s with parser
 				| [< name,p = ident >] -> next (name,p,NoQuotes)
 				| [< '(Const (String name),p) >] -> next (name,p,DoubleQuotes)
-				| [< >] ->
-					let p2 = pos (next_token s) in
-					if encloses_resume (punion p1 p2) then begin
-						let e = make_obj_decl acc p2 in
-						let e = EDisplay(e,DKStructure),(pos e) in
-						display e
-					end else
-						acc,p_end
+				| [< >] -> acc,p_end
 			end
 		| [< >] -> acc,p_end
 	in
 	let el,p_end = loop p0 [name,e] in
 	let e = make_obj_decl el p_end in
-	if !has_resume then begin
-		let e = EDisplay(e,DKStructure),(pos e) in
-		display e
-	end else
-		e
+	e
 
 and parse_array_decl p1 s =
 	let secure_expr acc s = try
@@ -1294,19 +1280,25 @@ and toplevel_expr s =
 	with
 		Display e -> e
 
+and secure_expr s =
+	expr_or_fail serror s
+
 (* Tries to parse a toplevel expression and defaults to a null expression when in display mode.
    This function always accepts in display mode and should only be used for expected expressions,
    not accepted ones! *)
-and secure_expr s =
-	match s with parser
-	| [< e = toplevel_expr >] -> e
-	| [< >] -> if do_resume() then mk_null_expr (punion_next (pos (last_token s)) s) else serror()
-
-(* Like secure_expr, but with a custom fail function *)
 and expr_or_fail fail s =
 	match s with parser
-	| [< e = expr >] -> e
-	| [< >] -> if do_resume() then mk_null_expr (punion_next (pos (last_token s)) s) else fail()
+	| [< e = toplevel_expr >] -> e
+	| [< >] -> if do_resume() then begin
+		let last = last_token s in
+		let plast = pos last in
+		let offset = match fst last with
+			| Const _ | Kwd _ | Dollar _ -> 0
+			| _ -> -1
+		in
+		let plast = {plast with pmin = plast.pmax + offset} in
+		mk_null_expr (punion_next plast s)
+	end else fail()
 
 let rec validate_macro_cond e = match fst e with
 	| EConst (Ident _)

+ 44 - 0
tests/display/src/cases/StructureCompletion.hx

@@ -161,4 +161,48 @@ class StructureCompletion extends DisplayTestCase {
 		eq(true, hasField(fields, "a", "Int"));
 		eq(true, hasField(fields, "b", "String"));
 	}
+
+	/**
+	typedef Foo = {
+		var field1:Int;
+		var field2:String;
+	}
+	class Main {
+		static function test1():Foo return { f{-1-}ie{-2-}
+		static function test2():Foo return { f{-3-}ie{-4-}:
+		static function test3():Foo return { f{-5-}ie{-6-} }
+		static function test4():Foo return { f{-7-}ie{-8-} : }
+		static function test5():Foo return { f{-9-}ie{-10-} : null }
+		static function test6():Foo return { f{-11-}ie{-12-} : null
+	**/
+	function testStructureVsToplevel9() {
+		for (i in 1...13) {
+			var fields = fields(pos(i));
+			eq(false, hasField(fields, "type", "T"));
+			eq(true, hasField(fields, "field1", "Int"));
+			eq(true, hasField(fields, "field2", "String"));
+		}
+	}
+
+	/**
+	typedef Foo = {
+		var field1:Int;
+		var field2:String;
+	}
+	class Main {
+		static function test1():Foo return { field1: 1, f{-1-}ie{-2-}
+		static function test2():Foo return { field1: 1, f{-3-}ie{-4-}:
+		static function test3():Foo return { field1: 1, f{-5-}ie{-6-} }
+		static function test4():Foo return { field1: 1, f{-7-}ie{-8-} : }
+		static function test5():Foo return { field1: 1, f{-9-}ie{-10-} : null }
+		static function test6():Foo return { field1: 1, f{-11-}ie{-12-} : null
+	**/
+	function testStructureVsToplevel10() {
+		for (i in 1...13) {
+			var fields = fields(pos(i));
+			eq(false, hasField(fields, "type", "T"));
+			eq(false, hasField(fields, "field1", "Int"));
+			eq(true, hasField(fields, "field2", "String"));
+		}
+	}
 }