Bladeren bron

Fix enclosing positions (#11892)

* Make zero range positions when reusing field/type pos for metadata

* [macro] Expose PositionTools.toZeroRange()

* That one was ok

* Restore CfOverride
Rudy Ges 6 maanden geleden
bovenliggende
commit
bdecee2bf3

+ 4 - 0
src/macro/macroApi.ml

@@ -2356,6 +2356,10 @@ let macro_api ccom get_api =
 			] in
 			] in
 			location
 			location
 		);
 		);
+		"position_to_zero_range", vfun1 (fun p ->
+			let p = decode_pos p in
+			encode_pos (mk_zero_range_pos p)
+		);
 		"on_null_safety_report", vfun1 (fun f ->
 		"on_null_safety_report", vfun1 (fun f ->
 			let f = prepare_callback f 1 in
 			let f = prepare_callback f 1 in
 			(ccom()).callbacks#add_null_safety_report (fun (errors:(string*pos) list) ->
 			(ccom()).callbacks#add_null_safety_report (fun (errors:(string*pos) list) ->

+ 1 - 1
src/optimization/analyzerTexpr.ml

@@ -1259,7 +1259,7 @@ module Purity = struct
 		Hashtbl.iter (fun _ node ->
 		Hashtbl.iter (fun _ node ->
 			match node.pn_purity with
 			match node.pn_purity with
 			| Pure | MaybePure when not (List.exists (fun (m,_,_) -> m = Meta.Pure) node.pn_field.cf_meta) ->
 			| Pure | MaybePure when not (List.exists (fun (m,_,_) -> m = Meta.Pure) node.pn_field.cf_meta) ->
-				node.pn_field.cf_meta <- (Meta.Pure,[EConst(Ident "inferredPure"),node.pn_field.cf_pos],node.pn_field.cf_pos) :: node.pn_field.cf_meta
+				node.pn_field.cf_meta <- (Meta.Pure,[EConst(Ident "inferredPure"),mk_zero_range_pos node.pn_field.cf_pos],mk_zero_range_pos node.pn_field.cf_pos) :: node.pn_field.cf_meta
 			| _ -> ()
 			| _ -> ()
 		) node_lut;
 		) node_lut;
 end
 end

+ 4 - 4
src/optimization/dce.ml

@@ -281,7 +281,7 @@ let mark_mt dce mt = match mt with
 		mark_enum dce e
 		mark_enum dce e
 	| TAbstractDecl a ->
 	| TAbstractDecl a ->
 		(* abstract 'feature' is defined as the abstract type beeing used as a value, not as a type *)
 		(* abstract 'feature' is defined as the abstract type beeing used as a value, not as a type *)
-		if not (Meta.has Meta.ValueUsed a.a_meta) then a.a_meta <- (Meta.ValueUsed,[],a.a_pos) :: a.a_meta;
+		if not (Meta.has Meta.ValueUsed a.a_meta) then a.a_meta <- (Meta.ValueUsed,[],mk_zero_range_pos a.a_pos) :: a.a_meta;
 		mark_abstract dce a
 		mark_abstract dce a
 	| TTypeDecl _ ->
 	| TTypeDecl _ ->
 		()
 		()
@@ -370,11 +370,11 @@ and field dce c n kind =
 and mark_directly_used_class dce c =
 and mark_directly_used_class dce c =
 	(* don't add @:directlyUsed if it's used within the class itself. this can happen with extern inline methods *)
 	(* don't add @:directlyUsed if it's used within the class itself. this can happen with extern inline methods *)
 	if c != dce.curclass && not (Meta.has Meta.DirectlyUsed c.cl_meta) then
 	if c != dce.curclass && not (Meta.has Meta.DirectlyUsed c.cl_meta) then
-		c.cl_meta <- (Meta.DirectlyUsed,[],c.cl_pos) :: c.cl_meta
+		c.cl_meta <- (Meta.DirectlyUsed,[],mk_zero_range_pos c.cl_pos) :: c.cl_meta
 
 
 and mark_directly_used_enum e =
 and mark_directly_used_enum e =
 	if not (Meta.has Meta.DirectlyUsed e.e_meta) then
 	if not (Meta.has Meta.DirectlyUsed e.e_meta) then
-		e.e_meta <- (Meta.DirectlyUsed,[],e.e_pos) :: e.e_meta
+		e.e_meta <- (Meta.DirectlyUsed,[],mk_zero_range_pos e.e_pos) :: e.e_meta
 
 
 and mark_directly_used_mt dce mt =
 and mark_directly_used_mt dce mt =
 	match mt with
 	match mt with
@@ -828,7 +828,7 @@ let sweep dce com =
 		| (TClassDecl c) as mt :: l ->
 		| (TClassDecl c) as mt :: l ->
 			let check_property cf stat =
 			let check_property cf stat =
 				let add_accessor_metadata cf =
 				let add_accessor_metadata cf =
-					if not (Meta.has Meta.Accessor cf.cf_meta) then cf.cf_meta <- (Meta.Accessor,[],c.cl_pos) :: cf.cf_meta
+					if not (Meta.has Meta.Accessor cf.cf_meta) then cf.cf_meta <- (Meta.Accessor,[],mk_zero_range_pos c.cl_pos) :: cf.cf_meta
 				in
 				in
 				begin match cf.cf_kind with
 				begin match cf.cf_kind with
 				| Var {v_read = AccCall} ->
 				| Var {v_read = AccCall} ->

+ 1 - 1
src/optimization/inlineConstructors.ml

@@ -729,7 +729,7 @@ let inline_constructors ctx original_e =
 	end else begin
 	end else begin
 		let el,_ = final_map e in
 		let el,_ = final_map e in
 		let cf = ctx.f.curfield in
 		let cf = ctx.f.curfield in
-		if !included_untyped && not (Meta.has Meta.HasUntyped cf.cf_meta) then cf.cf_meta <- (Meta.HasUntyped,[],e.epos) :: cf.cf_meta;
+		if !included_untyped && not (Meta.has Meta.HasUntyped cf.cf_meta) then cf.cf_meta <- (Meta.HasUntyped,[],mk_zero_range_pos e.epos) :: cf.cf_meta;
 		let e = make_expr_for_rev_list el e.etype e.epos in
 		let e = make_expr_for_rev_list el e.etype e.epos in
 		let rec get_pretty_name iv : string list = match iv.iv_kind with
 		let rec get_pretty_name iv : string list = match iv.iv_kind with
 			| IVKField(io,fname,None) ->
 			| IVKField(io,fname,None) ->

+ 2 - 1
src/typing/generic.ml

@@ -505,7 +505,8 @@ let type_generic_function ctx fa fcc with_type p =
 				| Meta.Generic -> false
 				| Meta.Generic -> false
 				| _ -> true
 				| _ -> true
 			) cf.cf_meta in
 			) cf.cf_meta in
