Selaa lähdekoodia

[typer] dig up structInit field positions from ctor expression

see #9318
Simon Krajewski 2 vuotta sitten
vanhempi
commit
dadc1c058e

+ 1 - 1
src/typing/typeloadFields.ml

@@ -215,7 +215,7 @@ let ensure_struct_init_constructor ctx c ast_fields p =
 				let has_default_expr = field_has_default_expr cf.cf_name in
 				let opt = has_default_expr || (Meta.has Meta.Optional cf.cf_meta) in
 				let t = if opt then ctx.t.tnull cf.cf_type else cf.cf_type in
-				let v = alloc_var VGenerated cf.cf_name t p in
+				let v = alloc_var VGenerated cf.cf_name t cf.cf_name_pos in
 				let ef = mk (TField(ethis,FInstance(c,params,cf))) cf.cf_type p in
 				let ev = mk (TLocal v) v.v_type p in
 				if opt && not (Meta.has Meta.Optional v.v_meta) then

+ 19 - 5
src/typing/typer.ml

@@ -954,12 +954,26 @@ and type_object_decl ctx fl with_type p =
 		let fa = FieldAccess.get_constructor_access c tl p in
 		let ctor = fa.fa_field in
 		let args = match follow (FieldAccess.get_map_function fa ctor.cf_type) with
-			| TFun(args,_) -> args
+			| TFun(args,_) ->
+				begin match ctor.cf_expr with
+					| Some {eexpr = TFunction tf} ->
+						let rec loop acc args vl = match args,vl with
+							| arg :: args,(v,_) :: vl ->
+								loop ((arg,v.v_pos) :: acc) args vl
+							| [],_ ->
+								List.rev acc
+							| arg :: args,[] ->
+								loop ((arg,ctor.cf_name_pos) :: acc) args []
+						in
+						loop [] args tf.tf_args
+					| _ ->
+						List.map (fun args -> (args,ctor.cf_name_pos)) args
+					end
 			| _ -> die "" __LOC__
 		in
-		let fields = List.fold_left (fun acc (n,opt,t) ->
-			let f = mk_field n t ctor.cf_pos ctor.cf_name_pos in
-			if opt then f.cf_meta <- [(Meta.Optional,[],ctor.cf_pos)];
+		let fields = List.fold_left (fun acc ((n,opt,t),parg) ->
+			let f = mk_field n t parg parg in
+			if opt then f.cf_meta <- [(Meta.Optional,[],null_pos)];
 			PMap.add n f acc
 		) PMap.empty args in
 		let t,fl = type_fields fields in
@@ -977,7 +991,7 @@ and type_object_decl ctx fl with_type p =
 					evars,(s,e) :: elocs,OptimizerTexpr.has_side_effect e
 			end
 		) ([],[],false) (List.rev fl) in
-		let el = List.map (fun (n,_,t) ->
+		let el = List.map (fun ((n,_,t),parg) ->
 			try Expr.field_assoc n fl
 			with Not_found ->
 				try

+ 39 - 0
tests/server/src/cases/display/issues/Issue9318.hx

@@ -0,0 +1,39 @@
+package cases.display.issues;
+
+class Issue9318 extends DisplayTestCase {
+	/**
+		typedef T = {
+			var {-1-}field{-2-}:Int;
+		}
+
+		@:structInit
+		class C {
+			public function new({-3-}field{-4-}:Int) {}
+		}
+
+		@:structInit
+		class D {
+			var {-5-}field{-6-}:Int;
+		}
+
+		class Main {
+			static function main() {
+				var t:T = {fie{-7-}ld: 1}; // clicking on `field` takes to the field position: ideal
+				var c:C = {fie{-8-}ld: 1}; // clicking on `field` takes to the contstructor position: not bad, but ideally should take to the argument position (not sure if possible)
+				var d:D = {fiel{-9-}d: 1}; // clicking on `field` doesn't work :()
+			}
+		}
+	**/
+	function test(_) {
+		var args = ["Main", "-js", "main.js"];
+		function parseGotoDefintion():GotoDefinitionResult {
+			return haxe.Json.parse(lastResult.stderr).result.result.map(result -> result.range);
+		}
+		runHaxeJson(args, DisplayMethods.GotoDefinition, {file: file, offset: offset(7), contents: source});
+		Assert.same([range(1, 2)], parseGotoDefintion());
+		// runHaxeJson(args, DisplayMethods.GotoDefinition, {file: file, offset: offset(8), contents: source});
+		// Assert.same([range(3, 4)], parseGotoDefintion());
+		runHaxeJson(args, DisplayMethods.GotoDefinition, {file: file, offset: offset(9), contents: source});
+		Assert.same([range(5, 6)], parseGotoDefintion());
+	}
+}