Repeat autodoc fixes for Octave and Ruby as done previously for Python

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12740 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2011-06-13 20:46:20 +00:00
commit 72ffdb930d
4 changed files with 252 additions and 139 deletions

View file

@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.5 (in progress) 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 2011-06-10: wsfulton
[Python] Few subtle bugfixes in autodoc documentation generation, [Python] Few subtle bugfixes in autodoc documentation generation,
- Unnamed argument names fix for autodoc levels > 0. - Unnamed argument names fix for autodoc levels > 0.

View file

@ -383,20 +383,54 @@ public:
return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0"; 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) { 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")); ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p; Parm *p;
Parm *pnext; Parm *pnext;
Node *lookup; int start_arg_num = is_wrapping_class() ? 1 : 0;
if (pdocs) addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
Append(pdocs, "\n");
Swig_typemap_attach_parms("in", plist, 0); Swig_typemap_attach_parms("in", plist, 0);
Swig_typemap_attach_parms("doc", plist, 0); Swig_typemap_attach_parms("doc", plist, 0);
for (p = plist; p; p = pnext) { 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 *name = 0;
String *type = 0; String *type = 0;
String *value = 0; String *value = 0;
@ -407,60 +441,81 @@ public:
value = Getattr(p, "tmap:doc:value"); 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, "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"); type = type ? type : Getattr(p, "type");
value = value ? value : Getattr(p, "value"); value = value ? value : Getattr(p, "value");
if (SwigType_isvarargs(type))
break;
String *tex_name = NewString(""); String *tex_name = NewString("");
if (name) if (name)
Printf(tex_name, "@var{%s}", name); Printf(tex_name, "@var{%s}", name);
else else
Printf(tex_name, "@var{?}"); 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)) if (Len(decl_str))
Append(decl_str, ", "); Append(decl_str, ", ");
Append(decl_str, tex_name); Append(decl_str, tex_name);
if (value) { if (value) {
if (Strcmp(value, "NULL") == 0) String *new_value = convertValue(value, Getattr(p, "type"));
value = NewString("nil"); if (new_value) {
else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0) value = new_value;
value = NewString("true"); } else {
else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0) Node *lookup = Swig_symbol_clookup(value, 0);
value = NewString("false");
else {
lookup = Swig_symbol_clookup(value, 0);
if (lookup) if (lookup)
value = Getattr(lookup, "sym:name"); value = Getattr(lookup, "sym:name");
} }
Printf(decl_str, " = %s", value); Printf(decl_str, " = %s", value);
} }
if (type) { Node *nn = classLookup(Getattr(p, "type"));
String *type_str = NewString(""); String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
type = SwigType_base(type); Printf(args_str, "%s is of type %s. ", tex_name, type_str);
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);
}
Delete(type_str);
Delete(tex_name); Delete(tex_name);
Delete(name);
} }
if (pdocs) if (pdocs)
Setattr(n, "feature:pdocs", pdocs); Setattr(n, "feature:pdocs", pdocs);
Delete(plist); 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) { virtual int functionWrapper(Node *n) {
Wrapper *f = NewWrapper(); Wrapper *f = NewWrapper();
Parm *p; Parm *p;

View file

@ -1384,9 +1384,9 @@ public:
// Write default value // Write default value
if (value && !calling) { if (value && !calling) {
String *pv = pyvalue(value, Getattr(p, "type")); String *new_value = convertValue(value, Getattr(p, "type"));
if (pv) { if (new_value) {
value = pv; value = new_value;
} else { } else {
Node *lookup = Swig_symbol_clookup(value, 0); Node *lookup = Swig_symbol_clookup(value, 0);
if (lookup) if (lookup)
@ -1542,11 +1542,11 @@ public:
} }
/* ------------------------------------------------------------ /* ------------------------------------------------------------
* pyvalue() * convertValue()
* Check if string v can be a Python value literal, * Check if string v can be a Python value literal,
* (eg. number or string), or translate it to a Python 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) { if (v && Len(v) > 0) {
char fc = (Char(v))[0]; char fc = (Char(v))[0];
if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) { if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
@ -1589,7 +1589,7 @@ public:
} }
String *type = Getattr(p, "type"); String *type = Getattr(p, "type");
String *value = Getattr(p, "value"); String *value = Getattr(p, "value");
if (!pyvalue(value, type)) if (!convertValue(value, type))
return false; return false;
} }
return true; return true;

View file

@ -296,6 +296,30 @@ private:
return doc; 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() * make_autodocParmList()
* Generate the documentation for the function parameters * Generate the documentation for the function parameters
@ -303,22 +327,36 @@ private:
String *make_autodocParmList(Node *n, bool showTypes) { String *make_autodocParmList(Node *n, bool showTypes) {
String *doc = NewString(""); String *doc = NewString("");
String *pdocs = Copy(Getattr(n, "feature:pdocs")); String *pdocs = 0;
ParmList *plist = CopyParmList(Getattr(n, "parms")); ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p; Parm *p;
Parm *pnext; Parm *pnext;
Node *lookup;
int lines = 0; int lines = 0;
const int maxwidth = 50; int start_arg_num = is_wrapping_class() ? 1 : 0;
const int maxwidth = 80;
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("in", plist, 0);
Swig_typemap_attach_parms("doc", 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) { 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 *name = 0;
String *type = 0; String *type = 0;
String *value = 0; String *value = 0;
@ -329,21 +367,16 @@ private:
value = Getattr(p, "tmap:doc:value"); 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, "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"); type = type ? type : Getattr(p, "type");
value = value ? value : Getattr(p, "value"); value = value ? value : Getattr(p, "value");
if (SwigType_isvarargs(type))
String *tm = Getattr(p, "tmap:in"); break;
if (tm) {
pnext = Getattr(p, "tmap:in:next");
} else {
pnext = nextSibling(p);
}
// Skip ignored input attributes
if (checkAttribute(p, "tmap:in:numinputs", "0"))
continue;
// Skip the 'self' parameter which in ruby is implicit // Skip the 'self' parameter which in ruby is implicit
if ( Cmp(name, "self") == 0 ) if ( Cmp(name, "self") == 0 )
@ -362,40 +395,33 @@ private:
lines += 1; 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) { // Do the param type too?
Append(doc, name); Node *nn = classLookup(Getattr(p, "type"));
if (pdoc) { String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
if (!pdocs) if (showTypes)
pdocs = NewString("Parameters:\n"); Printf(doc, "%s ", type_str);
Printf(pdocs, " %s.\n", pdoc);
} Append(doc, name);
} else { if (pdoc) {
Append(doc, "?"); if (!pdocs)
pdocs = NewString("Parameters:\n");
Printf(pdocs, " %s.\n", pdoc);
} }
if (value) { if (value) {
if (Strcmp(value, "NULL") == 0) String *new_value = convertValue(value, Getattr(p, "type"));
value = NewString("nil"); if (new_value) {
else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0) value = new_value;
value = NewString("true"); } else {
else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0) Node *lookup = Swig_symbol_clookup(value, 0);
value = NewString("false");
else {
lookup = Swig_symbol_clookup(value, 0);
if (lookup) if (lookup)
value = Getattr(lookup, "sym:name"); value = Getattr(lookup, "sym:name");
} }
Printf(doc, "=%s", value); Printf(doc, "=%s", value);
} }
Delete(type_str);
Delete(name);
} }
if (pdocs) if (pdocs)
Setattr(n, "feature:pdocs", pdocs); Setattr(n, "feature:pdocs", pdocs);
@ -425,55 +451,53 @@ private:
String* super_names = NewString(""); String* super_names = NewString("");
String* class_name = Getattr(pn, "sym:name") ; String* class_name = Getattr(pn, "sym:name") ;
if ( !class_name ) class_name = NewString(""); if ( !class_name ) {
else class_name = NewString("");
{ } else {
class_name = Copy(class_name); class_name = Copy(class_name);
List *baselist = Getattr(pn, "bases"); List *baselist = Getattr(pn, "bases");
if (baselist && Len(baselist)) { if (baselist && Len(baselist)) {
Iterator base = First(baselist); Iterator base = First(baselist);
while (base.item && GetFlag(base.item, "feature:ignore")) { while (base.item && GetFlag(base.item, "feature:ignore")) {
base = Next(base); base = Next(base);
}
int count = 0;
for ( ;base.item; ++count) {
if ( count ) Append(super_names, ", ");
String *basename = Getattr(base.item, "sym:name");
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; Append(super_names, basenamestr );
for ( ;base.item; ++count) { Delete(basenamestr);
if ( count ) Append(super_names, ", "); base = Next(base);
String *basename = Getattr(base.item, "sym:name");
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; String* full_name;
if ( module ) { if ( module ) {
full_name = NewString(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 else
full_name = NewString(""); full_name = NewString("");
@ -508,6 +532,7 @@ private:
bool skipAuto = false; bool skipAuto = false;
Node* on = n; Node* on = n;
for ( ; n; ++counter ) { for ( ; n; ++counter ) {
String *type_str = NULL;
skipAuto = false; skipAuto = false;
bool showTypes = false; bool showTypes = false;
String *autodoc = Getattr(n, "feature:autodoc"); String *autodoc = Getattr(n, "feature:autodoc");
@ -537,17 +562,15 @@ private:
SwigType *type = Getattr(n, "type"); SwigType *type = Getattr(n, "type");
if (type) { if (type) {
if (Strcmp(type, "void") == 0) if (Strcmp(type, "void") == 0) {
type = NULL; type_str = NULL;
else { } else {
SwigType *qt = SwigType_typedef_resolve_all(type); SwigType *qt = SwigType_typedef_resolve_all(type);
if (SwigType_isenum(qt)) if (SwigType_isenum(qt)) {
type = NewString("int"); type_str = NewString("int");
else { } else {
type = SwigType_base(type); Node *nn = classLookup(type);
Node *lookup = Swig_symbol_clookup(type, 0); type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
if (lookup)
type = Getattr(lookup, "sym:name");
} }
} }
} }
@ -582,7 +605,6 @@ private:
} }
} }
if (skipAuto) { if (skipAuto) {
if ( counter == 0 ) Printf(doc, " call-seq:\n"); if ( counter == 0 ) Printf(doc, " call-seq:\n");
switch( ad_type ) switch( ad_type )
@ -597,21 +619,21 @@ private:
Printf(doc, " %s(%s)", symname, paramList); Printf(doc, " %s(%s)", symname, paramList);
else else
Printf(doc, " %s", symname); Printf(doc, " %s", symname);
if (type) if (type_str)
Printf(doc, " -> %s", type); Printf(doc, " -> %s", type_str);
break; break;
} }
case AUTODOC_SETTER: case AUTODOC_SETTER:
{ {
Printf(doc, " %s=(x)", symname); Printf(doc, " %s=(x)", symname);
if (type) Printf(doc, " -> %s", type); if (type_str)
Printf(doc, " -> %s", type_str);
break; break;
} }
default: default:
break; break;
} }
} } else {
else {
switch (ad_type) { switch (ad_type) {
case AUTODOC_CLASS: case AUTODOC_CLASS:
{ {
@ -627,7 +649,8 @@ private:
} }
break; break;
case AUTODOC_CTOR: 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) { if (Strcmp(class_name, symname) == 0) {
String *paramList = make_autodocParmList(n, showTypes); String *paramList = make_autodocParmList(n, showTypes);
if (Len(paramList)) if (Len(paramList))
@ -647,21 +670,23 @@ private:
case AUTODOC_METHOD: case AUTODOC_METHOD:
case AUTODOC_GETTER: 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); String *paramList = make_autodocParmList(n, showTypes);
if (Len(paramList)) if (Len(paramList))
Printf(doc, " %s(%s)", symname, paramList); Printf(doc, " %s(%s)", symname, paramList);
else else
Printf(doc, " %s", symname); Printf(doc, " %s", symname);
if (type) if (type_str)
Printf(doc, " -> %s", type); Printf(doc, " -> %s", type_str);
break; break;
} }
case AUTODOC_SETTER: case AUTODOC_SETTER:
{ {
Printf(doc, " call-seq:\n"); Printf(doc, " call-seq:\n");
Printf(doc, " %s=(x)", symname); Printf(doc, " %s=(x)", symname);
if (type) Printf(doc, " -> %s", type); if (type_str)
Printf(doc, " -> %s", type_str);
break; break;
} }
} }
@ -671,6 +696,7 @@ private:
n = Getattr(n, "sym:nextSibling"); n = Getattr(n, "sym:nextSibling");
if (n) if (n)
Append(doc, "\n"); Append(doc, "\n");
Delete(type_str);
} }
Printf(doc, "\n\n"); Printf(doc, "\n\n");
@ -748,6 +774,35 @@ private:
return doc; 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: public:
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------