diff --git a/data/schema/core/actionwml.cfg b/data/schema/core/actionwml.cfg index 5613cf344a0e..a7b6113a6dc7 100644 --- a/data/schema/core/actionwml.cfg +++ b/data/schema/core/actionwml.cfg @@ -94,12 +94,7 @@ name="while" max=infinite super="$conditional_wml" - {ACTION_TAG "do" min,max=0,infinite} - [tag] - name="do" - max=infinite - super="$action_wml" - [/tag] + {ACTION_TAG "do" max=infinite} [/tag] [tag] name="for" @@ -261,7 +256,7 @@ {REQUIRED_KEY types string_list} [/tag] [tag] - name="allow_extra recruit,disallow_extra_recruit,set_recruit" + name="allow_extra_recruit,disallow_extra_recruit,set_extra_recruit" max=infinite super="$filter_unit" {INSERT_TAG} diff --git a/data/schema/schema.cfg b/data/schema/schema.cfg index 783ea4101383..fa89236fe14b 100644 --- a/data/schema/schema.cfg +++ b/data/schema/schema.cfg @@ -92,7 +92,6 @@ [tag] name="intersection" min=1 - {LINK_TAG "wml_schema/type"} [tag] name="type" max=infinite diff --git a/src/serialization/schema_validator.cpp b/src/serialization/schema_validator.cpp index 7c95e9e13ff2..c2da3de37e07 100644 --- a/src/serialization/schema_validator.cpp +++ b/src/serialization/schema_validator.cpp @@ -128,6 +128,18 @@ static void wrong_path_error(const std::string& file, print_output(ss.str(), flag_exception); } +static void duplicate_tag_error(const std::string& file, + int line, + const std::string& tag, + const std::string& key, + const std::string& value, + bool flag_exception) +{ + std::ostringstream ss; + ss << "Duplicate or fully-overlapping tag definition '" << value << "' in key '" << key << "=' 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, @@ -446,10 +458,43 @@ 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) +{ + for(const std::string& pat : utils::split(pattern)) { + if(utils::wildcard_string_match(tag, pat)) return true; + } + return false; +} + 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 tag_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; + } + } + } + tag_names.push_back(tag_name); + } } else if(name == "wml_schema") { using namespace std::placeholders; std::vector missing_types = referenced_types_, missing_tags = referenced_tag_paths_; @@ -551,6 +596,9 @@ void schema_self_validator::print(message_info& el) case WRONG_PATH: wrong_path_error(el.file, el.line, el.tag, el.key, el.value, create_exceptions_); break; + case DUPLICATE_TAG: + duplicate_tag_error(el.file, el.line, el.tag, el.key, el.value, create_exceptions_); + break; } } diff --git a/src/serialization/schema_validator.hpp b/src/serialization/schema_validator.hpp index 2a2128194905..9de368adecf9 100644 --- a/src/serialization/schema_validator.hpp +++ b/src/serialization/schema_validator.hpp @@ -182,8 +182,10 @@ class schema_self_validator : public schema_validator std::multimap 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 print(message_info& message) override; - enum { WRONG_TYPE = NEXT_ERROR, WRONG_PATH, NEXT_ERROR }; + enum { WRONG_TYPE = NEXT_ERROR, WRONG_PATH, DUPLICATE_TAG, NEXT_ERROR }; }; } // namespace schema_validation{