Skip to content

Commit

Permalink
Some fixes to the Lua deprecation API, and extend it to C++
Browse files Browse the repository at this point in the history
* Some improvements to the messages
* Don't clobber existing metatables on deprecated subtables
* Fix Lua deprecation messages not even being logged
* Fix deprecation of Lua subtables
* Don't clobber the metatable when deprecating a subtable
  • Loading branch information
CelticMinstrel committed Feb 12, 2018
1 parent ca06517 commit b4b5440
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 34 deletions.
37 changes: 28 additions & 9 deletions data/lua/core.lua
Expand Up @@ -146,6 +146,9 @@ end

--[========[Deprecation Helpers]========]

-- Need a textdomain for translatable deprecation strings.
-- Note that these strings are all duplicated in src/deprecation.cpp
-- Any changes here should also be reflected there.
local _ = wesnoth.textdomain "wesnoth"

-- Note: When using version (for level 2 or 3 deprecation), specify the first version
Expand All @@ -167,21 +170,31 @@ function wesnoth.deprecation_message(elem_name, level, version, detail)
end
elseif level == 3 then
logger = function(msg) wesnoth.log("err", msg) end
message = wesnoth.format(_"$elem has been deprecated and will be removed in the next version.", message_params)
message_params.version = version
message = wesnoth.format(_"$elem has been deprecated and will be removed in the next version ($version).", message_params)
elseif level == 4 then
logger = error
message = wesnoth.format(_"$elem has been deprecated and removed.", message_params)
else
error(_"Invalid deprecation level (should be 1-4)")
local err_params = {level = level}
error(wesnoth.format(_"Invalid deprecation level $level (should be 1-4)", err_params))
end
if #detail > 0 then
logger(message .. "\n " .. detail)
logger(tostring(message .. "\n " .. detail))
else
logger(message)
logger(tostring(message))
end
end

