浏览代码

allow resuming from expression-level metadata

closes #4720
Simon Krajewski 9 年之前
父节点
当前提交
a2a6439c24
共有 5 个文件被更改,包括 85 次插入14 次删除
  1. 11 0
      src/display/display.ml
  2. 8 3
      src/syntax/parser.ml
  3. 1 11
      src/typing/typeload.ml
  4. 1 0
      src/typing/typer.ml
  5. 64 0
      tests/display/src/cases/Metadata.hx

+ 11 - 0
src/display/display.ml

@@ -197,6 +197,17 @@ module DisplayEmitter = struct
 			raise (DisplayFields all)
 		| _ ->
 			()
+
+	let check_display_metadata ctx meta =
+		List.iter (fun (meta,args,p) ->
+			if is_display_position p then display_meta ctx.com.display meta;
+			List.iter (fun e ->
+				if is_display_position (pos e) then begin
+					let e = ExprPreprocessing.process_expr ctx.com e in
+					delay ctx PTypeField (fun _ -> ignore(type_expr ctx e Value));
+				end
+			) args
+		) meta
 end
 
 module DocumentSymbols = struct

+ 8 - 3
src/syntax/parser.ml

@@ -1290,10 +1290,15 @@ and parse_function p1 inl = parser
 
 and expr = parser
 	| [< (name,params,p) = parse_meta_entry; s >] ->
-		(try
+		begin try
 			make_meta name params (secure_expr s) p
-		with Display e ->
-			display (make_meta name params e p))
+		with
+		| Display e ->
+			display (make_meta name params e p)
+		| Stream.Failure | Stream.Error _ when Path.unique_full_path p.pfile = (!resume_display).pfile ->
+			let e = EConst (Ident "null"),p in
+			display (make_meta name params e p)
+		end
 	| [< '(BrOpen,p1); s >] ->
 		if is_resuming p1 then display (EDisplay ((EObjectDecl [],p1),false),p1);
 		(match s with parser

+ 1 - 11
src/typing/typeload.ml

@@ -1751,17 +1751,7 @@ let check_global_metadata ctx meta f_add mpath tpath so =
 		let add = ((field_mode && to_fields) || (not field_mode && to_types)) && (match_path recursive sl1 sl2) in
 		if add then f_add m
 	) ctx.g.global_metadata;
-	if ctx.is_display_file then begin
-		List.iter (fun (meta,args,p) ->
-			if Display.is_display_position p then Display.DisplayEmitter.display_meta ctx.com.display meta;
-			List.iter (fun e ->
-				if Display.is_display_position (pos e) then begin
-					let e = Display.ExprPreprocessing.process_expr ctx.com e in
-					delay ctx PTypeField (fun _ -> ignore(type_expr ctx e Value));
-				end
-			) args
-		) meta
-	end
+	if ctx.is_display_file then Display.DisplayEmitter.check_display_metadata ctx meta
 
 let patch_class ctx c fields =
 	let path = match c.cl_kind with

+ 1 - 0
src/typing/typer.ml

@@ -3633,6 +3633,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		let e = AbstractCast.cast_or_unify ctx t e p in
 		if e.etype == t then e else mk (TCast (e,None)) t p
 	| EMeta (m,e1) ->
+		if ctx.is_display_file then Display.DisplayEmitter.check_display_metadata ctx [m];
 		let old = ctx.meta in
 		ctx.meta <- m :: ctx.meta;
 		let e () = type_expr ctx e1 with_type in

+ 64 - 0
tests/display/src/cases/Metadata.hx

@@ -46,4 +46,68 @@ class Metadata extends DisplayTestCase {
 		eq(range(1, 2), position(pos(3)));
 		eq("Class<cases.SomeOther>", type(pos(3)));
 	}
+
+
+	/**
+	class Main {
+		public static function main() { @{-1-} }
+	}
+	**/
+	function testExpression1() {
+		eq(true, hasPath(fields(pos(1)), "@:generic"));
+	}
+
+	/**
+	class Main {
+		public static function main() { @{-1-}:{-2-} }
+	}
+	**/
+	function testExpression2() {
+		eq(true, hasPath(fields(pos(1)), "@:generic"));
+		eq(true, hasPath(fields(pos(2)), "@:generic"));
+	}
+
+	/**
+	class Main {
+		public static function main() { @{-1-}:{-2-}gene{-3-}ric }
+	}
+	**/
+	function testExpression3() {
+		eq(true, hasPath(fields(pos(1)), "@:generic"));
+		eq(true, hasPath(fields(pos(2)), "@:generic"));
+		eq(true, hasPath(fields(pos(3)), "@:generic"));
+	}
+
+	/**
+	class Main {
+		public static function main() { @{-1-}:{-2-}gene{-3-}ric null; }
+	}
+	**/
+	function testExpression4() {
+		eq(true, hasPath(fields(pos(1)), "@:generic"));
+		eq(true, hasPath(fields(pos(2)), "@:generic"));
+		eq(true, hasPath(fields(pos(3)), "@:generic"));
+	}
+
+	/**
+	class Main {
+		public static function main() { @{-1-}:{-2-}gene{-3-}ric }
+	}
+	**/
+	function testExpression5() {
+		eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(1)));
+		eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(2)));
+		eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(3)));
+	}
+
+	/**
+	class Main {
+		public static function main() { @{-1-}:{-2-}gene{-3-}ric null; }
+	}
+	**/
+	function testExpression6() {
+		eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(1)));
+		eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(2)));
+		eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(3)));
+	}
 }