std::string throws typemaps
Go, Guile, Racket, Scilab: Add throws typemaps for std::string so that thrown string exception messages can be seen. Test all language for std::string throws typemaps
This commit is contained in:
parent
4a29229bab
commit
ed333b6b97
24 changed files with 225 additions and 12 deletions
|
|
@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.1.0 (in progress)
|
Version 4.1.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2022-09-17: wsfulton
|
||||||
|
[Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown
|
||||||
|
string exception messages can be seen.
|
||||||
|
|
||||||
|
2022-09-17: wsfulton
|
||||||
|
[Racket] Add throws typemaps for char * so that thrown string exception
|
||||||
|
messages can be seen from Racket.
|
||||||
|
|
||||||
2022-09-17: wsfulton
|
2022-09-17: wsfulton
|
||||||
[Javascript, Octave, R] Improve exceptions for %catches and exception
|
[Javascript, Octave, R] Improve exceptions for %catches and exception
|
||||||
specifications for native types. String exception messages are shown as
|
specifications for native types. String exception messages are shown as
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,15 @@
|
||||||
%include <std_string.i>
|
%include <std_string.i>
|
||||||
|
|
||||||
%catches(const char *) StringsThrower::charstring;
|
%catches(const char *) StringsThrower::charstring;
|
||||||
|
%catches(std::string) StringsThrower::stdstring;
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
struct StringsThrower {
|
struct StringsThrower {
|
||||||
static void charstring() {
|
static void charstring() {
|
||||||
throw "charstring message";
|
throw "charstring message";
|
||||||
}
|
}
|
||||||
|
static void stdstring() {
|
||||||
|
throw std::string("stdstring message");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
%}
|
%}
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,17 @@ public class catches_strings_runme {
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
throw new ApplicationException("Should have thrown an exception");
|
throw new ApplicationException("Should have thrown an exception");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try {
|
||||||
|
StringsThrower.stdstring();
|
||||||
|
} catch (ApplicationException e) {
|
||||||
|
if (!e.Message.Contains("stdstring message"))
|
||||||
|
throw new ApplicationException("incorrect exception message:" + e);
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
if (!exception_thrown)
|
||||||
|
throw new ApplicationException("Should have thrown an exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,16 @@ void main() {
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
throw new Exception("Should have thrown an exception");
|
throw new Exception("Should have thrown an exception");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try {
|
||||||
|
StringsThrower.stdstring();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (!canFind(e.msg, "stdstring message"))
|
||||||
|
throw new Exception("incorrect exception message:" ~ e.msg);
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
if (!exception_thrown)
|
||||||
|
throw new Exception("Should have thrown an exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,16 @@ void main() {
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
throw new Exception("Should have thrown an exception");
|
throw new Exception("Should have thrown an exception");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try {
|
||||||
|
StringsThrower.stdstring();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (!canFind(e.msg, "stdstring message"))
|
||||||
|
throw new Exception("incorrect exception message:" ~ e.msg);
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
if (!exception_thrown)
|
||||||
|
throw new Exception("Should have thrown an exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,29 @@ import "strings"
|
||||||
import . "swigtests/catches_strings"
|
import . "swigtests/catches_strings"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
exception_thrown := false
|
{
|
||||||
func() {
|
exception_thrown := false
|
||||||
defer func() {
|
func() {
|
||||||
exception_thrown = strings.Index(recover().(string), "charstring message") == 0
|
defer func() {
|
||||||
|
exception_thrown = strings.Index(recover().(string), "charstring message") == 0
|
||||||
|
}()
|
||||||
|
StringsThrowerCharstring()
|
||||||
}()
|
}()
|
||||||
StringsThrowerCharstring()
|
if !exception_thrown {
|
||||||
}()
|
panic(0)
|
||||||
if !exception_thrown {
|
}
|
||||||
panic(0)
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
exception_thrown := false
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
exception_thrown = strings.Index(recover().(string), "stdstring message") == 0
|
||||||
|
}()
|
||||||
|
StringsThrowerStdstring()
|
||||||
|
}()
|
||||||
|
if !exception_thrown {
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,5 +24,18 @@ public class catches_strings_runme {
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
throw new RuntimeException("Should have thrown an exception");
|
throw new RuntimeException("Should have thrown an exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boolean exception_thrown = false;
|
||||||
|
try {
|
||||||
|
StringsThrower.stdstring();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
if (!e.getMessage().contains("stdstring message"))
|
||||||
|
throw new RuntimeException("incorrect exception message");
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
if (!exception_thrown)
|
||||||
|
throw new RuntimeException("Should have thrown an exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,20 @@ exception_thrown = false;
|
||||||
try {
|
try {
|
||||||
catches_strings.StringsThrower.charstring();
|
catches_strings.StringsThrower.charstring();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(typeof(e))
|
|
||||||
console.log(e.constructor.name)
|
|
||||||
console.log(typeof(e.message))
|
|
||||||
if (!e.message.includes("charstring message"))
|
if (!e.message.includes("charstring message"))
|
||||||
throw new Error("incorrect exception message " + e.message);
|
throw new Error("incorrect exception message " + e.message);
|
||||||
exception_thrown = true;
|
exception_thrown = true;
|
||||||
}
|
}
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
throw new Error("Should have thrown an exception");
|
throw new Error("Should have thrown an exception");
|
||||||
|
|
||||||
|
exception_thrown = false;
|
||||||
|
try {
|
||||||
|
catches_strings.StringsThrower.stdstring();
|
||||||
|
} catch (e) {
|
||||||
|
if (!e.message.includes("stdstring message"))
|
||||||
|
throw new Error("incorrect exception message " + e.message);
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
if (!exception_thrown)
|
||||||
|
throw new Error("Should have thrown an exception");
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,6 @@ setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i
|
||||||
|
|
||||||
s, msg = pcall(function() catches_strings.StringsThrower.charstring() end)
|
s, msg = pcall(function() catches_strings.StringsThrower.charstring() end)
|
||||||
assert(s == false and msg:find("charstring message", 1, true))
|
assert(s == false and msg:find("charstring message", 1, true))
|
||||||
|
|
||||||
|
s, msg = pcall(function() catches_strings.StringsThrower.stdstring() end)
|
||||||
|
assert(s == false and msg:find("stdstring message", 1, true))
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,11 @@
|
||||||
(unless (string-contains? exception_thrown "charstring message")
|
(unless (string-contains? exception_thrown "charstring message")
|
||||||
(error (format "incorrect exception message: ~a" exception_thrown)))
|
(error (format "incorrect exception message: ~a" exception_thrown)))
|
||||||
|
|
||||||
|
(define exception_thrown "no exception thrown for kin")
|
||||||
|
(with-handlers ([exn:fail? (lambda (exn)
|
||||||
|
(set! exception_thrown (exn-message exn)))])
|
||||||
|
(StringsThrower-stdstring))
|
||||||
|
(unless (string-contains? exception_thrown "stdstring message")
|
||||||
|
(error (format "incorrect exception message: ~a" exception_thrown)))
|
||||||
|
|
||||||
(exit 0)
|
(exit 0)
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,9 @@ let _ =
|
||||||
ignore (_StringsThrower_charstring (C_void)); assert false
|
ignore (_StringsThrower_charstring (C_void)); assert false
|
||||||
with Failure s ->
|
with Failure s ->
|
||||||
assert (s = "charstring message")
|
assert (s = "charstring message")
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
try
|
||||||
|
ignore (_StringsThrower_stdstring (C_void)); assert false
|
||||||
|
with Failure s ->
|
||||||
|
assert (s = "stdstring message")
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,16 @@ end_try_catch
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
error("Should have thrown an exception");
|
error("Should have thrown an exception");
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
exception_thrown = false;
|
||||||
|
try
|
||||||
|
StringsThrower.stdstring();
|
||||||
|
catch e
|
||||||
|
if (isempty(strfind(e.message, "stdstring message")))
|
||||||
|
error("incorrect exception message: %s", e.message)
|
||||||
|
endif
|
||||||
|
exception_thrown = true;
|
||||||
|
end_try_catch
|
||||||
|
if (!exception_thrown)
|
||||||
|
error("Should have thrown an exception");
|
||||||
|
endif
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use Test::More tests => 3;
|
use Test::More tests => 4;
|
||||||
BEGIN { use_ok('catches_strings') }
|
BEGIN { use_ok('catches_strings') }
|
||||||
require_ok('catches_strings');
|
require_ok('catches_strings');
|
||||||
|
|
||||||
|
|
@ -8,3 +8,8 @@ eval {
|
||||||
catches_strings::StringsThrower::charstring();
|
catches_strings::StringsThrower::charstring();
|
||||||
};
|
};
|
||||||
like($@, qr/\bcharstring message/, "Should have thrown an exception");
|
like($@, qr/\bcharstring message/, "Should have thrown an exception");
|
||||||
|
|
||||||
|
eval {
|
||||||
|
catches_strings::StringsThrower::stdstring();
|
||||||
|
};
|
||||||
|
like($@, qr/\bstdstring message/, "Should have thrown an exception");
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,13 @@ try {
|
||||||
}
|
}
|
||||||
check::equal($exception_thrown, true, "Should have thrown an exception");
|
check::equal($exception_thrown, true, "Should have thrown an exception");
|
||||||
|
|
||||||
|
$exception_thrown = false;
|
||||||
|
try {
|
||||||
|
StringsThrower::stdstring();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
check::str_contains($e->getMessage(), "stdstring message", "incorrect exception message: {$e->getMessage()}");
|
||||||
|
$exception_thrown = true;
|
||||||
|
}
|
||||||
|
check::equal($exception_thrown, true, "Should have thrown an exception");
|
||||||
|
|
||||||
check::done();
|
check::done();
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,13 @@ except RuntimeError as e:
|
||||||
exception_thrown = True
|
exception_thrown = True
|
||||||
if not exception_thrown:
|
if not exception_thrown:
|
||||||
raise RuntimeError("Should have thrown an exception")
|
raise RuntimeError("Should have thrown an exception")
|
||||||
|
|
||||||
|
exception_thrown = False
|
||||||
|
try:
|
||||||
|
StringsThrower.stdstring()
|
||||||
|
except RuntimeError as e:
|
||||||
|
if "stdstring message" not in str(e):
|
||||||
|
raise RuntimeError("incorrect exception message:" + str(e))
|
||||||
|
exception_thrown = True
|
||||||
|
if not exception_thrown:
|
||||||
|
raise RuntimeError("Should have thrown an exception")
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,12 @@ tryCatch({
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
unittest(exception_thrown, TRUE)
|
unittest(exception_thrown, TRUE)
|
||||||
|
|
||||||
|
exception_thrown = FALSE
|
||||||
|
tryCatch({
|
||||||
|
StringsThrower_stdstring()
|
||||||
|
}, error = function(e) {
|
||||||
|
exception_thrown <<- grepl(e$message, "stdstring message", fixed=TRUE)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
unittest(exception_thrown, TRUE)
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,16 @@ end
|
||||||
if (!exception_thrown)
|
if (!exception_thrown)
|
||||||
raise RuntimeError, "Should have thrown an exception"
|
raise RuntimeError, "Should have thrown an exception"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
exception_thrown = false
|
||||||
|
begin
|
||||||
|
Catches_strings::StringsThrower.stdstring()
|
||||||
|
rescue RuntimeError => e
|
||||||
|
if (!e.to_s.include? "stdstring message")
|
||||||
|
raise RuntimeError, "incorrect exception message: #{e.to_s}"
|
||||||
|
end
|
||||||
|
exception_thrown = true
|
||||||
|
end
|
||||||
|
if (!exception_thrown)
|
||||||
|
raise RuntimeError, "Should have thrown an exception"
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,8 @@
|
||||||
(StringsThrower-charstring))
|
(StringsThrower-charstring))
|
||||||
; TODO: check the exception message
|
; TODO: check the exception message
|
||||||
|
|
||||||
|
(expect-throw 'swig-exception
|
||||||
|
(StringsThrower-stdstring))
|
||||||
|
; TODO: check the exception message
|
||||||
|
|
||||||
(exit 0)
|
(exit 0)
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,11 @@ if (strstr(lasterror(), "charstring message") == '')
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ierr = execstr("StringsThrower_stdstring()", 'errcatch');
|
||||||
|
checkequal(ierr, 20000, "wrong/no exception thrown")
|
||||||
|
if (strstr(lasterror(), "stdstring message") == '')
|
||||||
|
printf("Should have thrown an exception")
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
exec("swigtest.quit", -1);
|
exec("swigtest.quit", -1);
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,16 @@ if [ catch {
|
||||||
if {!$exception_thrown} {
|
if {!$exception_thrown} {
|
||||||
error "Should have thrown an exception"
|
error "Should have thrown an exception"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set exception_thrown 0
|
||||||
|
if [ catch {
|
||||||
|
StringsThrower_stdstring
|
||||||
|
} e ] {
|
||||||
|
if {[string first "stdstring message" $e] == -1} {
|
||||||
|
error "incorrect exception message: $e"
|
||||||
|
}
|
||||||
|
set exception_thrown 1
|
||||||
|
}
|
||||||
|
if {!$exception_thrown} {
|
||||||
|
error "Should have thrown an exception"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@ class string;
|
||||||
%typemap(godirectorin,fragment="CopyString") string
|
%typemap(godirectorin,fragment="CopyString") string
|
||||||
%{ $result = swigCopyString($input) %}
|
%{ $result = swigCopyString($input) %}
|
||||||
|
|
||||||
|
%typemap(throws) string
|
||||||
|
%{ _swig_gopanic($1.c_str()); %}
|
||||||
|
|
||||||
%typemap(in) const string &
|
%typemap(in) const string &
|
||||||
%{
|
%{
|
||||||
$*1_ltype $1_str($input.p, $input.n);
|
$*1_ltype $1_str($input.p, $input.n);
|
||||||
|
|
@ -88,6 +91,9 @@ class string;
|
||||||
%typemap(godirectorin,fragment="CopyString") const string &
|
%typemap(godirectorin,fragment="CopyString") const string &
|
||||||
%{ $result = swigCopyString($input) %}
|
%{ $result = swigCopyString($input) %}
|
||||||
|
|
||||||
|
%typemap(throws) const string &
|
||||||
|
%{ _swig_gopanic($1.c_str()); %}
|
||||||
|
|
||||||
|
|
||||||
%typemap(gotype) string * "*string"
|
%typemap(gotype) string * "*string"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,4 +83,13 @@ namespace std {
|
||||||
$result = SWIG_str02scm($1.c_str());
|
$result = SWIG_str02scm($1.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(throws) string {
|
||||||
|
scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
|
||||||
|
scm_list_n(SWIG_str02scm($1.c_str()), SCM_UNDEFINED));
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(throws) const string & {
|
||||||
|
scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
|
||||||
|
scm_list_n(SWIG_str02scm($1.c_str()), SCM_UNDEFINED));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,13 @@ namespace std {
|
||||||
$result = scheme_make_string($1->c_str());
|
$result = scheme_make_string($1->c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(throws) string {
|
||||||
|
scheme_signal_error("%s: %s", FUNC_NAME, $1.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(throws) const string & {
|
||||||
|
scheme_signal_error("%s: %s", FUNC_NAME, $1.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,11 @@ SWIG_From_dec(std::string)(std::string pstValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
%include <typemaps/std_string.swg>
|
%include <typemaps/std_string.swg>
|
||||||
|
|
||||||
|
%typemap(throws, noblock=1) std::string {
|
||||||
|
SWIG_Scilab_Raise_Ex($1.c_str(), "$type", $&descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(throws, noblock=1) const std::string & {
|
||||||
|
SWIG_Scilab_Raise_Ex($1.c_str(), "$type", $descriptor);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue