Merge branch 'doxy/commands'
* doxy/commands: Update documentation for doxygen tags Fix doxygen translation of \p command for python Fix doxygen handling of \em tag for python Minor formatting updates to doxygen docs Reformat tag lists in doxygen documentation Add doxygen_code_blocks_runme.java Special handling for python doctest code blocks Add new doxygen test doxygen_code_blocks Handle doxygen code command with language option Improve doxygen parser handling of \code content Flag optional arguments in doxygen pydoc output Add parameter direction to doxygen pydoc output Support doxygen \param[] commands
This commit is contained in:
commit
00b47d4d1d
19 changed files with 699 additions and 437 deletions
|
|
@ -18,11 +18,13 @@
|
|||
const char *CMD_HTML_ONLY = "htmlonly";
|
||||
// doxy commands are not processed inside this block
|
||||
const char *CMD_VERBATIM = "verbatim";
|
||||
const char *CMD_CODE = "code";
|
||||
const char *CMD_LATEX_1 = "f$";
|
||||
const char *CMD_LATEX_2 = "f{";
|
||||
const char *CMD_LATEX_3 = "f[";
|
||||
const char *CMD_END_HTML_ONLY = "endhtmlonly";
|
||||
const char *CMD_END_VERBATIM = "endverbatim";
|
||||
const char *CMD_END_CODE = "endcode";
|
||||
const char *CMD_END_LATEX_1 = "f$";
|
||||
const char *CMD_END_LATEX_2 = "f}";
|
||||
const char *CMD_END_LATEX_3 = "f]";
|
||||
|
|
|
|||
|
|
@ -34,6 +34,30 @@ std::set<std::string> DoxygenParser::doxygenSectionIndicators;
|
|||
const int TOKENSPERLINE = 8; //change this to change the printing behaviour of the token list
|
||||
const std::string END_HTML_TAG_MARK("/");
|
||||
|
||||
std::string getBaseCommand(const std::string &cmd) {
|
||||
if (cmd.substr(0,5) == "param")
|
||||
return "param";
|
||||
else if (cmd.substr(0,4) == "code")
|
||||
return "code";
|
||||
else
|
||||
return cmd;
|
||||
}
|
||||
|
||||
// Find the first position beyond the word command. Extra logic is
|
||||
// used to avoid putting the characters "," and "." in
|
||||
// DOXYGEN_WORD_CHARS.
|
||||
static size_t getEndOfWordCommand(const std::string &line, size_t pos) {
|
||||
size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
|
||||
if (line.substr(pos, 6) == "param[")
|
||||
// include ",", which can appear in param[in,out]
|
||||
endOfWordPos = line.find_first_not_of(string(DOXYGEN_WORD_CHARS)+ ",", pos);
|
||||
else if (line.substr(pos, 5) == "code{")
|
||||
// include ".", which can appear in e.g. code{.py}
|
||||
endOfWordPos = line.find_first_not_of(string(DOXYGEN_WORD_CHARS)+ ".", pos);
|
||||
return endOfWordPos;
|
||||
}
|
||||
|
||||
|
||||
DoxygenParser::DoxygenParser(bool noisy) : noisy(noisy) {
|
||||
fillTables();
|
||||
}
|
||||
|
|
@ -118,7 +142,7 @@ void DoxygenParser::printTree(const DoxygenEntityList &rootList) {
|
|||
}
|
||||
|
||||
DoxygenParser::DoxyCommandEnum DoxygenParser::commandBelongs(const std::string &theCommand) {
|
||||
DoxyCommandsMapIt it = doxygenCommands.find(stringToLower(theCommand));
|
||||
DoxyCommandsMapIt it = doxygenCommands.find(stringToLower(getBaseCommand(theCommand)));
|
||||
|
||||
if (it != doxygenCommands.end()) {
|
||||
return it->second;
|
||||
|
|
@ -312,7 +336,7 @@ DoxygenParser::TokenListCIt DoxygenParser::getEndOfParagraph(const TokenList &to
|
|||
|
||||
} else if (endOfParagraph->m_tokenType == COMMAND) {
|
||||
|
||||
if (isSectionIndicator(endOfParagraph->m_tokenString)) {
|
||||
if (isSectionIndicator(getBaseCommand(endOfParagraph->m_tokenString))) {
|
||||
return endOfParagraph;
|
||||
} else {
|
||||
endOfParagraph++;
|
||||
|
|
@ -666,7 +690,7 @@ void DoxygenParser::addCommandUnique(const std::string &theCommand, const TokenL
|
|||
// \f{ ... \f}
|
||||
// \f{env}{ ... \f}
|
||||
// \f$ ... \f$
|
||||
else if (theCommand == "code" || theCommand == "verbatim"
|
||||
else if (getBaseCommand(theCommand) == "code" || theCommand == "verbatim"
|
||||
|| theCommand == "dot" || theCommand == "msc" || theCommand == "f[" || theCommand == "f{" || theCommand == "f$") {
|
||||
if (!endCommands.size()) {
|
||||
// fill in static table of end commands
|
||||
|
|
@ -683,7 +707,7 @@ void DoxygenParser::addCommandUnique(const std::string &theCommand, const TokenL
|
|||
if (it != endCommands.end())
|
||||
endCommand = it->second;
|
||||
else
|
||||
endCommand = "end" + theCommand;
|
||||
endCommand = "end" + getBaseCommand(theCommand);
|
||||
|
||||
std::string content = getStringTilEndCommand(endCommand, tokList);
|
||||
aNewList.push_back(DoxygenEntity("plainstd::string", content));
|
||||
|
|
@ -1090,7 +1114,7 @@ size_t DoxygenParser::processVerbatimText(size_t pos, const std::string &line) {
|
|||
size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
|
||||
string cmd = line.substr(pos, endOfWordPos - pos);
|
||||
|
||||
if (cmd == CMD_END_HTML_ONLY || cmd == CMD_END_VERBATIM || cmd == CMD_END_LATEX_1 || cmd == CMD_END_LATEX_2 || cmd == CMD_END_LATEX_3) {
|
||||
if (cmd == CMD_END_HTML_ONLY || cmd == CMD_END_VERBATIM || cmd == CMD_END_LATEX_1 || cmd == CMD_END_LATEX_2 || cmd == CMD_END_LATEX_3 || cmd == CMD_END_CODE) {
|
||||
|
||||
m_isVerbatimText = false;
|
||||
addDoxyCommand(m_tokenList, cmd);
|
||||
|
|
@ -1154,22 +1178,34 @@ bool DoxygenParser::processEscapedChars(size_t &pos, const std::string &line) {
|
|||
*/
|
||||
void DoxygenParser::processWordCommands(size_t &pos, const std::string &line) {
|
||||
pos++;
|
||||
size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
|
||||
size_t endOfWordPos = getEndOfWordCommand(line, pos);
|
||||
|
||||
string cmd = line.substr(pos, endOfWordPos - pos);
|
||||
addDoxyCommand(m_tokenList, cmd);
|
||||
|
||||
if (cmd == CMD_HTML_ONLY || cmd == CMD_VERBATIM || cmd == CMD_LATEX_1 || cmd == CMD_LATEX_2 || cmd == CMD_LATEX_3) {
|
||||
// A flag for whether we want to skip leading spaces after the command
|
||||
bool skipLeadingSpace = true;
|
||||
|
||||
if (cmd == CMD_HTML_ONLY || cmd == CMD_VERBATIM || cmd == CMD_LATEX_1 || cmd == CMD_LATEX_2 || cmd == CMD_LATEX_3 || getBaseCommand(cmd) == CMD_CODE) {
|
||||
|
||||
m_isVerbatimText = true;
|
||||
|
||||
} else {
|
||||
// Skipping leading space is necessary with inline \code command,
|
||||
// and it won't hurt anything for block \code (TODO: are the other
|
||||
// commands also compatible with skip leading space? If so, just
|
||||
// do it every time.)
|
||||
if (getBaseCommand(cmd) == CMD_CODE) skipLeadingSpace = true;
|
||||
else skipLeadingSpace = false;
|
||||
}
|
||||
|
||||
if (skipLeadingSpace) {
|
||||
// skip any possible spaces after command, because some commands have parameters,
|
||||
// and spaces between command and parameter must be ignored.
|
||||
if (endOfWordPos != string::npos) {
|
||||
endOfWordPos = line.find_first_not_of(" \t", endOfWordPos);
|
||||
}
|
||||
}
|
||||
|
||||
pos = endOfWordPos;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
#include "doxyentity.h"
|
||||
|
||||
// Utility function to return the base part of a command that may
|
||||
// include options, e.g. param[in] -> param
|
||||
std::string getBaseCommand(const std::string &cmd);
|
||||
|
||||
|
||||
class DoxygenParser {
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ std::string JavaDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
|
|||
void JavaDocConverter::translateEntity(DoxygenEntity &tag, std::string &translatedComment) {
|
||||
|
||||
std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
|
||||
it = tagHandlers.find(tag.typeOfEntity);
|
||||
it = tagHandlers.find(getBaseCommand(tag.typeOfEntity));
|
||||
|
||||
if (it != tagHandlers.end()) {
|
||||
(this->*(it->second.first))(tag, translatedComment, it->second.second);
|
||||
|
|
|
|||
|
|
@ -174,7 +174,8 @@ static string padCodeAndVerbatimBlocks(const string &docString) {
|
|||
} else {
|
||||
if (lastLineWasNonBlank &&
|
||||
(line.compare(pos, 13, ".. code-block") == 0 ||
|
||||
line.compare(pos, 7, ".. math") == 0)) {
|
||||
line.compare(pos, 7, ".. math") == 0 ||
|
||||
line.compare(pos, 3, ">>>") == 0)) {
|
||||
// Must separate code or math blocks from the previous line
|
||||
result += '\n';
|
||||
}
|
||||
|
|
@ -184,6 +185,21 @@ static string padCodeAndVerbatimBlocks(const string &docString) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Helper function to extract the option value from a command,
|
||||
// e.g. param[in] -> in
|
||||
static std::string getCommandOption(const std::string &command, char openChar, char closeChar) {
|
||||
string option;
|
||||
|
||||
size_t opt_begin, opt_end;
|
||||
opt_begin = command.find(openChar);
|
||||
opt_end = command.find(closeChar);
|
||||
if (opt_begin != string::npos && opt_end != string::npos)
|
||||
option = command.substr(opt_begin+1, opt_end-opt_begin-1);
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler) {
|
||||
return make_pair(handler, std::string());
|
||||
|
|
@ -245,7 +261,7 @@ void PyDocConverter::fillStaticTables() {
|
|||
tagHandlers["date"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["deprecated"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["details"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["em"] = make_handler(&PyDocConverter::handleParagraph, " ");
|
||||
tagHandlers["em"] = make_handler(&PyDocConverter::handleTagWrap, "*");
|
||||
tagHandlers["example"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["exception"] = tagHandlers["throw"] = tagHandlers["throws"] = make_handler(&PyDocConverter::handleTagException);
|
||||
tagHandlers["htmlonly"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
|
|
@ -254,7 +270,7 @@ void PyDocConverter::fillStaticTables() {
|
|||
tagHandlers["link"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["manonly"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["note"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["p"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["p"] = make_handler(&PyDocConverter::handleTagWrap, "``");
|
||||
tagHandlers["partofdescription"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["rtfonly"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
tagHandlers["remark"] = make_handler(&PyDocConverter::handleParagraph);
|
||||
|
|
@ -428,6 +444,23 @@ std::string PyDocConverter::getParamType(std::string param) {
|
|||
return type;
|
||||
}
|
||||
|
||||
std::string PyDocConverter::getParamValue(std::string param) {
|
||||
std::string value;
|
||||
|
||||
ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
|
||||
for (Parm *p = plist; p; p = nextSibling(p)) {
|
||||
String *pname = Getattr(p, "name");
|
||||
if (Char(pname) != param)
|
||||
continue;
|
||||
|
||||
String *pval = Getattr(p, "value");
|
||||
if (pval) value = Char(pval);
|
||||
break;
|
||||
}
|
||||
Delete(plist);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
|
||||
std::string translatedComment;
|
||||
|
||||
|
|
@ -456,7 +489,7 @@ std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
|
|||
void PyDocConverter::translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment) {
|
||||
// check if we have needed handler and call it
|
||||
std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
|
||||
it = tagHandlers.find(doxyEntity.typeOfEntity);
|
||||
it = tagHandlers.find(getBaseCommand(doxyEntity.typeOfEntity));
|
||||
if (it != tagHandlers.end())
|
||||
(this->*(it->second.first)) (doxyEntity, translatedComment, it->second.second);
|
||||
}
|
||||
|
|
@ -531,19 +564,29 @@ void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComme
|
|||
|
||||
trimWhitespace(translatedComment);
|
||||
|
||||
// Use the current indent for the code-block line itself.
|
||||
translatedComment += indent.getFirstLineIndent();
|
||||
|
||||
// Go out on a limb and assume that examples in the C or C++ sources use C++.
|
||||
// In the worst case, we'll highlight C code using C++ syntax which is not a
|
||||
// big deal (TODO: handle Doxygen code command language argument).
|
||||
translatedComment += ".. code-block:: c++\n\n";
|
||||
|
||||
// Specify the level of extra indentation that will be used for
|
||||
// subsequent lines within the code block. Note that the correct
|
||||
// "starting indentation" is already present in the input, so we
|
||||
// only need to add the desired code block indentation.
|
||||
string codeIndent = m_indent;
|
||||
// Check for an option given to the code command (e.g. code{.py}),
|
||||
// and try to set the code-block language accordingly.
|
||||
string option = getCommandOption(tag.typeOfEntity, '{', '}');
|
||||
// Set up the language option to the code-block command, which can
|
||||
// be any language supported by pygments:
|
||||
string codeLanguage;
|
||||
if (option == ".py")
|
||||
// Other possibilities here are "default" or "python3". In Sphinx
|
||||
// 2.1.2, basic syntax doesn't render quite the same in these as
|
||||
// with "python", which for basic keywords seems to provide
|
||||
// slightly richer formatting. Another option would be to leave
|
||||
// the language empty, but testing with Sphinx 1.8.5 has produced
|
||||
// an error "1 argument required".
|
||||
codeLanguage = "python";
|
||||
else if (option == ".java")
|
||||
codeLanguage = "java";
|
||||
else if (option == ".c")
|
||||
codeLanguage = "c";
|
||||
else
|
||||
// If there is not a match, or if no option was given, go out on a
|
||||
// limb and assume that the examples in the C or C++ sources use
|
||||
// C++.
|
||||
codeLanguage = "c++";
|
||||
|
||||
std::string code;
|
||||
handleTagVerbatim(tag, code, arg);
|
||||
|
|
@ -552,6 +595,27 @@ void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComme
|
|||
// command:
|
||||
eraseLeadingNewLine(code);
|
||||
|
||||
// Check for python doctest blocks, and treat them specially:
|
||||
bool isDocTestBlock = false;
|
||||
size_t startPos;
|
||||
// ">>>" would normally appear at the beginning, but doxygen comment
|
||||
// style may have space in front, so skip leading whitespace
|
||||
if ((startPos=code.find_first_not_of(" \t")) != string::npos && code.substr(startPos,3) == ">>>")
|
||||
isDocTestBlock = true;
|
||||
|
||||
string codeIndent;
|
||||
if (! isDocTestBlock) {
|
||||
// Use the current indent for the code-block line itself.
|
||||
translatedComment += indent.getFirstLineIndent();
|
||||
translatedComment += ".. code-block:: " + codeLanguage + "\n\n";
|
||||
|
||||
// Specify the level of extra indentation that will be used for
|
||||
// subsequent lines within the code block. Note that the correct
|
||||
// "starting indentation" is already present in the input, so we
|
||||
// only need to add the desired code block indentation.
|
||||
codeIndent = m_indent;
|
||||
}
|
||||
|
||||
translatedComment += codeIndent;
|
||||
for (size_t n = 0; n < code.length(); n++) {
|
||||
if (code[n] == '\n') {
|
||||
|
|
@ -636,8 +700,26 @@ void PyDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedC
|
|||
const std::string ¶mName = paramNameEntity.data;
|
||||
|
||||
const std::string paramType = getParamType(paramName);
|
||||
const std::string paramValue = getParamValue(paramName);
|
||||
|
||||
// Get command option, e.g. "in", "out", or "in,out"
|
||||
string commandOpt = getCommandOption(tag.typeOfEntity, '[', ']');
|
||||
if (commandOpt == "in,out") commandOpt = "in/out";
|
||||
|
||||
// If provided, append the parameter direction to the type
|
||||
// information via a suffix:
|
||||
std::string suffix;
|
||||
if (commandOpt.size() > 0)
|
||||
suffix = ", " + commandOpt;
|
||||
|
||||
// If the parameter has a default value, flag it as optional in the
|
||||
// generated type definition. Particularly helpful when the python
|
||||
// call is generated with *args, **kwargs.
|
||||
if (paramValue.size() > 0)
|
||||
suffix += ", optional";
|
||||
|
||||
if (!paramType.empty()) {
|
||||
translatedComment += ":type " + paramName + ": " + paramType + "\n";
|
||||
translatedComment += ":type " + paramName + ": " + paramType + suffix + "\n";
|
||||
translatedComment += indent.getFirstLineIndent();
|
||||
}
|
||||
|
||||
|
|
@ -909,3 +991,4 @@ String *PyDocConverter::makeDocumentation(Node *n) {
|
|||
|
||||
return NewString(pyDocString.c_str());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,11 @@ protected:
|
|||
*/
|
||||
std::string getParamType(std::string name);
|
||||
|
||||
/*
|
||||
* Simple helper function to retrieve the parameter value
|
||||
*/
|
||||
std::string getParamValue(std::string name);
|
||||
|
||||
private:
|
||||
// temporary thing, should be refactored somehow
|
||||
Node *currentNode;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue