Browse Source

[display] fix completion for key => value loops (#8046) (#8091)

* [display] fix completion for key => value loops (#8046)

* a test for #8046

* cleanup

* [display] make `for` loop detection more generic
Alexander Kuzmenko 6 years ago
parent
commit
3598531fb5
2 changed files with 51 additions and 12 deletions
  1. 33 12
      src/optimization/optimizer.ml
  2. 18 0
      tests/display/src/cases/Issue8046.hx

+ 33 - 12
src/optimization/optimizer.ml

@@ -660,18 +660,39 @@ let optimize_completion_expr e args =
 			let e = map e in
 			old();
 			e
-		| EFor ((EBinop (OpIn,((EConst (Ident n),_) as id),it),p),efor) ->
-			let it = loop it in
-			let old = save() in
-			let etmp = (EConst (Ident "$tmp"),p) in
-			decl n None (Some (EBlock [
-				(EVars [("$tmp",null_pos),false,None,None],p);
-				(EFor ((EBinop (OpIn,id,it),p),(EBinop (OpAssign,etmp,(EConst (Ident n),p)),p)),p);
-				etmp
-			],p));
-			let efor = loop efor in
-			old();
-			(EFor ((EBinop (OpIn,id,it),p),efor),p)
+		| EFor (header,body) ->
+			let idents = ref []
+			and has_in = ref false in
+			let rec collect_idents e =
+				match e with
+					| EConst (Ident name), p ->
+						idents := (name,p) :: !idents;
+						e
+					| EBinop (OpIn, e, it), p ->
+						has_in := true;
+						(EBinop (OpIn, collect_idents e, loop it), p)
+					| _ ->
+						Ast.map_expr collect_idents e
+			in
+			let header = collect_idents header in
+			(match !idents,!has_in with
+				| [],_ | _,false -> map e
+				| idents,true ->
+					let old = save() in
+					List.iter
+						(fun (name, pos) ->
+							let etmp = (EConst (Ident "$tmp"),pos) in
+							decl name None (Some (EBlock [
+								(EVars [("$tmp",null_pos),false,None,None],p);
+								(EFor(header,(EBinop (OpAssign,etmp,(EConst (Ident name),p)),p)), p);
+								etmp
+							],p));
+						)
+						idents;
+					let body = loop body in
+					old();
+					(EFor(header,body),p)
+			)
 		| EReturn _ ->
 			typing_side_effect := true;
 			map e

+ 18 - 0
tests/display/src/cases/Issue8046.hx

@@ -0,0 +1,18 @@
+package cases;
+
+class Issue8046 extends DisplayTestCase {
+	/**
+		class Main {
+			static function main() {
+				for(k => v in ['hello' => {field:true}]) {
+					k.{-1-}
+					v.{-2-}
+				}
+			}
+		}
+	**/
+	function testKeyValue() {
+		eq(true, hasField(fields(pos(1)), "length", "Int"));
+		eq(true, hasField(fields(pos(2)), "field", "Bool"));
+	}
+}