From 6fb345feb26d331814ce7111682a4b3b809c6d16 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 26 Nov 2019 19:32:34 +0000 Subject: [PATCH 01/12] 'out' or 'ref' usage in a cstype typemap in directors 'out' / 'ref' was not always stripped out in parts of the director code generation. Issue #1628 --- CHANGES.current | 4 ++ Examples/test-suite/csharp/Makefile.in | 1 + .../csharp/csharp_director_typemaps_runme.cs | 53 +++++++++++++++++++ .../test-suite/csharp_director_typemaps.i | 37 +++++++++++++ Source/Modules/csharp.cxx | 7 ++- 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/csharp/csharp_director_typemaps_runme.cs create mode 100644 Examples/test-suite/csharp_director_typemaps.i diff --git a/CHANGES.current b/CHANGES.current index 15a2fc516..39ec98e09 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.2 (in progress) =========================== +2019-11-26: wsfulton + [C#] #1628 'out' or 'ref' used in a cstype typemap was not always stripped out in parts + of director code generation. + 2019-11-01: wsfulton [Python] #1595 Fix bug in support for keyword arguments (kwargs feature or -keyword) when using -builtin. The fix is in the argument error checking when wrapping zero diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 8272864d5..57a81e357 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -16,6 +16,7 @@ CPP_TEST_CASES = \ complextest \ csharp_attributes \ csharp_swig2_compatibility \ + csharp_director_typemaps \ csharp_exceptions \ csharp_features \ csharp_lib_arrays \ diff --git a/Examples/test-suite/csharp/csharp_director_typemaps_runme.cs b/Examples/test-suite/csharp/csharp_director_typemaps_runme.cs new file mode 100644 index 000000000..6143332db --- /dev/null +++ b/Examples/test-suite/csharp/csharp_director_typemaps_runme.cs @@ -0,0 +1,53 @@ + +using System; +using System.Reflection; +using csharp_director_typemapsNamespace; + +public class csharp_director_typemaps_runme { + + class CSharpDirectorTypemaps_InStreamDerived : InStream + { + private int constant; + public CSharpDirectorTypemaps_InStreamDerived(int constant) { this.constant = constant; } + public override int Read(global::System.IntPtr buf, int len, out int readLen) { + readLen = (buf == global::System.IntPtr.Zero) ? -len - constant : len + constant; + return readLen; + } + public override int Write(global::System.IntPtr buf, int len, out int writeLen) { + writeLen = (buf == global::System.IntPtr.Zero) ? -len - constant : len + constant; + return writeLen; + } + } + public static void Main() { + int outLen = -1; + int k = 100; + int j = 23; + InStream instream = new CSharpDirectorTypemaps_InStreamDerived(k); + + { + int ret = csharp_director_typemaps.callRead(instream, InStream.getCPtr(instream).Handle, j, out outLen); + Assert(outLen, j + k); + Assert(ret, j + k); + } + { + int ret = csharp_director_typemaps.callRead(instream, global::System.IntPtr.Zero, j, out outLen); + Assert(outLen, -j - k); + Assert(ret, -j - k); + } + + { + int ret = csharp_director_typemaps.callWrite(instream, InStream.getCPtr(instream).Handle, j, out outLen); + Assert(outLen, j + k); + Assert(ret, j + k); + } + { + int ret = csharp_director_typemaps.callWrite(instream, global::System.IntPtr.Zero, j, out outLen); + Assert(outLen, -j - k); + Assert(ret, -j - k); + } + } + private static void Assert(int i1, int i2) { + if (i1 != i2) + throw new Exception("assertion failure. " + i1 + " != " + i2); + } +} diff --git a/Examples/test-suite/csharp_director_typemaps.i b/Examples/test-suite/csharp_director_typemaps.i new file mode 100644 index 000000000..2bc0281ee --- /dev/null +++ b/Examples/test-suite/csharp_director_typemaps.i @@ -0,0 +1,37 @@ +%module (directors="1") csharp_director_typemaps + +// This tests that the csout typemap is handled correctly in the director code. +// The 'out' needs stripping in some parts of the generated director code. + +%feature("director") InStream; + +%apply void *VOID_INT_PTR { void * } + +%typemap(ctype) int* readLen, int* writeLen "/*ctype*/ int*" +%typemap(imtype) int* readLen, int* writeLen "/*imtype*/ out int" +%typemap(cstype) int* readLen "/*cstype*/ out int" +//%typemap(cstype) int* writeLen "/*out cstype out*/ out int" +%apply int *readLen { int* writeLen } // Replaced above - 'out' in a comment is not working yet +%typemap(csin) int* readLen, int* writeLen "/*csin*/ out $csinput" +%typemap(in) int* readLen, int* writeLen %{/*in*/ $1 = ($1_ltype)$input; %} +%typemap(out) int* readLen, int* writeLen %{/*out*/ $result = (void *)$1; %} +%typemap(csdirectorin) int* readLen, int* writeLen "/*csdirectorin*/ out $iminput" +%typemap(csdirectorout) int* readLen, int* writeLen "/*csdirectorout*/ $cscall" +%typemap(directorin) int* readLen, int* writeLen "/*directorin*/ $input = $1;" +%typemap(directorout) int* readLen, int* writeLen %{/*directorout*/ $result = ($1_ltype)$input; %} + +%inline %{ +class InStream +{ +public: + virtual int Read(void* buf, int len, int* readLen) = 0; + virtual int Write(void* buf, int len, int* writeLen) = 0; + virtual ~InStream() {} +}; +int callRead(InStream* stream, void* buf, int len, int* readLen) { + return stream->Read(buf, len, readLen); +} +int callWrite(InStream* stream, void* buf, int len, int* writeLen) { + return stream->Write(buf, len, writeLen); +} +%} diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 17100b330..27dbd6427 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -4064,11 +4064,10 @@ public: /* Get the C# parameter type */ if ((tm = Getattr(p, "tmap:cstype"))) { substituteClassname(pt, tm); - if (Strncmp(tm, "ref ", 4) == 0) { - Replace(tm, "ref ", "", DOH_REPLACE_FIRST); + int flags = DOH_REPLACE_FIRST | DOH_REPLACE_ID_BEGIN; + if (Replace(tm, "ref ", "", flags) || Replace(tm, "ref\t", "", flags)) { Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm); - } else if (Strncmp(tm, "out ", 4) == 0) { - Replace(tm, "out ", "", DOH_REPLACE_FIRST); + } else if (Replace(tm, "out ", "", flags) || Replace(tm, "out\t", "", flags)) { Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm); } else { Printf(proxy_method_types, "typeof(%s)", tm); From 18b2dcd2220b13296e12bb729741542750faab31 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 26 Nov 2019 19:39:28 +0000 Subject: [PATCH 02/12] C# 'out' or 'ref' removal improvements in director typemaps. - Add support to DOH Replace for not replacing inside C comments - Fix removing 'out' or 'ref' when these are present in C comments in cstype typemaps. Closes #1628 --- .../test-suite/csharp_director_typemaps.i | 4 +- Source/DOH/README | 16 ++- Source/DOH/doh.h | 11 +- Source/DOH/string.c | 106 ++++++++++++++++++ Source/Modules/csharp.cxx | 2 +- 5 files changed, 126 insertions(+), 13 deletions(-) diff --git a/Examples/test-suite/csharp_director_typemaps.i b/Examples/test-suite/csharp_director_typemaps.i index 2bc0281ee..614bdbf23 100644 --- a/Examples/test-suite/csharp_director_typemaps.i +++ b/Examples/test-suite/csharp_director_typemaps.i @@ -10,8 +10,8 @@ %typemap(ctype) int* readLen, int* writeLen "/*ctype*/ int*" %typemap(imtype) int* readLen, int* writeLen "/*imtype*/ out int" %typemap(cstype) int* readLen "/*cstype*/ out int" -//%typemap(cstype) int* writeLen "/*out cstype out*/ out int" -%apply int *readLen { int* writeLen } // Replaced above - 'out' in a comment is not working yet +// Note for below: 'out' used in typemap comment +%typemap(cstype) int* writeLen "/*out cstype out*/ out int" %typemap(csin) int* readLen, int* writeLen "/*csin*/ out $csinput" %typemap(in) int* readLen, int* writeLen %{/*in*/ $1 = ($1_ltype)$input; %} %typemap(out) int* readLen, int* writeLen %{/*out*/ $result = (void *)$1; %} diff --git a/Source/DOH/README b/Source/DOH/README index 8be5f652a..be90f25b4 100644 --- a/Source/DOH/README +++ b/Source/DOH/README @@ -73,11 +73,17 @@ Replace(obj, orig, rep, flags) Replace occurrences of orig with rep. Chop(obj) Remove trailing whitespace flags is one of the following: - DOH_REPLACE_ANY - DOH_REPLACE_NOQUOTE - DOH_REPLACE_ID - DOH_REPLACE_FIRST - + DOH_REPLACE_ID + DOH_REPLACE_ID_BEGIN + DOH_REPLACE_ID_END + DOH_REPLACE_NUMBER_END + +and can be combined with one or more of the following: + DOH_REPLACE_ANY + DOH_REPLACE_NOQUOTE + DOH_REPLACE_NOCOMMENT + DOH_REPLACE_FIRST + Callable Operations ------------------- Call(obj, args) Perform a function call with arguments args. diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index 7fb64c058..fd0530e9c 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -289,11 +289,12 @@ extern char *DohStrchr(const DOHString_or_char *s1, int ch); #define DOH_REPLACE_ANY 0x01 #define DOH_REPLACE_NOQUOTE 0x02 -#define DOH_REPLACE_ID 0x04 -#define DOH_REPLACE_FIRST 0x08 -#define DOH_REPLACE_ID_BEGIN 0x10 -#define DOH_REPLACE_ID_END 0x20 -#define DOH_REPLACE_NUMBER_END 0x40 +#define DOH_REPLACE_NOCOMMENT 0x04 +#define DOH_REPLACE_ID 0x08 +#define DOH_REPLACE_FIRST 0x10 +#define DOH_REPLACE_ID_BEGIN 0x20 +#define DOH_REPLACE_ID_END 0x40 +#define DOH_REPLACE_NUMBER_END 0x80 #define Replaceall(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ANY) #define Replaceid(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ID) diff --git a/Source/DOH/string.c b/Source/DOH/string.c index 6c6728578..3689f4ffe 100644 --- a/Source/DOH/string.c +++ b/Source/DOH/string.c @@ -595,6 +595,13 @@ static char *end_quote(char *s) { } } +static char *end_comment(char *s) { + char *substring = strstr(s, "*/"); + if (substring) + ++substring; + return substring; +} + static char *match_simple(char *base, char *s, char *token, int tokenlen) { (void) base; (void) tokenlen; @@ -677,6 +684,7 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co int ic; int rcount = 0; int noquote = 0; + int nocomment = 0; char *c, *s, *t, *first; char *q, *q2; char *base; @@ -698,6 +706,11 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co if (flags & DOH_REPLACE_NOQUOTE) noquote = 1; + if (flags & DOH_REPLACE_NOCOMMENT) + nocomment = 1; + + assert(!(noquote && nocomment)); /* quote and comment combination not implemented */ + /* If we are not replacing inside quotes, we need to do a little extra work */ if (noquote) { q = strpbrk(base, "\"\'"); @@ -723,6 +736,31 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co } } + /* If we are not replacing inside comments, we need to do a little extra work */ + if (nocomment) { + q = strstr(base, "/*"); + if (!q) { + nocomment = 0; /* Well, no comments to worry about. Oh well */ + } else { + while (q && (q < s)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + return 0; + } + if (q2 > s) { + /* Find next match */ + s = (*match) (base, q2 + 1, token, tokenlen); + } + if (!s) + return 0; /* Oh well, no matches */ + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; /* No more comments */ + } + } + } + first = s; replen = (int)strlen(rep); @@ -768,6 +806,28 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co } } } + if (nocomment) { + q = strstr(s, "/*"); + if (!q) { + nocomment = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; /* No more comments */ + } + } + } if (delta) { if (c) { memmove(t, s, c - s); @@ -823,6 +883,29 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co } } } + if (nocomment) { + q = strstr(s, "/*"); + if (!q) { + break; + } else { + while (q && (q < c)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; + } + } + } if (c) { rcount++; ic--; @@ -875,6 +958,29 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co } } } + if (nocomment) { + q = strstr(s, "/*"); + if (!q) { + nocomment = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a comment. Try to find another match */ + q2 = end_comment(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strstr(q2 + 1, "/*"); + if (!q) + nocomment = 0; /* No more comments */ + } + } + } if (i < (rcount - 1)) { memcpy(t, s, c - s); t += (c - s); diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 27dbd6427..d08884b0f 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -4064,7 +4064,7 @@ public: /* Get the C# parameter type */ if ((tm = Getattr(p, "tmap:cstype"))) { substituteClassname(pt, tm); - int flags = DOH_REPLACE_FIRST | DOH_REPLACE_ID_BEGIN; + int flags = DOH_REPLACE_FIRST | DOH_REPLACE_ID_BEGIN | DOH_REPLACE_NOCOMMENT; if (Replace(tm, "ref ", "", flags) || Replace(tm, "ref\t", "", flags)) { Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm); } else if (Replace(tm, "out ", "", flags) || Replace(tm, "out\t", "", flags)) { From 3d98179fd3b38d86e7f689dd7e19f11b53449a2f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 26 Nov 2019 19:45:08 +0000 Subject: [PATCH 03/12] Temporarily remove broken Appveyor Python3 testing --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 42eaa36f4..f87cefd0f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,10 +16,10 @@ environment: - SWIGLANG: python VSVER: 14 VER: 27 - - SWIGLANG: python - VSVER: 14 - VER: 36 - PY3: 3 +# - SWIGLANG: python +# VSVER: 14 +# VER: 36 +# PY3: 3 - SWIGLANG: python OSVARIANT: cygwin - SWIGLANG: python From 8122929ba95c34132b9cb9c5cbeaf4eeb7c300e0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 3 Dec 2019 22:07:49 +0000 Subject: [PATCH 04/12] Improve .NET docs. Add minimum .NET version required Issue #1623 [skip-ci] --- Doc/Manual/CSharp.html | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 1fc2d211e..d041bf5dd 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -66,7 +66,16 @@ PInvoke is part of the ECMA/ISO C# specification. It is also better suited for robust production environments due to the Managed C++ flaw called the Mixed DLL Loading Problem. SWIG C# works equally well on non-Microsoft operating systems such as Linux, Solaris and Apple Mac using -Mono and Portable.NET. +Mono. +

