Index: TODO =================================================================== diff -u -rf41ae7e802868efee95b5d5682edfdbbe9ba2f64 -ra390a38437dec2a7c3461f9fadef108ebf74b928 --- TODO (.../TODO) (revision f41ae7e802868efee95b5d5682edfdbbe9ba2f64) +++ TODO (.../TODO) (revision a390a38437dec2a7c3461f9fadef108ebf74b928) @@ -3645,7 +3645,13 @@ * extended method resolution section * documented invocation flags for colon +- nsf.c: + * add flags "-closure" and "-source" to "/cls/ info methods" + (the cases for "/obj/ info methods" are already covered by + "/obj/ info lookup methods") + * extend regression test + TODO: - warnings for "numeric" names for args and nonpos-args? - special handling of values looking like nonpos-flags, Index: generic/nsf.c =================================================================== diff -u -r69f3a8652d6215433837d0335a66b4d7e85110cb -ra390a38437dec2a7c3461f9fadef108ebf74b928 --- generic/nsf.c (.../nsf.c) (revision 69f3a8652d6215433837d0335a66b4d7e85110cb) +++ generic/nsf.c (.../nsf.c) (revision a390a38437dec2a7c3461f9fadef108ebf74b928) @@ -306,7 +306,7 @@ static int SetInstVar(Tcl_Interp *interp, NsfObject *object, Tcl_Obj *nameObj, Tcl_Obj *valueObj); static int ListDefinedMethods(Tcl_Interp *interp, NsfObject *object, CONST char *pattern, int withPer_object, int methodType, int withCallproctection, - int withExpand); + int withPath); static int NextSearchAndInvoke(Tcl_Interp *interp, CONST char *methodName, int objc, Tcl_Obj *CONST objv[], NsfCallStackContent *cscPtr, int freeArgumentVector); @@ -16909,7 +16909,8 @@ static int MethodTypeMatches(Tcl_Interp *interp, int methodType, Tcl_Command cmd, - NsfObject *object, CONST char *methodName, int withPer_object, int *isObject) { + NsfObject *object, CONST char *methodName, int withPer_object, + int *isObject) { Tcl_Command importedCmd; Tcl_ObjCmdProc *proc, *resolvedProc; @@ -17012,7 +17013,7 @@ static int ListMethodKeys(Tcl_Interp *interp, Tcl_HashTable *tablePtr, Tcl_DString *prefix, CONST char *pattern, - int methodType, int withCallprotection, int withExpand, + int methodType, int withCallprotection, int withPath, Tcl_HashTable *dups, NsfObject *object, int withPer_object) { Tcl_HashSearch hSrch; Tcl_HashEntry *hPtr; @@ -17039,7 +17040,7 @@ if (Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD && !NsfObjectIsClass(object)) { return TCL_OK; } - if (isObject && withExpand) { + if (isObject && withPath) { return TCL_OK; } @@ -17070,8 +17071,7 @@ if (prefixLength) {Tcl_DStringTrunc(prefix, prefixLength);} methodTypeMatch = MethodTypeMatches(interp, methodType, cmd, object, key, withPer_object, &isObject); - - if (isObject && withExpand) { + if (isObject && withPath) { Tcl_DString ds, *dsPtr = &ds; NsfObject *ensembleObject = NsfGetObjectFromCmdPtr(cmd); Tcl_HashTable *cmdTablePtr = ensembleObject && ensembleObject->nsPtr ? @@ -17235,7 +17235,7 @@ static int ListDefinedMethods(Tcl_Interp *interp, NsfObject *object, CONST char *pattern, int withPer_object, int methodType, int withCallproctection, - int withExpand) { + int withPath) { Tcl_HashTable *cmdTablePtr; Tcl_DString ds, *dsPtr = NULL; @@ -17273,7 +17273,7 @@ } if (cmdTablePtr) { - ListMethodKeys(interp, cmdTablePtr, dsPtr, pattern, methodType, withCallproctection, withExpand, + ListMethodKeys(interp, cmdTablePtr, dsPtr, pattern, methodType, withCallproctection, withPath, NULL, object, withPer_object); if (dsPtr) { Tcl_DStringFree(dsPtr); @@ -21770,12 +21770,32 @@ {-argName "-incontext"} {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} {-argName "-nomixins"} - {-argName "-path"} + {-argName "-path" -nrargs 0} {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} {-argName "pattern" -required 0} } */ static int +ListMethodKeysClassList(Tcl_Interp *interp, NsfClasses *classList, + int withSource, CONST char *pattern, + int methodType, int withCallprotection, + int withPath, Tcl_HashTable *dups, + NsfObject *object, int withPer_object) { + NsfClasses *pl; + + /* append method keys from inheritance order */ + for (pl = classList; pl; pl = pl->nextPtr) { + Tcl_HashTable *cmdTablePtr = Tcl_Namespace_cmdTablePtr(pl->cl->nsPtr); + + if (!MethodSourceMatches(withSource, pl->cl, NULL)) continue; + ListMethodKeys(interp, cmdTablePtr, NULL, pattern, methodType, + withCallprotection, withPath, + dups, object, withPer_object); + } + return TCL_OK; +} + +static int NsfObjInfoLookupMethodsMethod(Tcl_Interp *interp, NsfObject *object, int withCallprotection, int withIncontext, @@ -21784,10 +21804,9 @@ int withPath, int withSource, CONST char *pattern) { - NsfClasses *pl; int withPer_object = 1; Tcl_HashTable *cmdTablePtr, dupsTable, *dups = &dupsTable; - int methodType = AggregatedMethodType(withMethodtype); + int result, methodType = AggregatedMethodType(withMethodtype); /* * TODO: we could make this faster for patterns without metachars @@ -21839,16 +21858,13 @@ } } - /* append method keys from inheritance order */ - for (pl = ComputeOrder(object->cl, SUPER_CLASSES); pl; pl = pl->nextPtr) { - Tcl_HashTable *cmdTablePtr = Tcl_Namespace_cmdTablePtr(pl->cl->nsPtr); - if (!MethodSourceMatches(withSource, pl->cl, NULL)) continue; - ListMethodKeys(interp, cmdTablePtr, NULL, pattern, methodType, - withCallprotection, withPath, - dups, object, withPer_object); - } + result = ListMethodKeysClassList(interp, ComputeOrder(object->cl, SUPER_CLASSES), + withSource, pattern, + methodType, withCallprotection, + withPath, dups, object, withPer_object); + Tcl_DeleteHashTable(dups); - return TCL_OK; + return result; } /* @@ -21933,7 +21949,7 @@ objectInfoMethod methods NsfObjInfoMethodsMethod { {-argName "-callprotection" -type "all|public|protected|private" -default all} {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} - {-argName "-path"} + {-argName "-path" -nrargs 0} {-argName "pattern"} } */ @@ -22180,7 +22196,7 @@ /* classInfoMethod instances NsfClassInfoInstancesMethod { - {-argName "-closure"} + {-argName "-closure" -nrargs 0} {-argName "pattern" -type objpattern} } */ @@ -22229,25 +22245,65 @@ /* classInfoMethod methods NsfClassInfoMethodsMethod { {-argName "-callprotection" -type "all|public|protected|private" -default all} + {-argName "-closure" -nrargs 0} {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} - {-argName "-path"} + {-argName "-path" -nrargs 0} + {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} {-argName "pattern"} } */ static int NsfClassInfoMethodsMethod(Tcl_Interp *interp, NsfClass *class, - int withCallproctection, + int withCallprotection, + int withClosure, int withMethodtype, int withPath, + int withSource, CONST char *pattern) { - return ListDefinedMethods(interp, &class->object, pattern, 0 /* per-object */, - AggregatedMethodType(withMethodtype), withCallproctection, - withPath); + if (withClosure) { + NsfClasses *checkList = NULL, *mixinClasses = NULL; + Tcl_HashTable dupsTable, *dups = &dupsTable; + int result; + +#if 0 + if (withCallprotection == CallprotectionNULL) { + withCallprotection = CallprotectionPublicIdx; + } +#endif + if (withSource == SourceNULL) { + withSource = SourceAllIdx; + } + + Tcl_InitHashTable(dups, TCL_STRING_KEYS); + /* guards are ignored */ + NsfClassListAddPerClassMixins(interp, class, &mixinClasses, &checkList); + result = ListMethodKeysClassList(interp, mixinClasses, + withSource, pattern, + AggregatedMethodType(withMethodtype), withCallprotection, + withPath, dups, &class->object, 0); + NsfClassListFree(checkList); + NsfClassListFree(mixinClasses); + + result = ListMethodKeysClassList(interp, ComputeOrder(class, SUPER_CLASSES), + withSource, pattern, + AggregatedMethodType(withMethodtype), withCallprotection, + withPath, dups, &class->object, 0); + + Tcl_DeleteHashTable(dups); + return result; + } else { + if (withSource) { + return NsfPrintError(interp, "-source cannot be used without -closure\n"); + } + return ListDefinedMethods(interp, &class->object, pattern, 0 /* per-object */, + AggregatedMethodType(withMethodtype), withCallprotection, + withPath); + } } /* classInfoMethod mixinclasses NsfClassInfoMixinclassesMethod { - {-argName "-closure"} + {-argName "-closure" -nrargs 0} {-argName "-guards"} {-argName "-heritage"} {-argName "pattern" -type objpattern} @@ -22313,7 +22369,7 @@ /* classInfoMethod mixinof NsfClassInfoMixinOfMethod { - {-argName "-closure"} + {-argName "-closure" -nrargs 0} {-argName "-scope" -required 0 -nrargs 1 -type "all|class|object"} {-argName "pattern" -type objpattern} } @@ -22448,7 +22504,7 @@ /* classInfoMethod slots NsfClassInfoSlotobjectsMethod { - {-argName "-closure"} + {-argName "-closure" -nrargs 0} {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} {-argName "-type" -required 0 -nrargs 1 -type class} {-argName "pattern" -required 0} @@ -22518,7 +22574,7 @@ /* classInfoMethod subclass NsfClassInfoSubclassMethod { - {-argName "-closure"} + {-argName "-closure" -nrargs 0} {-argName "pattern" -type objpattern} } */ @@ -22547,7 +22603,7 @@ /* classInfoMethod superclass NsfClassInfoSuperclassMethod { - {-argName "-closure"} + {-argName "-closure" -nrargs 0} {-argName "pattern" -type tclobj} } */ Index: generic/nsfAPI.decls =================================================================== diff -u -r3b654bd0096ee0be729cbdefa63c0d981a708828 -ra390a38437dec2a7c3461f9fadef108ebf74b928 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision a390a38437dec2a7c3461f9fadef108ebf74b928) @@ -350,7 +350,7 @@ objectInfoMethod lookupmethods NsfObjInfoLookupMethodsMethod { {-argName "-callprotection" -type "all|public|protected|private" -default all} {-argName "-incontext" -nrargs 0} - {-argName "-methodtype" -type "all|scripted|builtin|alias|forwarder|object|setter"} + {-argName "-methodtype" -type "all|scripted|builtin|alias|forwarder|object|setter|nsfproc"} {-argName "-nomixins" -nrargs 0} {-argName "-path" -nrargs 0} {-argName "-source" -type "all|application|baseclasses"} @@ -422,8 +422,10 @@ } classInfoMethod methods NsfClassInfoMethodsMethod { {-argName "-callprotection" -type "all|public|protected|private" -default all} - {-argName "-methodtype" -type "all|scripted|builtin|alias|forwarder|object|setter|nsfproc"} + {-argName "-closure" -nrargs 0} + {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter|nsfproc"} {-argName "-path" -nrargs 0} + {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} {-argName "pattern"} } classInfoMethod mixinclasses NsfClassInfoMixinclassesMethod { Index: generic/nsfAPI.h =================================================================== diff -u -r3b654bd0096ee0be729cbdefa63c0d981a708828 -ra390a38437dec2a7c3461f9fadef108ebf74b928 --- generic/nsfAPI.h (.../nsfAPI.h) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision a390a38437dec2a7c3461f9fadef108ebf74b928) @@ -38,40 +38,40 @@ return result; } -enum ScopeIdx {ScopeNULL, ScopeAllIdx, ScopeClassIdx, ScopeObjectIdx}; +enum SourceIdx {SourceNULL, SourceAllIdx, SourceApplicationIdx, SourceBaseclassesIdx}; -static int ConvertToScope(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, +static int ConvertToSource(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static CONST char *opts[] = {"all", "class", "object", NULL}; + static CONST char *opts[] = {"all", "application", "baseclasses", NULL}; (void)pPtr; - result = Tcl_GetIndexFromObj(interp, objPtr, opts, "-scope", 0, &index); + result = Tcl_GetIndexFromObj(interp, objPtr, opts, "-source", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); *outObjPtr = objPtr; return result; } -enum InfoobjectparametersubcmdIdx {InfoobjectparametersubcmdNULL, InfoobjectparametersubcmdListIdx, InfoobjectparametersubcmdNameIdx, InfoobjectparametersubcmdParameterIdx, InfoobjectparametersubcmdParametersyntaxIdx}; +enum ScopeIdx {ScopeNULL, ScopeAllIdx, ScopeClassIdx, ScopeObjectIdx}; -static int ConvertToInfoobjectparametersubcmd(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, +static int ConvertToScope(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static CONST char *opts[] = {"list", "name", "parameter", "parametersyntax", NULL}; + static CONST char *opts[] = {"all", "class", "object", NULL}; (void)pPtr; - result = Tcl_GetIndexFromObj(interp, objPtr, opts, "infoobjectparametersubcmd", 0, &index); + result = Tcl_GetIndexFromObj(interp, objPtr, opts, "-scope", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); *outObjPtr = objPtr; return result; } -enum SourceIdx {SourceNULL, SourceAllIdx, SourceApplicationIdx, SourceBaseclassesIdx}; +enum InfoobjectparametersubcmdIdx {InfoobjectparametersubcmdNULL, InfoobjectparametersubcmdListIdx, InfoobjectparametersubcmdNameIdx, InfoobjectparametersubcmdParameterIdx, InfoobjectparametersubcmdParametersyntaxIdx}; -static int ConvertToSource(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, +static int ConvertToInfoobjectparametersubcmd(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static CONST char *opts[] = {"all", "application", "baseclasses", NULL}; + static CONST char *opts[] = {"list", "name", "parameter", "parametersyntax", NULL}; (void)pPtr; - result = Tcl_GetIndexFromObj(interp, objPtr, opts, "-source", 0, &index); + result = Tcl_GetIndexFromObj(interp, objPtr, opts, "infoobjectparametersubcmd", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); *outObjPtr = objPtr; return result; @@ -322,7 +322,7 @@ static int NsfClassInfoHeritageMethod(Tcl_Interp *interp, NsfClass *cl, CONST char *pattern); static int NsfClassInfoInstancesMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, CONST char *patternString, NsfObject *patternObject); static int NsfClassInfoMethodMethod(Tcl_Interp *interp, NsfClass *cl, int infomethodsubcmd, Tcl_Obj *name); -static int NsfClassInfoMethodsMethod(Tcl_Interp *interp, NsfClass *cl, int withCallprotection, int withMethodtype, int withPath, CONST char *pattern); +static int NsfClassInfoMethodsMethod(Tcl_Interp *interp, NsfClass *cl, int withCallprotection, int withClosure, int withMethodtype, int withPath, int withSource, CONST char *pattern); static int NsfClassInfoMixinOfMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, int withScope, CONST char *patternString, NsfObject *patternObject); static int NsfClassInfoMixinclassesMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, int withGuards, int withHeritage, CONST char *patternString, NsfObject *patternObject); static int NsfClassInfoMixinguardMethod(Tcl_Interp *interp, NsfClass *cl, CONST char *mixin); @@ -796,12 +796,14 @@ return TCL_ERROR; } else { int withCallprotection = (int )PTR2INT(pc.clientData[0]); - int withMethodtype = (int )PTR2INT(pc.clientData[1]); - int withPath = (int )PTR2INT(pc.clientData[2]); - CONST char *pattern = (CONST char *)pc.clientData[3]; + int withClosure = (int )PTR2INT(pc.clientData[1]); + int withMethodtype = (int )PTR2INT(pc.clientData[2]); + int withPath = (int )PTR2INT(pc.clientData[3]); + int withSource = (int )PTR2INT(pc.clientData[4]); + CONST char *pattern = (CONST char *)pc.clientData[5]; assert(pc.status == 0); - return NsfClassInfoMethodsMethod(interp, cl, withCallprotection, withMethodtype, withPath, pattern); + return NsfClassInfoMethodsMethod(interp, cl, withCallprotection, withClosure, withMethodtype, withPath, withSource, pattern); } } @@ -2446,10 +2448,12 @@ {"infomethodsubcmd", 0|NSF_ARG_IS_ENUMERATION, 1, ConvertToInfomethodsubcmd, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"name", NSF_ARG_REQUIRED, 1, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, -{"::nsf::methods::class::info::methods", NsfClassInfoMethodsMethodStub, 4, { +{"::nsf::methods::class::info::methods", NsfClassInfoMethodsMethodStub, 6, { {"-callprotection", 0|NSF_ARG_IS_ENUMERATION, 1, ConvertToCallprotection, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, + {"-closure", 0, 0, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"-methodtype", 0|NSF_ARG_IS_ENUMERATION, 1, ConvertToMethodtype, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"-path", 0, 0, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, + {"-source", 0|NSF_ARG_IS_ENUMERATION, 1, ConvertToSource, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"pattern", 0, 1, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, {"::nsf::methods::class::info::mixinof", NsfClassInfoMixinOfMethodStub, 3, { Index: tests/info-method.test =================================================================== diff -u -rd62bca12731d1c7a1a5cf63f950275852c5b05a2 -ra390a38437dec2a7c3461f9fadef108ebf74b928 --- tests/info-method.test (.../info-method.test) (revision d62bca12731d1c7a1a5cf63f950275852c5b05a2) +++ tests/info-method.test (.../info-method.test) (revision a390a38437dec2a7c3461f9fadef108ebf74b928) @@ -983,4 +983,43 @@ ? {set implHandle [o public method "foo bar" {x} {;}]} "::o::foo::bar" ? {set regHandle [o info method handle "foo bar"]} "::o::foo bar" ? {set origin [o info method origin "foo bar"]} "::o::foo::bar" +} + +# +# test "info methods -closure" +# + +nx::Test case info-methods-closure { + nx::Class create C { + :public method c1 {} {...} + :method c2 {} {...} + } + + nx::Class create D -superclass C { + :public method c1 {} {...} + :public method d1 {} {...} + :method d2 {} {...} + } + + nx::Class create M { + :public method m1 {} {...} + :method m2 {} {...} + } + + ? {D info methods} "c1 d1 d2" + + # + # info methods -closure lists instance methods + # + ? {D info methods -closure *2} "d2 c2" + ? {D info methods -closure -source application} "c1 d1 d2 c2" + + D mixin M + + # + # Check as well methods inherited from per-class mixins + # + ? {D info methods} "c1 d1 d2" + ? {D info methods -closure *2} "m2 d2 c2" + ? {D info methods -closure -source application} "m1 m2 c1 d1 d2 c2" } \ No newline at end of file