Progress towards a working pydoc implementation.

- Nodes are now passed to the documentation translator so that type information can be looked up and used in parameter comments.
- Class comments are now inserted as well as some method information,


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-cherylfoil@10838 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Jamie Kirkpatrick 2008-09-12 11:17:39 +00:00
commit 0db7edfa63
11 changed files with 314 additions and 23 deletions

View file

@ -13,7 +13,7 @@
#define yylex yylex
char cvsroot_parser_y[] = "$Id$";
char cvsroot_parser_y[] = "$Id: parser.y 10767 2008-08-16 07:31:05Z cherylfoil $";
#include "swig.h"
#include "cparse.h"
@ -3209,15 +3209,18 @@ c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
doxygen_comment : DOXYGENSTRING
{
while(Strchr($1,'/') == Char($1))
Replace($1,"/","",DOH_REPLACE_FIRST);
if(isStructuralDoxygen($1)){
$$ = new_node("doxycomm");
Setattr($$,"DoxygenComment",$1);
}
else {
if(currentComment != 0){
Append(currentComment, $1);
Append(currentComment,$1);
}
else currentComment = $1;
else
currentComment = $1;
$$ = 0;
}
}

View file

@ -21,5 +21,17 @@ public:
int isLeaf;
};
struct find_entity {
find_entity(string typeString) {
typeOfEntity = typeString;
}
bool operator()(DoxygenEntity& entity) {
return entity.typeOfEntity == typeOfEntity;
}
string typeOfEntity;
};
#endif /*TOKENLIST_H_*/

View file