-			cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: meta;
+			let p_zero = mk_zero_range_pos p in
+			cf2.cf_meta <- (Meta.NoCompletion,[],p_zero) :: (Meta.NoUsing,[],p_zero) :: (Meta.GenericInstance,[],p_zero) :: meta;
 			cf2.cf_params <- params
 			cf2.cf_params <- params
 		in
 		in
 		let mk_cf2 name =
 		let mk_cf2 name =

+ 2 - 2
src/typing/typeloadCheck.ml

@@ -58,7 +58,7 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 		if is_null t1 <> is_null t2 || ((follow t1) == t_dynamic && (follow t2) != t_dynamic) then raise (Unify_error [Cannot_unify (t1,t2)]);
 		if is_null t1 <> is_null t2 || ((follow t1) == t_dynamic && (follow t2) != t_dynamic) then raise (Unify_error [Cannot_unify (t1,t2)]);
 	in
 	in
 	begin match PurityState.get_purity_from_meta f2.cf_meta,PurityState.get_purity_from_meta f1.cf_meta with
 	begin match PurityState.get_purity_from_meta f2.cf_meta,PurityState.get_purity_from_meta f1.cf_meta with
-		| PurityState.Pure,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),f2.cf_pos],null_pos) :: f1.cf_meta
+		| PurityState.Pure,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),mk_zero_range_pos f2.cf_pos],null_pos) :: f1.cf_meta
 		| PurityState.ExpectPure p,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),p],null_pos) :: f1.cf_meta
 		| PurityState.ExpectPure p,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),p],null_pos) :: f1.cf_meta
 		| _ -> ()
 		| _ -> ()
 	end;
 	end;
