summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml12
-rw-r--r--CHANGES.current8
-rw-r--r--Examples/test-suite/common.mk1
-rw-r--r--Examples/test-suite/cpp11_initializer_list.i22
-rw-r--r--Examples/test-suite/cpp11_rvalue_reference2.i2
-rw-r--r--Examples/test-suite/doxygen_basic_translate_style2.i105
-rw-r--r--Examples/test-suite/doxygen_translate_all_tags.i10
-rw-r--r--Examples/test-suite/java/cpp11_initializer_list_runme.java21
-rw-r--r--Examples/test-suite/java/doxygen_basic_translate_style2_runme.java99
-rw-r--r--Examples/test-suite/java/doxygen_translate_all_tags_runme.java12
-rw-r--r--Examples/test-suite/python/doxygen_basic_translate_runme.py2
-rw-r--r--Examples/test-suite/python/doxygen_basic_translate_style2_runme.py80
-rw-r--r--Examples/test-suite/python/doxygen_translate_all_tags_runme.py17
-rw-r--r--Examples/test-suite/python/doxygen_translate_runme.py6
-rw-r--r--Source/Doxygen/pydoc.cxx93
-rw-r--r--Source/Doxygen/pydoc.h5
-rw-r--r--Source/Modules/mzscheme.cxx6
-rw-r--r--Source/Modules/ocaml.cxx6
-rw-r--r--appveyor.yml2
19 files changed, 466 insertions, 43 deletions
diff --git a/.travis.yml b/.travis.yml
index 60196c3c5..bf9010973 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -383,6 +383,18 @@ matrix:
env: SWIGLANG=python GCC=8 CPP17=1 PY3=3 VER=3.7
sudo: required
dist: xenial
+ - os: linux
+ env: SWIGLANG=csharp GCC=9 CPP17=1
+ sudo: required
+ dist: xenial
+ - os: linux
+ env: SWIGLANG=java GCC=9 CPP17=1
+ sudo: required
+ dist: xenial
+ - os: linux
+ env: SWIGLANG=python GCC=9 CPP17=1 PY3=3 VER=3.7
+ sudo: required
+ dist: xenial
- compiler: gcc
os: osx
env: SWIGLANG=
diff --git a/CHANGES.current b/CHANGES.current
index 8aef21f75..22f074616 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -11,6 +11,14 @@ Version 4.0.1 (in progress)
[C#, Java] #1570 Fix name of generated C#/Java classes for %interface macros
in swiginterface.i when wrapping nested C++ classes.
+2019-07-05: wsfulton
+ [Python] #1547 Whitespace fixes in Doxygen translated comments into pydoc comments
+ for Sphinx compatibility.
+
+2019-06-28: wsfulton
+ [MzScheme, OCaml] #1559 $arg and $input were incorrectly substituted in the
+ argout typemap when two or more arguments were present.
+
2019-06-24: wsfulton
[Python, Ruby] #1538 Remove the UnknownExceptionHandler class in order to be
C++17 compliant as it uses std::unexpected_handler which was removed in C++17.
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 795dc6209..742536201 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -621,6 +621,7 @@ DOXYGEN_TEST_CASES += \
doxygen_alias \
doxygen_basic_notranslate \
doxygen_basic_translate \
+ doxygen_basic_translate_style2 \
doxygen_ignore \
doxygen_misc_constructs \
doxygen_nested_class \
diff --git a/Examples/test-suite/cpp11_initializer_list.i b/Examples/test-suite/cpp11_initializer_list.i
index 58d2ecc50..b309576c1 100644
--- a/Examples/test-suite/cpp11_initializer_list.i
+++ b/Examples/test-suite/cpp11_initializer_list.i
@@ -6,12 +6,21 @@
%ignore A::A(std::initializer_list<int>);
%ignore B::method;
-%typemap(in) std::initializer_list<const char *> {
+%typemap(in) std::initializer_list<const char *> %{
$1 = {"Ab", "Fab"};
-}
+%}
+
+%begin %{
+#if __GNUC__ >= 9
+/* warning: ‘new’ of initializer_list does not extend the lifetime of the underlying array [-Winit-list-lifetime] */
+/* incorrect warning for C::C(std::initializer_list<const char *>) */
+#pragma GCC diagnostic ignored "-Winit-list-lifetime"
+#endif
+%}
%inline %{
#include <initializer_list>
+#include <string>
class A {
public:
@@ -26,9 +35,16 @@ public:
void method(std::initializer_list<int> init) {}
};
class C {
+ std::string joined;
public:
- C(std::initializer_list<const char *>) {}
+ C(std::initializer_list<const char *> init) {
+ for (auto& val : init)
+ joined += val;
+ }
C() {}
+ const char * get_joined_string() {
+ return joined.c_str();
+ }
};
%}
diff --git a/Examples/test-suite/cpp11_rvalue_reference2.i b/Examples/test-suite/cpp11_rvalue_reference2.i
index 9aaf4accb..a2a0020f5 100644
--- a/Examples/test-suite/cpp11_rvalue_reference2.i
+++ b/Examples/test-suite/cpp11_rvalue_reference2.i
@@ -31,7 +31,7 @@ struct Thingy {
// test both primitive and user defined rvalue reference default arguments and compactdefaultargs
void compactDefaultArgs(const bool &&b = (const bool &&)PublicGlobalTrue, const UserDef &&u = (const UserDef &&)PublicUserDef) {}
void privateDefaultArgs(const bool &&b = (const bool &&)PrivateTrue) {}
- operator int &&() { return std::move(0); }
+ operator int &&() { return std::move(val); }
Thingy(const Thingy& rhs) : val(rhs.val), lvalref(rhs.lvalref), rvalref(std::move(rhs.rvalref)) {}
Thingy& operator=(const Thingy& rhs) {
val = rhs.val;
diff --git a/Examples/test-suite/doxygen_basic_translate_style2.i b/Examples/test-suite/doxygen_basic_translate_style2.i
new file mode 100644
index 000000000..23e8de4f7
--- /dev/null
+++ b/Examples/test-suite/doxygen_basic_translate_style2.i
@@ -0,0 +1,105 @@
+%module doxygen_basic_translate_style2
+
+%include "doxygen_basic_translate.h"
+
+// This test demonstrates a doxygen comment style that starts on the
+// first line and so uses extra spacing in subsequent lines.
+
+%inline %{
+
+/** \brief
+ * Brief description.
+ *
+ * The comment text.
+ *
+ * \author Some author
+ *
+ * \return Some number
+ *
+ * \sa function2
+ */
+int function()
+{
+ return 0;
+}
+
+/** 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 string.
+ */
+void function2()
+{
+}
+
+/** A test for overloaded functions
+ * This is function \b one
+ */
+void function3(int a)
+{
+}
+
+/** A test for overloaded functions
+ * This is function \b two
+ */
+void function3(int a, int b)
+{
+}
+
+/** A test of some mixed tag usage
+ * \if CONDITION
+ * This \a code fragment shows us something \.
+ * \par Minuses:
+ * \arg it's senseless
+ * \arg it's stupid
+ * \arg it's null
+ *
+ * \warning This may not work as expected
+ * \code
+ * int main() { while(true); }
+ * \endcode
+ * \endif
+ */
+void function4()
+{
+}
+
+
+void function5(int a)
+{
+}
+/**< This is a post comment. */
+
+/** Test for default args
+ * @param a Some parameter, default is 42
+ */
+void function6(int a=42)
+{
+}
+
+class Shape
+{
+public:
+ typedef Shape* superType;
+};
+
+/** Test for a parameter with difficult type
+ * (mostly for python)
+ * @param a Very strange param
+ */
+void function7(Shape::superType *a[10])
+{
+}
+
+/** Multiple parameters test.
+ *
+ * @param y Vertical coordinate.
+ * @param x Horizontal coordinate.
+ * @return Arc tangent of @c y/x.
+ */
+double Atan2(double y, double x)
+{
+ return 0;
+}
+
+/** Comment at the end of file should be ignored.
+ */
+%}
diff --git a/Examples/test-suite/doxygen_translate_all_tags.i b/Examples/test-suite/doxygen_translate_all_tags.i
index 6e96a57c5..8da683d52 100644
--- a/Examples/test-suite/doxygen_translate_all_tags.i
+++ b/Examples/test-suite/doxygen_translate_all_tags.i
@@ -38,6 +38,10 @@
* \cite citationword
* \class someClass headerFile.h headerName
* \code some test code \endcode
+ *
+ * Code immediately following text. Pydoc translation must add an
+ * empty line before:
+ * \code more test code \endcode
*/
void func01(int a)
{
@@ -121,6 +125,12 @@ void func03(int a)
* \sqrt{(x_2-x_1)^2+(y_2-y_1)^2}
* \f}
*
+ * Math immediately following text. Pydoc translation must add an
+ * empty line before:
+ * \f[
+ * \sqrt{(x_2-x_1)^2+(y_2-y_1)^2}
+ * \f]
+ *
* \file file.h
*
* \fn someFn
diff --git a/Examples/test-suite/java/cpp11_initializer_list_runme.java b/Examples/test-suite/java/cpp11_initializer_list_runme.java
new file mode 100644
index 000000000..0318c9e90
--- /dev/null
+++ b/Examples/test-suite/java/cpp11_initializer_list_runme.java
@@ -0,0 +1,21 @@
+
+import cpp11_initializer_list.*;
+
+public class cpp11_initializer_list_runme {
+
+ static {
+ try {
+ System.loadLibrary("cpp11_initializer_list");
+ } 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[]) {
+ C c = new C(null);
+ String joined = c.get_joined_string();
+ if (!joined.equals("AbFab"))
+ throw new RuntimeException("Wrong joined string " + joined);
+ }
+}
diff --git a/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java b/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java
new file mode 100644
index 000000000..aa015eeac
--- /dev/null
+++ b/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java
@@ -0,0 +1,99 @@
+
+import doxygen_basic_translate_style2.*;
+import com.sun.javadoc.*;
+import java.util.HashMap;
+
+public class doxygen_basic_translate_style2_runme {
+ static {
+ try {
+ System.loadLibrary("doxygen_basic_translate_style2");
+ } 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_basic_translate_style2 runtime test",
+ "CommentParser",
+ new String[]{"-quiet", "doxygen_basic_translate_style2"});
+
+ HashMap<String, String> wantedComments = new HashMap<String, String>();
+
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function()",
+ " \n" +
+ " Brief description.\n" +
+ " \n" +
+ " The comment text.\n" +
+ " @author Some author\n" +
+ " @return Some number\n" +
+ " @see function2\n" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function2()",
+ " A test of a very very very very very very very very very very very very very very very very \n" +
+ " very very very very very long comment string. \n" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function4()",
+ " A test of some mixed tag usage \n" +
+ " If: CONDITION {\n" +
+ " This <i>code </i>fragment shows us something . \n" +
+ " <p alt=\"Minuses: \">\n" +
+ " <li>it's senseless \n" +
+ " </li><li>it's stupid \n" +
+ " </li><li>it's null \n" +
+ " \n" +
+ " </li></p>Warning: This may not work as expected \n" +
+ " \n" +
+ " {@code \n" +
+ "int main() { while(true); } \n" +
+ " }\n" +
+ " }\n" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function3(int)",
+ " A test for overloaded functions \n" +
+ " This is function <b>one </b>\n" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function5(int)",
+ " This is a post comment. \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function6(int)",
+ " Test for default args \n" +
+ " @param a Some parameter, default is 42" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function6()",
+ " Test for default args \n" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function7(doxygen_basic_translate_style2.SWIGTYPE_p_p_p_Shape)",
+ " Test for a parameter with difficult type \n" +
+ " (mostly for python) \n" +
+ " @param a Very strange param \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function3(int, int)",
+ " A test for overloaded functions \n" +
+ " This is function <b>two </b>\n" +
+ " \n" +
+ "");
+ wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.Atan2(double, double)",
+ " Multiple parameters test.\n" +
+ " \n" +
+ " @param y Vertical coordinate.\n" +
+ " @param x Horizontal coordinate.\n" +
+ " @return Arc tangent of <code>y/x</code>.\n" +
+ "");
+
+ // and ask the parser to check comments for us
+ System.exit(parser.check(wantedComments));
+ }
+}
diff --git a/Examples/test-suite/java/doxygen_translate_all_tags_runme.java b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java
index 8bd65224f..d5c533f4e 100644
--- a/Examples/test-suite/java/doxygen_translate_all_tags_runme.java
+++ b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java
@@ -40,7 +40,10 @@ public class doxygen_translate_all_tags_runme {
" Not everything works right now...\n" +
" <code>codeword</code>\n\n\n\n\n\n" +
" <i>citationword</i>\n" +
- " {@code some test code }\n");
+ " {@code some test code }\n\n" +
+ " Code immediately following text. Pydoc translation must add an\n" +
+ " empty line before:\n" +
+ " {@code more test code }");
wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func02(int)",
" Conditional comment: SOMECONDITION \n" +
@@ -63,8 +66,11 @@ public class doxygen_translate_all_tags_runme {
" @exception SuperError \n" +
" \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n" +
" \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n" +
- " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n" +
- " This will only appear in hmtl \n");
+ " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n\n" +
+ "Math immediately following text. Pydoc translation must add an\n" +
+ "empty line before:\n\n" +
+ " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}\n" +
+ " This will only appear in hmtl \n");
wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func05(int)",
" If: ANOTHERCONDITION {\n" +
diff --git a/Examples/test-suite/python/doxygen_basic_translate_runme.py b/Examples/test-suite/python/doxygen_basic_translate_runme.py
index e664e06f6..b6023224d 100644
--- a/Examples/test-suite/python/doxygen_basic_translate_runme.py
+++ b/Examples/test-suite/python/doxygen_basic_translate_runme.py
@@ -49,9 +49,7 @@ Warning: This may not work as expected
.. code-block:: c++
-
int main() { while(true); }
-
}"""
)
comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function5),
diff --git a/Examples/test-suite/python/doxygen_basic_translate_style2_runme.py b/Examples/test-suite/python/doxygen_basic_translate_style2_runme.py
new file mode 100644
index 000000000..2d62eecbd
--- /dev/null
+++ b/Examples/test-suite/python/doxygen_basic_translate_style2_runme.py
@@ -0,0 +1,80 @@
+import doxygen_basic_translate_style2
+import inspect
+import string
+import sys
+import comment_verifier
+
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function),
+ """\
+Brief description.
+
+The comment text.
+
+Author: Some author
+
+:rtype: int
+:return: Some number
+
+See also: function2"""
+)
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function2),
+ """\
+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 string."""
+)
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function3),
+ """*Overload 1:*
+A test for overloaded functions
+This is function **one**
+
+|
+
+*Overload 2:*
+A test for overloaded functions
+This is function **two**"""
+)
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function4),
+ """\
+A test of some mixed tag usage
+If: CONDITION {
+This *code* fragment shows us something .
+Title: Minuses:
+* it\'s senseless
+* it\'s stupid
+* it\'s null
+
+Warning: This may not work as expected
+
+.. code-block:: c++
+
+ int main() { while(true); }
+}"""
+)
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function5),
+ """This is a post comment."""
+)
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function6),
+ """\
+Test for default args
+:type a: int
+:param a: Some parameter, default is 42"""
+)
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function7),
+ """\
+Test for a parameter with difficult type
+(mostly for python)
+:type a: :py:class:`Shape`
+:param a: Very strange param"""
+)
+
+comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.Atan2),
+ """\
+Multiple parameters test.
+
+:type y: float
+:param y: Vertical coordinate.
+:type x: float
+:param x: Horizontal coordinate.
+:rtype: float
+:return: Arc tangent of ``y/x``."""
+)
diff --git a/Examples/test-suite/python/doxygen_translate_all_tags_runme.py b/Examples/test-suite/python/doxygen_translate_all_tags_runme.py
index 53d087e69..df1c0eba5 100644
--- a/Examples/test-suite/python/doxygen_translate_all_tags_runme.py
+++ b/Examples/test-suite/python/doxygen_translate_all_tags_runme.py
@@ -34,10 +34,16 @@ Not everything works right now...
'citationword'
+.. code-block:: c++
+
+ some test code
+
+Code immediately following text. Pydoc translation must add an
+empty line before:
.. code-block:: c++
- some test code""")
+ more test code""")
comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func02),
r"""Conditional comment: SOMECONDITION
@@ -90,12 +96,16 @@ r""":raises: SuperError
:math:`\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}`
-
.. math::
\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}
+.. math::
+
+ \sqrt{(x_2-x_1)^2+(y_2-y_1)^2}
+Math immediately following text. Pydoc translation must add an
+empty line before:
.. math::
@@ -111,7 +121,6 @@ r""":raises: SuperError
-
This will only appear in hmtl""")
comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func05),
@@ -283,13 +292,11 @@ r"""TODO: Some very important task
-
very long
text with tags <sometag>
-
Version: 0.0.0.2
Warning: This is senseless!
diff --git a/Examples/test-suite/python/doxygen_translate_runme.py b/Examples/test-suite/python/doxygen_translate_runme.py
index 2d0840a1f..d698ba873 100644
--- a/Examples/test-suite/python/doxygen_translate_runme.py
+++ b/Examples/test-suite/python/doxygen_translate_runme.py
@@ -20,11 +20,9 @@ Author: Zubr
'citationword'
-
.. code-block:: c++
- some test code
-
+ some test code
Conditional comment: SOMECONDITION
Some conditional comment
@@ -121,11 +119,9 @@ TODO: Some very important task
:type b: float
:param b: B is mentioned again...
-
very long
text with tags <sometag>
-
Version: 0.0.0.2
Warning: This is senseless!
diff --git a/Source/Doxygen/pydoc.cxx b/Source/Doxygen/pydoc.cxx
index fc3b0ea09..eb489932a 100644
--- a/Source/Doxygen/pydoc.cxx
+++ b/Source/Doxygen/pydoc.cxx
@@ -138,6 +138,52 @@ static void trimWhitespace(string &s) {
s.erase(lastNonSpace + 1);
}
+// Erase the first character in the string if it is a newline
+static void eraseLeadingNewLine(string &s) {
+ if (!s.empty() && s[0] == '\n')
+ s.erase(s.begin());
+}
+
+// Erase the last character in the string if it is a newline
+static void eraseTrailingNewLine(string &s) {
+ if (!s.empty() && s[s.size() - 1] == '\n')
+ s.erase(s.size() - 1);
+}
+
+// Check the generated docstring line by line and make sure that any
+// code and verbatim blocks have an empty line preceding them, which
+// is necessary for Sphinx. Additionally, this strips any empty lines
+// appearing at the beginning of the docstring.
+static string padCodeAndVerbatimBlocks(const string &docString) {
+ std::string result;
+
+ std::istringstream iss(docString);
+
+ // Initialize to false because there is no previous line yet
+ bool lastLineWasNonBlank = false;
+
+ for (string line; std::getline(iss, line); result += line) {
+ if (!result.empty()) {
+ // Terminate the previous line
+ result += '\n';
+ }
+
+ const size_t pos = line.find_first_not_of(" \t");
+ if (pos == string::npos) {
+ lastLineWasNonBlank = false;
+ } else {
+ if (lastLineWasNonBlank &&
+ (line.compare(pos, 13, ".. code-block") == 0 ||
+ line.compare(pos, 7, ".. math") == 0)) {
+ // Must separate code or math blocks from the previous line
+ result += '\n';
+ }
+ lastLineWasNonBlank = true;
+ }
+ }
+ return result;
+}
+
/* static */
PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler) {
return make_pair(handler, std::string());
@@ -219,7 +265,7 @@ void PyDocConverter::fillStaticTables() {
tagHandlers["short"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["todo"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["version"] = make_handler(&PyDocConverter::handleParagraph);
- tagHandlers["verbatim"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["verbatim"] = make_handler(&PyDocConverter::handleVerbatimBlock);
tagHandlers["warning"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["xmlonly"] = make_handler(&PyDocConverter::handleParagraph);
// these commands have special handlers
@@ -419,6 +465,17 @@ void PyDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translated
translatedComment += translateSubtree(tag);
}
+void PyDocConverter::handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ string verb = translateSubtree(tag);
+
+ eraseLeadingNewLine(verb);
+
+ // Remove the last newline to prevent doubling the newline already present after \endverbatim
+ trimWhitespace(verb); // Needed to catch trailing newline below
+ eraseTrailingNewLine(verb);
+ translatedComment += verb;
+}
+
void PyDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
IndentGuard indent;
@@ -433,7 +490,6 @@ void PyDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComme
indent.Init(translatedComment, m_indent);
trimWhitespace(translatedComment);
- translatedComment += '\n';
const string formulaIndent = indent.getFirstLineIndent();
translatedComment += formulaIndent;
@@ -467,8 +523,6 @@ void PyDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComme
if (inlineFormula) {
translatedComment += "`";
- } else {
- translatedComment += '\n';
}
}
@@ -476,23 +530,28 @@ void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComme
IndentGuard indent(translatedComment, m_indent);
trimWhitespace(translatedComment);
- translatedComment += '\n';
// Use the current indent for the code-block line itself.
- string codeIndent = indent.getFirstLineIndent();
- translatedComment += codeIndent;
+ 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";
- // For now on, use extra indent level for all the subsequent lines.
- codeIndent += m_indent;
+ // 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;
std::string code;
handleTagVerbatim(tag, code, arg);
+ // Try and remove leading newline, which is present for block \code
+ // command:
+ eraseLeadingNewLine(code);
+
translatedComment += codeIndent;
for (size_t n = 0; n < code.length(); n++) {
if (code[n] == '\n') {
@@ -510,8 +569,11 @@ void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComme
}
trimWhitespace(translatedComment);
- if (*translatedComment.rbegin() != '\n')
- translatedComment += '\n';
+
+ // For block commands, the translator adds the newline after
+ // \endcode, so try and compensate by removing the last newline from
+ // the code text:
+ eraseTrailingNewLine(translatedComment);
}
void PyDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
@@ -519,7 +581,7 @@ void PyDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translat
}
void PyDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
- translatedComment += arg + " ";
+ translatedComment += arg;
for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
translatedComment += it->data;
}
@@ -833,9 +895,10 @@ String *PyDocConverter::makeDocumentation(Node *n) {
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);
- }
+ eraseTrailingNewLine(pyDocString);
+
+ // ensure that a blank line occurs before code or math blocks
+ pyDocString = padCodeAndVerbatimBlocks(pyDocString);
if (m_flags & debug_translator) {
std::cout << "\n---RESULT IN PYDOC---" << std::endl;
diff --git a/Source/Doxygen/pydoc.h b/Source/Doxygen/pydoc.h
index 8f432fd18..df8997d76 100644
--- a/Source/Doxygen/pydoc.h
+++ b/Source/Doxygen/pydoc.h
@@ -80,6 +80,11 @@ protected:
void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
/*
+ * Handle Doxygen verbatim tag
+ */
+ void handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
* Handle one of the Doxygen formula-related tags.
*/
void handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx
index 543874172..788681330 100644
--- a/Source/Modules/mzscheme.cxx
+++ b/Source/Modules/mzscheme.cxx
@@ -221,7 +221,6 @@ public:
Wrapper *f = NewWrapper();
String *proc_name = NewString("");
- String *source = NewString("");
String *target = NewString("");
String *arg = NewString("");
String *cleanup = NewString("");
@@ -312,10 +311,9 @@ public:
String *ln = Getattr(p, "lname");
// Produce names of source and target
- Clear(source);
Clear(target);
Clear(arg);
- Printf(source, "argv[%d]", i);
+ String *source = NewStringf("argv[%d]", i);
Printf(target, "%s", ln);
Printv(arg, Getattr(p, "name"), NIL);
@@ -339,6 +337,7 @@ public:
if (i >= numreq) {
Printf(f->code, "}\n");
}
+ Delete(source);
}
/* Insert constraint checking code */
@@ -465,7 +464,6 @@ public:
}
Delete(proc_name);
- Delete(source);
Delete(target);
Delete(arg);
Delete(outarg);
diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx
index ad9c94800..6f2a34962 100644
--- a/Source/Modules/ocaml.cxx
+++ b/Source/Modules/ocaml.cxx
@@ -473,7 +473,6 @@ public:
Wrapper *f = NewWrapper();
String *proc_name = NewString("");
- String *source = NewString("");
String *target = NewString("");
String *arg = NewString("");
String *cleanup = NewString("");
@@ -580,10 +579,9 @@ public:
pt = SwigType_typedef_qualified(pt);
// Produce names of source and target
- Clear(source);
Clear(target);
Clear(arg);
- Printf(source, "caml_list_nth(args,%d)", i);
+ String *source = NewStringf("caml_list_nth(args,%d)", i);
Printf(target, "%s", ln);
Printv(arg, Getattr(p, "name"), NIL);
@@ -607,6 +605,7 @@ public:
if (i >= numreq) {
Printf(f->code, "}\n");
}
+ Delete(source);
}
/* Insert constraint checking code */
@@ -787,7 +786,6 @@ public:
Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name);
Delete(proc_name);
- Delete(source);
Delete(target);
Delete(arg);
Delete(outarg);
diff --git a/appveyor.yml b/appveyor.yml
index 10bf064df..42eaa36f4 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -89,7 +89,7 @@ install:
- if "%OSVARIANT%"=="" bash -c "cl.exe /? 2>&1 | head -n 1"
- if "%OSVARIANT%"=="" bash -c "which csc.exe"
- if "%OSVARIANT%"=="" bash -c "csc.exe /? | head -n 1"
-- if "%OSVARIANT%"=="cygwin" %CYGWINSETUP% --quiet-mode --packages python-devel,libpcre-devel,libboost-devel > cygwin-install.txt || bash -c "cat cygwin-install.txt"
+- if "%OSVARIANT%"=="cygwin" %CYGWINSETUP% --quiet-mode --packages python2-devel,libpcre-devel,libboost-devel > cygwin-install.txt || bash -c "cat cygwin-install.txt"
- if "%OSVARIANT%"=="mingw" bash -c "pacman --noconfirm --sync mingw%MBITS%/mingw-w64-%MARCH%-pcre mingw%MBITS%/mingw-w64-%MARCH%-boost"
- if not "%WITHLANG%"=="" set SWIGWITHLANG==%WITHLANG%
- if not "%WITHLANG%"=="" where %WITHLANG%