Prevents logging of duplicate deprecation messages and messages missing timestamps.

Fixes #5942
This commit is contained in:
Pentarctagon 2021-07-17 23:35:04 -05:00
parent e5eb1c38ce
commit 8e2996661f
No known key found for this signature in database
GPG Key ID: 9456BC54A21DBFA0
30 changed files with 218 additions and 94 deletions

View File

@ -24,10 +24,13 @@ class UnitTestResult(enum.Enum):
TIMEOUT = 2
FAIL_LOADING_REPLAY = 3
FAIL_PLAYING_REPLAY = 4
FAIL_BROKE_STRICT = 5
FAIL_WML_EXCEPTION = 6
FAIL_BY_DEFEAT = 7
PASS_BY_VICTORY = 8
BROKE_STRICT_TEST_PASS = 9
BROKE_STRICT_TEST_FAIL = 10
BROKE_STRICT_TEST_FAIL_BY_DEFEAT = 11
BROKE_STRICT_TEST_PASS_BY_VICTORY = 12
def __str__(self):
return str(self.value) + ' ' + self.name
@ -188,7 +191,12 @@ class WesnothRunner:
if self.verbose >= Verbosity.NAMES_OF_TESTS_RUN:
print('Skipping test', test_list[0].name, 'because timeout is disabled')
return
if expected_result == UnitTestResult.FAIL_BROKE_STRICT and not options.strict_mode:
if (
expected_result == UnitTestResult.BROKE_STRICT_TEST_PASS or
expected_result == UnitTestResult.BROKE_STRICT_TEST_FAIL or
expected_result == UnitTestResult.BROKE_STRICT_TEST_FAIL_BY_DEFEAT or
expected_result == UnitTestResult.BROKE_STRICT_TEST_PASS_BY_VICTORY
) and not options.strict_mode:
test_summary.skip_test(test_list)
if self.verbose >= Verbosity.NAMES_OF_TESTS_RUN:
print('Skipping test', test_list[0].name, 'because strict mode is disabled')

View File

@ -37,6 +37,9 @@ static lg::log_domain log_ai_configuration("ai/config");
#define WRN_AI_CONFIGURATION LOG_STREAM(warn, log_ai_configuration)
#define ERR_AI_CONFIGURATION LOG_STREAM(err, log_ai_configuration)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
void configuration::init(const game_config_view &game_config)
{
ai_configurations_.clear();
@ -292,7 +295,8 @@ void configuration::expand_simplified_aspects(side_number side, config &cfg) {
algorithm = aiparam["ai_algorithm"].str();
base_config = get_ai_config_for(algorithm);
} else if(algorithm != aiparam["ai_algorithm"]) {
lg::wml_error() << "side " << side << " has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.\n";
lg::log_to_chat() << "side " << side << " has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.\n";
ERR_WML << "side " << side << " has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.";
}
}
std::deque<std::pair<std::string, config>> facet_configs;

View File

