From 751f617aac000ea1cddc0d52d58ba5ed3a6318a3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 1 Feb 2017 02:06:16 +0100 Subject: [PATCH] Add support for doxygen:alias feature This allows to replace non-standard Doxygen commands with some (fixed) text instead of just ignoring them, as was already possible with the feature doxygen:ignore. --- Doc/Manual/Doxygen.html | 53 +++++++++++++++++-- Examples/test-suite/common.mk | 1 + Examples/test-suite/doxygen_alias.i | 22 ++++++++ .../test-suite/java/doxygen_alias_runme.java | 32 +++++++++++ .../test-suite/python/doxygen_alias_runme.py | 12 +++++ .../DoxygenTranslator/src/DoxygenParser.cpp | 20 +++++++ Source/DoxygenTranslator/src/DoxygenParser.h | 8 +++ 7 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/doxygen_alias.i create mode 100644 Examples/test-suite/java/doxygen_alias_runme.java create mode 100644 Examples/test-suite/python/doxygen_alias_runme.py diff --git a/Doc/Manual/Doxygen.html b/Doc/Manual/Doxygen.html index faea2c7d9..5fa4b820e 100644 --- a/Doc/Manual/Doxygen.html +++ b/Doc/Manual/Doxygen.html @@ -226,13 +226,58 @@ instead of the corresponding language tool (javadoc, sphinx,

+

doxygen:alias:<command-name>

+ +

+Specify an alias for a Doxygen command with the given name. This can be useful +for custom Doxygen commands which can be defined using ALIASES option +for Doxygen itself but which are unknown to SWIG. "command-name" is the +name of the command in the Doxyfile, e.g. if it contains +

+ +
+ALIASES = "sideeffect=\par Side Effects:\n"
+
+ +

+Then you could also the same expansion for SWIG with: +

+ +
+%feature("doxygen:alias:sideeffect") "\par Side Effects:\n"
+
+ +

+Please note that command arguments are not currently supported with this +feature. +

+ +

+Notice that it is perfectly possible and potentially useful to define the alias +expansion differently depending on the target language, e.g. with +

+ +
+#ifdef SWIGJAVA
+%feature("doxygen:alias:not_for_java") "This functionality is not available for Java"
+#else
+%feature("doxygen:alias:not_for_java") ""
+#endif
+
+ +

+you could use @not_for_java in the documentation comments of all +functions which can't, for whatever reason, be currently exposed in Java +wrappers of the C++ API. +

+ +

doxygen:ignore:<command-name>

-Specify that the Doxygen command with the given name should be ignored. This is -useful for custom Doxygen commands which can be defined using ALIASES -option for Doxygen itself but which are unknown to SWIG. "command-name" -is the real name of the command, e.g. you could use +This feature allows to just ignore an unknown Doxygen command, instead of +replacing it with a predefined text as doxygen:alias features allows to +do. For example, you could use

diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index c8670801c..806be3da3 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -583,6 +583,7 @@ $(eval HAS_DOXYGEN := $($(LANGUAGE)_HAS_DOXYGEN))
 ifdef HAS_DOXYGEN
 DOXYGEN_TEST_CASES += \
 	doxygen_parsing \
+	doxygen_alias \
 	doxygen_ignore \
 	doxygen_basic_translate \
 	doxygen_basic_notranslate \
diff --git a/Examples/test-suite/doxygen_alias.i b/Examples/test-suite/doxygen_alias.i
new file mode 100644
index 000000000..79cb7964b
--- /dev/null
+++ b/Examples/test-suite/doxygen_alias.i
@@ -0,0 +1,22 @@
+%module doxygen_alias
+
+#ifdef SWIGJAVA
+%feature("doxygen:alias:nullptr") "null"
+#elif defined(SWIGPYTHON)
+%feature("doxygen:alias:nullptr") "None"
+#else
+%feature("doxygen:alias:nullptr") "NULL"
+#endif
+
+%inline %{
+
+class Something {};
+
+/**
+    A function returning something.
+
+    @returns A new object which may be @nullptr.
+ */
+Something* make_something() { return 0; }
+
+%}
diff --git a/Examples/test-suite/java/doxygen_alias_runme.java b/Examples/test-suite/java/doxygen_alias_runme.java
new file mode 100644
index 000000000..e21ed6d19
--- /dev/null
+++ b/Examples/test-suite/java/doxygen_alias_runme.java
@@ -0,0 +1,32 @@
+
+import doxygen_alias.*;
+import com.sun.javadoc.*;
+import java.util.HashMap;
+
+public class doxygen_alias_runme {
+  static {
+    try {
+      System.loadLibrary("doxygen_alias");
+    } 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[])
+  {
+    CommentParser parser = new CommentParser();
+    com.sun.tools.javadoc.Main.execute("doxygen_alias runtime test",
+                                       "CommentParser",
+                                       new String[]{"-quiet", "doxygen_alias"});
+
+    HashMap wantedComments = new HashMap();
+    wantedComments.put("doxygen_alias.doxygen_alias.make_something()",
+      "     A function returning something.
\n" + + "
\n" + + " @return A new object which may be null.\n" + + ""); + + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/python/doxygen_alias_runme.py b/Examples/test-suite/python/doxygen_alias_runme.py new file mode 100644 index 000000000..4117f00e5 --- /dev/null +++ b/Examples/test-suite/python/doxygen_alias_runme.py @@ -0,0 +1,12 @@ +#!/usr/bin/python + +import doxygen_alias +import inspect +import commentVerifier + +commentVerifier.check(inspect.getdoc(doxygen_alias.make_something), + """\ +A function returning something. + +:rtype: :py:class:`Something` +:return: A new object which may be None.""") diff --git a/Source/DoxygenTranslator/src/DoxygenParser.cpp b/Source/DoxygenTranslator/src/DoxygenParser.cpp index 88b2863cf..e42f7400a 100644 --- a/Source/DoxygenTranslator/src/DoxygenParser.cpp +++ b/Source/DoxygenTranslator/src/DoxygenParser.cpp @@ -137,6 +137,11 @@ DoxygenParser::commandBelongs(const std::string &theCommand) return it->second; } + // Check if this command is defined as an alias. + if (String* const alias = Getattr(m_node, ("feature:doxygen:alias:" + theCommand).c_str())) { + return COMMAND_ALIAS; + } + // Check if this command should be ignored. if (String* const ignore = getIgnoreFeature(theCommand)) { // Check that no value is specified for this feature ("1" is the implicit @@ -895,6 +900,18 @@ DoxygenParser::addCommandUnique(const std::string &theCommand, } } +void +DoxygenParser::aliasCommand(const std::string& theCommand, + const TokenList& /* tokList */, + DoxygenEntityList &doxyList) +{ + String* const alias = Getattr(m_node, ("feature:doxygen:alias:" + theCommand).c_str()); + if (!alias) + return; + + doxyList.push_back(DoxygenEntity("plainstd::string", Char(alias))); +} + String* DoxygenParser::getIgnoreFeature(const std::string& theCommand, const char* argument) const { @@ -1052,6 +1069,9 @@ DoxygenParser::addCommand(const std::string &commandString, case COMMAND_HTML_ENTITY: addCommandHtmlEntity(theCommand, tokList, doxyList); break; + case COMMAND_ALIAS: + aliasCommand(commandString, tokList, doxyList); + break; case COMMAND_IGNORE: ignoreCommand(commandString, tokList, doxyList); break; diff --git a/Source/DoxygenTranslator/src/DoxygenParser.h b/Source/DoxygenTranslator/src/DoxygenParser.h index 521d2a02f..82550465d 100644 --- a/Source/DoxygenTranslator/src/DoxygenParser.h +++ b/Source/DoxygenTranslator/src/DoxygenParser.h @@ -39,6 +39,7 @@ private: COMMANDUNIQUE, COMMAND_HTML, COMMAND_HTML_ENTITY, + COMMAND_ALIAS, COMMAND_IGNORE, END_LINE, PARAGRAPH_END, @@ -346,6 +347,13 @@ private: const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * Replace the given command with its predefined alias expansion. + */ + void aliasCommand(const std::string& theCommand, + const TokenList &tokList, + DoxygenEntityList &doxyList); + /* * Simply ignore the given command, possibly with the word following it or * until the matching end command.