From cea8bd770bfae7a2eeaea8e71838832be36b044b Mon Sep 17 00:00:00 2001 From: Dima Granetchi Date: Fri, 21 Nov 2014 14:22:59 +0200 Subject: [PATCH] fix work with chain gaps --- src/bindx/BindxExt.hx | 23 ++++++++++-- test/ChainBindTest.hx | 83 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/bindx/BindxExt.hx b/src/bindx/BindxExt.hx index ff046b1..d6b1a17 100644 --- a/src/bindx/BindxExt.hx +++ b/src/bindx/BindxExt.hx @@ -68,11 +68,28 @@ class BindExt { public static function internalBindChain(expr:Expr, listener:Expr):Expr { var fields = checkFields(expr); + if (fields.length == 0) + Context.fatalError("can't bind empty expression", expr.pos); + var flag = false; + var i = fields.length; + var first = null; + while (i-- > 0) { + var f = fields[i]; + if (flag) f.bindable = false; + else if (!f.bindable) { + flag = true; + if (first == null) first = f; + } + } + if (flag) { + Context.warning('expr in not full bindable. Can bind only "${first.e.toString()}"', expr.pos); + } + var chain = prepareBindChain(fields, listener, expr.pos); var res = macro $b { chain.bind.concat(chain.init).concat([macro function __unbind__():Void $b { chain.unbind } ]) }; - trace(new Printer().printExpr(res)); + //trace(new Printer().printExpr(res)); return res; } @@ -105,7 +122,6 @@ class BindExt { var type = Context.typeof(field.e).toComplexType(); - var callPrev = macro $prevListenerNameExpr($a { prev.params != null ? [] : [macro null, macro n != null ? n.$fieldName : null] } ); if (prev.bindable) { var unbind = BindMacros.bindingSignalProvider.getClassFieldUnbindExpr(valueExpr, prev.field, prevListenerNameExpr ); @@ -117,6 +133,7 @@ class BindExt { fieldListenerBody.push(macro if (n != null) $ { BindMacros.bindingSignalProvider.getClassFieldBindExpr(macro n, prev.field, prevListenerNameExpr ) }); } + var callPrev = macro $prevListenerNameExpr($a { prev.params != null ? [] : [macro null, macro n != null ? n.$fieldName : null] } ); fieldListenerBody.push(callPrev); if (field.params != null) { @@ -140,7 +157,7 @@ class BindExt { prevListenerNameExpr = listenerNameExpr; } - if (zeroListener == null) { + if (zeroListener == null || zeroListener.f.bindable == false) { Context.error("Chain is not bindable", pos); } diff --git a/test/ChainBindTest.hx b/test/ChainBindTest.hx index af1e20a..e259326 100644 --- a/test/ChainBindTest.hx +++ b/test/ChainBindTest.hx @@ -16,17 +16,59 @@ class ChainBindTest extends BuddySuite { var val:String; var b:BindableChain; - var b2:BindableChain; var callNum:Int; before({ val = "a"; b = new BindableChain(4); - b2 = new BindableChain(4); callNum = 0; }); + it("BindExt.chain should bind chain changes (unset links)", { + b.c.c.d = val; + + var unbind = BindExt.chain(b.c.c.d, function (_, t:String) { + callNum++; + t.should.be(val); + }); + + callNum.should.be(1); + + val = null; + b.c = null; + callNum.should.be(2); + + b.c = new BindableChain(2); + callNum.should.be(3); // d null value change to null value + + b.c.c.d = val = "b"; + callNum.should.be(4); + + val = null; + b.c.c = null; + callNum.should.be(5); + }); + + it("BindExt.chain should bind chain changes (null links)", { + b.c = null; + val = null; + + var unbind = BindExt.chain(b.c.c.d, function (_, t:String) { + callNum++; + t.should.be(val); + }); + + callNum.should.be(1); + + b.c = new BindableChain(2); + callNum.should.be(2); + + b.c.c.d = val = "b"; + callNum.should.be(3); + }); + it("BindExt.chain should bind chain changes (0 gap)", { + var b2 = new BindableChain(4); b.c.c.f("tada").d = val; b2.c.c.f("tada").d = val; var unbind = BindExt.chain(b.c.c.f("tada").d, function (_, t:String) { @@ -60,38 +102,59 @@ class ChainBindTest extends BuddySuite { callNum.should.be(1); - b.c.nc.c.f("tada").d = val = "b"; - callNum.should.be(2); + b.c.nc.c.f("tada").d = val = "b"; // nc gap + callNum.should.be(1); + var b2 = new BindableChain(4); b2.c.nc.c.f("tada").d = val = "c"; var t = b.c; b.c = b2.c; - callNum.should.be(3); + callNum.should.be(2); val = t.nc.c.f("tada").d; b.c = t; - callNum.should.be(4); + callNum.should.be(3); b2.c.nc.c.f("tada").d = val = "d"; b.c.nc.c = b2.c.nc.c; - callNum.should.be(5); + callNum.should.be(3); // nc gap unbind(); b.c.nc.c.f("tada").d = "c"; - callNum.should.be(5); + callNum.should.be(3); }); it("BindExt.chain should bind chain changes (double gap)", { - b.c.d = "a"; + b.c.nc.nc.d = "a"; - BindExt.chain(b.c.d, function (_, _) callNum++); + BindExt.chain(b.c.nc.nc.d, function (_, t:String) { + callNum++; + t.should.be(val); + }); callNum.should.be(1); + var b2 = new BindableChain(2); b2.d = "b"; + b.c.nc.nc = b2; + + callNum.should.be(1); + + b2 = new BindableChain(3); + b2.nc.d = "c"; + b.c.nc = b2; + + callNum.should.be(1); + + b.c.nc.nc.d = val = "d"; + + callNum.should.be(1); + + b2 = new BindableChain(3); + b2.nc.nc.d = val = "e"; b.c = b2; callNum.should.be(2);