diff --git a/CHANGES.current b/CHANGES.current index 269c71bf7..b47de9b69 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.5 (in progress) =========================== +2011-06-13: wsfulton + [Ruby, Octave] SF #3310528 Autodoc fixes similar to those described below for Python. + 2011-06-10: wsfulton [Python] Few subtle bugfixes in autodoc documentation generation, - Unnamed argument names fix for autodoc levels > 0. diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index 11fbc46fd..c22d90195 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -383,20 +383,54 @@ public: return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0"; } + /* ----------------------------------------------------------------------------- + * addMissingParameterNames() + * For functions that have not had nameless parameters set in the Language class. + * + * Inputs: + * plist - entire parameter list + * arg_offset - argument number for first parameter + * Side effects: + * The "lname" attribute in each parameter in plist will be contain a parameter name + * ----------------------------------------------------------------------------- */ + + void addMissingParameterNames(ParmList *plist, int arg_offset) { + Parm *p = plist; + int i = arg_offset; + while (p) { + if (!Getattr(p, "lname")) { + String *pname = Swig_cparm_name(p, i); + Delete(pname); + } + i++; + p = nextSibling(p); + } + } + void make_autodocParmList(Node *n, String *decl_str, String *args_str) { - String *pdocs = Copy(Getattr(n, "feature:pdocs")); + String *pdocs = 0; ParmList *plist = CopyParmList(Getattr(n, "parms")); Parm *p; Parm *pnext; - Node *lookup; + int start_arg_num = is_wrapping_class() ? 1 : 0; - if (pdocs) - Append(pdocs, "\n"); + addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms Swig_typemap_attach_parms("in", plist, 0); Swig_typemap_attach_parms("doc", plist, 0); for (p = plist; p; p = pnext) { + + String *tm = Getattr(p, "tmap:in"); + if (tm) { + pnext = Getattr(p, "tmap:in:next"); + if (checkAttribute(p, "tmap:in:numinputs", "0")) { + continue; + } + } else { + pnext = nextSibling(p); + } + String *name = 0; String *type = 0; String *value = 0; @@ -407,60 +441,81 @@ public: value = Getattr(p, "tmap:doc:value"); } + // Note: the generated name should be consistent with that in kwnames[] name = name ? name : Getattr(p, "name"); + name = name ? name : Getattr(p, "lname"); + name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword + type = type ? type : Getattr(p, "type"); value = value ? value : Getattr(p, "value"); + if (SwigType_isvarargs(type)) + break; + String *tex_name = NewString(""); if (name) Printf(tex_name, "@var{%s}", name); else Printf(tex_name, "@var{?}"); - String *tm = Getattr(p, "tmap:in"); - if (tm) { - pnext = Getattr(p, "tmap:in:next"); - } else { - pnext = nextSibling(p); - } - if (Len(decl_str)) Append(decl_str, ", "); Append(decl_str, tex_name); if (value) { - if (Strcmp(value, "NULL") == 0) - value = NewString("nil"); - else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0) - value = NewString("true"); - else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0) - value = NewString("false"); - else { - lookup = Swig_symbol_clookup(value, 0); + String *new_value = convertValue(value, Getattr(p, "type")); + if (new_value) { + value = new_value; + } else { + Node *lookup = Swig_symbol_clookup(value, 0); if (lookup) value = Getattr(lookup, "sym:name"); } Printf(decl_str, " = %s", value); } - if (type) { - String *type_str = NewString(""); - type = SwigType_base(type); - lookup = Swig_symbol_clookup(type, 0); - if (lookup) - type = Getattr(lookup, "sym:name"); - Printf(type_str, "%s is of type %s. ", tex_name, type); - Append(args_str, type_str); - Delete(type_str); - } + Node *nn = classLookup(Getattr(p, "type")); + String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0); + Printf(args_str, "%s is of type %s. ", tex_name, type_str); + Delete(type_str); Delete(tex_name); + Delete(name); } if (pdocs) Setattr(n, "feature:pdocs", pdocs); Delete(plist); } + /* ------------------------------------------------------------ + * convertValue() + * Check if string v can be an Octave value literal, + * (eg. number or string), or translate it to an Octave literal. + * ------------------------------------------------------------ */ + String *convertValue(String *v, SwigType *t) { + if (v && Len(v) > 0) { + char fc = (Char(v))[0]; + if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) { + /* number or string (or maybe NULL pointer) */ + if (SwigType_ispointer(t) && Strcmp(v, "0") == 0) + return NewString("None"); + else + return v; + } + if (Strcmp(v, "NULL") == 0) + return SwigType_ispointer(t) ? NewString("nil") : NewString("0"); + else if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0) + return NewString("true"); + else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0) + return NewString("false"); + if (Strcmp(v, "true") == 0 || Strcmp(v, "FALSE") == 0) + return NewString("true"); + if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0) + return NewString("false"); + } + return 0; + } + virtual int functionWrapper(Node *n) { Wrapper *f = NewWrapper(); Parm *p; diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index aab40ca94..e1dad5259 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1384,9 +1384,9 @@ public: // Write default value if (value && !calling) { - String *pv = pyvalue(value, Getattr(p, "type")); - if (pv) { - value = pv; + String *new_value = convertValue(value, Getattr(p, "type")); + if (new_value) { + value = new_value; } else { Node *lookup = Swig_symbol_clookup(value, 0); if (lookup) @@ -1542,11 +1542,11 @@ public: } /* ------------------------------------------------------------ - * pyvalue() + * convertValue() * Check if string v can be a Python value literal, * (eg. number or string), or translate it to a Python literal. * ------------------------------------------------------------ */ - String *pyvalue(String *v, SwigType *t) { + String *convertValue(String *v, SwigType *t) { if (v && Len(v) > 0) { char fc = (Char(v))[0]; if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) { @@ -1589,7 +1589,7 @@ public: } String *type = Getattr(p, "type"); String *value = Getattr(p, "value"); - if (!pyvalue(value, type)) + if (!convertValue(value, type)) return false; } return true; diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index d2ce97592..1ad1241ee 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -296,6 +296,30 @@ private: return doc; } + /* ----------------------------------------------------------------------------- + * addMissingParameterNames() + * For functions that have not had nameless parameters set in the Language class. + * + * Inputs: + * plist - entire parameter list + * arg_offset - argument number for first parameter + * Side effects: + * The "lname" attribute in each parameter in plist will be contain a parameter name + * ----------------------------------------------------------------------------- */ + + void addMissingParameterNames(ParmList *plist, int arg_offset) { + Parm *p = plist; + int i = arg_offset; + while (p) { + if (!Getattr(p, "lname")) { + String *pname = Swig_cparm_name(p, i); + Delete(pname); + } + i++; + p = nextSibling(p); + } + } + /* ------------------------------------------------------------ * make_autodocParmList() * Generate the documentation for the function parameters @@ -303,22 +327,36 @@ private: String *make_autodocParmList(Node *n, bool showTypes) { String *doc = NewString(""); - String *pdocs = Copy(Getattr(n, "feature:pdocs")); + String *pdocs = 0; ParmList *plist = CopyParmList(Getattr(n, "parms")); Parm *p; Parm *pnext; - Node *lookup; int lines = 0; - const int maxwidth = 50; - - if (pdocs) - Append(pdocs, ".\n"); + int start_arg_num = is_wrapping_class() ? 1 : 0; + const int maxwidth = 80; + addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms Swig_typemap_attach_parms("in", plist, 0); Swig_typemap_attach_parms("doc", plist, 0); + if (Strcmp(ParmList_protostr(plist), "void") == 0) { + //No parameters actually + return doc; + } + for (p = plist; p; p = pnext) { + + String *tm = Getattr(p, "tmap:in"); + if (tm) { + pnext = Getattr(p, "tmap:in:next"); + if (checkAttribute(p, "tmap:in:numinputs", "0")) { + continue; + } + } else { + pnext = nextSibling(p); + } + String *name = 0; String *type = 0; String *value = 0; @@ -329,21 +367,16 @@ private: value = Getattr(p, "tmap:doc:value"); } + // Note: the generated name should be consistent with that in kwnames[] name = name ? name : Getattr(p, "name"); + name = name ? name : Getattr(p, "lname"); + name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword + type = type ? type : Getattr(p, "type"); value = value ? value : Getattr(p, "value"); - - String *tm = Getattr(p, "tmap:in"); - if (tm) { - pnext = Getattr(p, "tmap:in:next"); - } else { - pnext = nextSibling(p); - } - - // Skip ignored input attributes - if (checkAttribute(p, "tmap:in:numinputs", "0")) - continue; + if (SwigType_isvarargs(type)) + break; // Skip the 'self' parameter which in ruby is implicit if ( Cmp(name, "self") == 0 ) @@ -362,40 +395,33 @@ private: lines += 1; } } - // Do the param type too? - if (showTypes) { - type = SwigType_base(type); - lookup = Swig_symbol_clookup(type, 0); - if (lookup) - type = Getattr(lookup, "sym:name"); - Printf(doc, "%s ", type); - } - if (name) { - Append(doc, name); - if (pdoc) { - if (!pdocs) - pdocs = NewString("Parameters:\n"); - Printf(pdocs, " %s.\n", pdoc); - } - } else { - Append(doc, "?"); + // Do the param type too? + Node *nn = classLookup(Getattr(p, "type")); + String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0); + if (showTypes) + Printf(doc, "%s ", type_str); + + Append(doc, name); + if (pdoc) { + if (!pdocs) + pdocs = NewString("Parameters:\n"); + Printf(pdocs, " %s.\n", pdoc); } if (value) { - if (Strcmp(value, "NULL") == 0) - value = NewString("nil"); - else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0) - value = NewString("true"); - else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0) - value = NewString("false"); - else { - lookup = Swig_symbol_clookup(value, 0); + String *new_value = convertValue(value, Getattr(p, "type")); + if (new_value) { + value = new_value; + } else { + Node *lookup = Swig_symbol_clookup(value, 0); if (lookup) value = Getattr(lookup, "sym:name"); } Printf(doc, "=%s", value); } + Delete(type_str); + Delete(name); } if (pdocs) Setattr(n, "feature:pdocs", pdocs); @@ -425,55 +451,53 @@ private: String* super_names = NewString(""); String* class_name = Getattr(pn, "sym:name") ; - if ( !class_name ) class_name = NewString(""); - else - { - class_name = Copy(class_name); - List *baselist = Getattr(pn, "bases"); - if (baselist && Len(baselist)) { - Iterator base = First(baselist); - while (base.item && GetFlag(base.item, "feature:ignore")) { - base = Next(base); - } - - int count = 0; - for ( ;base.item; ++count) { - if ( count ) Append(super_names, ", "); - String *basename = Getattr(base.item, "sym:name"); + if ( !class_name ) { + class_name = NewString(""); + } else { + class_name = Copy(class_name); + List *baselist = Getattr(pn, "bases"); + if (baselist && Len(baselist)) { + Iterator base = First(baselist); + while (base.item && GetFlag(base.item, "feature:ignore")) { + base = Next(base); + } - String* basenamestr = NewString(basename); - Node* parent = parentNode(base.item); - while (parent) - { - String *parent_name = Copy( Getattr(parent, "sym:name") ); - if ( !parent_name ) { - Node* mod = Getattr(parent, "module"); - if ( mod ) - parent_name = Copy( Getattr(mod, "name") ); - if ( parent_name ) - { - (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]); - } - } - if ( parent_name ) - { - Insert(basenamestr, 0, "::"); - Insert(basenamestr, 0, parent_name); - Delete(parent_name); - } - parent = parentNode(parent); - } + int count = 0; + for ( ;base.item; ++count) { + if ( count ) Append(super_names, ", "); + String *basename = Getattr(base.item, "sym:name"); - Append(super_names, basenamestr ); - Delete(basenamestr); - base = Next(base); + String* basenamestr = NewString(basename); + Node* parent = parentNode(base.item); + while (parent) + { + String *parent_name = Copy( Getattr(parent, "sym:name") ); + if ( !parent_name ) { + Node* mod = Getattr(parent, "module"); + if ( mod ) + parent_name = Copy( Getattr(mod, "name") ); + if ( parent_name ) + (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]); + } + if ( parent_name ) { + Insert(basenamestr, 0, "::"); + Insert(basenamestr, 0, parent_name); + Delete(parent_name); + } + parent = parentNode(parent); } + + Append(super_names, basenamestr ); + Delete(basenamestr); + base = Next(base); } } + } String* full_name; if ( module ) { full_name = NewString(module); - if (class_name && Len(class_name) > 0) Append(full_name, "::"); + if (class_name && Len(class_name) > 0) + Append(full_name, "::"); } else full_name = NewString(""); @@ -508,6 +532,7 @@ private: bool skipAuto = false; Node* on = n; for ( ; n; ++counter ) { + String *type_str = NULL; skipAuto = false; bool showTypes = false; String *autodoc = Getattr(n, "feature:autodoc"); @@ -537,17 +562,15 @@ private: SwigType *type = Getattr(n, "type"); if (type) { - if (Strcmp(type, "void") == 0) - type = NULL; - else { + if (Strcmp(type, "void") == 0) { + type_str = NULL; + } else { SwigType *qt = SwigType_typedef_resolve_all(type); - if (SwigType_isenum(qt)) - type = NewString("int"); - else { - type = SwigType_base(type); - Node *lookup = Swig_symbol_clookup(type, 0); - if (lookup) - type = Getattr(lookup, "sym:name"); + if (SwigType_isenum(qt)) { + type_str = NewString("int"); + } else { + Node *nn = classLookup(type); + type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0); } } } @@ -582,7 +605,6 @@ private: } } - if (skipAuto) { if ( counter == 0 ) Printf(doc, " call-seq:\n"); switch( ad_type ) @@ -597,21 +619,21 @@ private: Printf(doc, " %s(%s)", symname, paramList); else Printf(doc, " %s", symname); - if (type) - Printf(doc, " -> %s", type); + if (type_str) + Printf(doc, " -> %s", type_str); break; } case AUTODOC_SETTER: { Printf(doc, " %s=(x)", symname); - if (type) Printf(doc, " -> %s", type); + if (type_str) + Printf(doc, " -> %s", type_str); break; } default: break; } - } - else { + } else { switch (ad_type) { case AUTODOC_CLASS: { @@ -627,7 +649,8 @@ private: } break; case AUTODOC_CTOR: - if (counter == 0) Printf(doc, " call-seq:\n"); + if (counter == 0) + Printf(doc, " call-seq:\n"); if (Strcmp(class_name, symname) == 0) { String *paramList = make_autodocParmList(n, showTypes); if (Len(paramList)) @@ -647,21 +670,23 @@ private: case AUTODOC_METHOD: case AUTODOC_GETTER: { - if (counter == 0) Printf(doc, " call-seq:\n"); + if (counter == 0) + Printf(doc, " call-seq:\n"); String *paramList = make_autodocParmList(n, showTypes); if (Len(paramList)) Printf(doc, " %s(%s)", symname, paramList); else Printf(doc, " %s", symname); - if (type) - Printf(doc, " -> %s", type); + if (type_str) + Printf(doc, " -> %s", type_str); break; } case AUTODOC_SETTER: { Printf(doc, " call-seq:\n"); Printf(doc, " %s=(x)", symname); - if (type) Printf(doc, " -> %s", type); + if (type_str) + Printf(doc, " -> %s", type_str); break; } } @@ -671,6 +696,7 @@ private: n = Getattr(n, "sym:nextSibling"); if (n) Append(doc, "\n"); + Delete(type_str); } Printf(doc, "\n\n"); @@ -748,6 +774,35 @@ private: return doc; } + /* ------------------------------------------------------------ + * convertValue() + * Check if string v can be a Ruby value literal, + * (eg. number or string), or translate it to a Ruby literal. + * ------------------------------------------------------------ */ + String *convertValue(String *v, SwigType *t) { + if (v && Len(v) > 0) { + char fc = (Char(v))[0]; + if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) { + /* number or string (or maybe NULL pointer) */ + if (SwigType_ispointer(t) && Strcmp(v, "0") == 0) + return NewString("None"); + else + return v; + } + if (Strcmp(v, "NULL") == 0) + return SwigType_ispointer(t) ? NewString("nil") : NewString("0"); + else if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0) + return NewString("true"); + else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0) + return NewString("false"); + if (Strcmp(v, "true") == 0 || Strcmp(v, "FALSE") == 0) + return NewString("True"); + if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0) + return NewString("False"); + } + return 0; + } + public: /* ---------------------------------------------------------------------