浏览代码

[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
 					e
 			| EBlock [] when is_annotated (pos e) ->
 			| EBlock [] when is_annotated (pos e) ->
 				annotate e DKStructure
 				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 ->
 			| EBlock el when is_annotated (pos e) && is_completion ->
 				let el = loop_el el in
 				let el = loop_el el in
 				EBlock el,(pos e)
 				EBlock el,(pos e)
@@ -74,6 +77,8 @@ module ExprPreprocessing = struct
 			| EArrayDecl el when is_annotated (pos e) && is_completion ->
 			| EArrayDecl el when is_annotated (pos e) && is_completion ->
 				let el = loop_el el in
 				let el = loop_el el in
 				EArrayDecl el,(pos e)
 				EArrayDecl el,(pos e)
+			| EObjectDecl fl when is_annotated (pos e) && is_completion ->
+				annotate e DKStructure
 			| EDisplay _ ->
 			| EDisplay _ ->
 				raise Exit
 				raise Exit
 			| EConst (String _) when (not (Lexer.is_fmt_string (pos e)) || !Parser.was_auto_triggered) && is_annotated (pos e) && is_completion ->
 			| 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 ->
 			| EObjectDecl fl ->
 				add "EObjectDecl";
 				add "EObjectDecl";
 				List.iter (fun ((n,p,_),e1) ->
 				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;
 				) fl;
 			| EArrayDecl el ->
 			| EArrayDecl el ->
 				add "EArrayDecl";
 				add "EArrayDecl";

+ 24 - 32
src/syntax/grammar.mly

@@ -852,46 +852,32 @@ and parse_block_elt = parser
 	| [< e = expr; _ = semicolon >] -> e
 	| [< e = expr; _ = semicolon >] -> e
 
 
 and parse_obj_decl name e p0 s =
 and parse_obj_decl name e p0 s =
-	let has_resume = ref false in
 	let make_obj_decl el p1 =
 	let make_obj_decl el p1 =
 		EObjectDecl (List.rev el),punion p0 p1
 		EObjectDecl (List.rev el),punion p0 p1
 	in
 	in
 	let rec loop p_end acc = match s with parser
 	let rec loop p_end acc = match s with parser
 		| [< '(Comma,p1); s >] ->
 		| [< '(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
 			let next key = match s with parser
 				| [< '(DblDot,_) >] ->
 				| [< '(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
 			in
 			begin match s with parser
 			begin match s with parser
 				| [< name,p = ident >] -> next (name,p,NoQuotes)
 				| [< name,p = ident >] -> next (name,p,NoQuotes)
 				| [< '(Const (String name),p) >] -> next (name,p,DoubleQuotes)
 				| [< '(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
 			end
 		| [< >] -> acc,p_end
 		| [< >] -> acc,p_end
 	in
 	in
 	let el,p_end = loop p0 [name,e] in
 	let el,p_end = loop p0 [name,e] in
 	let e = make_obj_decl el p_end 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 =
 and parse_array_decl p1 s =
 	let secure_expr acc s = try
 	let secure_expr acc s = try
@@ -1294,19 +1280,25 @@ and toplevel_expr s =
 	with
 	with
 		Display e -> e
 		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.
 (* 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,
    This function always accepts in display mode and should only be used for expected expressions,
    not accepted ones! *)
    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 =
 and expr_or_fail fail s =
 	match s with parser
 	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
 let rec validate_macro_cond e = match fst e with
 	| EConst (Ident _)
 	| 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, "a", "Int"));
 		eq(true, hasField(fields, "b", "String"));
 		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"));
+		}
+	}
 }
 }