Index: TODO =================================================================== diff -u -r56fc3af13d127cdfa54db9c89e8d44308b72bba9 -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 --- TODO (.../TODO) (revision 56fc3af13d127cdfa54db9c89e8d44308b72bba9) +++ TODO (.../TODO) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) @@ -2822,17 +2822,24 @@ - migration-guide: add third level to toc - fix regression test for 8.6 to use nx prefix +- nsf.c: added cmd "::nsd::method::registered /handle/" that returns + the object on which the method identified by the handle was registered, + or empty. +- extended regression test + + TODO: - add "link" form 2.4 (parameters) to "info parameters" - MixinComputeOrderFullList() could receive a flag to store source classes in checkList - if the check on eg. info-heritage-circular in test/info.method.tcl - fails, we get an exception. + reports a warning on exit, if we get an exception. +- should be be concerned about message like + DEBUG obj 0x100227960 ::nx::Object activationcount 2 on stack 3; might be from non-stacked but active callstack content + in the regression test? -- ::nsf::method::exists /handle/ -> check, if handle is a handle of a registered method - (to be be used in serializer alias-dependency) - profiling missing when NSF_INVOKE_SHADOWED_TRADITIONAL is turned off. - maybe change nx::Test to nx::test (user never has to know that nx::Test is a class). Index: generic/gentclAPI.decls =================================================================== diff -u -re29434ffef30bea10b7422f1f295787d41377839 -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 --- generic/gentclAPI.decls (.../gentclAPI.decls) (revision e29434ffef30bea10b7422f1f295787d41377839) +++ generic/gentclAPI.decls (.../gentclAPI.decls) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) @@ -102,6 +102,9 @@ {-argName "methodproperty" -required 1 -type "class-only|call-protected|redefine-protected|returns|slotcontainer|slotobj"} {-argName "value" -type tclobj} } +cmd "method::registered" NsfMethodRegisteredCmd { + {-argName "handle" -required 1 -type tclobj} +} cmd "method::setter" NsfSetterCmd { {-argName "object" -required 1 -type object} {-argName "-per-object"} Index: generic/nsf.c =================================================================== diff -u -r046e5f798cbb4ce5473fb11da8e63a3db998a376 -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 --- generic/nsf.c (.../nsf.c) (revision 046e5f798cbb4ce5473fb11da8e63a3db998a376) +++ generic/nsf.c (.../nsf.c) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) @@ -16431,6 +16431,33 @@ } /* +cmd "method::registered" NsfMethodRegisteredCmd { + {-argName "handle" -required 1 -type tclobj} +} +*/ +static int +NsfMethodRegisteredCmd(Tcl_Interp *interp, Tcl_Obj *methodNameObj) { + NsfObject *regObject, *defObject; + CONST char *methodName1 = NULL; + int fromClassNS = 0; + Tcl_DString ds, *dsPtr = &ds; + Tcl_Command cmd; + + Tcl_DStringInit(dsPtr); + cmd = ResolveMethodName(interp, NULL, methodNameObj, + dsPtr, ®Object, &defObject, &methodName1, &fromClassNS); + /* + * In case the provided cmd is fully qualified and refers to a registered + * method, the function returns the object, on which the method was + * registed. + */ + Tcl_SetObjResult(interp, (cmd && regObject) ? regObject->cmdName : NsfGlobalObjs[NSF_EMPTY]); + + Tcl_DStringFree(dsPtr); + return TCL_OK; +} + +/* nsfCmd my NsfMyCmd { {-argName "-local"} {-argName "method" -required 1 -type tclobj} Index: generic/tclAPI.h =================================================================== diff -u -re29434ffef30bea10b7422f1f295787d41377839 -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 --- generic/tclAPI.h (.../tclAPI.h) (revision e29434ffef30bea10b7422f1f295787d41377839) +++ generic/tclAPI.h (.../tclAPI.h) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) @@ -237,6 +237,7 @@ static int NsfMethodCreateCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfMethodDeleteCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfMethodPropertyCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); +static int NsfMethodRegisteredCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfMyCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfNSCopyCmdsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfNSCopyVarsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); @@ -329,6 +330,7 @@ static int NsfMethodCreateCmd(Tcl_Interp *interp, NsfObject *object, int withInner_namespace, int withPer_object, NsfObject *withReg_object, Tcl_Obj *methodName, Tcl_Obj *arguments, Tcl_Obj *body, Tcl_Obj *withPrecondition, Tcl_Obj *withPostcondition); static int NsfMethodDeleteCmd(Tcl_Interp *interp, NsfObject *object, int withPer_object, Tcl_Obj *methodName); static int NsfMethodPropertyCmd(Tcl_Interp *interp, NsfObject *object, int withPer_object, Tcl_Obj *methodName, int methodproperty, Tcl_Obj *value); +static int NsfMethodRegisteredCmd(Tcl_Interp *interp, Tcl_Obj *handle); static int NsfMyCmd(Tcl_Interp *interp, int withLocal, Tcl_Obj *methodName, int nobjc, Tcl_Obj *CONST nobjv[]); static int NsfNSCopyCmdsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs); static int NsfNSCopyVarsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs); @@ -422,6 +424,7 @@ NsfMethodCreateCmdIdx, NsfMethodDeleteCmdIdx, NsfMethodPropertyCmdIdx, + NsfMethodRegisteredCmdIdx, NsfMyCmdIdx, NsfNSCopyCmdsCmdIdx, NsfNSCopyVarsCmdIdx, @@ -1343,6 +1346,22 @@ } static int +NsfMethodRegisteredCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + (void)clientData; + + + + if (objc != 2) { + return NsfArgumentError(interp, "wrong # of arguments:", + method_definitions[NsfMethodRegisteredCmdIdx].paramDefs, + NULL, objv[0]); + } + + return NsfMethodRegisteredCmd(interp, objc == 2 ? objv[1] : NULL); + +} + +static int NsfMyCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { ParseContext pc; (void)clientData; @@ -2442,6 +2461,9 @@ {"methodproperty", NSF_ARG_REQUIRED|NSF_ARG_IS_ENUMERATION, 0, ConvertToMethodproperty, NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"value", 0, 0, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, +{"::nsf::method::registered", NsfMethodRegisteredCmdStub, 1, { + {"handle", NSF_ARG_REQUIRED, 0, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL}} +}, {"::nsf::my", NsfMyCmdStub, 3, { {"-local", 0, 0, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"methodName", NSF_ARG_REQUIRED, 0, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL}, Index: library/serialize/serializer.tcl =================================================================== diff -u -r5972bd087afec6d23d1192d552a29c92e570d8a6 -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 --- library/serialize/serializer.tcl (.../serializer.tcl) (revision 5972bd087afec6d23d1192d552a29c92e570d8a6) +++ library/serialize/serializer.tcl (.../serializer.tcl) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) @@ -674,17 +674,15 @@ # # The aliasedCmd is fully qualified and could be a method # handle or a primitive cmd. For a primitive cmd, we have no - # alias dependency. Currently we check here only, of we can - # obtain the method definition for this handle. It would be - # better to use ::nsf::method::exists when implemented. + # alias dependency. If the cmd is registed on an object, we + # report the dependency. # - set source [::nx::Object ::nsf::methods::class::info::method definition $aliasedCmd] - if {$source ne ""} { - set obj [lindex $source 0] - if {$obj eq $x} { + set regObj [::nsf::method::registered $aliasedCmd] + if {$regObj ne ""} { + if {$regObj eq $x} { :warn "Dependency for alias $alias from $x to $x not handled (no guarantee on method order)" } else { - lappend needed [lindex $source 0] + lappend needed $regObj } } } Index: tests/info-method.test =================================================================== diff -u -r679a4d086fb9b8a728e0d33f5fa6520f2ce2f954 -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 --- tests/info-method.test (.../info-method.test) (revision 679a4d086fb9b8a728e0d33f5fa6520f2ce2f954) +++ tests/info-method.test (.../info-method.test) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) @@ -897,4 +897,38 @@ ? {B info mixin classes -heritage} "::TPCMB ::TPCMA ::PCMB ::PCMA ::A" ? {C info mixin classes -heritage} "::PCMC ::TPCMB ::TPCMA ::PCMB ::PCMA ::A" +} + +# +# ::nsf::method::ishandle +# +nx::Test case method-isregistered { + + ? {::nsf::method::registered c} "" + ? {::nsf::method::registered info} "" + ? {::nsf::method::registered ::info} "" + + Class create C { + :method bar {} {return bar} + set h1 [:info method handle bar] + ? [list set _ $h1] "::nsf::classes::C::bar" + ? [list [self] info method handle bar] "::nsf::classes::C::bar" + + ? [list ::nsf::method::registered $h1] ::C + + :class method bar {} {return bar} + set h2 [:class info method handle bar] + ? [list [self] class info method handle bar] "::C::bar" + + ? [list ::nsf::method::registered $h2] ::C + } + + Object create o { + :method bar {} {return bar} + set h1 [:info method handle bar] + ? [list set _ $h1] "::o::bar" + ? [list [self] info method handle bar] "::o::bar" + + ? [list ::nsf::method::registered $h1] ::o + } } \ No newline at end of file