-- Usage: module.something = wesnoth.deprecate(module.something, "something", ...)
-- Marks a function or subtable as deprecated.
-- Parameters:
---- elem_name: the full name of the element being deprecated (including the module)
---- replacement: the name of the element that will replace it (including the module)
---- level: deprecation level (1-4)
---- version: the version at which the element may be removed (level 2 or 3 only)
---- Set to nil if deprecation level is 1 or 4
---- elem: The actual element being deprecated
---- detail_msg: An optional message to add to the deprecation message
function wesnoth.deprecate_api(elem_name, replacement, level, version, elem, detail_msg)
local message = detail_msg or ''
if replacement then
Expand All @@ -190,7 +203,8 @@ function wesnoth.deprecate_api(elem_name, replacement, level, version, elem, det
{replacement = replacement})
end
if type(level) ~= "number" or level < 1 or level > 4 then
error("Invalid deprecation level! Must be 1-4.")
local err_params = {level = level}
error(wesnoth.format(_"Invalid deprecation level $level (should be 1-4)", err_params))
end
local msg_shown = false
if type(elem) == "function" then
Expand All @@ -201,23 +215,28 @@ function wesnoth.deprecate_api(elem_name, replacement, level, version, elem, det
end
return elem(...)
end
elseif type(elem) == "table" or type(elem) == "userdata" then
elseif type(elem) == "table" then
local mt = {
__index = function(key)
__index = function(self, key)
if not msg_shown then
msg_shown = true
wesnoth.deprecation_message(elem_name, level, version, message)
end
return elem[key]
end,
__newindex = function(key, val)
__newindex = function(self, key, val)
if not msg_shown then
msg_shown = true
wesnoth.deprecation_message(elem_name, level, version, message)
end
elem[key] = val
end,
}
-- Don't clobber the old metatable.
local old_mt = getmetatable(elem)
if type(old_mt) == "table" then
setmetatable(mt, old_mt)
end
return setmetatable({}, mt)
else
wesnoth.log('warn', "Attempted to deprecate something that is not a table or function: " ..
Expand Down
8 changes: 0 additions & 8 deletions projectfiles/VC12/wesnoth.vcxproj
Expand Up @@ -1095,13 +1095,6 @@
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)Formula\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\formula\string_utils.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)Formula\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\formula\tokenizer.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Formula\</ObjectFileName>
Expand Down Expand Up @@ -3663,7 +3656,6 @@
<ClInclude Include="..\..\src\formula\formula_fwd.hpp" />
<ClInclude Include="..\..\src\formula\function_gamestate.hpp" />
<ClInclude Include="..\..\src\formula\function.hpp" />
<ClInclude Include="..\..\src\formula\string_utils.hpp" />
<ClInclude Include="..\..\src\formula\tokenizer.hpp" />
<ClInclude Include="..\..\src\formula\variant.hpp" />
<ClInclude Include="..\..\src\formula\variant_value.hpp" />
Expand Down
8 changes: 2 additions & 6 deletions projectfiles/VC12/wesnoth.vcxproj.filters
Expand Up @@ -1322,9 +1322,6 @@
<ClCompile Include="..\..\src\formula\function_gamestate.cpp">
<Filter>Formula</Filter>
</ClCompile>
<ClCompile Include="..\..\src\formula\string_utils.cpp">
<Filter>Formula</Filter>
</ClCompile>
<ClCompile Include="..\..\src\formula\tokenizer.cpp">
<Filter>Formula</Filter>
</ClCompile>
Expand Down Expand Up @@ -1561,6 +1558,7 @@
<ClCompile Include="..\..\src\gui\dialogs\surrender_quit.cpp">
<Filter>Gui\Dialogs</Filter>
</ClCompile>
<ClCompile Include="..\..\src\deprecation.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\addon\client.hpp">
Expand Down Expand Up @@ -2745,9 +2743,6 @@
<ClInclude Include="..\..\src\formula\function_gamestate.hpp">
<Filter>Formula</Filter>
</ClInclude>
<ClInclude Include="..\..\src\formula\string_utils.hpp">
<Filter>Formula</Filter>
</ClInclude>
<ClInclude Include="..\..\src\formula\tokenizer.hpp">
<Filter>Formula</Filter>
</ClInclude>
Expand Down Expand Up @@ -3031,6 +3026,7 @@
<ClInclude Include="..\..\src\gui\dialogs\surrender_quit.hpp">
<Filter>Gui\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\src\deprecation.hpp" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\tests\test_sdl_utils.hpp">
Expand Down
8 changes: 8 additions & 0 deletions projectfiles/VC12/wesnothlib.vcxproj
Expand Up @@ -134,9 +134,15 @@
<ClCompile Include="..\..\src\color_range.cpp" />
<ClCompile Include="..\..\src\config.cpp" />
<ClCompile Include="..\..\src\config_attribute_value.cpp" />
<ClCompile Include="..\..\src\deprecation.cpp" />
<ClCompile Include="..\..\src\filesystem_boost.cpp" />
<ClCompile Include="..\..\src\filesystem_common.cpp" />
<ClCompile Include="..\..\src\font\constants.cpp" />
<ClCompile Include="..\..\src\formula\string_utils.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Formula\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)Formula\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\game_config.cpp" />
<ClCompile Include="..\..\src\gettext_boost.cpp" />
<ClCompile Include="..\..\src\log.cpp" />
Expand All @@ -162,8 +168,10 @@
<ClInclude Include="..\..\src\color_range.hpp" />
<ClInclude Include="..\..\src\config.hpp" />
<ClInclude Include="..\..\src\config_attribute_value.hpp" />
<ClInclude Include="..\..\src\deprecation.hpp" />
<ClInclude Include="..\..\src\filesystem.hpp" />
<ClInclude Include="..\..\src\font\constants.hpp" />
<ClInclude Include="..\..\src\formula\string_utils.hpp" />
<ClInclude Include="..\..\src\game_config.hpp" />
<ClInclude Include="..\..\src\gettext.hpp" />
<ClInclude Include="..\..\src\global.hpp" />
Expand Down
11 changes: 11 additions & 0 deletions projectfiles/VC12/wesnothlib.vcxproj.filters
Expand Up @@ -17,6 +17,9 @@
<Filter Include="Utils">
<UniqueIdentifier>{dd5bcb3f-5af9-4dce-bcf3-9c23cec65372}</UniqueIdentifier>
</Filter>
<Filter Include="Formula">
<UniqueIdentifier>{89506bfd-cc4a-4db3-84f4-b90d70040b9c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\serialization\binary_or_text.cpp">
Expand Down Expand Up @@ -59,6 +62,10 @@
<ClCompile Include="..\..\src\font\constants.cpp">
<Filter>Font</Filter>
</ClCompile>
<ClCompile Include="..\..\src\formula\string_utils.cpp">
<Filter>Formula</Filter>
</ClCompile>
<ClCompile Include="..\..\src\deprecation.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\serialization\binary_or_text.hpp">
Expand Down Expand Up @@ -140,5 +147,9 @@
<ClInclude Include="..\..\src\utils\type_trait_aliases.hpp">
<Filter>Utils</Filter>
</ClInclude>
<ClInclude Include="..\..\src\formula\string_utils.hpp">
<Filter>Formula</Filter>
</ClInclude>
<ClInclude Include="..\..\src\deprecation.hpp" />
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions source_lists/libwesnoth
@@ -1,6 +1,7 @@
arrow.cpp
cursor.cpp
desktop/clipboard.cpp
deprecation.cpp
display.cpp
display_context.cpp
events.cpp
Expand All @@ -14,6 +15,7 @@ font/text_cache.cpp
font/text_formatting.cpp
font/text_surface.cpp
format_time_summary.cpp
formula/string_utils.cpp
game_end_exceptions.cpp
generators/cave_map_generator.cpp
generators/default_map_generator.cpp
Expand Down
1 change: 0 additions & 1 deletion source_lists/wesnoth
Expand Up @@ -109,7 +109,6 @@ formula/debugger_fwd.cpp
formula/formula.cpp
formula/function.cpp
formula/function_gamestate.cpp
formula/string_utils.cpp
formula/tokenizer.cpp
formula/variant.cpp
formula/variant_value.cpp
Expand Down
63 changes: 63 additions & 0 deletions src/deprecation.cpp
@@ -0,0 +1,63 @@
/*
Copyright (C) 2017 by the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/

#include "deprecation.hpp"

#include "log.hpp"
#include "gettext.hpp"
#include "formula/string_utils.hpp"
#include "tstring.hpp"
#include "game_config.hpp"
#include "version.hpp"

static lg::log_domain log_wml("wml");

// Note that these strings are all duplicated in data/lua/core.lua
// Any changes here should also be reflected there.
void deprecated_message(const std::string& elem_name, int level, const version_info& version, const std::string& detail) {
utils::string_map msg_params = {{"elem", elem_name}};
lg::logger* log_ptr = nullptr;
std::string message;
if(level == 1) {
log_ptr = &lg::info();
message = VGETTEXT("$elem has been deprecated indefinitely.", msg_params);
} else if(level == 2) {
log_ptr = &lg::warn();
if(game_config::wesnoth_version < version) {
msg_params["version"] = version.str();
message = VGETTEXT("$elem has been deprecated and may be removed in version $version.", msg_params);
} else {
message = VGETTEXT("$elem has been deprecated and may be removed at any time.", msg_params);
}
} else if(level == 3) {
log_ptr = &lg::err();
msg_params["version"] = version.str();
message = VGETTEXT("$elem has been deprecated and will be removed in the next version ($version).", msg_params);
} else if(level == 4) {
log_ptr = &lg::err();
message = VGETTEXT("$elem has been deprecated and removed.", msg_params);
} else {
utils::string_map err_params = {{"level", std::to_string(level)}};
LOG_STREAM(err, "general") << VGETTEXT("Invalid deprecation level $level (should be 1-4)", err_params);
}
// TODO: Decide when to dump to wml_error()
if(log_ptr && !log_ptr->dont_log(log_wml)) {
const lg::logger& out_log = *log_ptr;
out_log(log_wml) << message << '\n';
//lg::wml_error() << message << '\n';
if(!detail.empty()) {
out_log(log_wml) << detail << '\n';
//lg::wml_error() << detail << '\n';
}
}
}
19 changes: 19 additions & 0 deletions src/deprecation.hpp
@@ -0,0 +1,19 @@
/*
Copyright (C) 2017 by the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/

#include <string>

// Note: When using version (for level 2 or 3 deprecation), specify the first version
// in which the feature could be removed... NOT the version at which it was deprecated.
// For level 1 or 4 deprecation, it's fine to just pass an empty string, as the parameter will not be used.
void deprecated_message(const std::string& elem_name, int level, const class version_info& version, const std::string& detail = "");
29 changes: 29 additions & 0 deletions src/formula/formula.cpp
Expand Up @@ -16,13 +16,42 @@

#include "formula/callable.hpp"
#include "formula/function.hpp"
#include "formula/string_utils.hpp"
#include "random.hpp"
#include "serialization/string_utils.hpp"
#include "log.hpp"

#include <cassert>
#include <set>
#include <sstream>

// This is here only for the below initialization code.
// If other logging is required in this file, it should use a different logdomain
// (probably "scripting/formula" or something)
static lg::log_domain log_engine("engine");
#define ERR_NG LOG_STREAM(err, log_engine)

namespace utils {
namespace detail {
std::string evaluate_formula_impl(const std::string& formula) {
try {
const wfl::formula form(formula);
return form.evaluate().string_cast();
} catch(wfl::formula_error& e) {
ERR_NG << "Formula in WML string cannot be evaluated due to "
<< e.type << "\n\t--> \"";
return "";
}
}

struct formula_initer {
formula_initer() {
evaluate_formula = &evaluate_formula_impl;
}
} init;
}
}

namespace wfl
{
using expr_table = std::map<std::string, expression_ptr>;
Expand Down

0 comments on commit b4b5440

Please sign in to comment.