Add a new check to the WML schema self-validator
This warns about tag definitions that can never match any tag (or for which one element of the comma-separated list can never match) because there is an earlier-defined tag definition that would match it instead. The new check also found some errors in the schema, which have been fixed.
This commit is contained in:
parent
23859c6d78
commit
6d7f8e8ce6
4 changed files with 53 additions and 9 deletions
|
@ -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}
|
||||
|
|
|
@ -92,7 +92,6 @@
|
|||
[tag]
|
||||
name="intersection"
|
||||
min=1
|
||||
{LINK_TAG "wml_schema/type"}
|
||||
[tag]
|
||||
name="type"
|
||||
max=infinite
|
||||
|
|
|
@ -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<std::string> 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<reference> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,8 +182,10 @@ private:
|
|||
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 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{
|
||||
|
|
Loading…
Add table
Reference in a new issue