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)
===========================
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.

View file

@ -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;

View file

@ -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;

View file

@ -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:
/* ---------------------------------------------------------------------