Skip to content

Commit

Permalink
The method of detecting duplicate/overlapping schema tags is now appl…
Browse files Browse the repository at this point in the history
…ied also to keys.

This detected one genuine error in the schema, so yay!
  • Loading branch information
CelticMinstrel committed Oct 24, 2020
1 parent 8266e0f commit a184b39
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 29 deletions.
1 change: 0 additions & 1 deletion data/schema/core/addons.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@
super="$addon"
{ADDON_DESCRIPTION}
{SIMPLE_KEY next_scenario string}
{SIMPLE_KEY name t_string}
{SIMPLE_KEY map_data map_data}
{SIMPLE_KEY map_file string}
{DEFAULT_KEY turns turns unlimited}
Expand Down
2 changes: 1 addition & 1 deletion data/schema/core/config.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,6 @@
{SIMPLE_KEY mouse string}
{DEFAULT_KEY ctrl bool no}
{DEFAULT_KEY alt bool no}
{DEFAULT_KEY command bool no}
{DEFAULT_KEY cmd bool no}
{DEFAULT_KEY shift bool no}
[/tag]
4 changes: 2 additions & 2 deletions data/schema/units/animations.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
{SIMPLE_KEY {PREFIX}blend_ratio prog_real}
{SIMPLE_KEY {PREFIX}text string}
{SIMPLE_KEY {PREFIX}text_color color}
{SIMPLE_KEY {PREFIX}x prog_int}
{SIMPLE_KEY {PREFIX}y prog_int}
{SIMPLE_KEY {PREFIX}directional_x prog_int}
{SIMPLE_KEY {PREFIX}directional_y prog_int}
{SIMPLE_KEY {PREFIX}x prog_int}
{SIMPLE_KEY {PREFIX}y prog_int}
{SIMPLE_KEY {PREFIX}layer prog_int}
{SIMPLE_KEY {PREFIX}auto_hflip bool}
{SIMPLE_KEY {PREFIX}auto_vflip bool}
Expand Down
1 change: 0 additions & 1 deletion data/schema/units/single.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
{SIMPLE_KEY max_hitpoints s_int}
{SIMPLE_KEY max_experience s_int}
{SIMPLE_KEY max_moves s_int}
{SIMPLE_KEY vision s_int}
{SIMPLE_KEY max_attacks s_int}
{SIMPLE_KEY profile string}
{SIMPLE_KEY small_profile string}
Expand Down
72 changes: 50 additions & 22 deletions src/serialization/schema_validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ static void duplicate_tag_error(const std::string& file,
print_output(ss.str(), flag_exception);
}

static void duplicate_key_error(const std::string& file,
int line,
const std::string& tag,
const std::string& pat,
const std::string& value,
bool flag_exception)
{
std::ostringstream ss;
ss << "Duplicate or fully-overlapping key definition '" << value << "' (which is also matched by '" << pat << "') in tag [" << tag << "]\n" << at(file, line) << "\n";
print_output(ss.str(), flag_exception);
}

static void wrong_type_error(const std::string & file, int line,
const std::string & tag,
const std::string & key,
Expand Down Expand Up @@ -468,42 +480,55 @@ bool schema_self_validator::tag_path_exists(const config& cfg, const reference&
return false;
}

bool schema_self_validator::tag_matches(const std::string& pattern, const std::string& tag)
bool schema_self_validator::name_matches(const std::string& pattern, const std::string& name)
{
for(const std::string& pat : utils::split(pattern)) {
if(utils::wildcard_string_match(tag, pat)) return true;
if(utils::wildcard_string_match(name, pat)) return true;
}
return false;
}

void schema_self_validator::check_for_duplicates(const std::string& name, std::vector<std::string>& seen, const config& cfg, message_type type, const std::string& file, int line, const std::string& tag) {
auto split = utils::split(name);
for(const std::string& pattern : seen) {
for(const std::string& key : split) {
if(name_matches(pattern, key)) {
queue_message(cfg, type, file, line, 0, tag, pattern, name);
continue;
}
}
}
seen.push_back(name);
}

void schema_self_validator::validate(const config& cfg, const std::string& name, int start_line, const std::string& file)
{
if(type_nesting_ == 1 && name == "type") {
defined_types_.insert(cfg["name"]);
} else if(name == "tag") {
bool first = true;
std::vector<std::string> tag_names;
bool first_tag = true, first_key = true;
std::vector<std::string> tag_names, key_names;
for(auto current : cfg.all_children_range()) {
if(current.key != "tag" && current.key != "link") continue;
std::string tag_name = current.cfg["name"];
if(current.key == "link") {
tag_name.erase(0, tag_name.find_last_of('/') + 1);
}
if(first) {
tag_names.push_back(tag_name);
first = false;
continue;
}
auto split = utils::split(tag_name);
for(const std::string& pattern : tag_names) {
for(const std::string& tag : split) {
if(tag_matches(pattern, tag)) {
queue_message(current.cfg, DUPLICATE_TAG, file, start_line, 0, current.key, "name", tag_name);
continue;
}
if(current.key == "tag" || current.key == "link") {
std::string tag_name = current.cfg["name"];
if(current.key == "link") {
tag_name.erase(0, tag_name.find_last_of('/') + 1);
}
if(first_tag) {
tag_names.push_back(tag_name);
first_tag = false;
continue;
}
check_for_duplicates(tag_name, tag_names, current.cfg, DUPLICATE_TAG, file, start_line, current.key);
} else if(current.key == "key") {
std::string key_name = current.cfg["name"];
if(first_key) {
key_names.push_back(key_name);
first_key = false;
continue;
}
check_for_duplicates(key_name, key_names, current.cfg, DUPLICATE_KEY, file, start_line, current.key);
}
tag_names.push_back(tag_name);
}
} else if(name == "wml_schema") {
using namespace std::placeholders;
Expand Down Expand Up @@ -610,6 +635,9 @@ void schema_self_validator::print(message_info& el)
case DUPLICATE_TAG:
duplicate_tag_error(el.file, el.line, el.tag, el.key, el.value, create_exceptions_);
break;
case DUPLICATE_KEY:
duplicate_key_error(el.file, el.line, el.tag, el.key, el.value, create_exceptions_);
break;
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/serialization/schema_validator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,11 @@ class schema_self_validator : public schema_validator
std::multimap<std::string, std::string> derivations_;
int type_nesting_, condition_nesting_;
bool tag_path_exists(const config& cfg, const reference& ref);
static bool tag_matches(const std::string& pattern, const std::string& tag);
void check_for_duplicates(const std::string& name, std::vector<std::string>& seen, const config& cfg, message_type type, const std::string& file, int line, const std::string& tag);
static bool name_matches(const std::string& pattern, const std::string& name);

void print(message_info& message) override;
enum { WRONG_TYPE = NEXT_ERROR, WRONG_PATH, DUPLICATE_TAG, NEXT_ERROR };
enum { WRONG_TYPE = NEXT_ERROR, WRONG_PATH, DUPLICATE_TAG, DUPLICATE_KEY, NEXT_ERROR };
};

} // namespace schema_validation{

0 comments on commit a184b39

Please sign in to comment.