From d107cb8cc9443c5cc84f1121855f7fc0b2a535a8 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 26 Oct 2017 12:53:52 -0400 Subject: [PATCH] allow final classes to be used improve error reporting for stack checks --- single/sol/sol.hpp | 52 ++++++++++++++++++++++++++++++++++--------- sol/error_handler.hpp | 35 ++++++++++++++++++++++++----- sol/stack_check.hpp | 2 +- sol/traits.hpp | 11 +++++++-- 4 files changed, 82 insertions(+), 18 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index a9ddd308..beb88a33 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2017-10-21 00:59:28.565154 UTC -// This header was generated with sol v2.18.4 (revision 3ee36c7) +// Generated 2017-10-26 16:52:58.996254 UTC +// This header was generated with sol v2.18.4 (revision e9580bc) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -1147,7 +1147,14 @@ namespace sol { struct is_callable : std::is_function> {}; template - struct is_callable>::value && std::is_destructible>::value>> { + struct is_callable>::value + && std::is_class>::value + && std::is_same::value>> { + + }; + + template + struct is_callable>::value && std::is_class>::value && std::is_destructible>::value>> { using yes = char; using no = struct { char s[2]; }; @@ -1168,7 +1175,7 @@ namespace sol { }; template - struct is_callable>::value && !std::is_destructible>::value>> { + struct is_callable>::value && std::is_class>::value && !std::is_destructible>::value>> { using yes = char; using no = struct { char s[2]; }; @@ -5685,19 +5692,44 @@ namespace detail { namespace sol { + inline std::string associated_type_name(lua_State* L, int index, type t) { + switch (t) { + case type::poly: + return "anything"; + case type::userdata: + { + if (lua_getmetatable(L, index) == 0) { + break; + } + lua_pushlstring(L, "__name", 6); + lua_rawget(L, -2); + size_t sz; + const char* name = lua_tolstring(L, -1, &sz); + std::string tn(name, static_cast(sz)); + lua_pop(L, 2); + return name; + } + default: + break; + } + return lua_typename(L, static_cast(t)); + } + inline int type_panic_string(lua_State* L, int index, type expected, type actual, const std::string& message = "") noexcept(false) { - const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s with message %s"; + const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; + std::string actualname = associated_type_name(L, index, actual); return luaL_error(L, err, index, expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), - actual == type::poly ? "anything" : lua_typename(L, static_cast(actual)), + actualname.c_str(), message.c_str()); } inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) { - const char* err = message == nullptr || (std::char_traits::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s with message %s"; + const char* err = message == nullptr || (std::char_traits::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; + std::string actualname = associated_type_name(L, index, actual); return luaL_error(L, err, index, expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), - actual == type::poly ? "anything" : lua_typename(L, static_cast(actual)), + actualname.c_str(), message); } @@ -5731,7 +5763,7 @@ namespace sol { template struct argument_handler> { int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { - std::string addendum = " (bad argument to type expecting '"; + std::string addendum = " (bad argument into '"; addendum += detail::demangle(); addendum += "("; int marker = 0; @@ -7794,7 +7826,7 @@ namespace stack { } if (!success) { lua_pop(L, 1); - handler(L, index, type::userdata, indextype, "value is not a valid sol userdata of any kind"); + handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type"); return false; } lua_pop(L, 1); diff --git a/sol/error_handler.hpp b/sol/error_handler.hpp index 34fc4dee..0c0bdbed 100644 --- a/sol/error_handler.hpp +++ b/sol/error_handler.hpp @@ -27,19 +27,44 @@ namespace sol { + inline std::string associated_type_name(lua_State* L, int index, type t) { + switch (t) { + case type::poly: + return "anything"; + case type::userdata: + { + if (lua_getmetatable(L, index) == 0) { + break; + } + lua_pushlstring(L, "__name", 6); + lua_rawget(L, -2); + size_t sz; + const char* name = lua_tolstring(L, -1, &sz); + std::string tn(name, static_cast(sz)); + lua_pop(L, 2); + return name; + } + default: + break; + } + return lua_typename(L, static_cast(t)); + } + inline int type_panic_string(lua_State* L, int index, type expected, type actual, const std::string& message = "") noexcept(false) { - const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s with message %s"; + const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; + std::string actualname = associated_type_name(L, index, actual); return luaL_error(L, err, index, expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), - actual == type::poly ? "anything" : lua_typename(L, static_cast(actual)), + actualname.c_str(), message.c_str()); } inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) { - const char* err = message == nullptr || (std::char_traits::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s with message %s"; + const char* err = message == nullptr || (std::char_traits::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; + std::string actualname = associated_type_name(L, index, actual); return luaL_error(L, err, index, expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), - actual == type::poly ? "anything" : lua_typename(L, static_cast(actual)), + actualname.c_str(), message); } @@ -73,7 +98,7 @@ namespace sol { template struct argument_handler> { int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { - std::string addendum = " (bad argument to type expecting '"; + std::string addendum = " (bad argument into '"; addendum += detail::demangle(); addendum += "("; int marker = 0; diff --git a/sol/stack_check.hpp b/sol/stack_check.hpp index c59a6132..b366c0dd 100644 --- a/sol/stack_check.hpp +++ b/sol/stack_check.hpp @@ -449,7 +449,7 @@ namespace stack { } if (!success) { lua_pop(L, 1); - handler(L, index, type::userdata, indextype, "value is not a valid sol userdata of any kind"); + handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type"); return false; } lua_pop(L, 1); diff --git a/sol/traits.hpp b/sol/traits.hpp index 6adab060..5ced4ee5 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -260,7 +260,14 @@ namespace sol { struct is_callable : std::is_function> {}; template - struct is_callable>::value && std::is_destructible>::value>> { + struct is_callable>::value + && std::is_class>::value + && std::is_same::value>> { + + }; + + template + struct is_callable>::value && std::is_class>::value && std::is_destructible>::value>> { using yes = char; using no = struct { char s[2]; }; @@ -281,7 +288,7 @@ namespace sol { }; template - struct is_callable>::value && !std::is_destructible>::value>> { + struct is_callable>::value && std::is_class>::value && !std::is_destructible>::value>> { using yes = char; using no = struct { char s[2]; };