Index: TODO =================================================================== diff -u -rfd2ab350d77416892fadf797132b86bcafa5e87a -r15a93252f0d9d8961ded6fd8f9b610a535ddbdb5 --- TODO (.../TODO) (revision fd2ab350d77416892fadf797132b86bcafa5e87a) +++ TODO (.../TODO) (revision 15a93252f0d9d8961ded6fd8f9b610a535ddbdb5) @@ -5382,12 +5382,16 @@ ResetOrderOfObjectsUsingThisClassAsObjectMixin() - used consistenlty DependentSubClasses() instead of TransitiveSubClasses() for invalidations. -- extend regression test +- extended regression test + +nsf.c: +- added option "-dependent" to "info subclass" +- extended regression test + ======================================================================== TODO: -- maybe add "/cl/ info subclasses -dependent" to return union of - transitive closure + class mixins. +- shouldn't "info subclass" be named "info subclasses"? - how should we treat cyclic subclass relationships built via class mixins. (either complain at mixin registration or soft warnings or ignoring - Index: generic/nsf.c =================================================================== diff -u -re014a6a18a4801102162659f5156600ebd0f7c85 -r15a93252f0d9d8961ded6fd8f9b610a535ddbdb5 --- generic/nsf.c (.../nsf.c) (revision e014a6a18a4801102162659f5156600ebd0f7c85) +++ generic/nsf.c (.../nsf.c) (revision 15a93252f0d9d8961ded6fd8f9b610a535ddbdb5) @@ -29685,21 +29685,27 @@ /* classInfoMethod subclass NsfClassInfoSubclassMethod { - {-argName "-closure" -nrargs 0} + {-argName "-closure" -nrargs 0 -type switch} + {-argName "-dependent" -nrargs 0 -type switch} {-argName "pattern" -type objpattern} } */ static int -NsfClassInfoSubclassMethod(Tcl_Interp *interp, NsfClass *class, int withClosure, - CONST char *patternString, NsfObject *patternObj) { +NsfClassInfoSubclassMethod(Tcl_Interp *interp, NsfClass *class, + int withClosure, int withDependent, + CONST char *patternString, NsfObject *patternObj) { int rc = 0; assert(interp); assert(class); - if (withClosure) { - NsfClasses *subClasses = TransitiveSubClasses(class); + if (withClosure && withDependent) { + return NsfPrintError(interp, "only -closure or -dependent can be specified, not both"); + } + if (withClosure || withDependent) { + NsfClasses *subClasses = withClosure ? TransitiveSubClasses(class) : DependentSubClasses(class); + if (subClasses) { rc = AppendMatchingElementsFromClasses(interp, subClasses, patternString, patternObj); NsfClassListFree(subClasses); Index: generic/nsfAPI.decls =================================================================== diff -u -rd86805a2250aaa861470d4f4a13945d603585aca -r15a93252f0d9d8961ded6fd8f9b610a535ddbdb5 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision d86805a2250aaa861470d4f4a13945d603585aca) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 15a93252f0d9d8961ded6fd8f9b610a535ddbdb5) @@ -545,6 +545,7 @@ } classInfoMethod subclass NsfClassInfoSubclassMethod { {-argName "-closure" -nrargs 0 -type switch} + {-argName "-dependent" -nrargs 0 -type switch} {-argName "pattern" -type objpattern} } classInfoMethod superclass NsfClassInfoSuperclassMethod { Index: generic/nsfAPI.h =================================================================== diff -u -rd86805a2250aaa861470d4f4a13945d603585aca -r15a93252f0d9d8961ded6fd8f9b610a535ddbdb5 --- generic/nsfAPI.h (.../nsfAPI.h) (revision d86805a2250aaa861470d4f4a13945d603585aca) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 15a93252f0d9d8961ded6fd8f9b610a535ddbdb5) @@ -550,7 +550,7 @@ NSF_nonnull(1) NSF_nonnull(2) NSF_nonnull(3); static int NsfClassInfoSlotobjectsMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, int withSource, NsfClass *withType, CONST char *pattern) NSF_nonnull(1) NSF_nonnull(2); -static int NsfClassInfoSubclassMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, CONST char *patternString, NsfObject *patternObject) +static int NsfClassInfoSubclassMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, int withDependent, CONST char *patternString, NsfObject *patternObject) NSF_nonnull(1) NSF_nonnull(2); static int NsfClassInfoSuperclassMethod(Tcl_Interp *interp, NsfClass *cl, int withClosure, Tcl_Obj *pattern) NSF_nonnull(1) NSF_nonnull(2); @@ -1347,20 +1347,21 @@ method_definitions[NsfClassInfoSubclassMethodIdx].nrParameters, 0, NSF_ARGPARSE_BUILTIN, &pc) == TCL_OK)) { int withClosure = (int )PTR2INT(pc.clientData[0]); + int withDependent = (int )PTR2INT(pc.clientData[1]); CONST char *patternString = NULL; NsfObject *patternObject = NULL; - Tcl_Obj *pattern = (Tcl_Obj *)pc.clientData[1]; + Tcl_Obj *pattern = (Tcl_Obj *)pc.clientData[2]; int returnCode; - if (GetMatchObject(interp, pattern, objc>1 ? objv[1] : NULL, &patternObject, &patternString) == -1) { + if (GetMatchObject(interp, pattern, objc>2 ? objv[2] : NULL, &patternObject, &patternString) == -1) { if (pattern) { DECR_REF_COUNT2("patternObj", pattern); } return TCL_OK; } assert(pc.status == 0); - returnCode = NsfClassInfoSubclassMethod(interp, cl, withClosure, patternString, patternObject); + returnCode = NsfClassInfoSubclassMethod(interp, cl, withClosure, withDependent, patternString, patternObject); if (pattern) { DECR_REF_COUNT2("patternObj", pattern); @@ -3285,8 +3286,9 @@ {"-type", 0, 1, Nsf_ConvertTo_Class, NULL,NULL,"class",NULL,NULL,NULL,NULL,NULL}, {"pattern", 0, 1, Nsf_ConvertTo_String, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, -{"::nsf::methods::class::info::subclass", NsfClassInfoSubclassMethodStub, 2, { +{"::nsf::methods::class::info::subclass", NsfClassInfoSubclassMethodStub, 3, { {"-closure", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, + {"-dependent", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, {"pattern", 0, 1, ConvertToObjpattern, NULL,NULL,"objpattern",NULL,NULL,NULL,NULL,NULL}} }, {"::nsf::methods::class::info::superclass", NsfClassInfoSuperclassMethodStub, 2, { Index: tests/properties.test =================================================================== diff -u -re014a6a18a4801102162659f5156600ebd0f7c85 -r15a93252f0d9d8961ded6fd8f9b610a535ddbdb5 --- tests/properties.test (.../properties.test) (revision e014a6a18a4801102162659f5156600ebd0f7c85) +++ tests/properties.test (.../properties.test) (revision 15a93252f0d9d8961ded6fd8f9b610a535ddbdb5) @@ -1049,6 +1049,11 @@ ? {c1 info precedence} "::C ::nx::Object" ? {d1 info precedence} "::D ::C ::nx::Object" + ? {C info subclass -dependent} "::C ::D" + ? {C info subclass -closure} "::C ::D" + ? {M0 info subclass -dependent} "::M0 ::M1 ::M2" + ? {M0 info subclass -closure} "::M0 ::M1 ::M2" + #puts stderr =========C-mixin-add-M2 C mixin add M2 #puts stderr ========= @@ -1062,6 +1067,12 @@ ? {C info heritage} "::M2 ::M1 ::M0 ::nx::Object" ? {D info heritage} "::M2 ::M1 ::M0 ::C ::nx::Object" + ? {C info subclass -dependent} "::C ::D" + ? {C info subclass -closure} "::C ::D" + ? {M0 info subclass -dependent} "::M0 ::M1 ::M2 ::C ::D" + ? {M0 info subclass -closure} "::M0 ::M1 ::M2" + + # Only M2 is a direct mixin, visible through "mixinof", # but query-able via transitive -closure operator