diff --git a/Examples/test-suite/doxygen_translate_links.i b/Examples/test-suite/doxygen_translate_links.i new file mode 100644 index 000000000..5eee1d67f --- /dev/null +++ b/Examples/test-suite/doxygen_translate_links.i @@ -0,0 +1,67 @@ + + +%module doxygen_translate_links +%include "std_string.i" + +%inline %{ + +class Shape +{ +public: + typedef Shape* superType; +}; + +/** + * Testing typenames converting in \@ link + * + * \link superFunc(int,std::string) + * Test for std_string member + * \endlink + * + * \link superFunc(int,long,void*) + * Test for simple types + * \endlink + * + * \link superFunc(Shape::superType*) + * Test for custom types + * \endlink + * + * \link superFunc(int**[13]) + * Test for complex types + * \endlink + * + * same works for 'See also:' links: + * + * \sa superFunc(int,std::string) + * \sa superFunc(int,long,void*) + * \sa superFunc(Shape::superType*) + * \sa superFunc(int**[13]) + * + * some failing params: + * + * \sa superFunc() + * \sa superFunc() + * \sa superFunc() + * + */ +int function() +{ +} + +void superFunc(int, std::string) +{ +} + +void superFunc(int, long, void *) +{ +} + +void superFunc(Shape::superType *) +{ +} + +void superFunc(int **arr[13]) +{ +} + +%} diff --git a/Examples/test-suite/java/doxygen_translate_links_runme.java b/Examples/test-suite/java/doxygen_translate_links_runme.java new file mode 100644 index 000000000..080063430 --- /dev/null +++ b/Examples/test-suite/java/doxygen_translate_links_runme.java @@ -0,0 +1,68 @@ + +import doxygen_translate_links.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_translate_links_runme { + static { + try { + System.loadLibrary("doxygen_translate_links"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + commentParser parser = new commentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_translate_links runtime test", + "commentParser", new String[]{"-quiet", "doxygen_translate_links"}); + + HashMap wantedComments = new HashMap(); + + + wantedComments.put("doxygen_translate_links.doxygen_translate_links.function()", + " \n" + + " Testing typenames converting in @ link \n" + + " \n" + + " {@link superFunc(int,String) \n" + + " Test for std_string member \n" + + " }\n" + + " \n" + + " {@link superFunc(int,int,SWIGTYPE_p_void) \n" + + " Test for simple types \n" + + " }\n" + + " \n" + + " {@link superFunc(SWIGTYPE_p_p_Shape) \n" + + " Test for custom types \n" + + " }\n" + + " \n" + + " {@link superFunc(SWIGTYPE_p_p_p_int) \n" + + " Test for complex types \n" + + " }\n" + + " \n" + + " same works for 'See also:' links: \n" + + " \n" + + " @see superFunc(int,String)\n" + + " @see superFunc(int,int,SWIGTYPE_p_void)\n" + + " @see superFunc(SWIGTYPE_p_p_Shape)\n" + + " @see superFunc(SWIGTYPE_p_p_p_int)\n" + + " \n" + + " some failing params: \n" + + " \n" + + " @see superFunc() \n" + + " @see superFunc() \n" + + " @see superFunc() \n" + + " \n" + + " \n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} \ No newline at end of file diff --git a/Source/DoxygenTranslator/src/JavaDocConverter.cpp b/Source/DoxygenTranslator/src/JavaDocConverter.cpp index 421134828..123eb040b 100644 --- a/Source/DoxygenTranslator/src/JavaDocConverter.cpp +++ b/Source/DoxygenTranslator/src/JavaDocConverter.cpp @@ -12,6 +12,8 @@ #include "JavaDocConverter.h" #include "DoxygenParser.h" #include +#include +#include "../../Modules/swigmod.h" #define APPROX_LINE_LENGTH 64 //characters per line allowed #define TAB_SIZE 8 //current tab size in spaces //TODO {@link} {@linkplain} {@docRoot}, and other useful doxy commands that are not a javadoc tag @@ -71,8 +73,8 @@ void JavaDocConverter::fillStaticTables() { tagHandlers["result"] = make_pair(&JavaDocConverter::handleTagSame, "return"); tagHandlers["return"] = make_pair(&JavaDocConverter::handleTagSame, ""); tagHandlers["returns"] = make_pair(&JavaDocConverter::handleTagSame, "return"); - tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSame, ""); - tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSame, "see"); + //tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSame, ""); + //tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSame, "see"); tagHandlers["since"] = make_pair(&JavaDocConverter::handleTagSame, ""); tagHandlers["throws"] = make_pair(&JavaDocConverter::handleTagSame, ""); tagHandlers["throw"] = make_pair(&JavaDocConverter::handleTagSame, "throws"); @@ -87,7 +89,9 @@ void JavaDocConverter::fillStaticTables() { tagHandlers["if"] = make_pair(&JavaDocConverter::handleTagIf, "If: "); tagHandlers["ifnot"] = make_pair(&JavaDocConverter::handleTagIf, "If not: "); tagHandlers["image"] = make_pair(&JavaDocConverter::handleTagImage, ""); - tagHandlers["link"] = make_pair(&JavaDocConverter::handleTagExtended, "link"); + tagHandlers["link"] = make_pair(&JavaDocConverter::handleTagLink, ""); + tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSee, ""); + tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSee, ""); tagHandlers["note"] = make_pair(&JavaDocConverter::handleTagMessage, "Note: "); tagHandlers["overload"] = make_pair(&JavaDocConverter::handleTagMessage, "This is an overloaded member function, provided for" " convenience. It differs from the above function only in what" @@ -152,10 +156,12 @@ std::string JavaDocConverter::formatCommand(std::string unformattedLine, int ind } bool JavaDocConverter::paramExists(std::string param) { + if (GetFlag(currentNode, "feature:doxygen:nostripparams")) + return true; ParmList *plist = CopyParmList(Getattr(currentNode, "parms")); Parm *p = NULL; for (p = plist; p;) { - if (Char(Getattr(p, "name")) == param) + if (Getattr(p, "name") && Char(Getattr(p, "name")) == param) return true; /* * doesn't seem to work always: in some cases (especially for 'self' parameters) @@ -289,6 +295,115 @@ void JavaDocConverter::handleTagParam(DoxygenEntity& tag, std::string& translate handleParagraph(tag, translatedComment, dummy); } +string JavaDocConverter::convertLink(string linkObject) { + if (GetFlag(currentNode, "feature:doxygen:nolinktranslate")) + return linkObject; + // find the params in function in linkObject (if any) + size_t lbracePos = linkObject.find('(', 0); + size_t rbracePos = linkObject.find(')', 0); + if (lbracePos == string::npos && rbracePos == string::npos && lbracePos >= rbracePos) + return ""; + + string paramsStr = linkObject.substr(lbracePos + 1, rbracePos - lbracePos - 1); + // strip the params, to fill them later + linkObject = linkObject.substr(0, lbracePos); + + // find all the params + vector params; + size_t lastPos = 0, commaPos = 0; + while (true) { + commaPos = paramsStr.find(',', lastPos); + if (commaPos == string::npos) + commaPos = paramsStr.size(); + string param = paramsStr.substr(lastPos, commaPos - lastPos); + // if any param type is empty, we are failed + if (!param.size()) + return ""; + params.push_back(param); + lastPos = commaPos + 1; + if (lastPos >= paramsStr.size()) + break; + } + + linkObject += "("; + for (size_t i=0; i 'a(100).a(10).p.p.int' + // also converting arrays to pointers + string paramStr = params[i]; + String *swigType = NewString(""); + for (int j=(int)params[i].size() - 1; j>=0; j--) { + // skip all the [...] blocks, write 'p.' for every of it + if (paramStr[j] == ']') { + while (j>=0 && paramStr[j] != '[') + j--; + // no closing brace + if (!j) + return ""; + Append(swigType, "p."); + continue; + } + else if (paramStr[j] == '*') + Append(swigType, "p."); + else if (isalnum(paramStr[j])) { + Append(swigType, paramStr.substr(0, j + 1).c_str()); + break; + } + } + + // make dummy param list, to lookup typemaps for it + Parm *dummyParam = NewParm(swigType, "", 0); + Swig_typemap_attach_parms("jstype", dummyParam, NULL); + Language::instance()->replaceSpecialVariables(0, Getattr(dummyParam, "tmap:jstype"), dummyParam); + + //Swig_print(dummyParam, 1); + linkObject += Char(Getattr(dummyParam, "tmap:jstype")); + if (i != params.size() - 1) + linkObject += ","; + + Delete(dummyParam); + Delete(swigType); + } + linkObject += ")"; + + return linkObject; +} + +void JavaDocConverter::handleTagLink(DoxygenEntity& tag, std::string& translatedComment, std::string&) { + std::string dummy; + if (!tag.entityList.size()) + return; + + string linkObject = convertLink(tag.entityList.begin()->data); + if (!linkObject.size()) + linkObject = tag.entityList.begin()->data; + tag.entityList.pop_front(); + + translatedComment += "{@link "; + translatedComment += linkObject + " "; + handleParagraph(tag, translatedComment, dummy); + translatedComment += "}"; +} + +void JavaDocConverter::handleTagSee(DoxygenEntity& tag, std::string& translatedComment, std::string&) { + std::string dummy; + if (!tag.entityList.size()) + return; + + list::iterator it; + for (it = tag.entityList.begin(); it!=tag.entityList.end(); it++) { + if (it->typeOfEntity == "plainstd::endl") + handleNewLine(*it, translatedComment, dummy); + if (it->typeOfEntity != "plainstd::string") + continue; + translatedComment += "@see "; + string linkObject = convertLink(it->data); + if (!linkObject.size()) + linkObject = it->data; + translatedComment += linkObject; + } +} + String *JavaDocConverter::makeDocumentation(Node *node) { String *documentation = getDoxygenComment(node); diff --git a/Source/DoxygenTranslator/src/JavaDocConverter.h b/Source/DoxygenTranslator/src/JavaDocConverter.h index f68a712b9..a547a17f8 100644 --- a/Source/DoxygenTranslator/src/JavaDocConverter.h +++ b/Source/DoxygenTranslator/src/JavaDocConverter.h @@ -30,6 +30,11 @@ protected: std::string translateSubtree(DoxygenEntity & doxygenEntity); void translateEntity(DoxygenEntity &tag, std::string &translatedComment); + /* + * Convert params in link-objects and references + */ + std::string convertLink(std::string linkObject); + /* * Typedef for the function that handles one tag * arg - some string argument to easily pass it through lookup table @@ -89,6 +94,16 @@ protected: * Insert @param command, if it is really a function param */ void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + /* + * Insert {@link...} command, and handle all the s correctly + * (like converting types of params, etc) + */ + void handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + /* + * Insert @see command, and handle all the s correctly + * (like converting types of params, etc) + */ + void handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); private: