Index: TODO =================================================================== diff -u -rf671281a240219965d436e2bfa762baf85274ca6 -r24cc5e107fd8d246061a9d4b4fafefc767811c2b --- TODO (.../TODO) (revision f671281a240219965d436e2bfa762baf85274ca6) +++ TODO (.../TODO) (revision 24cc5e107fd8d246061a9d4b4fafefc767811c2b) @@ -5122,6 +5122,10 @@ - use "mixin|filter clear" instead of "mixin|filter unset" - name parameter option "slotset" instead of "slotassign" +nsfObj.c: +- allow to omit "-guard" within arguments to flag + definition of a filter/mixin guard +- extended regression test ======================================================================== TODO: Index: generic/nsfObj.c =================================================================== diff -u -r92ab630ebd3c1b907e3d0fdf97cc07914245c028 -r24cc5e107fd8d246061a9d4b4fafefc767811c2b --- generic/nsfObj.c (.../nsfObj.c) (revision 92ab630ebd3c1b907e3d0fdf97cc07914245c028) +++ generic/nsfObj.c (.../nsfObj.c) (revision 24cc5e107fd8d246061a9d4b4fafefc767811c2b) @@ -410,21 +410,28 @@ int oc; Tcl_Obj **ov; if (Tcl_ListObjGetElements(interp, objPtr, &oc, &ov) == TCL_OK) { - if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { + + if (oc == 1) { nameObj = ov[0]; - guardObj = ov[2]; - /* fprintf(stderr, "mixinadd name = '%s', guard = '%s'\n", ObjStr(nameObj), ObjStr(guardObj));*/ - } else if (oc == 1) { + + } else if (oc == 2) { nameObj = ov[0]; + guardObj = ov[1]; + + } else if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { + nameObj = ov[0]; + guardObj = ov[2]; + } else { return TCL_ERROR; } + } else { return TCL_ERROR; } /* - * Try to resolve unknowns + * Syntax was ok. Try to lookup mixin classes: */ if (NsfGetClassFromObj(interp, nameObj, &mixin, 1) != TCL_OK) { return NsfObjErrType(interp, "mixin", nameObj, "a class as mixin", NULL); @@ -600,16 +607,21 @@ int oc; Tcl_Obj **ov; if (Tcl_ListObjGetElements(interp, objPtr, &oc, &ov) == TCL_OK) { - if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { + if (oc == 1) { filterObj = ov[0]; - guardObj = ov[2]; - /*fprintf(stderr, "filteradd name = '%s', guard = '%s'\n", ObjStr(name), ObjStr(guard));*/ - } else if (oc == 1) { + + } else if (oc == 2) { filterObj = ov[0]; + guardObj = ov[1]; + + } else if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { + filterObj = ov[0]; + guardObj = ov[2]; + } else { return TCL_ERROR; } - } else { + } else { return TCL_ERROR; } Index: tests/interceptor-slot.test =================================================================== diff -u -rae7d7d03bf76d21dd52d45181c3ab310e51845ec -r24cc5e107fd8d246061a9d4b4fafefc767811c2b --- tests/interceptor-slot.test (.../interceptor-slot.test) (revision ae7d7d03bf76d21dd52d45181c3ab310e51845ec) +++ tests/interceptor-slot.test (.../interceptor-slot.test) (revision 24cc5e107fd8d246061a9d4b4fafefc767811c2b) @@ -438,8 +438,162 @@ ? {c1 [Y info method definitionhandle bar]} "Z Y " } +# +# Test filter guards (define filter and guard separtely) +# +nx::test case filter-guard-separately { + + # + # Define a room with occupancy and methods for entering and leaving + # + nx::Class create Room { + :property name + :variable occupancy:integer 0 + + :public method enter {name} {incr ::occupancy} + :public method leave {name} {incr ::occupancy -1} + + # + # We are interested, what happens with the room, so we define a + # logging filter.... + # + :method loggingFilter args { + lappend ::_ [current calledmethod] + next + } + + # + # ... and we register it. + # + :filter add loggingFilter + } + + set ::_ {} + + ? {Room create r} ::r + r enter Uwe + r leave Uwe + r configure -name "Office" + ? {set ::_} "__objectparameter init enter leave configure" + + # + # Hmm, we not so much interested on all these calls. Just the + # "enter" and "leave" operations are fine. We could have certainly + # as well mixin for these two methods, but the guards are more + # general since the can as well trigger on arbitrary patterns. + # + + Room filter guard loggingFilter { + [current calledmethod] in {enter leave} + } + + r destroy + set ::_ {} + + ? {Room create r} ::r + r enter Uwe + r leave Uwe + r configure -name "Office" + ? {set ::_} "enter leave" + + r destroy + + # Now we define a subclass DangerRoom, which refines the filter by + # logging into a "dangerRoomLog". We want here entries for all + # operations. + + set ::_ {} + set ::dangerRoomLog {} + + nx::Class create DangerRoom -superclass Room { + :method loggingFilter args { + lappend ::dangerRoomLog [current calledmethod] + next + } + :filter add loggingFilter + } + + ? {DangerRoom create d} ::d + d enter Uwe + d leave Uwe + d configure -name "Safe Room" + ? {set ::_} "enter leave" + ? {expr [llength $::dangerRoomLog] > 2} 1 + + d destroy + +} + # +# Test filter guards (define filter together with guard) +# + +nx::test case filter-guard-separately { + + # + # Define a room with occupancy and methods for entering and leaving + # + nx::Class create Room { + :property name + :variable occupancy:integer 0 + + :public method enter {name} {incr ::occupancy} + :public method leave {name} {incr ::occupancy -1} + + # + # We are interested, what happens with the room, so we define a + # logging filter.... + # + :method loggingFilter args { + lappend ::_ [current calledmethod] + next + } + + # + # ... and we register it together with a guard. + # + :filter add {loggingFilter { + [current calledmethod] in {enter leave} + }} + } + + set ::_ {} + + ? {Room create r} ::r + r enter Uwe + r leave Uwe + r configure -name "Office" + ? {set ::_} "enter leave" + + # Now we define a subclass DangerRoom, which refines the filter by + # logging into a "dangerRoomLog". We want here entries for all + # operations. + + set ::_ {} + set ::dangerRoomLog {} + + nx::Class create DangerRoom -superclass Room { + + :method loggingFilter args { + lappend ::dangerRoomLog [current calledmethod] + next + } + :filter add loggingFilter + } + + ? {DangerRoom create d} ::d + d enter Uwe + d leave Uwe + d configure -name "Safe Room" + ? {set ::_} "enter leave" + ? {expr [llength $::dangerRoomLog] > 2} 1 + + d destroy +} + + +# # Local variables: # mode: tcl # tcl-indent-level: 2