+ +

+SWIG 3 and later requires .NET 2.0 at a minimum. +There are some minor exceptions, where the minimum required is .NET 4.0. +This is when using the std::complex and std::list STL containers. +

+ +

From 66752cde4858a780fecba47793f99ba49ce8b15e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 4 Dec 2019 20:08:41 +0000 Subject: [PATCH 05/12] Remove Travis osx java testing Removed until doxygen testing is ported to something that doesn't use com.sun.javadoc which was remoed in jdk 13 --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 72ede27f9..e0d8ac74a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -449,6 +449,11 @@ matrix: env: SWIGLANG=php VER=7.2 sudo: required dist: xenial + # jdk 13 has removed tools.jar resulting in: CommentParser.java:2: error: package com.sun.javadoc does not exist + - compiler: clang + os: osx + env: SWIGLANG=java CPP17=1 + osx_image: xcode10.2 # Sometimes hits the Travis 50 minute time limit - compiler: clang os: osx From aa47b4c438421595b2764044b54502ad378cd7e5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 10 Dec 2019 19:26:05 +0000 Subject: [PATCH 06/12] Fix some C++11 identifiers with special meaning parsing problems Fix parsing of C++11 identifiers with special meaning (final and override) when they are used as part of the scope name of an identifier, such as a namespace name. Closes #1679 --- CHANGES.current | 4 ++++ Examples/test-suite/cpp11_final_override.i | 28 ++++++++++++++++++++++ Source/CParse/cscanner.c | 8 +++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 39ec98e09..09facd90b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.2 (in progress) =========================== +2019-12-10: wsfulton + #1679 Fix parsing of C++11 identifiers with special meaning (final and override) when + they are used as part of the scope name of an identifier, such as a namespace name. + 2019-11-26: wsfulton [C#] #1628 'out' or 'ref' used in a cstype typemap was not always stripped out in parts of director code generation. diff --git a/Examples/test-suite/cpp11_final_override.i b/Examples/test-suite/cpp11_final_override.i index 8d275b322..c31ae73b6 100644 --- a/Examples/test-suite/cpp11_final_override.i +++ b/Examples/test-suite/cpp11_final_override.i @@ -138,3 +138,31 @@ void DerivedNoVirtualStruct::ef() {} DerivedNoVirtualStruct::~DerivedNoVirtualStruct() {} %} +%inline %{ +namespace Outer { + namespace final { + template struct smart_ptr { + typedef T type; + }; + } + namespace override { + template struct dumb_ptr { + typedef T type; + }; + } +} +%} + +%template(SmartPtrBaseStruct) Outer::final::smart_ptr; + +%inline %{ +class ObjectDB +{ +public: + static void smart1(typename Outer::final::smart_ptr::type *objectT) {} + static void smart2(Outer::final::smart_ptr::type *objectT) {} + static void dumb1(typename Outer::override::dumb_ptr::type *objectT) {} + static void dumb2(Outer::override::dumb_ptr::type *objectT) {} + static Outer::final::smart_ptr::type get() { return DerivedStruct(); } +}; +%} diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 4566817a0..7a9c05c95 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -873,10 +873,14 @@ int yylex(void) { return (USING); if (strcmp(yytext, "namespace") == 0) return (NAMESPACE); - if (strcmp(yytext, "override") == 0) + if (strcmp(yytext, "override") == 0) { + last_id = 1; return (OVERRIDE); - if (strcmp(yytext, "final") == 0) + } + if (strcmp(yytext, "final") == 0) { + last_id = 1; return (FINAL); + } } else { if (strcmp(yytext, "class") == 0) { Swig_warning(WARN_PARSE_CLASS_KEYWORD, cparse_file, cparse_line, "class keyword used, but not in C++ mode.\n"); From fe6968e5e2dfc365ca009e9bcd2d4ed3f6d8d6a6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 18 Dec 2019 02:24:01 +0100 Subject: [PATCH 07/12] Reuse existing variable in CommentParser code used in Java tests No real changes, just a tiny simplification. --- Examples/test-suite/java/CommentParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/java/CommentParser.java b/Examples/test-suite/java/CommentParser.java index 7dc6d591d..f202c1384 100644 --- a/Examples/test-suite/java/CommentParser.java +++ b/Examples/test-suite/java/CommentParser.java @@ -93,13 +93,13 @@ public class CommentParser { System.out.println("Output is also saved to files '" + expectedFileName + "' and '" + gotFileName + "'"); // here we print original strings, for nicer output - System.out.println("\n\n---\nexpected:\n" + wantedComments.get(e.getKey())); + System.out.println("\n\n---\nexpected:\n" + wantedStr); System.out.println("\n\n---\ngot:\n" + e.getValue()); try { // write expected string to file BufferedWriter expectedFile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(expectedFileName))); - expectedFile.write(wantedComments.get(e.getKey())); + expectedFile.write(wantedStr); expectedFile.close(); // write translated string to file From 5a8875ca9da7046b2b3b7fea3f1e056f289c5be1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 18 Dec 2019 02:25:08 +0100 Subject: [PATCH 08/12] Don't crash if unexpected comment is found in Java Doxygen tests Don't pass null pointer to BufferedWriter.write(), as this results in NullPointerException. --- Examples/test-suite/java/CommentParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/java/CommentParser.java b/Examples/test-suite/java/CommentParser.java index f202c1384..7d5740b51 100644 --- a/Examples/test-suite/java/CommentParser.java +++ b/Examples/test-suite/java/CommentParser.java @@ -99,7 +99,8 @@ public class CommentParser { try { // write expected string to file BufferedWriter expectedFile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(expectedFileName))); - expectedFile.write(wantedStr); + if (wantedStr != null) + expectedFile.write(wantedStr); expectedFile.close(); // write translated string to file From 66a78261924174791a4952d05b58d52c16a36a57 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 18 Dec 2019 02:42:12 +0100 Subject: [PATCH 09/12] Rewrite Doxygen unit tests for Java using Java 9 API In particular, do not use com.sun.javadoc deprecated since Java 9 and finally removed in Java 13, to allow the tests to run under modern JRE. They don't run under Java 8 and earlier any more, but this shouldn't be a huge problem nowadays and as SWIG output is independent from the Java version used, it's enough to test it with modern Java versions. Note that the tests themselves were changed only in the most minimal way, to adapt them to the new way of running javadoc (which is now also integrated into CommentParser itself instead of being duplicated in every test). --- Examples/test-suite/java/CommentParser.java | 134 ++++++++++++++---- Examples/test-suite/java/Makefile.in | 4 +- .../test-suite/java/doxygen_alias_runme.java | 8 +- .../java/doxygen_basic_notranslate_runme.java | 12 +- .../java/doxygen_basic_translate_runme.java | 12 +- .../doxygen_basic_translate_style2_runme.java | 12 +- .../test-suite/java/doxygen_ignore_runme.java | 8 +- .../java/doxygen_misc_constructs_runme.java | 12 +- .../java/doxygen_nested_class_runme.java | 12 +- .../doxygen_parsing_enums_proper_runme.java | 12 +- .../doxygen_parsing_enums_simple_runme.java | 12 +- .../doxygen_parsing_enums_typesafe_runme.java | 12 +- ...oxygen_parsing_enums_typeunsafe_runme.java | 12 +- .../java/doxygen_parsing_runme.java | 12 +- .../doxygen_translate_all_tags_runme.java | 12 +- .../java/doxygen_translate_links_runme.java | 12 +- .../java/doxygen_translate_runme.java | 12 +- configure.ac | 10 -- 18 files changed, 140 insertions(+), 180 deletions(-) diff --git a/Examples/test-suite/java/CommentParser.java b/Examples/test-suite/java/CommentParser.java index 7d5740b51..1fc6f646a 100644 --- a/Examples/test-suite/java/CommentParser.java +++ b/Examples/test-suite/java/CommentParser.java @@ -1,5 +1,6 @@ -import com.sun.javadoc.*; +import com.sun.source.doctree.*; +import com.sun.source.util.DocTrees; import java.util.HashMap; import java.util.Map.Entry; import java.util.Map; @@ -9,45 +10,120 @@ import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.io.FileOutputStream; import java.io.IOException; +import java.util.*; +import java.util.spi.ToolProvider; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import jdk.javadoc.doclet.*; -public class CommentParser { +public class CommentParser implements Doclet { private static Map m_parsedComments = new HashMap(); - public static boolean start(RootDoc root) { + // We need to implement these base class pure virtual methods. + @Override + public void init(Locale locale, Reporter reporter) { + } + + @Override + public Set getSupportedOptions() { + return new HashSet<>(); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + @Override + public String getName() { + return "CommentParser"; + } + + // Element name must be the fully qualified name of the element. + // + // If there is no comment associated with this element, simply do nothing. + private void storeCommentFor(DocTrees docTrees, String fullName, Element e) { + DocCommentTree docCommentTree = docTrees.getDocCommentTree(e); + if (docCommentTree == null) + return; + + StringBuilder name = new StringBuilder(fullName); + + // We must use signature in the key for methods for compatibility with + // the existing tests and to allow distinguishing between overloaded + // methods. + if (e instanceof ExecutableElement) { + ExecutableElement ex = (ExecutableElement)e; + name.append("("); + + boolean firstParam = true; + for (VariableElement p : ex.getParameters()) { + if (firstParam) { + firstParam = false; + } else { + name.append(", "); + } + + name.append(p.asType().toString()); + } + + name.append(")"); + } + + // For some reason the comment in the source is split into "body" and + // "block tags" parts, so we need to concatenate them back together. + StringBuilder comment = new StringBuilder(); + for (DocTree d : docCommentTree.getFullBody()) { + comment.append(d.toString()); + comment.append("\n"); + } + + boolean firstBlockTag = true; + for (DocTree d : docCommentTree.getBlockTags()) { + if (firstBlockTag) { + firstBlockTag = false; + comment.append("\n"); + } + + comment.append(d.toString()); + comment.append("\n"); + } + + m_parsedComments.put(name.toString(), comment.toString()); + } + + @Override + public boolean run(DocletEnvironment docEnv) { /* * This method is called by 'javadoc' and gets the whole parsed java * file, we get comments and store them */ + DocTrees docTrees = docEnv.getDocTrees(); + for (TypeElement t : ElementFilter.typesIn(docEnv.getIncludedElements())) { + String typeName = t.getQualifiedName().toString(); - for (ClassDoc classDoc : root.classes()) { + storeCommentFor(docTrees, typeName, t); - if (classDoc.getRawCommentText().length() > 0) - m_parsedComments.put(classDoc.qualifiedName(), classDoc.getRawCommentText()); + for (Element e : t.getEnclosedElements()) { + // Omit the method name for ctors: this is a bit weird, but + // this is what the existing tests expect. + String fullName = typeName; + if (e.getKind() != ElementKind.CONSTRUCTOR) { + fullName = fullName + "." + e.getSimpleName(); + } - for (FieldDoc f : classDoc.enumConstants()) { - if (f.getRawCommentText().length() > 0) - m_parsedComments.put(f.qualifiedName(), f.getRawCommentText()); - } - for (FieldDoc f : classDoc.fields()) { - if (f.getRawCommentText().length() > 0) - m_parsedComments.put(f.qualifiedName(), f.getRawCommentText()); - } - for (ConstructorDoc c : classDoc.constructors()) { - if (c.getRawCommentText().length() > 0) - m_parsedComments.put(c.toString(), c.getRawCommentText()); - } - for (MethodDoc m : classDoc.methods()) { - if (m.getRawCommentText().length() > 0) - m_parsedComments.put(m.toString(), m.getRawCommentText()); + storeCommentFor(docTrees, fullName, e); } } + return true; } - public int check(Map wantedComments) { + public static int check(Map wantedComments) { int errorCount=0; Iterator> it = m_parsedComments.entrySet().iterator(); @@ -131,7 +207,7 @@ public class CommentParser { } - private void printKeys(Map map) { + private static void printKeys(Map map) { Set keys = map.keySet(); for (String key : keys) { @@ -155,6 +231,15 @@ public class CommentParser { } } + public static void parse(String sourcefile) { + ToolProvider javadoc = ToolProvider.findFirst("javadoc").orElseThrow(); + int result = javadoc.run(System.out, System.err, new String[]{"-quiet", "-doclet", "CommentParser", sourcefile}); + if (result != 0) { + System.err.println("Executing javadoc failed."); + System.exit(result); + } + } + public static void main(String argv[]) { @@ -163,8 +248,7 @@ public class CommentParser { System.exit(1); } - com.sun.tools.javadoc.Main.execute("The comment parser program", - "CommentParser", new String[]{"-quiet", argv[0]}); + parse(argv[0]); // if we are run as standalone app, print the list of found comments as it would appear in java source diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 2e788fa07..3f4a71711 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -108,13 +108,11 @@ setup = \ mkdir $(JAVA_PACKAGE); \ fi -# Doxygen test cases need to be compiled together with the CommentParser class -# which depends on com.sun.javadoc package which is located in this JAR. +# Doxygen test cases need to be compiled together with the CommentParser class. CommentParser.class: $(COMPILETOOL) $(JAVAC) -classpath $(JAVA_CLASSPATH) -d . $(srcdir)/CommentParser.java JAVA_CLASSPATH := . -$(DOXYGEN_TEST_CASES:=.cpptest): JAVA_CLASSPATH := "$(JAVA_TOOLS_JAR)$(JAVA_CLASSPATH_SEP)." $(DOXYGEN_TEST_CASES:=.cpptest): CommentParser.class # Compiles java files then runs the testcase. A testcase is only run if diff --git a/Examples/test-suite/java/doxygen_alias_runme.java b/Examples/test-suite/java/doxygen_alias_runme.java index e21ed6d19..98cd97752 100644 --- a/Examples/test-suite/java/doxygen_alias_runme.java +++ b/Examples/test-suite/java/doxygen_alias_runme.java @@ -1,6 +1,5 @@ import doxygen_alias.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_alias_runme { @@ -15,10 +14,7 @@ public class doxygen_alias_runme { 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"}); + CommentParser.parse("doxygen_alias"); HashMap wantedComments = new HashMap(); wantedComments.put("doxygen_alias.doxygen_alias.make_something()", @@ -27,6 +23,6 @@ public class doxygen_alias_runme { " @return A new object which may be null.\n" + ""); - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_basic_notranslate_runme.java b/Examples/test-suite/java/doxygen_basic_notranslate_runme.java index e3d9b0279..621cc9eef 100644 --- a/Examples/test-suite/java/doxygen_basic_notranslate_runme.java +++ b/Examples/test-suite/java/doxygen_basic_notranslate_runme.java @@ -1,6 +1,5 @@ import doxygen_basic_notranslate.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_basic_notranslate_runme { @@ -15,14 +14,7 @@ public class doxygen_basic_notranslate_runme { 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_notranslate runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_basic_notranslate"}); + CommentParser.parse("doxygen_basic_notranslate"); HashMap wantedComments = new HashMap(); wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function3(int)", @@ -97,6 +89,6 @@ public class doxygen_basic_notranslate_runme { ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_basic_translate_runme.java b/Examples/test-suite/java/doxygen_basic_translate_runme.java index ab343b560..f0b1efb6b 100644 --- a/Examples/test-suite/java/doxygen_basic_translate_runme.java +++ b/Examples/test-suite/java/doxygen_basic_translate_runme.java @@ -1,6 +1,5 @@ import doxygen_basic_translate.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_basic_translate_runme { @@ -15,14 +14,7 @@ public class doxygen_basic_translate_runme { 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 runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_basic_translate"}); + CommentParser.parse("doxygen_basic_translate"); HashMap wantedComments = new HashMap(); @@ -96,6 +88,6 @@ public class doxygen_basic_translate_runme { ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java b/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java index 05e51cff8..28cf2daba 100644 --- a/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java +++ b/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java @@ -1,6 +1,5 @@ import doxygen_basic_translate_style2.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_basic_translate_style2_runme { @@ -15,14 +14,7 @@ public class doxygen_basic_translate_style2_runme { 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"}); + CommentParser.parse("doxygen_basic_translate_style2"); HashMap wantedComments = new HashMap(); @@ -96,6 +88,6 @@ public class doxygen_basic_translate_style2_runme { ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_ignore_runme.java b/Examples/test-suite/java/doxygen_ignore_runme.java index 6250ce525..29b6e0640 100644 --- a/Examples/test-suite/java/doxygen_ignore_runme.java +++ b/Examples/test-suite/java/doxygen_ignore_runme.java @@ -1,6 +1,5 @@ import doxygen_ignore.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_ignore_runme { @@ -15,10 +14,7 @@ public class doxygen_ignore_runme { public static void main(String argv[]) { - CommentParser parser = new CommentParser(); - com.sun.tools.javadoc.Main.execute("doxygen_ignore runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_ignore"}); + CommentParser.parse("doxygen_ignore"); HashMap wantedComments = new HashMap(); wantedComments.put("doxygen_ignore.doxygen_ignore.func()", @@ -39,6 +35,6 @@ public class doxygen_ignore_runme { "\n" + ""); - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_misc_constructs_runme.java b/Examples/test-suite/java/doxygen_misc_constructs_runme.java index 5d95bd565..b1f4e2ef5 100644 --- a/Examples/test-suite/java/doxygen_misc_constructs_runme.java +++ b/Examples/test-suite/java/doxygen_misc_constructs_runme.java @@ -1,6 +1,5 @@ import doxygen_misc_constructs.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_misc_constructs_runme { @@ -15,14 +14,7 @@ public class doxygen_misc_constructs_runme { 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_misc_constructs runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_misc_constructs"}); + CommentParser.parse("doxygen_misc_constructs"); HashMap wantedComments = new HashMap(); @@ -195,6 +187,6 @@ public class doxygen_misc_constructs_runme { // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_nested_class_runme.java b/Examples/test-suite/java/doxygen_nested_class_runme.java index 3ffa796f0..e9d1a068e 100644 --- a/Examples/test-suite/java/doxygen_nested_class_runme.java +++ b/Examples/test-suite/java/doxygen_nested_class_runme.java @@ -1,5 +1,4 @@ import doxygen_nested_class.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_nested_class_runme { @@ -14,14 +13,7 @@ public class doxygen_nested_class_runme { 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_nested_class runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_nested_class"}); + CommentParser.parse("doxygen_nested_class"); HashMap wantedComments = new HashMap(); @@ -43,6 +35,6 @@ public class doxygen_nested_class_runme { " doxShort const variable "); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java index ef1f06af5..6b1e2b08e 100644 --- a/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java +++ b/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java @@ -1,6 +1,5 @@ import doxygen_parsing_enums_proper.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_parsing_enums_proper_runme { @@ -15,14 +14,7 @@ public class doxygen_parsing_enums_proper_runme { 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_parsing_enums_proper runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_parsing_enums_proper"}); + CommentParser.parse("doxygen_parsing_enums_proper"); HashMap wantedComments = new HashMap(); @@ -61,6 +53,6 @@ public class doxygen_parsing_enums_proper_runme { "Post comment after last comma."); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java index 85ec0cb55..1e0dd74ee 100644 --- a/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java +++ b/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java @@ -1,6 +1,5 @@ import doxygen_parsing_enums_simple.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_parsing_enums_simple_runme { @@ -15,14 +14,7 @@ public class doxygen_parsing_enums_simple_runme { 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_parsing_enums_simple runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_parsing_enums_simple"}); + CommentParser.parse("doxygen_parsing_enums_simple"); HashMap wantedComments = new HashMap(); @@ -53,6 +45,6 @@ public class doxygen_parsing_enums_simple_runme { "Post comment after last comma."); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java index 4e5f4b489..7cf3b17ef 100644 --- a/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java +++ b/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java @@ -1,6 +1,5 @@ import doxygen_parsing_enums_typesafe.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_parsing_enums_typesafe_runme { @@ -15,14 +14,7 @@ public class doxygen_parsing_enums_typesafe_runme { 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_parsing_enums_typesafe runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_parsing_enums_typesafe"}); + CommentParser.parse("doxygen_parsing_enums_typesafe"); HashMap wantedComments = new HashMap(); @@ -62,6 +54,6 @@ public class doxygen_parsing_enums_typesafe_runme { // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java index 428649196..3a41fe56f 100644 --- a/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java +++ b/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java @@ -1,6 +1,5 @@ import doxygen_parsing_enums_typeunsafe.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_parsing_enums_typeunsafe_runme { @@ -15,14 +14,7 @@ public class doxygen_parsing_enums_typeunsafe_runme { 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_parsing_enums_typeunsafe runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_parsing_enums_typeunsafe"}); + CommentParser.parse("doxygen_parsing_enums_typeunsafe"); HashMap wantedComments = new HashMap(); @@ -61,6 +53,6 @@ public class doxygen_parsing_enums_typeunsafe_runme { "Post comment after last comma."); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_parsing_runme.java b/Examples/test-suite/java/doxygen_parsing_runme.java index d58b1f486..10d65fca8 100644 --- a/Examples/test-suite/java/doxygen_parsing_runme.java +++ b/Examples/test-suite/java/doxygen_parsing_runme.java @@ -1,6 +1,5 @@ import doxygen_parsing.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_parsing_runme { @@ -15,14 +14,7 @@ public class doxygen_parsing_runme { 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_parsing runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_parsing"}); + CommentParser.parse("doxygen_parsing"); HashMap wantedComments = new HashMap(); @@ -136,6 +128,6 @@ public class doxygen_parsing_runme { ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.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 d5c533f4e..40702bdff 100644 --- a/Examples/test-suite/java/doxygen_translate_all_tags_runme.java +++ b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java @@ -1,6 +1,5 @@ import doxygen_translate_all_tags.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_translate_all_tags_runme { @@ -15,14 +14,7 @@ public class doxygen_translate_all_tags_runme { 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_all_tags runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_translate_all_tags"}); + CommentParser.parse("doxygen_translate_all_tags"); HashMap wantedComments = new HashMap(); @@ -154,6 +146,6 @@ public class doxygen_translate_all_tags_runme { " And here goes simple text \n" + ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/Examples/test-suite/java/doxygen_translate_links_runme.java b/Examples/test-suite/java/doxygen_translate_links_runme.java index 6d74e16fe..afee4eac6 100644 --- a/Examples/test-suite/java/doxygen_translate_links_runme.java +++ b/Examples/test-suite/java/doxygen_translate_links_runme.java @@ -1,6 +1,5 @@ import doxygen_translate_links.*; -import com.sun.javadoc.*; import java.util.HashMap; public class doxygen_translate_links_runme { @@ -15,14 +14,7 @@ public class doxygen_translate_links_runme { 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"}); + CommentParser.parse("doxygen_translate_links"); HashMap wantedComments = new HashMap(); @@ -64,6 +56,6 @@ public class doxygen_translate_links_runme { ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } \ No newline at end of file diff --git a/Examples/test-suite/java/doxygen_translate_runme.java b/Examples/test-suite/java/doxygen_translate_runme.java index 55e5d23d3..b049a6466 100644 --- a/Examples/test-suite/java/doxygen_translate_runme.java +++ b/Examples/test-suite/java/doxygen_translate_runme.java @@ -1,6 +1,5 @@ import doxygen_translate.*; -import com.sun.javadoc.*; import java.util.HashMap; import java.util.Map; @@ -16,14 +15,7 @@ public class doxygen_translate_runme { 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 runtime test", - "CommentParser", - new String[]{"-quiet", "doxygen_translate"}); + CommentParser.parse("doxygen_translate"); Map wantedComments = new HashMap(); @@ -274,6 +266,6 @@ public class doxygen_translate_runme { ""); // and ask the parser to check comments for us - System.exit(parser.check(wantedComments)); + System.exit(CommentParser.check(wantedComments)); } } diff --git a/configure.ac b/configure.ac index ea469c24e..809a216e0 100644 --- a/configure.ac +++ b/configure.ac @@ -1408,15 +1408,6 @@ if test -z "$JAVA_HOME" && test -n "$JAVA_HOME_MAYBE" ; then fi fi -# Javadoc support required for the Java test-suite is available by default in jdk9+ and in tools.jar in earlier jdk versions -AC_MSG_CHECKING(for java tools.jar) -if test -n "$JAVA_HOME" && test -r "$JAVA_HOME/lib/tools.jar" ; then - JAVA_TOOLS_JAR="$JAVA_HOME/lib/tools.jar" - AC_MSG_RESULT([$JAVA_TOOLS_JAR]) -else - AC_MSG_RESULT(not found) -fi - case $host in *-*-cygwin*) # TODO: Only use this flag if the compiler supports it, later versions of gcc no longer have it @@ -1483,7 +1474,6 @@ AC_SUBST(JAVA) AC_SUBST(JAVAC) AC_SUBST(JAVAINC) AC_SUBST(JAVA_CLASSPATH_SEP) -AC_SUBST(JAVA_TOOLS_JAR) AC_SUBST(JAVADYNAMICLINKING) AC_SUBST(JAVALIBRARYPREFIX) AC_SUBST(JAVASO) From a271785f1a77a17c5c436bae4d1f9407b720db44 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 18 Dec 2019 02:41:49 +0100 Subject: [PATCH 10/12] Revert "Remove Travis osx java testing" This reverts commit 66752cde4858a780fecba47793f99ba49ce8b15e as Doxygen tests do pass with Java 13 now. --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e0d8ac74a..72ede27f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -449,11 +449,6 @@ matrix: env: SWIGLANG=php VER=7.2 sudo: required dist: xenial - # jdk 13 has removed tools.jar resulting in: CommentParser.java:2: error: package com.sun.javadoc does not exist - - compiler: clang - os: osx - env: SWIGLANG=java CPP17=1 - osx_image: xcode10.2 # Sometimes hits the Travis 50 minute time limit - compiler: clang os: osx From b52af4039856cce3dc924d970572350b85f2652d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 18 Dec 2019 16:24:28 +0100 Subject: [PATCH 11/12] Disable Doxygen tests when using Java 8 or older Check Java version in configure and define SKIP_DOXYGEN_TEST_CASES if it's less than 9, which is required by the new implementation of CommentParser used in the Doxygen tests. --- Examples/test-suite/common.mk | 5 ++++- Examples/test-suite/java/Makefile.in | 1 + configure.ac | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 5f7792810..c817bdf80 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -610,11 +610,14 @@ CPP11_TEST_BROKEN = \ # cpp11_reference_wrapper \ # No typemaps # Doxygen support test cases: can only be used with languages supporting -# Doxygen comment translation, currently only Python and Java. +# Doxygen comment translation (currently Python and Java) and only if not +# disabled by configure via SKIP_DOXYGEN_TEST_CASES. +ifneq ($(SKIP_DOXYGEN_TEST_CASES),1) python_HAS_DOXYGEN := 1 java_HAS_DOXYGEN := 1 $(eval HAS_DOXYGEN := $($(LANGUAGE)_HAS_DOXYGEN)) +endif ifdef HAS_DOXYGEN DOXYGEN_TEST_CASES += \ diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 3f4a71711..f8e290ee3 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -9,6 +9,7 @@ JAVAFLAGS = @JAVAFLAGS@ JAVA_CLASSPATH_SEP = @JAVA_CLASSPATH_SEP@ JAVA_TOOLS_JAR = @JAVA_TOOLS_JAR@ SCRIPTSUFFIX = _runme.java +SKIP_DOXYGEN_TEST_CASES = @JAVA_SKIP_DOXYGEN_TEST_CASES@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ diff --git a/configure.ac b/configure.ac index 809a216e0..13b37d4ad 100644 --- a/configure.ac +++ b/configure.ac @@ -1348,6 +1348,33 @@ else JAVAC="$JAVACBIN" fi +# Check Java version: we require Java 9 or later for Doxygen tests. +if test -n "$JAVAC"; then + AC_MSG_CHECKING(if java version is 9 or greater) + javac_version=`$JAVAC -version 2>&1` + java_version_num=`echo $javac_version | sed -n 's/^javac //p'` + if test -z "$java_version_num"; then + AC_MSG_WARN([unknown format for Java version returned by $JAVAC ($javac_version)]) + JAVA_SKIP_DOXYGEN_TEST_CASES=1 + AC_MSG_RESULT(unknown) + else + dnl Until Java 8 version number was in format "1.x", starting from + dnl Java 9 it's just "x". + case $java_version_num in + 1.*) + JAVA_SKIP_DOXYGEN_TEST_CASES=1 + AC_MSG_RESULT([no, disabling Doxygen tests]) + ;; + + *) + AC_MSG_RESULT(yes) + ;; + esac + fi + + AC_SUBST(JAVA_SKIP_DOXYGEN_TEST_CASES) +fi + AC_MSG_CHECKING(for java include file jni.h) AC_ARG_WITH(javaincl, [ --with-javaincl=path Set location of Java include directory], [JAVAINCDIR="$withval"], [JAVAINCDIR=]) From e7d0533a6feebbfce9813998f9d059a99aaed6dd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 19 Dec 2019 16:17:24 +0100 Subject: [PATCH 12/12] Quote JAVAC expansion in configure to deal with spaces This avoids errors about unknown Java version format when JAVAC is in a path with spaces in it (as is often the case under Windows). --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 13b37d4ad..b4cadefd0 100644 --- a/configure.ac +++ b/configure.ac @@ -1351,10 +1351,10 @@ fi # Check Java version: we require Java 9 or later for Doxygen tests. if test -n "$JAVAC"; then AC_MSG_CHECKING(if java version is 9 or greater) - javac_version=`$JAVAC -version 2>&1` + javac_version=`"$JAVAC" -version 2>&1` java_version_num=`echo $javac_version | sed -n 's/^javac //p'` if test -z "$java_version_num"; then - AC_MSG_WARN([unknown format for Java version returned by $JAVAC ($javac_version)]) + AC_MSG_WARN([unknown format for Java version returned by "$JAVAC" ($javac_version)]) JAVA_SKIP_DOXYGEN_TEST_CASES=1 AC_MSG_RESULT(unknown) else