improved comment formatting for Python

This commit is contained in:
Marko Klopcic 2013-02-02 23:01:09 +01:00
commit 29d1bba70a
10 changed files with 213 additions and 140 deletions

View file

@ -8,9 +8,12 @@
* \brief * \brief
* Brief description. * Brief description.
* *
* The comment text * The comment text.
*
* \author Some author * \author Some author
*
* \return Some number * \return Some number
*
* \sa function2 * \sa function2
*/ */
int function() int function()
@ -51,7 +54,6 @@ int function3(int a, int b)
* \arg it's null * \arg it's null
* *
* \warning This may not work as expected * \warning This may not work as expected
*
* \code * \code
* int main() { while(true); } * int main() { while(true); }
* \endcode * \endcode

View file

@ -0,0 +1,24 @@
def check(got, expected):
#if got is Null
# raise RuntimeError('Expected comment string\n')
#gotStr = string.replace(got, ' ', '')
#gotStr = string.replace(gotStr, '\n', '')
# gotStr = string.replace(gotStr, '\t', '')
#expectedStr = string.replace(expected, ' ', '')
#expectedStr = string.replace(expectedStr, '\n', '')
#expectedStr = string.replace(expectedStr, '\t', '')
if not got == expected:
print "\n\n////////////////////////////////////////////////////////////////////////"
expectedFileName = "expected.txt"
gotFileName = "got.txt"
print "Output is also saved to files '" + expectedFileName + \
"' and '" + gotFileName + "'";
expectedFile = open(expectedFileName, "w")
expectedFile.write(expected)
expectedFile.close()
gotFile = open(gotFileName, "w")
gotFile.write(got)
gotFile.close()
raise RuntimeError("Expected: [" + str(expected) + "]\n" + "Got : [" + str(got) + "]\n")

View file

