Index: TODO =================================================================== diff -u -r2a11cb4bf319c9aa366aaf0906604ff0efa43ff2 -rbd69e3a318c530a893bcf86b2d6d41f7064d3c07 --- TODO (.../TODO) (revision 2a11cb4bf319c9aa366aaf0906604ff0efa43ff2) +++ TODO (.../TODO) (revision bd69e3a318c530a893bcf86b2d6d41f7064d3c07) @@ -2762,6 +2762,8 @@ - nsf.c: removed all but one occurrence of Tcl_AppendElement() - nsf.c: removed all occurrences of Tcl_AppendElement() - nsf.c: passed around resultObj explicitly +- nsf.c: fix and document GetMatchObject() +- extend regression test TODO: @@ -2771,7 +2773,6 @@ * "info slots", "info parameter" is not in the migration guide * add method delete to the migration guide -- shouldn't GetMatchObject() return -1 instead of 1? - MixinComputeOrderFullList() could receive a flag to store source classes in checkList - if the check on eg. info-heritage-circular in test/info.method.tcl Index: generic/nsf.c =================================================================== diff -u -r2a11cb4bf319c9aa366aaf0906604ff0efa43ff2 -rbd69e3a318c530a893bcf86b2d6d41f7064d3c07 --- generic/nsf.c (.../nsf.c) (revision 2a11cb4bf319c9aa366aaf0906604ff0efa43ff2) +++ generic/nsf.c (.../nsf.c) (revision bd69e3a318c530a893bcf86b2d6d41f7064d3c07) @@ -5420,9 +5420,10 @@ NsfObject *object = (NsfObject *)cls->cl; if (object) { if (matchObject && object == matchObject) { - /* we have a matchObject and it is identical to obj, - just return true and don't continue search - */ + /* + * We have a matchObject and it is identical to obj, + * just return true and don't continue search + */ return 1; break; } else { @@ -9313,14 +9314,38 @@ return result; } +/* + *---------------------------------------------------------------------- + * ConvertToObjpattern -- + * + * This function obtains a Tcl_Obj *, which contains the pattern if an Next + * Scripting Object. When this pattern contains no meta characters, we + * check if the object exists. If it exists, the Tcl_Obj is converted to + * the cmd-type. If it does not exit, the function using this pattern will + * fail. If the pattern contains meta characters, we prepend to the pattern + * "::" if necessary to avoid errors, if one specifies a pattern object + * without the prefix. In this case, the patternObj is is of plain type. + * The resulting patternObj has always the refcount incremented, which has + * to be decremented by the caller.x + * + * Results: + * Tcl result code. + * + * Side effects: + * Incremented refcount for the patternObj. + * + *---------------------------------------------------------------------- + */ static int ConvertToObjpattern(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *UNUSED(pPtr), - ClientData *clientData, Tcl_Obj **outObjPtr) { + ClientData *clientData, Tcl_Obj **outObjPtr) { Tcl_Obj *patternObj = objPtr; CONST char *pattern = ObjStr(objPtr); if (NoMetaChars(pattern)) { - /* we have no meta characters, we try to check for an existing object */ + /* + * We have no meta characters, we try to check for an existing object + */ NsfObject *object = NULL; GetObjectFromObj(interp, objPtr, &object); if (object) { @@ -10473,7 +10498,10 @@ * the properties of the object have to be tested. * * Results: - * 0 or 1, potentially the matchObject. + * 0 or 1 or -1, potentially the matchObject (when 0 is returned) + * 0: we have wild-card characters, iterate to get matches + * 1: we have an existing object + * -1: we no wild-card characters and a non-existing object * * Side effects: * None. @@ -10487,13 +10515,11 @@ if (patternObj) { *pattern = ObjStr(patternObj); if (TclObjIsNsfObject(interp, patternObj, matchObject)) { - } else if (patternObj == origObj && **pattern != ':') { - /* no meta chars, but no appropriate nsf object found, so - return empty; we could check above with NoMetaChars(pattern) - as well, but the only remaining case are leading colons and - metachars. */ return 1; } + if (patternObj == origObj && **pattern != ':') { + return -1; + } } return 0; } @@ -15170,6 +15196,10 @@ if (pattern && ConvertToObjpattern(interp, pattern, NULL, (ClientData *)&patternObj, &outObjPtr) == TCL_OK) { if (GetMatchObject(interp, patternObj, pattern, &matchObject, &patternString) == -1) { + /* + * The pattern has no meta chars and does not correspond to an existing + * object. Therefore, it can't be a superclass. + */ if (patternObj) { DECR_REF_COUNT(patternObj); } @@ -19824,7 +19854,7 @@ class->order = NULL; subclasses = ComputeOrder(class, class->order, Sub); class->order = saved; - rc = AppendMatchingElementsFromClasses(interp, subclasses ? subclasses->nextPtr:NULL, + rc = AppendMatchingElementsFromClasses(interp, subclasses ? subclasses->nextPtr : NULL, patternString, patternObj); NsfClassListFree(subclasses); } else { Index: tests/info-method.test =================================================================== diff -u -r4e0a14b67ffc6ac5087eacf53207f877c33d599f -rbd69e3a318c530a893bcf86b2d6d41f7064d3c07 --- tests/info-method.test (.../info-method.test) (revision 4e0a14b67ffc6ac5087eacf53207f877c33d599f) +++ tests/info-method.test (.../info-method.test) (revision bd69e3a318c530a893bcf86b2d6d41f7064d3c07) @@ -3,7 +3,63 @@ ::nx::configure defaultMethodCallProtection false package require nx::test -nx::Test case base { +# +# Test info superclass with closure and patterns (with and without +# wildcards, prefixed or not, success or not). +# +nx::Test case info-superclass { + nx::Class create C + nx::Class create D -superclass C + + # no patterns + ? {D info superclass} "::C" + ? {D info superclass -closure} "::C ::nx::Object" + + # fully qualified pattern, no wild-card characters, success + ? {D info superclass ::C} "::C" + ? {D info superclass -closure ::C} "::C" + + # unprefixed pattern, no wild-card characters, success + ? {D info superclass C} "::C" + ? {D info superclass -closure C} "::C" + + # fully qualified pattern, no wild-card characters, no success + ? {D info superclass ::D} "" + ? {D info superclass -closure ::D} "" + ? {D info superclass ::Dx} "" + ? {D info superclass -closure ::Dx} "" + + # unprefixed pattern, no wild-card characters, no success + ? {D info superclass D} "" + ? {D info superclass -closure D} "" + ? {D info superclass Dx} "" + ? {D info superclass -closure Dx} "" + + # fully qualified pattern, wild-card characters, success + ? {D info superclass ::*} "::C" + ? {D info superclass -closure ::C*} "::C" + ? {D info superclass -closure ::*} "::C ::nx::Object" + ? {D info superclass -closure ::nx*} "::nx::Object" + + # unprefixed pattern, wild-card characters, success + ? {D info superclass C*} "::C" + ? {D info superclass -closure *} "::C ::nx::Object" + ? {D info superclass -closure nx*} "::nx::Object" + + # fully qualified pattern, wild-card characters, no success + ? {D info superclass ::*D} "" + ? {D info superclass -closure ::*D} "" + + # unprefixed pattern, wild-card characters, no success + ? {D info superclass C*x} "" + ? {D info superclass -closure C*x} "" +} + +# +# Test "info method", base cases +# + +nx::Test case info-method-base { nx::Object create o { :alias set ::set }