@@ -501,7 +501,7 @@ module Inheritance = struct
 		let process_meta csup =
 		let process_meta csup =
 			List.iter (fun m ->
 			List.iter (fun m ->
 				match m with
 				match m with
-				| Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,{ c.cl_pos with pmax = c.cl_pos.pmin }(* prevent display metadata *)) :: m :: c.cl_meta
+				| Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,mk_zero_range_pos c.cl_pos) :: m :: c.cl_meta
 				| _ -> ()
 				| _ -> ()
 			) (List.rev csup.cl_meta);
 			) (List.rev csup.cl_meta);
 			if has_class_flag csup CFinal && not (((has_class_flag csup CExtern) && Meta.has Meta.Hack c.cl_meta) || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then
 			if has_class_flag csup CFinal && not (((has_class_flag csup CExtern) && Meta.has Meta.Hack c.cl_meta) || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then

+ 5 - 3
src/typing/typeloadFields.ml

@@ -735,7 +735,7 @@ module TypeBinding = struct
 		let p = cf.cf_pos in
 		let p = cf.cf_pos in
 		let ctx = TyperManager.clone_for_expr ctx_f (if fctx.is_static then FunStatic else FunMember) false in
 		let ctx = TyperManager.clone_for_expr ctx_f (if fctx.is_static then FunStatic else FunMember) false in
 		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
 		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
-		cf.cf_meta <- ((Meta.Value,[e],cf.cf_pos) :: cf.cf_meta);
+		cf.cf_meta <- ((Meta.Value,[e],mk_zero_range_pos cf.cf_pos) :: cf.cf_meta);
 		let check_cast e =
 		let check_cast e =
 			(* insert cast to keep explicit field type (issue #1901) *)
 			(* insert cast to keep explicit field type (issue #1901) *)
 			if type_iseq e.etype cf.cf_type then
 			if type_iseq e.etype cf.cf_type then
@@ -1246,8 +1246,10 @@ let create_method (ctx,cctx,fctx) c f cf fd p =
 		if fctx.is_inline then invalid_modifier_combination fctx ctx.com fctx "dynamic" "inline" p;
 		if fctx.is_inline then invalid_modifier_combination fctx ctx.com fctx "dynamic" "inline" p;
 		if fctx.is_abstract_member then invalid_modifier ctx.com fctx "dynamic" "method of abstract" p;
 		if fctx.is_abstract_member then invalid_modifier ctx.com fctx "dynamic" "method of abstract" p;
 	end;
 	end;
-	let is_override = Option.is_some fctx.override in
-	if (is_override && fctx.is_static) then invalid_modifier_combination fctx ctx.com fctx "override" "static" p;
+	if Option.is_some fctx.override then begin
+		if fctx.is_static then invalid_modifier_combination fctx ctx.com fctx "override" "static" p;
+		add_class_field_flag cf CfOverride;
+	end;
 
 
 	ctx.type_params <- params @ ctx.type_params;
 	ctx.type_params <- params @ ctx.type_params;
 	let args,ret = setup_args_ret ctx cctx fctx (fst f.cff_name) fd p in
 	let args,ret = setup_args_ret ctx cctx fctx (fst f.cff_name) fd p in

+ 1 - 1
src/typing/typer.ml

@@ -1995,7 +1995,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 	| EUntyped e ->
 	| EUntyped e ->
 		let old = ctx.f.untyped in
 		let old = ctx.f.untyped in
 		ctx.f.untyped <- true;
 		ctx.f.untyped <- true;
-		if not (Meta.has Meta.HasUntyped ctx.f.curfield.cf_meta) then ctx.f.curfield.cf_meta <- (Meta.HasUntyped,[],p) :: ctx.f.curfield.cf_meta;
+		if not (Meta.has Meta.HasUntyped ctx.f.curfield.cf_meta) then ctx.f.curfield.cf_meta <- (Meta.HasUntyped,[],mk_zero_range_pos p) :: ctx.f.curfield.cf_meta;
 		let e = type_expr ctx e with_type in
 		let e = type_expr ctx e with_type in
 		ctx.f.untyped <- old;
 		ctx.f.untyped <- old;
 		{
 		{

+ 10 - 0
std/haxe/macro/PositionTools.hx

@@ -70,5 +70,15 @@ class PositionTools {
 	public static function toLocation(p:Position):Location {
 	public static function toLocation(p:Position):Location {
 		return Context.load("position_to_range", 1)(p);
 		return Context.load("position_to_range", 1)(p);
 	}
 	}
+
+	/**
+		Returns a copy of a `haxe.macro.Position`, with `pmax` set to `pmin`.
+
+		This ensures that the resulting position will not enclose other positions that might be
+		looked at for display requests, which could lead to unexpected results.
+	**/
+	public static function toZeroRange(p:Position):Position {
+		return Context.load("position_to_zero_range", 1)(p);
+	}
 	#end
 	#end
 }
 }