@ -49,6 +49,9 @@ static lg::log_domain log_ai_recruitment("ai/recruitment");
#define LOG_AI_RECRUITMENT LOG_STREAM(info, log_ai_recruitment)
#define ERR_AI_RECRUITMENT LOG_STREAM(err, log_ai_recruitment)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace ai {
namespace default_recruitment {
@ -246,7 +249,8 @@ void recruitment::execute() {
// Add team recruits.
for (const std::string& recruit : current_team().recruits()) {
if (!unit_types.find(recruit)) {
lg::wml_error() << "Unit-type \"" << recruit << "\" doesn't exist.\n";
lg::log_to_chat() << "Unit-type \"" << recruit << "\" doesn't exist.\n";
ERR_WML << "Unit-type \"" << recruit << "\" doesn't exist.";
}
data.recruits.insert(recruit);
data.scores[recruit] = 0.0;
@ -256,7 +260,8 @@ void recruitment::execute() {
// Add extra recruits.
for (const std::string& recruit : leader->recruits()) {
if (!unit_types.find(recruit)) {
lg::wml_error() << "Unit-type \"" << recruit << "\" doesn't exist.\n";
lg::log_to_chat() << "Unit-type \"" << recruit << "\" doesn't exist.\n";
ERR_WML << "Unit-type \"" << recruit << "\" doesn't exist.";
}
data.recruits.insert(recruit);
data.scores[recruit] = 0.0;

View File

@ -38,6 +38,9 @@ static lg::log_domain log_config("config");
#define ERR_CF LOG_STREAM(err, log_config)
#define DBG_CF LOG_STREAM(debug, log_config)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace
{
// std::map::operator[] does not support heterogeneous lookup so we need this to work around.
@ -217,7 +220,8 @@ bool config::has_old_attribute(config_key_type key, const std::string& old_key,
return true;
} else if(values_.find(old_key) != values_.end()) {
if(!msg.empty()) {
lg::wml_error() << msg;
lg::log_to_chat() << msg << '\n';
ERR_WML << msg;
}
return true;
@ -799,7 +803,8 @@ const config::attribute_value& config::get_old_attribute(
const std::string what = formatter() << "[" << in_tag << "]" << old_key << "=";
const std::string msg = formatter() << "Use " << key << "= instead.";
deprecated_message(what, DEP_LEVEL::INDEFINITE, "", msg);
lg::wml_error() << msg;
lg::log_to_chat() << msg << '\n';
ERR_WML << msg;
}
return i->second;

View File

@ -78,10 +78,9 @@ std::string deprecated_message(
if(log_ptr && !log_ptr->dont_log(log_deprecate)) {
const lg::logger& out_log = *log_ptr;
FORCE_LOG_TO(out_log, log_deprecate) << message << '\n';
// show deprecation warnings if enabled or if this is a development (odd numbered) release
if(preferences::get("show_deprecation", false) || game_config::wesnoth_version.is_dev_version()) {
lg::wml_error() << message << '\n';
// whether to show the error in the ingame chat area
if(preferences::get("show_deprecation", game_config::wesnoth_version.is_dev_version())) {
lg::log_to_chat() << message << '\n';
}
}

View File

@ -613,7 +613,8 @@ WML_HANDLER_FUNCTION(replace_map,, cfg)
}
} catch(const incorrect_map_format_error&) {
const std::string log_map_name = cfg["map"].empty() ? cfg["map_file"] : std::string("from inline data");
lg::wml_error() << "replace_map: Unable to load map " << log_map_name << std::endl;
lg::log_to_chat() << "replace_map: Unable to load map " << log_map_name << '\n';
ERR_WML << "replace_map: Unable to load map " << log_map_name;
return;
} catch(const wml_exception& e) {
e.show();
@ -623,7 +624,8 @@ WML_HANDLER_FUNCTION(replace_map,, cfg)
if (map.total_width() > game_map->total_width()
|| map.total_height() > game_map->total_height()) {
if (!cfg["expand"].to_bool()) {
lg::wml_error() << "replace_map: Map dimension(s) increase but expand is not set" << std::endl;
lg::log_to_chat() << "replace_map: Map dimension(s) increase but expand is not set\n";
ERR_WML << "replace_map: Map dimension(s) increase but expand is not set";
return;
}
}
@ -631,7 +633,8 @@ WML_HANDLER_FUNCTION(replace_map,, cfg)
if (map.total_width() < game_map->total_width()
|| map.total_height() < game_map->total_height()) {
if (!cfg["shrink"].to_bool()) {
lg::wml_error() << "replace_map: Map dimension(s) decrease but shrink is not set" << std::endl;
lg::log_to_chat() << "replace_map: Map dimension(s) decrease but shrink is not set\n";
ERR_WML << "replace_map: Map dimension(s) decrease but shrink is not set";
return;
}
}
@ -639,7 +642,8 @@ WML_HANDLER_FUNCTION(replace_map,, cfg)
std::optional<std::string> errmsg = resources::gameboard->replace_map(map);
if (errmsg) {
lg::wml_error() << *errmsg << std::endl;
lg::log_to_chat() << *errmsg << '\n';
ERR_WML << *errmsg;
}
display::get_singleton()->reload_map();

View File

@ -37,6 +37,9 @@
static lg::log_domain log_engine("engine");
#define WRN_NG LOG_STREAM(warn, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
// This file is in the game_events namespace.
namespace game_events {
@ -94,16 +97,19 @@ namespace builtin_conditions {
bool variable_matches(const vconfig& values)
{
if(values["name"].blank()) {
lg::wml_error() << "[variable] with missing name=\n";
lg::log_to_chat() << "[variable] with missing name=\n";
ERR_WML << "[variable] with missing name=";
return true;
}
const std::string name = values["name"];
config::attribute_value value = resources::gamedata->get_variable_const(name);
if(auto n = values.get_config().attribute_count(); n > 2) {
lg::wml_error() << "[variable] name='" << name << "' found with multiple comparison attributes\n";
lg::log_to_chat() << "[variable] name='" << name << "' found with multiple comparison attributes\n";
ERR_WML << "[variable] name='" << name << "' found with multiple comparison attributes";
} else if(n < 2) {
lg::wml_error() << "[variable] name='" << name << "' found with no comparison attribute\n";
lg::log_to_chat() << "[variable] name='" << name << "' found with no comparison attribute\n";
ERR_WML << "[variable] name='" << name << "' found with no comparison attribute";
}
#define TEST_STR_ATTR(name, test) \

View File

@ -31,6 +31,9 @@ static lg::log_domain log_engine("engine");
static lg::log_domain log_event_handler("event_handler");
#define DBG_EH LOG_STREAM(debug, log_event_handler)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace game_events
{
void event_handlers::log_handlers()
@ -110,7 +113,8 @@ void event_handlers::add_event_handler(const config& cfg, bool is_menu_item)
}
if(name.empty() && id.empty()) {
lg::wml_error() << "[event] is missing name or id field\n";
lg::log_to_chat() << "[event] is missing name or id field\n";
ERR_WML << "[event] is missing name or id field";
return;
}

View File

@ -343,9 +343,11 @@ void wml_event_pump::fill_wml_messages_map(std::map<std::string, int>& msg_map,
* the number of times that message was encountered.
* The order in which the messages are shown does not need
* to be the order in which these messages are encountered.
* Messages are also written to std::cerr if to_cerr is true.
*
* @param source The source to be parsed before being displayed.
* @param caption The text to display before each message parsed from @a source.
*/
void wml_event_pump::show_wml_messages(std::stringstream& source, const std::string& caption, bool to_cerr)
void wml_event_pump::show_wml_messages(std::stringstream& source, const std::string& caption)
{
// Get all unique messages in messages,
// with the number of encounters for these messages
@ -362,10 +364,6 @@ void wml_event_pump::show_wml_messages(std::stringstream& source, const std::str
game_display::get_singleton()->get_chat_manager().add_chat_message(
std::time(nullptr), caption, 0, msg.str(), events::chat_handler::MESSAGE_PUBLIC, false);
if(to_cerr) {
std::cerr << caption << ": " << msg.str() << '\n';
}
}
}
@ -380,9 +378,7 @@ void wml_event_pump::show_wml_messages(std::stringstream& source, const std::str
*/
void wml_event_pump::show_wml_errors()
{
static const std::string caption("Invalid WML found");
show_wml_messages(lg::wml_error(), caption, true);
show_wml_messages(lg::log_to_chat(), "");
}
/**
@ -394,9 +390,7 @@ void wml_event_pump::show_wml_errors()
*/
void wml_event_pump::show_wml_messages()
{
static const std::string caption("WML");
show_wml_messages(impl_->wml_messages_stream, caption, false);
show_wml_messages(impl_->wml_messages_stream, "WML: ");
}
void wml_event_pump::put_wml_message(

View File

@ -148,7 +148,7 @@ private:
void fill_wml_messages_map(std::map<std::string, int>& msg_map, std::stringstream& source);
void show_wml_messages(std::stringstream& source, const std::string& caption, bool to_cerr);
void show_wml_messages(std::stringstream& source, const std::string& caption);
void show_wml_errors();

View File

@ -513,9 +513,6 @@ game_launcher::unit_test_result game_launcher::unit_test()
case unit_test_result::TEST_FAIL_PLAYING_REPLAY:
describe_result = "FAIL TEST (ERRORED REPLAY)";
break;
case unit_test_result::TEST_FAIL_BROKE_STRICT:
describe_result = "FAIL TEST (BROKE STRICT)";
break;
case unit_test_result::TEST_FAIL_WML_EXCEPTION:
describe_result = "FAIL TEST (WML EXCEPTION)";
break;
@ -525,8 +522,20 @@ game_launcher::unit_test_result game_launcher::unit_test()
case unit_test_result::TEST_PASS_BY_VICTORY:
describe_result = "PASS TEST (VICTORY)";
break;
case unit_test_result::BROKE_STRICT_TEST_PASS:
describe_result = "BROKE STRICT (PASS)";
break;
case unit_test_result::BROKE_STRICT_TEST_FAIL:
describe_result = "BROKE STRICT (FAIL)";
break;
case unit_test_result::BROKE_STRICT_TEST_FAIL_BY_DEFEAT:
describe_result = "BROKE STRICT (DEFEAT)";
break;
case unit_test_result::BROKE_STRICT_TEST_PASS_BY_VICTORY:
describe_result = "BROKE STRICT (VICTORY)";
break;
default:
describe_result = "FAIL TEST";
describe_result = "FAIL TEST (UNKNOWN)";
break;
}
@ -547,13 +556,12 @@ game_launcher::unit_test_result game_launcher::single_unit_test()
try {
campaign_controller ccontroller(state_, true);
game_res = ccontroller.play_game();
// TODO: How to handle the case where a unit test scenario ends without an explicit {SUCCEED} or {FAIL}?
// ex: check_victory_never_ai_fail results in victory by killing one side's leaders
if(game_res == LEVEL_RESULT::TEST_FAIL) {
return unit_test_result::TEST_FAIL;
}
if(lg::broke_strict()) {
return unit_test_result::TEST_FAIL_BROKE_STRICT;
if(lg::broke_strict()) {
return unit_test_result::BROKE_STRICT_TEST_FAIL;
} else {
return unit_test_result::TEST_FAIL;
}
}
} catch(const wml_exception& e) {
std::cerr << "Caught WML Exception:" << e.dev_message << std::endl;
@ -578,9 +586,10 @@ game_launcher::unit_test_result game_launcher::single_unit_test()
}
try {
const bool was_strict_broken = lg::broke_strict();
campaign_controller ccontroller(state_, true);
ccontroller.play_replay();
if(lg::broke_strict()) {
if(!was_strict_broken && lg::broke_strict()) {
std::cerr << "Observed failure on replay" << std::endl;
return unit_test_result::TEST_FAIL_PLAYING_REPLAY;
}
@ -595,12 +604,24 @@ game_launcher::unit_test_result game_launcher::single_unit_test()
game_launcher::unit_test_result game_launcher::pass_victory_or_defeat(LEVEL_RESULT res)
{
if(res == LEVEL_RESULT::DEFEAT) {
return unit_test_result::TEST_FAIL_BY_DEFEAT;
if(lg::broke_strict()) {
return unit_test_result::BROKE_STRICT_TEST_FAIL_BY_DEFEAT;
} else {
return unit_test_result::TEST_FAIL_BY_DEFEAT;
}
} else if(res == LEVEL_RESULT::VICTORY) {
return unit_test_result::TEST_PASS_BY_VICTORY;
if(lg::broke_strict()) {
return unit_test_result::BROKE_STRICT_TEST_PASS_BY_VICTORY;
} else {
return unit_test_result::TEST_PASS_BY_VICTORY;
}
}
return unit_test_result::TEST_PASS;
if(lg::broke_strict()) {
return unit_test_result::BROKE_STRICT_TEST_PASS;
} else {
return unit_test_result::TEST_PASS;
}
}
bool game_launcher::play_screenshot_mode()

View File

@ -70,10 +70,14 @@ public:
// 2 is reserved for timeouts
TEST_FAIL_LOADING_REPLAY = 3,
TEST_FAIL_PLAYING_REPLAY = 4,
TEST_FAIL_BROKE_STRICT = 5,
//TEST_FAIL_BROKE_STRICT = 5,
TEST_FAIL_WML_EXCEPTION = 6,
TEST_FAIL_BY_DEFEAT = 7,
TEST_PASS_BY_VICTORY = 8,
BROKE_STRICT_TEST_PASS = 9,
BROKE_STRICT_TEST_FAIL = 10,
BROKE_STRICT_TEST_FAIL_BY_DEFEAT = 11,
BROKE_STRICT_TEST_PASS_BY_VICTORY = 12,
};
bool init_video();

View File

@ -27,6 +27,9 @@
static lg::log_domain log_engine("engine");
#define LOG_NG LOG_STREAM(info, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
cave_map_generator::cave_map_generator(const config &cfg) :
wall_(t_translation::CAVE_WALL),
clear_(t_translation::CAVE),
@ -160,7 +163,8 @@ void cave_map_generator::cave_map_generator_job::generate_chambers()
min_xpos = std::stoi(items.front()) - 1;
max_xpos = std::stoi(items.back());
} catch(const std::invalid_argument&) {
lg::wml_error() << "Invalid min/max coordinates in cave_map_generator: " << items.front() << ", " << items.back() << "\n";
lg::log_to_chat() << "Invalid min/max coordinates in cave_map_generator: " << items.front() << ", " << items.back() << "\n";
ERR_WML << "Invalid min/max coordinates in cave_map_generator: " << items.front() << ", " << items.back();
continue;
}
}
@ -173,7 +177,8 @@ void cave_map_generator::cave_map_generator_job::generate_chambers()
min_ypos = std::stoi(items.front()) - 1;
max_ypos = std::stoi(items.back());
} catch(const std::invalid_argument&) {
lg::wml_error() << "Invalid min/max coordinates in cave_map_generator: " << items.front() << ", " << items.back() << "\n";
lg::log_to_chat() << "Invalid min/max coordinates in cave_map_generator: " << items.front() << ", " << items.back() << "\n";
ERR_WML << "Invalid min/max coordinates in cave_map_generator: " << items.front() << ", " << items.back();
}
}
}

View File

@ -26,6 +26,9 @@
#include <functional>
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace gui2
{
@ -231,7 +234,8 @@ builder_stacked_widget::builder_stacked_widget(const config& real_cfg)
{
const config& cfg = real_cfg.has_child("stack") ? real_cfg.child("stack") : real_cfg;
if(&cfg != &real_cfg) {
lg::wml_error() << "Stacked widgets no longer require a [stack] tag. Instead, place [layer] tags directly in the widget definition.\n";
lg::log_to_chat() << "Stacked widgets no longer require a [stack] tag. Instead, place [layer] tags directly in the widget definition.\n";
ERR_WML << "Stacked widgets no longer require a [stack] tag. Instead, place [layer] tags directly in the widget definition.";
}
VALIDATE(cfg.has_child("layer"), _("No stack layers defined."));
for(const auto & layer : cfg.child_range("layer"))

View File

@ -285,7 +285,7 @@ void scope_logger::do_log_exit() noexcept
output | formatter() << "} END: " << str_ << " (took " << ticks << "ms)\n";
}
std::stringstream& wml_error()
std::stringstream& log_to_chat()
{
static std::stringstream lg;
return lg;

View File

@ -60,6 +60,14 @@
namespace lg {
enum severity
{
LG_ERROR=0,
LG_WARN=1,
LG_INFO=2,
LG_DEBUG=3
};
/**
* Helper class to redirect the output of the logger in a certain scope.
*
@ -142,6 +150,14 @@ public:
return severity_ > domain.domain_->second;
}
/**
* Returns following values depending on the logger:
* error: 0
* warn: 1
* info: 2
* debug: 3
* See also the lg::severity enum.
*/
int get_severity() const
{
return severity_;
@ -191,15 +207,10 @@ private:
};
/**
* Use this logger to send errors due to deprecated WML.
* The preferred format is:
* xxx is deprecated; support will be removed in version X. or
* xxx is deprecated; support has been removed in version X.
*
* After every wml-event the errors are shown to the user,
* so they can inform the campaign maintainer.
* Use this to show WML errors in the ingame chat.
* After every WML event the errors are shown to the user so they can inform the campaign maintainer.
*/
std::stringstream& wml_error();
std::stringstream& log_to_chat();
} // namespace lg

View File

@ -53,6 +53,9 @@ static lg::log_domain log_engine("engine");
#define ERR_NG LOG_STREAM(err, log_engine)
#define LOG_NG LOG_STREAM(info, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace events
{
mouse_handler::mouse_handler(game_display* gui, play_controller& pc)
@ -1296,7 +1299,8 @@ void mouse_handler::attack_enemy(const map_location& attacker_loc, const map_loc
try {
attack_enemy_(attacker_loc, defender_loc, choice);
} catch(const std::bad_alloc&) {
lg::wml_error() << "Memory exhausted a unit has either a lot hitpoints or a negative amount.\n";
lg::log_to_chat() << "Memory exhausted a unit has either a lot hitpoints or a negative amount.\n";
ERR_WML << "Memory exhausted a unit has either a lot hitpoints or a negative amount.";
}
}

View File

@ -28,6 +28,9 @@
static lg::log_domain log_engine("engine");
#define ERR_PF LOG_STREAM(err, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace pathfind {
@ -287,7 +290,8 @@ manager::manager(const config &cfg) : tunnels_(), id_(cfg["next_teleport_group_i
for(int i = 0; i < tunnel_count; ++i) {
const config& t = cfg.child("tunnel", i);
if(!t["saved"].to_bool()) {
lg::wml_error() << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.\n";
lg::log_to_chat() << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.\n";
ERR_WML << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.";
continue;
}
const teleport_group tunnel(t);

View File

@ -136,6 +136,9 @@ static lg::log_domain log_scripting_lua("scripting/lua");
#define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
std::vector<config> game_lua_kernel::preload_scripts;
config game_lua_kernel::preload_config;
@ -4164,7 +4167,8 @@ int game_lua_kernel::intf_log(lua_State *L)
const std::string& msg = lua_isstring(L, 2) ? luaL_checkstring(L, 2) : luaL_checkstring(L, 1);
if(logger == "wml" || logger == "WML") {
lg::wml_error() << msg << '\n';
lg::log_to_chat() << msg << '\n';
ERR_WML << msg;
} else {
bool in_chat = luaW_toboolean(L, -1);
game_state_.events_manager_->pump().put_wml_message(logger,msg,in_chat);
@ -5035,7 +5039,8 @@ bool game_lua_kernel::run_wml_conditional(const std::string& cmd, const vconfig&
// If an invalid coniditional tag is used, consider it a pass.
if(!luaW_getglobal(L, "wesnoth", "wml_conditionals", cmd)) {
lg::wml_error() << "unknown conditional wml: [" << cmd << "]\n";
lg::log_to_chat() << "unknown conditional wml: [" << cmd << "]\n";
ERR_WML << "unknown conditional wml: [" << cmd << "]";
return true;
}

View File

@ -53,6 +53,9 @@ static lg::log_domain log_scripting_lua("scripting/lua");
#define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace lua_common {
/**
@ -1124,7 +1127,8 @@ bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
if (allow_wml_error && strncmp(m, "~wml:", 5) == 0) {
m += 5;
char const *e = strstr(m, "stack traceback");
lg::wml_error() << std::string(m, e ? e - m : strlen(m));
lg::log_to_chat() << std::string(m, e ? e - m : strlen(m)) << '\n';
ERR_WML << std::string(m, e ? e - m : strlen(m));
} else if (allow_wml_error && strncmp(m, "~lua:", 5) == 0) {
m += 5;
char const *e = nullptr, *em = m;

View File

@ -39,6 +39,9 @@
static lg::log_domain log_engine_sf("engine/side_filter");
#define ERR_NG LOG_STREAM(err, log_engine_sf)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
side_filter::~side_filter() {}
side_filter::side_filter(const vconfig& cfg, const filter_context * fc, bool flat_tod)
@ -239,7 +242,8 @@ bool side_filter::match_internal(const team &t) const
}
return true;
} catch(const wfl::formula_error& e) {
lg::wml_error() << "Formula error in side filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
lg::log_to_chat() << "Formula error in side filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
ERR_WML << "Formula error in side filter: " << e.type << " at " << e.filename << ':' << e.line << ")";
// Formulae with syntax errors match nothing
return false;
}

View File

@ -40,6 +40,9 @@ static lg::log_domain log_engine("engine");
#define ERR_NG LOG_STREAM(err, log_engine)
#define WRN_NG LOG_STREAM(warn, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
terrain_filter::~terrain_filter()
{
}
@ -346,7 +349,8 @@ bool terrain_filter::match_internal(const map_location& loc, const unit* ref_uni
}
return true;
} catch(const wfl::formula_error& e) {
lg::wml_error() << "Formula error in location filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
lg::log_to_chat() << "Formula error in location filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
ERR_WML << "Formula error in location filter: " << e.type << " at " << e.filename << ':' << e.line << ")";
// Formulae with syntax errors match nothing
return false;
}

View File

@ -45,6 +45,9 @@
static lg::log_domain log_engine("engine");
#define ERR_NG LOG_STREAM(err, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
namespace {
class temporary_facing
{
@ -536,7 +539,8 @@ T get_single_ability_value(const config::attribute_value& v, T def, const unit_a
}
return formula_handler(wfl::formula(s, new wfl::gamestate_function_symbol_table), callable);
} catch(const wfl::formula_error& e) {
lg::wml_error() << "Formula error in ability or weapon special: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
lg::log_to_chat() << "Formula error in ability or weapon special: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
ERR_WML << "Formula error in ability or weapon special: " << e.type << " at " << e.filename << ':' << e.line << ")";
return def;
}
}));

View File

@ -43,6 +43,9 @@ static lg::log_domain log_unit("unit");
#define DBG_UT LOG_STREAM(debug, log_unit)
#define ERR_UT LOG_STREAM(err, log_unit)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
attack_type::attack_type(const config& cfg) :
self_loc_(),
other_loc_(),
@ -222,7 +225,8 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil
return false;
}
} catch(const wfl::formula_error& e) {
lg::wml_error() << "Formula error in weapon filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
lg::log_to_chat() << "Formula error in weapon filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
ERR_WML << "Formula error in weapon filter: " << e.type << " at " << e.filename << ':' << e.line << ")";
// Formulae with syntax errors match nothing
return false;
}

View File

@ -42,6 +42,9 @@ static lg::log_domain log_config("config");
#define WRN_CF LOG_STREAM(warn, log_config)
#define DBG_CF LOG_STREAM(debug, log_config)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
using namespace unit_filter_impl;
unit_filter::unit_filter(vconfig cfg)
@ -712,7 +715,8 @@ void unit_filter_compound::fill(vconfig cfg)
}
return true;
} catch(const wfl::formula_error& e) {
lg::wml_error() << "Formula error in unit filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
lg::log_to_chat() << "Formula error in unit filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
ERR_WML << "Formula error in unit filter: " << e.type << " at " << e.filename << ':' << e.line << ")";
// Formulae with syntax errors match nothing
return false;
}

View File

@ -26,6 +26,9 @@
#include "utils/name_generator.hpp"
#include "utils/name_generator_factory.hpp"
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
/** Dummy race used when a race is not yet known. */
const unit_race unit_race::null_race;
/** Standard string id (not translatable) for FEMALE */
@ -77,10 +80,12 @@ unit_race::unit_race(const config& cfg) :
{
if (id_.empty()) {
lg::wml_error() << "[race] '" << cfg["name"] << "' is missing an id field.";
lg::log_to_chat() << "[race] '" << cfg["name"] << "' is missing an id field.\n";
ERR_WML << "[race] '" << cfg["name"] << "' is missing an id field.";
}
if (plural_name_.empty()) {
lg::wml_error() << "[race] '" << cfg["name"] << "' is missing a plural_name field.";
lg::log_to_chat() << "[race] '" << cfg["name"] << "' is missing a plural_name field.\n";
ERR_WML << "[race] '" << cfg["name"] << "' is missing a plural_name field.";
plural_name_ = (cfg["name"]);
}

View File

@ -28,6 +28,9 @@
#include <boost/algorithm/string.hpp>
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
context_free_grammar_generator::~context_free_grammar_generator()
{
}
@ -143,7 +146,8 @@ std::string context_free_grammar_generator::print_nonterminal(const std::string&
std::map<std::string,nonterminal>::const_iterator found = nonterminals_.find(name);
if (found == nonterminals_.end()) {
lg::wml_error() << "[context_free_grammar_generator] Warning: needed nonterminal" << name << " not defined";
lg::log_to_chat() << "[context_free_grammar_generator] Warning: needed nonterminal " << name << " not defined\n";
ERR_WML << "[context_free_grammar_generator] Warning: needed nonterminal " << name << " not defined";
return "!" + name;
}
const context_free_grammar_generator::nonterminal& got = found->second;

View File

@ -19,6 +19,9 @@
#include "utils/markov_generator.hpp"
#include "formula/string_utils.hpp"
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
std::string name_generator::generate(const std::map<std::string,std::string>& variables) const {
return utils::interpolate_variables_into_string(generate(), &variables);
}
@ -42,7 +45,8 @@ void name_generator_factory::add_name_generator_from_config(const config& config
return;
}
catch (const name_generator_invalid_exception& ex) {
lg::wml_error() << ex.what() << '\n';
lg::log_to_chat() << ex.what() << '\n';
ERR_WML << ex.what();
}
}

View File

@ -29,6 +29,9 @@
static lg::log_domain log_engine("engine");
#define WRN_NG LOG_STREAM(warn, log_engine)
static lg::log_domain log_wml("wml");
#define ERR_WML LOG_STREAM(err, log_wml)
void throw_wml_exception(
const char* cond
, const char* file
@ -149,12 +152,9 @@ const config::attribute_value& get_renamed_config_attribute(
result = cfg.get(deprecated_key);
if(result) {
lg::wml_error()
<< deprecated_renamed_wml_key_warning(
deprecated_key
, key
, removal_version)
<< '\n';
std::string msg = deprecated_renamed_wml_key_warning(deprecated_key, key, removal_version);
lg::log_to_chat() << msg << '\n';
ERR_WML << msg;
return *result;
}

View File

@ -44,7 +44,7 @@
# Security test
#
0 cve_2018_1999023
5 cve_2018_1999023_2
9 cve_2018_1999023_2
#
# Test Check Victory (If this isn't working other tests may have dubious value)
#
@ -76,7 +76,7 @@
# WML API tests
#
0 two_plus_two
1 two_plus_two_fail
10 two_plus_two_fail
0 order_of_nested_events
0 test_clear_one
0 test_clear_two
@ -85,12 +85,12 @@
0 units_offmap_goto_recall
0 recall_by_unit_tag
0 test_move
5 test_move_fail_1
5 test_move_fail_2
5 test_move_fail_3
5 test_move_fail_4
5 test_move_fail_5
5 test_move_fail_6
9 test_move_fail_1
9 test_move_fail_2
9 test_move_fail_3
9 test_move_fail_4
9 test_move_fail_5
9 test_move_fail_6
0 test_move_unit
0 test_move_unit_in_circle
0 sighted_on_move
@ -151,7 +151,7 @@
0 events-test_defeat
0 events-test_die
0 test_store_unit_defense_on
5 test_store_unit_defense_deprecated
9 test_store_unit_defense_deprecated
# Terrain mask tests
0 test_terrain_mask_simple_nop
0 test_terrain_mask_simple_set
@ -266,7 +266,7 @@
# Interface tests
#
0 test_wml_menu_items_1
1 test_wml_menu_items_2
10 test_wml_menu_items_2
0 test_wml_menu_items_3
#
# Conditional tests
@ -278,19 +278,19 @@
0 filter_this_unit_tl
0 filter_this_unit_formula
0 filter_formula_unit
5 filter_formula_unit_error
9 filter_formula_unit_error
# Interrupt tag tests
0 check_interrupts_break
0 check_interrupts_return
0 check_interrupts_continue
0 check_interrupts_break_global
0 check_interrupts_return_nested
0 check_interrupts_continue_global
9 check_interrupts_continue_global
0 check_interrupts_elseif
0 check_interrupts_case
# For-loop tests
0 forloop_all_zero
0 forloop_step_zero
9 forloop_all_zero
9 forloop_step_zero
0 forloop_once_positive
0 forloop_once_negative
0 forloop_twice_matched
@ -336,4 +336,4 @@
# Warnings about WML
0 unknown_scenario_false_positives
0 unknown_scenario_interpolated
5 unknown_scenario_1_0
9 unknown_scenario_1_0