@ -5,13 +5,16 @@
#include <string>
#include "DoxygenEntity.h"
#include "JavaDocConverter.h"
#include "PyDocConverter.h"
DoxygenParser doxyParse;
JavaDocConverter jDC;
PyDocConverter pyDC;
DoxygenTranslator::DoxygenTranslator(){
doxyParse = DoxygenParser();
JavaDocConverter jDC = JavaDocConverter();
PyDocConverter pyDC = PyDocConverter();
}
DoxygenTranslator::~DoxygenTranslator(){
@ -19,13 +22,16 @@ DoxygenTranslator::~DoxygenTranslator(){
}
char *DoxygenTranslator::convert(char* doxygenBlob, char* option){
char *DoxygenTranslator::convert(Node *n, char* doxygenBlob, char* option){
list <DoxygenEntity> rootList = doxyParse.createTree(string(doxygenBlob));
string returnedString;
if(strcmp(option, "JAVADOC") == 0){
returnedString = jDC.convertToJavaDoc(rootList);
returnedString = jDC.convertToJavaDoc(n, rootList);
}
else if(strcmp(option, "PYDOC") == 0){
returnedString = pyDC.convertToPyDoc(n, rootList);
}
else cout << "Option not current supported.\n";
char *nonConstString;
@ -59,7 +65,7 @@ int testCommands(){
//cout << "---ORIGINAL DOXYGEN--- " << endl << exampleArray[i] << endl;
char *nonConstString = (char *)malloc(exampleArray[i].length()+1);
strcpy(nonConstString, exampleArray[i].c_str());
char * result = dT.convert(nonConstString, "JAVADOC");
char * result = dT.convert(NULL, nonConstString, "JAVADOC");
free(nonConstString);
free(result);
}

View file

@ -1,10 +1,13 @@
#ifndef DOXYGENTRANSLATOR_H_
#define DOXYGENTRANSLATOR_H_
#include "swig.h"
class DoxygenTranslator
{
public:
DoxygenTranslator();
virtual ~DoxygenTranslator();
char* convert(char* doxygenBlob, char* option);
char* convert(Node *n, char* doxygenBlob, char* option);
};
#endif /*DOXYGENTRANSLATOR_H_*/

View file

@ -213,7 +213,7 @@ string translateEntity(DoxygenEntity &doxyEntity){
return "";
}
string JavaDocConverter:: convertToJavaDoc(list <DoxygenEntity> entityList){
string JavaDocConverter:: convertToJavaDoc(Node *n, list <DoxygenEntity> entityList){
entityList.sort(compare_DoxygenEntities);

View file

@ -1,15 +1,17 @@
#include <list>
#include <string>
#include "DoxygenEntity.h"
#ifndef JAVADOCCONVERTER_H_
#define JAVADOCCONVERTER_H_
#include <list>
#include <string>
#include "swig.h"
#include "DoxygenEntity.h"
class JavaDocConverter
{
public:
JavaDocConverter();
string convertToJavaDoc(list <DoxygenEntity> entityList);
string convertToJavaDoc(Node *n, list <DoxygenEntity> entityList);
~JavaDocConverter();
void printSortedTree(list <DoxygenEntity> &entityList);
};

View file

@ -0,0 +1,205 @@
#include "PyDocConverter.h"
#include <iostream>
#include <sstream>
#define APPROX_LINE_LENGTH 64//characters per line allowed
#define TAB_SIZE 8//characters per line allowed
//TODO {@link} {@linkplain} {@docRoot}, and other useful doxy commands that are not a pydoc tag
PyDocConverter::PyDocConverter()
{
debug = 1;
}
PyDocConverter::~PyDocConverter()
{
}
/* Sorts entities by pyDoc standard order for commands
* NOTE: will not behave entirely properly until "First level" comments
* such as brief descriptions are TAGGED as such
*/
bool compare_DoxygenEntities(DoxygenEntity first, DoxygenEntity second);
void PyDocConverter::printSortedTree(list <DoxygenEntity> &entityList){
list<DoxygenEntity>::iterator p = entityList.begin();
while (p != entityList.end()){
(*p).printEntity(0);
p++;
}
}
string PyDocConverter::formatParam(Node *n, DoxygenEntity &doxygenEntity) {
string result;
ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p = NULL;
DoxygenEntity& paramNameEntity = *doxygenEntity.entityList.begin();
DoxygenEntity& paramDescriptionEntity = *(++doxygenEntity.entityList.begin());
for (p = plist; p;) {
if(Char(Getattr(p, "name")) == paramNameEntity.data) {
std::string name = Char(Swig_name_make(n, 0, Getattr(p, "name"), 0, 0));
std::string type = Char(Swig_name_make(n, 0, Getattr(p, "type"), 0, 0));
std::ostringstream parameterDocString;
parameterDocString << std::endl << name << " (" << type << "): ";
parameterDocString << paramDescriptionEntity.data;
result = parameterDocString.str();
break;
}
p = Getattr(p, "tmap:in") ? Getattr(p, "tmap:in:next") : nextSibling(p);
}
Delete(plist);
return result;
}
string PyDocConverter::formatCommand(string unformattedLine, int indent){
string formattedLines = "\n";
int lastPosition = 0;
int i = 0;
int isFirstLine = 1;
while (i != -1 && i < unformattedLine.length()){
lastPosition = i;
if (isFirstLine){
i+=APPROX_LINE_LENGTH;
}
else i+=APPROX_LINE_LENGTH - indent*TAB_SIZE;
i = unformattedLine.find(" ", i);
if (i > 0 && i + 1 < unformattedLine.length()){
if (!isFirstLine) for (int j = 0; j < indent; j++) {
formattedLines.append("\t");
}
else {
isFirstLine = 0;
}
formattedLines.append(unformattedLine.substr(lastPosition, i - lastPosition + 1));
formattedLines.append("\n");
}
}
if (lastPosition < unformattedLine.length()){
if (!isFirstLine) {for (int j = 0; j < indent; j++) {formattedLines.append("\t");}}
formattedLines.append(unformattedLine.substr(lastPosition, unformattedLine.length() - lastPosition));
}
return formattedLines;
}
/* Contains the conversions for tags
* could probably be much more efficient...
*/
string PyDocConverter::pyDocFormat(DoxygenEntity &doxygenEntity){
if(doxygenEntity.typeOfEntity.compare("partofdescription") == 0){
return doxygenEntity.data;
}
if (doxygenEntity.typeOfEntity.compare("plainstring") == 0){
return doxygenEntity.data;
}
else if (doxygenEntity.typeOfEntity.compare("b") == 0){
return "<b>" + doxygenEntity.data + "</b>";
}
else if (doxygenEntity.typeOfEntity.compare("c") == 0){
return "<tt>" + doxygenEntity.data + "</tt>";
}
else if (doxygenEntity.typeOfEntity.compare("@") == 0){
return "@";
}
else if (doxygenEntity.typeOfEntity.compare("\\") == 0){
return "\\";
}
else if (doxygenEntity.typeOfEntity.compare("<") == 0){
return "&lt;";
}
else if (doxygenEntity.typeOfEntity.compare(">") == 0){
return "&gt;";
}
else if (doxygenEntity.typeOfEntity.compare("&") == 0){
return "&amp;";
}
else if (doxygenEntity.typeOfEntity.compare("#") == 0){
return "#";
}
else if (doxygenEntity.typeOfEntity.compare("%") == 0){
return "%";
}
else if (doxygenEntity.typeOfEntity.compare("~") == 0){
return "~";
}
return "";
}
string PyDocConverter::translateSubtree( DoxygenEntity &doxygenEntity){
string returnedString;
if (doxygenEntity.isLeaf){ return pyDocFormat(doxygenEntity) + " ";}
else {
returnedString += pyDocFormat(doxygenEntity);
list<DoxygenEntity>::iterator p = doxygenEntity.entityList.begin();
while (p != doxygenEntity.entityList.end()){
returnedString+= translateSubtree(*p);
p++;
}
}
return returnedString;
}
string PyDocConverter::translateEntity(Node *n, DoxygenEntity &doxyEntity){
if(doxyEntity.typeOfEntity.compare("partofdescription")== 0) return formatCommand(string(translateSubtree(doxyEntity)), 0);
if ((doxyEntity.typeOfEntity.compare("brief") == 0)||(doxyEntity.typeOfEntity.compare("details") == 0)){
return formatCommand(string(translateSubtree(doxyEntity)), 0) + "\n * ";}
else if(doxyEntity.typeOfEntity.compare("plainstring")== 0
|| doxyEntity.typeOfEntity.compare("deprecated")== 0
|| doxyEntity.typeOfEntity.compare("brief")== 0)
return formatCommand(doxyEntity.data, 0) + "\n * ";
else if(doxyEntity.typeOfEntity.compare("see") == 0){
return formatCommand(string("@" + doxyEntity.typeOfEntity + "\t\t" + translateSubtree(doxyEntity)), 2);
}
else if(doxyEntity.typeOfEntity.compare("param") == 0) {
return formatParam(n, doxyEntity);
}
else if(doxyEntity.typeOfEntity.compare("return")== 0
|| doxyEntity.typeOfEntity.compare("author")== 0
|| doxyEntity.typeOfEntity.compare("param")== 0
|| doxyEntity.typeOfEntity.compare("since")== 0
|| doxyEntity.typeOfEntity.compare("version")== 0
|| doxyEntity.typeOfEntity.compare("exception") == 0
|| doxyEntity.typeOfEntity.compare("deprecated") == 0){
return formatCommand(string("@" + doxyEntity.typeOfEntity + "\t" + translateSubtree(doxyEntity)), 2);
}
else if(doxyEntity.typeOfEntity.compare("sa")== 0){
return formatCommand(string("@see\t\t" + translateSubtree(doxyEntity)), 2);
}
else return formatCommand(pyDocFormat(doxyEntity), 0 );
return "";
}
string PyDocConverter::convertToPyDoc(Node *n, list <DoxygenEntity> entityList){
entityList.sort(compare_DoxygenEntities);
if(debug){
cout << "---RESORTED LIST---" << endl;
printSortedTree(entityList);
}
string pyDocString = "\"\"\"";
list<DoxygenEntity>::iterator entityIterator = entityList.begin();
while (entityIterator != entityList.end()){
pyDocString += translateEntity(n, *entityIterator);
entityIterator++;
}
pyDocString += "\n\"\"\"\n";
if(debug){
cout << "\n---RESULT IN PYDOC---" << endl;
cout << pyDocString;
}
return pyDocString;
}

View file

@ -0,0 +1,29 @@
#ifndef PYDOCCONVERTER_H_
#define PYDOCCONVERTER_H_
#include <list>
#include <string>
#include "swig.h"
#include "DoxygenEntity.h"
class PyDocConverter
{
public:
PyDocConverter();
string convertToPyDoc(Node *n, list <DoxygenEntity> entityList);
~PyDocConverter();
void printSortedTree(list <DoxygenEntity> &entityList);
protected:
std::string formatParam(Node *n, DoxygenEntity &doxygenEntity);
std::string formatCommand(string unformattedLine, int indent);
std::string pyDocFormat(DoxygenEntity &doxygenEntity);
std::string translateSubtree( DoxygenEntity &doxygenEntity);
std::string translateEntity(Node *n, DoxygenEntity &doxyEntity);
private:
bool debug;
};
#endif /*PYDOCCONVERTER_H_*/

View file

@ -97,6 +97,8 @@ eswig_SOURCES = CParse/cscanner.c \
DoxygenTranslator/src/DoxygenTranslator.cpp\
DoxygenTranslator/src/JavaDocConverter.h\
DoxygenTranslator/src/JavaDocConverter.cpp\
DoxygenTranslator/src/PyDocConverter.h\
DoxygenTranslator/src/PyDocConverter.cpp\
DoxygenTranslator/src/Token.h\
DoxygenTranslator/src/Token.cpp\
DoxygenTranslator/src/TokenList.h\

View file

@ -510,7 +510,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printf(f_module, "/* This was generated from top() */");
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printf(f_module, convertedString);
free(convertedString);
}
@ -1238,7 +1238,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printv(proxy_class_constants_code, "/* This was generated from enumvalueDeclaration */", NIL );
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printv(proxy_class_constants_code, convertedString, NIL);
free(convertedString);
}
@ -1310,7 +1310,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printf(enum_code, "/* This was generated from enumvalueDeclaration() */" );
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printf(enum_code, convertedString);
free(convertedString);
}
@ -1382,7 +1382,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printv(structuralComments, "/* This was generated from doxygenComment() */\n", NIL);
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printv(structuralComments, convertedString, NIL);
free(convertedString);
}
@ -1412,7 +1412,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printf(constants_code, "/* This was generated from enumvalueDeclaration */\n");
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printf(constants_code, convertedString);
free(convertedString);
}
@ -1683,7 +1683,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printv(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n", NIL );
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printv(proxy_class_def, convertedString, NIL);
free(convertedString);
}
@ -2026,7 +2026,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printf(function_code, "/* This was generated from proxyclassfunctionhandler */");
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printf(function_code, convertedString);
free(convertedString);
}
@ -2258,7 +2258,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printf(function_code, "/* This was generated from constructionhandler */\n" );
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printf(function_code, convertedString);
free(convertedString);
}
@ -2529,7 +2529,7 @@ public:
if (doxygen_javadoc_flag){
if (Getattr(n,"DoxygenComment")){
if(comment_creation_chatter) Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n" );
char *convertedString = doxyTranslator.convert(Char(Getattr(n,"DoxygenComment")),"JAVADOC");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")),"JAVADOC");
Printf(function_code, convertedString);
free(convertedString);
}

View file

@ -7,7 +7,7 @@
* Python language module for SWIG.
* ----------------------------------------------------------------------------- */
char cvsroot_python_cxx[] = "$Id$";
char cvsroot_python_cxx[] = "$Id: python.cxx 10453 2008-05-15 21:18:44Z wsfulton $";
#include "swigmod.h"
#define ctab2 " "
@ -18,6 +18,7 @@ char cvsroot_python_cxx[] = "$Id$";
static int treduce = SWIG_cparse_template_reduce(0);
#include <ctype.h>
#include "../DoxygenTranslator/src/DoxygenTranslator.h"
#define PYSHADOW_MEMBER 0x2
@ -70,6 +71,7 @@ static int buildnone = 0;
static int nobuildnone = 0;
static int safecstrings = 0;
static int dirvtable = 0;
static int doxygen = 1;
static int proxydel = 1;
static int fastunpack = 0;
static int fastproxy = 0;
@ -83,6 +85,8 @@ static int extranative = 0;
static int outputtuple = 0;
static int nortti = 0;
static DoxygenTranslator doxyTranslator;
/* flags for the make_autodoc function */
enum autodoc_t {
AUTODOC_CLASS,
@ -103,6 +107,7 @@ Python Options (available with -python)\n\
-classptr - Generate shadow 'ClassPtr' as in older swig versions\n\
-cppcast - Enable C++ casting operators (default) \n\
-dirvtable - Generate a pseudo virtual table for directors for faster dispatch \n\
-doxygen - Convert C++ doxygen comments to pydoc comments in proxy classes \n\
-extranative - Return extra native C++ wraps for std containers when possible \n\
-fastinit - Use fast init mechanism for classes (default)\n\
-fastunpack - Use fast unpack mechanism to parse the argument functions \n\
@ -324,6 +329,9 @@ public:
} else if (strcmp(argv[i], "-dirvtable") == 0) {
dirvtable = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-doxygen") == 0) {
doxygen = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nodirvtable") == 0) {
dirvtable = 0;
Swig_mark_arg(i);
@ -2898,11 +2906,24 @@ public:
}
}
Printf(f_shadow, ":\n");
if (have_docstring(n)) {
//translate and write pydoc comment if flagged
if (doxygen){
if (Getattr(n,"DoxygenComment")){
//if(comment_creation_chatter) Printf(function_code, "/* This was generated from classHandler */");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")), "PYDOC");
Printf(f_shadow, Char(pythoncode(convertedString, shadow_indent)));
free(convertedString);
}
}
// otherwise use default docstrings if requested
else if (have_docstring(n)) {
String *str = docstring(n, AUTODOC_CLASS, tab4);
if (str != NULL && Len(str))
Printv(f_shadow, tab4, str, "\n", NIL);
}
if (!modern) {
Printv(f_shadow, tab4, "__swig_setmethods__ = {}\n", NIL);
if (Len(base_class)) {
@ -3109,6 +3130,14 @@ public:
} else {
Printv(f_shadow, tab4, "def ", symname, "(",parms , ")", returnTypeAnnotation(n), ":", NIL);
Printv(f_shadow, "\n", NIL);
if (doxygen) {
if (Getattr(n,"DoxygenComment")){
//if(comment_creation_chatter) Printf(function_code, "/* This was generated from classHandler */");
char *convertedString = doxyTranslator.convert(n, Char(Getattr(n,"DoxygenComment")), "PYDOC");
Printf(f_shadow, Char(pythoncode(convertedString, tab8)));
free(convertedString);
}
}
if (have_docstring(n))
Printv(f_shadow, tab8, docstring(n, AUTODOC_METHOD, tab8), "\n", NIL);
if (have_pythonprepend(n)) {