@ -3,71 +3,77 @@
import doxygen_basic_translate import doxygen_basic_translate
import string import string
import sys import sys
import commentVerifier
def check(got, expected): commentVerifier.check(doxygen_basic_translate.function.__doc__,
#if got is Null """
# raise RuntimeError('Expected comment string\n') Brief description.
gotStr = string.replace(got, ' ', '')
gotStr = string.replace(gotStr, '\n', '')
gotStr = string.replace(gotStr, '\t', '')
expectedStr = string.replace(expected, ' ', '')
expectedStr = string.replace(expectedStr, '\n', '')
expectedStr = string.replace(expectedStr, '\t', '')
if not gotStr == expectedStr:
raise RuntimeError("Expected: [" + str(expected) + "]\n" + "Got : [" + str(got) + "]\n")
check(doxygen_basic_translate.function.__doc__, '' The comment text.
' Brief description.\n'
' The comment text\n' Author: Some author
' Authors:\n'
' Some author\n' Return: Some number
' Return:\n'
' Some number\n' See also: function2
' See also:\n' """
' function2\n'
) )
check(doxygen_basic_translate.function2.__doc__, '' commentVerifier.check(doxygen_basic_translate.function2.__doc__,
' A test of a very very very very very very very very very very very' """
' very very very very very' A test of a very very very very very very very very very very very very very very very very
' very very very very very long comment' very very very very very long comment string.
' string.' """
) )
check(doxygen_basic_translate.function3.__doc__, '' commentVerifier.check(doxygen_basic_translate.function3.__doc__,
' ----------------------------------------------------------------\n' """
' Overload 1:\n' ----------------------------------------------------------------
' ----------------------------------------------------------------\n' Overload 1:
' A test for overloaded functions\n' ----------------------------------------------------------------
' This is function __one__\n' A test for overloaded functions
' ----------------------------------------------------------------\n' This is function __one__
' Overload 2:\n'
' ----------------------------------------------------------------\n' ----------------------------------------------------------------
' A test for overloaded functions\n' Overload 2:
' This is function __two__\n' ----------------------------------------------------------------
A test for overloaded functions
This is function __two__
"""
) )
check(doxygen_basic_translate.function4.__doc__, '' commentVerifier.check(doxygen_basic_translate.function4.__doc__,
' A test of some mixed tag usage\n' """
' If: CONDITION {\n' A test of some mixed tag usage
' This _code_fragment shows us something .\n' If: CONDITION {
' Title: Minuses:\n' This _code_ fragment shows us something .
' -it\'s senseless\n' Title: Minuses:
' -it\'s stupid\n' -it\'s senseless
' -it\'s null\n' -it\'s stupid
' Warning:\n' -it\'s null
' This may not work as expected\n'
' int main() { while(true); }\n' Warning: This may not work as expected
' }'
int main() { while(true); }
}
"""
) )
check(doxygen_basic_translate.function5.__doc__, '' commentVerifier.check(doxygen_basic_translate.function5.__doc__,
' This is a post comment. \n' """
This is a post comment.
"""
) )
check(doxygen_basic_translate.function6.__doc__, '' commentVerifier.check(doxygen_basic_translate.function6.__doc__,
' Test for default args \n' """
' Arguments: \n' Test for default args
' a (int) -- Some parameter, default is 42\n' Arguments:
a (int) -- Some parameter, default is 42
"""
) )
check(doxygen_basic_translate.function7.__doc__, '' commentVerifier.check(doxygen_basic_translate.function7.__doc__,
' Test for a parameter with difficult type \n' """
' (mostly for python) \n' Test for a parameter with difficult type
' Arguments: \n' (mostly for python)
' a (Shape::superType *[10]) -- Very strange param \n' Arguments:
a (Shape::superType *[10]) -- Very strange param
"""
) )

View file

@ -1,54 +1,48 @@
#!/usr/bin/python #!/usr/bin/python
import doxygen_tricky_constructs import doxygen_misc_constructs
import string import string
import sys import sys
import commentVerifier
def check(got, expected):
#if got is Null
# raise RuntimeError('Expected comment string\n')
gotStr = string.replace(got, ' ', '')
gotStr = string.replace(gotStr, '\n', '')
gotStr = string.replace(gotStr, '\t', '')
expectedStr = string.replace(expected, ' ', '')
expectedStr = string.replace(expectedStr, '\n', '')
expectedStr = string.replace(expectedStr, '\t', '')
if not gotStr == expectedStr:
raise RuntimeError("Expected: [" + str(expected) + "]\n" + "Got : [" + str(got) + "]\n")
check(doxygen_tricky_constructs.getAddress.__doc__, '' commentVerifier.check(doxygen_misc_constructs.getAddress.__doc__,
'Returns address of file line.' r"""
'' Returns address of file line.
' Arguments:'
' fileName (int &) -- name of the file, where the source' Arguments:
' line is located' fileName (int &) -- name of the file, where the source line is located
' line (int) -- line number' line (int) -- line number
' isGetSize (bool) -- if set, for every object location' isGetSize (bool) -- if set, for every object location both address and size are returned
' both address and size are returned'
'' Connection::getId()
'' """)
' Connection::getId() <br>'
commentVerifier.check(doxygen_misc_constructs.CConnectionConfig.__doc__,
r"""
This class contains information for connection to winIDEA. Its methods
return reference to self, so we can use it like this:
CConnectionConfig config = new CConnectionConfig();
config.discoveryPort(5534).dllPath("C:\\myWinIDEA\\connect.dll").id("main");
All parameters are optional. Set only what is required, default values are
used for unspecified parameters.
advancedWinIDEALaunching.py Python example.
""")
commentVerifier.check(doxygen_misc_constructs.waitTime.__doc__,
r"""
Determines how long the 'isystem.connect' should wait for running
instances to respond. Only one of 'lfWaitXXX' flags from IConnect::ELaunchFlags
may be specified.
"""
) )
check(doxygen_tricky_constructs.CConnectionConfig.__doc__, '' commentVerifier.check(doxygen_misc_constructs.getConnection.__doc__,
' This class contains information for connection to winIDEA. Its methods' r"""
' return reference to self, so we can use it like this:' This function returns connection id.
' <pre>' """
' CConnectionConfig config = new CConnectionConfig();'
' config.discoveryPort(5534).dllPath("C: \yWinIDEA \onnect.dll").id("main");'
' </pre>'
''
' All parameters are optional. Set only what is required, default values are'
' used for unspecified parameters.'
' <p>'
''
' advancedWinIDEALaunching.py Python example. <br>'
''
) )
check(doxygen_tricky_constructs.waitTime.__doc__, ''
' Determines how long the isystem.connect should wait for running'
' instances to respond. Only one of lfWaitXXX flags from IConnect::ELaunchFlags'
' may be specified.'
)
check(doxygen_tricky_constructs.getConnection.__doc__, ''
'This class manages connection.'
)

0
Examples/test-suite/python/doxygen_parsing_runme.py Normal file → Executable file
View file

View file

0
Examples/test-suite/python/doxygen_translate_runme.py Normal file → Executable file
View file

View file

@ -1247,6 +1247,16 @@ void DoxygenParser::tokenizeDoxygenComment(const std::string &doxygenComment,
StringVector lines = split(doxygenComment, '\n'); StringVector lines = split(doxygenComment, '\n');
// remove trailing spaces, because they cause additional new line at the end
// comment, which is wrong, because these spaces are space preceding
// end of comment : ' */'
if (!doxygenComment.empty() && doxygenComment[doxygenComment.size() - 1] == ' ') {
string lastLine = lines[lines.size() - 1];
if (trim(lastLine).empty()) {
lines.pop_back(); // remove trailing empy line
}
}
for (StringVectorCIt it = lines.begin(); it != lines.end(); it++) { for (StringVectorCIt it = lines.begin(); it != lines.end(); it++) {
const string &line = *it; const string &line = *it;
size_t pos = line.find_first_not_of(" \t"); size_t pos = line.find_first_not_of(" \t");

View file

@ -31,32 +31,33 @@ void PyDocConverter::fillStaticTables() {
// table of section titles, they are printed only once // table of section titles, they are printed only once
// for each group of specified doxygen commands // for each group of specified doxygen commands
sectionTitles["author"] = "Authors:"; sectionTitles["author"] = "Author: ";
sectionTitles["authors"] = "Authors:"; sectionTitles["authors"] = "Authors: ";
sectionTitles["copyright"] = "Copyright:"; sectionTitles["copyright"] = "Copyright: ";
sectionTitles["deprecated"] = "Deprecated:"; sectionTitles["deprecated"] = "Deprecated: ";
sectionTitles["example"] = "Example:"; sectionTitles["example"] = "Example: ";
sectionTitles["exception"] = "Throws:"; sectionTitles["exception"] = "Throws: ";
sectionTitles["param"] = "Arguments:"; sectionTitles["param"] = "Arguments:\n";
sectionTitles["tparam"] = "Arguments:"; sectionTitles["tparam"] = "Arguments:\n";
sectionTitles["note"] = "Notes:"; sectionTitles["note"] = "Notes: ";
sectionTitles["remark"] = "Remarks:"; sectionTitles["remark"] = "Remarks: ";
sectionTitles["remarks"] = "Remarks:"; sectionTitles["remarks"] = "Remarks: ";
sectionTitles["warning"] = "Warning:"; sectionTitles["warning"] = "Warning: ";
sectionTitles["result"] = "Return:"; sectionTitles["result"] = "Return: ";
sectionTitles["return"] = "Return:"; sectionTitles["return"] = "Return: ";
sectionTitles["returns"] = "Return:"; sectionTitles["returns"] = "Returns: ";
sectionTitles["sa"] = "See also:"; sectionTitles["sa"] = "See also: ";
sectionTitles["see"] = "See also:"; sectionTitles["see"] = "See also: ";
sectionTitles["since"] = "Since:"; sectionTitles["since"] = "Since: ";
sectionTitles["throw"] = "Throws:"; sectionTitles["throw"] = "Throw: ";
sectionTitles["throws"] = "Throws:"; sectionTitles["throws"] = "Throws: ";
sectionTitles["todo"] = "TODO:"; sectionTitles["todo"] = "TODO: ";
sectionTitles["version"] = "Version:"; sectionTitles["version"] = "Version: ";
// these commands insert HTML tags
tagHandlers["a"] = make_pair(&PyDocConverter::handleTagWrap, "_"); tagHandlers["a"] = make_pair(&PyDocConverter::handleTagWrap, "_");
tagHandlers["b"] = make_pair(&PyDocConverter::handleTagWrap, "__"); tagHandlers["b"] = make_pair(&PyDocConverter::handleTagWrap, "__");
// \c command is translated as single quotes around next word
tagHandlers["c"] = make_pair(&PyDocConverter::handleTagWrap, "'");
tagHandlers["cite"] = make_pair(&PyDocConverter::handleTagWrap, "'"); tagHandlers["cite"] = make_pair(&PyDocConverter::handleTagWrap, "'");
tagHandlers["e"] = make_pair(&PyDocConverter::handleTagWrap, "_"); tagHandlers["e"] = make_pair(&PyDocConverter::handleTagWrap, "_");
// these commands insert just a single char, some of them need to be escaped // these commands insert just a single char, some of them need to be escaped
@ -78,7 +79,6 @@ void PyDocConverter::fillStaticTables() {
tagHandlers["authors"] = make_pair(&PyDocConverter::handleParagraph, ""); tagHandlers["authors"] = make_pair(&PyDocConverter::handleParagraph, "");
tagHandlers["brief"] = make_pair(&PyDocConverter::handleParagraph, ""); tagHandlers["brief"] = make_pair(&PyDocConverter::handleParagraph, "");
tagHandlers["bug"] = make_pair(&PyDocConverter::handleParagraph, ""); tagHandlers["bug"] = make_pair(&PyDocConverter::handleParagraph, "");
tagHandlers["c"] = make_pair(&PyDocConverter::handleParagraph, " ");
tagHandlers["code"] = make_pair(&PyDocConverter::handleParagraph, ""); tagHandlers["code"] = make_pair(&PyDocConverter::handleParagraph, "");
tagHandlers["copyright"] = make_pair(&PyDocConverter::handleParagraph, ""); tagHandlers["copyright"] = make_pair(&PyDocConverter::handleParagraph, "");
tagHandlers["date"] = make_pair(&PyDocConverter::handleParagraph, ""); tagHandlers["date"] = make_pair(&PyDocConverter::handleParagraph, "");
@ -196,7 +196,7 @@ std::string PyDocConverter::translateSubtree(DoxygenEntity & doxygenEntity) {
if (it != sectionTitles.end()) { if (it != sectionTitles.end()) {
if (it->second != currentSection) { if (it->second != currentSection) {
currentSection = it->second; currentSection = it->second;
translatedComment += currentSection + "\n"; translatedComment += currentSection;
} }
} }
translateEntity(*p, translatedComment); translateEntity(*p, translatedComment);
@ -215,22 +215,31 @@ void PyDocConverter::translateEntity(DoxygenEntity & doxyEntity, std::string &tr
(this->*(it->second.first))(doxyEntity, translatedComment, it->second.second); (this->*(it->second.first))(doxyEntity, translatedComment, it->second.second);
} }
void PyDocConverter::handleParagraph(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) { void PyDocConverter::handleParagraph(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) {
translatedComment += translateSubtree(tag) + arg; translatedComment += translateSubtree(tag) + arg;
} }
void PyDocConverter::handlePlainString(DoxygenEntity& tag, std::string& translatedComment, std::string&) { void PyDocConverter::handlePlainString(DoxygenEntity& tag, std::string& translatedComment, std::string&) {
translatedComment += tag.data; translatedComment += tag.data;
if (tag.data.size() && tag.data[tag.data.size()-1] != ' ') if (tag.data.size() && tag.data[tag.data.size()-1] != ' ')
translatedComment += ""; translatedComment += "";
} }
void PyDocConverter::handleTagMessage(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) { void PyDocConverter::handleTagMessage(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) {
std::string dummy; std::string dummy;
translatedComment += arg; translatedComment += arg;
handleParagraph(tag, translatedComment, dummy); handleParagraph(tag, translatedComment, dummy);
} }
void PyDocConverter::handleTagChar(DoxygenEntity& tag, std::string& translatedComment, std::string&) { void PyDocConverter::handleTagChar(DoxygenEntity& tag, std::string& translatedComment, std::string&) {
translatedComment += tag.typeOfEntity; translatedComment += tag.typeOfEntity;
} }
void PyDocConverter::handleTagIf(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) { void PyDocConverter::handleTagIf(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) {
std::string dummy; std::string dummy;
translatedComment += arg; translatedComment += arg;
@ -240,6 +249,8 @@ void PyDocConverter::handleTagIf(DoxygenEntity& tag, std::string& translatedComm
translatedComment += " {" + translateSubtree(tag) + "}"; translatedComment += " {" + translateSubtree(tag) + "}";
} }
} }
void PyDocConverter::handleTagPar(DoxygenEntity& tag, std::string& translatedComment, std::string&) { void PyDocConverter::handleTagPar(DoxygenEntity& tag, std::string& translatedComment, std::string&) {
std::string dummy; std::string dummy;
translatedComment += "Title: "; translatedComment += "Title: ";
@ -248,6 +259,8 @@ void PyDocConverter::handleTagPar(DoxygenEntity& tag, std::string& translatedCom
tag.entityList.pop_front(); tag.entityList.pop_front();
handleParagraph(tag, translatedComment, dummy); handleParagraph(tag, translatedComment, dummy);
} }
void PyDocConverter::handleTagImage(DoxygenEntity& tag, std::string& translatedComment, std::string&) { void PyDocConverter::handleTagImage(DoxygenEntity& tag, std::string& translatedComment, std::string&) {
if (tag.entityList.size() < 2) if (tag.entityList.size() < 2)
return; return;
@ -258,7 +271,11 @@ void PyDocConverter::handleTagImage(DoxygenEntity& tag, std::string& translatedC
if (tag.entityList.size()) if (tag.entityList.size())
translatedComment += "(" + tag.entityList.begin()->data + ")"; translatedComment += "(" + tag.entityList.begin()->data + ")";
} }
void PyDocConverter::handleTagParam(DoxygenEntity& tag, std::string& translatedComment, std::string&) {
void PyDocConverter::handleTagParam(DoxygenEntity& tag,
std::string& translatedComment,
std::string&) {
std::string dummy; std::string dummy;
if (tag.entityList.size() < 2) if (tag.entityList.size() < 2)
return; return;
@ -270,9 +287,11 @@ void PyDocConverter::handleTagParam(DoxygenEntity& tag, std::string& translatedC
if (!paramType.size()) if (!paramType.size())
paramType = "none"; paramType = "none";
translatedComment += paramNameEntity.data + " (" + paramType + ") -- "; translatedComment += " " + paramNameEntity.data + " (" + paramType + ") --";
handleParagraph(tag, translatedComment, dummy); handleParagraph(tag, translatedComment, dummy);
} }
void PyDocConverter::handleTagWrap(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) { void PyDocConverter::handleTagWrap(DoxygenEntity& tag, std::string& translatedComment, std::string &arg) {
if (tag.entityList.size()) { // do not include empty tags if (tag.entityList.size()) { // do not include empty tags
std::string tagData = translateSubtree(tag); std::string tagData = translateSubtree(tag);
@ -281,13 +300,16 @@ void PyDocConverter::handleTagWrap(DoxygenEntity& tag, std::string& translatedCo
if (wsPos != std::string::npos && wsPos != tagData.size() - 1) if (wsPos != std::string::npos && wsPos != tagData.size() - 1)
translatedComment += arg + tagData.substr(0, wsPos + 1) + arg + tagData.substr(wsPos + 1); translatedComment += arg + tagData.substr(0, wsPos + 1) + arg + tagData.substr(wsPos + 1);
else else
translatedComment += arg + tagData + arg + " "; translatedComment += arg + tagData + arg;
} }
} }
void PyDocConverter::handleNewLine(DoxygenEntity&, std::string& translatedComment, std::string&) { void PyDocConverter::handleNewLine(DoxygenEntity&, std::string& translatedComment, std::string&) {
translatedComment += "\n"; translatedComment += "\n";
} }
String *PyDocConverter::makeDocumentation(Node *n) { String *PyDocConverter::makeDocumentation(Node *n) {
String *documentation; String *documentation;
std::string pyDocString, result; std::string pyDocString, result;
@ -358,7 +380,13 @@ String *PyDocConverter::makeDocumentation(Node *n) {
} }
// if we got something log the result and construct DOH string to return // if we got something log the result and construct DOH string to return
if (pyDocString.length()) { if (!pyDocString.empty()) {
// remove the last '\n' since additional one is added during writing to file
if (pyDocString[pyDocString.size() - 1] == '\n') {
pyDocString.erase(pyDocString.size() - 1);
}
result = pyDocString; result = pyDocString;
if (debug) { if (debug) {

View file

@ -1257,26 +1257,35 @@ public:
// //
// otherwise, put it all on a single line // otherwise, put it all on a single line
// //
// All comments translated from doxygen are given as raw stringr (prefix "r"),
// because '\' is used often in comments, but may break Python module from
// loading. For example, in doxy comment one may write path in quotes:
//
// This is path to file "C:\x\file.txt"
//
// Python will no load the module with such comment becaue of illegal
// escape '\x'. '\' may additionally appear in verbatim or htmlonly sections
// of doxygen doc, Latex expressions, ...
if (have_auto && have_ds) { // Both autodoc and docstring are present if (have_auto && have_ds) { // Both autodoc and docstring are present
doc = NewString(""); doc = NewString("");
Printv(doc, triple_double, "\n", pythoncode(autodoc, indent), "\n", pythoncode(str, indent), indent, triple_double, NIL); Printv(doc, "r", triple_double, "\n", pythoncode(autodoc, indent), "\n", pythoncode(str, indent), indent, triple_double, NIL);
} else if (!have_auto && have_ds) { // only docstring } else if (!have_auto && have_ds) { // only docstring
if (Strchr(str, '\n') == 0) { if (Strchr(str, '\n') == 0) {
doc = NewStringf("%s%s%s", triple_double, str, triple_double); doc = NewStringf("%s%s%s", triple_double, str, triple_double);
} else { } else {
doc = NewString(""); doc = NewString("");
Printv(doc, triple_double, "\n", pythoncode(str, indent), indent, triple_double, NIL); Printv(doc, "r", triple_double, "\n", pythoncode(str, indent), indent, triple_double, NIL);
} }
} else if (have_auto && !have_ds) { // only autodoc } else if (have_auto && !have_ds) { // only autodoc
if (Strchr(autodoc, '\n') == 0) { if (Strchr(autodoc, '\n') == 0) {
doc = NewStringf("%s%s%s", triple_double, autodoc, triple_double); doc = NewStringf("%s%s%s", triple_double, autodoc, triple_double);
} else { } else {
doc = NewString(""); doc = NewString("");
Printv(doc, triple_double, "\n", pythoncode(autodoc, indent), indent, triple_double, NIL); Printv(doc, "r", triple_double, "\n", pythoncode(autodoc, indent), indent, triple_double, NIL);
} }
} else if (have_doxygen) { // the lowest priority } else if (have_doxygen) { // the lowest priority
doc = NewString(""); doc = NewString("");
Printv(doc, triple_double, "\n", pythoncode(doxygen_comment, indent), indent, triple_double, NIL); Printv(doc, "r", triple_double, "\n", pythoncode(doxygen_comment, indent), indent, triple_double, NIL);
} }
else else
doc = NewString(""); doc = NewString("");