Compare commits

...

15 Commits

Author SHA1 Message Date
Richard Menzies
9b5401e075
Merge d7d94625b0 into 533c616cb8 2024-10-22 22:13:37 +02:00
Clay John
533c616cb8
Merge pull request #98391 from RandomShaper/rd_thread_switch
Some checks are pending
🔗 GHA / 📊 Static checks (push) Waiting to run
🔗 GHA / 🤖 Android (push) Blocked by required conditions
🔗 GHA / 🍏 iOS (push) Blocked by required conditions
🔗 GHA / 🐧 Linux (push) Blocked by required conditions
🔗 GHA / 🍎 macOS (push) Blocked by required conditions
🔗 GHA / 🏁 Windows (push) Blocked by required conditions
🔗 GHA / 🌐 Web (push) Blocked by required conditions
🔗 GHA / 🪲 Godot CPP (push) Blocked by required conditions
Implement thread ownership change for RenderingDevice
2024-10-22 13:10:32 -07:00
Pedro J. Estébanez
d5d509bbd6 Implement thread ownership change for RenderingDevice 2024-10-21 20:56:42 +02:00
Richard Menzies
d7d94625b0 Free object at end of test 2024-10-20 01:35:11 +01:00
Richard Menzies
3c39471f8f Add tests for Godot types 2024-10-20 00:29:56 +01:00
Richard Menzies
befd41ba91 Fix formatting errors 2024-10-18 00:12:23 +01:00
Richard Menzies
b50c88b590 Fix dictionary variable matching dictionary 2024-09-18 23:05:24 +01:00
Richard Menzies
b93e188919 Fix formatting 2024-09-18 19:24:53 +01:00
Richard Menzies
4fe6f4bbf1 Add mismatched type doc 2024-09-18 19:24:53 +01:00
Richard Menzies
cefd96fd1a Fix existing tests 2024-09-18 19:24:53 +01:00
Richard Menzies
d5bc65be99 Fix formatting 2024-09-18 19:24:53 +01:00
Richard Menzies
d9af0c0e10 Fix warnings 2024-09-18 19:24:53 +01:00
Richard Menzies
50c03957fb Fix formatting errors 2024-09-18 19:24:53 +01:00
Richard Menzies
d819ca8877 Fix warnings 2024-09-18 19:24:53 +01:00
Richard Menzies
ec6ff764ca Add match warnings 2024-09-18 19:24:53 +01:00
9 changed files with 7382 additions and 0 deletions

View File

@ -528,6 +528,9 @@
<member name="debug/gdscript/warnings/integer_division" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when dividing an integer by another integer (the decimal part will be discarded).
</member>
<member name="debug/gdscript/warnings/mismatched_type" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a match pattern cannot match a match expression.
</member>
<member name="debug/gdscript/warnings/missing_tool" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when the base class script has the [code]@tool[/code] annotation, but the current class script does not have it.
</member>

View File

@ -2427,6 +2427,413 @@ void GDScriptAnalyzer::resolve_match_pattern(GDScriptParser::PatternNode *p_matc
}
p_match_pattern->set_datatype(result);
#ifdef DEBUG_ENABLED
if (p_match_test != nullptr && (p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT || p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED) && (p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT || p_match_pattern->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED) && p_match_pattern->pattern_type != GDScriptParser::PatternNode::PT_REST && p_match_pattern->pattern_type != GDScriptParser::PatternNode::PT_BIND && p_match_pattern->pattern_type != GDScriptParser::PatternNode::PT_WILDCARD) {
switch (p_match_test->get_datatype().builtin_type) {
case Variant::NIL:
case Variant::VARIANT_MAX:
break;
case Variant::BOOL:
case Variant::INT:
case Variant::FLOAT:
case Variant::VECTOR2:
case Variant::VECTOR2I:
case Variant::RECT2:
case Variant::RECT2I:
case Variant::VECTOR3:
case Variant::VECTOR3I:
case Variant::TRANSFORM2D:
case Variant::VECTOR4:
case Variant::VECTOR4I:
case Variant::PLANE:
case Variant::QUATERNION:
case Variant::AABB:
case Variant::BASIS:
case Variant::TRANSFORM3D:
case Variant::PROJECTION:
case Variant::COLOR:
case Variant::NODE_PATH:
case Variant::RID:
case Variant::CALLABLE:
case Variant::SIGNAL:
case Variant::OBJECT:
case Variant::PACKED_BYTE_ARRAY:
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY:
case Variant::PACKED_FLOAT32_ARRAY:
case Variant::PACKED_FLOAT64_ARRAY:
case Variant::PACKED_STRING_ARRAY:
case Variant::PACKED_VECTOR2_ARRAY:
case Variant::PACKED_VECTOR3_ARRAY:
case Variant::PACKED_COLOR_ARRAY:
case Variant::PACKED_VECTOR4_ARRAY:
if (p_match_pattern->get_datatype() != p_match_test->get_datatype()) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "", "", "");
}
break;
case Variant::STRING:
case Variant::STRING_NAME:
if (p_match_pattern->get_datatype().builtin_type != Variant::STRING && p_match_pattern->get_datatype().builtin_type != Variant::STRING_NAME) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "", "", "");
}
break;
case Variant::DICTIONARY:
if (p_match_pattern->get_datatype() != p_match_test->get_datatype()) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "", "", "");
break;
}
if (p_match_pattern->pattern_type == GDScriptParser::PatternNode::Type::PT_ARRAY) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::ARRAY), p_match_test->get_datatype().to_string(), "", "", "");
break;
}
if (p_match_test->type != GDScriptParser::Node::DICTIONARY && p_match_test->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT && p_match_test->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED && p_match_pattern->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT && p_match_pattern->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED) {
break; // Types must be provided
}
if (p_match_pattern->pattern_type != GDScriptParser::PatternNode::PT_DICTIONARY && (p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT || p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED)) {
Pair<GDScriptParser::DataType, GDScriptParser::DataType> other_type_found;
bool incorrect_type_present = false;
bool incorrect_key_present = false;
Pair<GDScriptParser::DataType, GDScriptParser::DataType> correct_type;
bool has_value = false;
GDScriptParser::DataType correct_type_key;
GDScriptParser::DataType correct_type_value;
if (p_match_test->get_datatype().container_element_types.size() == 2) {
// Both dict key and value specified
correct_type_key = p_match_test->get_datatype().container_element_types[0];
correct_type_value = p_match_test->get_datatype().container_element_types[1];
has_value = true;
} else if (p_match_test->get_datatype().container_element_types.size() == 1) {
// Only dict key specified
correct_type_key = p_match_test->get_datatype().container_element_types[0];
} else if (p_match_test->type == GDScriptParser::Node::Type::DICTIONARY) {
GDScriptParser::DictionaryNode *dict_node_match = dynamic_cast<GDScriptParser::DictionaryNode *>(p_match_test);
if (dict_node_match->elements.size() == 0) {
break;
}
correct_type_key = dict_node_match->elements[0].key->get_datatype();
correct_type_value = dict_node_match->elements[0].value->get_datatype();
has_value = true;
bool dict_mismatch_found = false;
for (int i = 1; i < dict_node_match->elements.size(); i++) {
if (correct_type_key != dict_node_match->elements[i].key->get_datatype() || (has_value && correct_type_value != dict_node_match->elements[i].value->get_datatype())) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "array_typed_match", "", "");
dict_mismatch_found = true;
break;
}
}
if (dict_mismatch_found) {
break;
}
}
if (p_match_pattern->get_datatype().container_element_types.size() == 2) {
if (p_match_pattern->get_datatype().container_element_types[0] != correct_type_key || (has_value && correct_type_value != p_match_pattern->get_datatype().container_element_types[1])) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string() + "[" + correct_type_key.to_string() + ", " + correct_type_value.to_string() + "]", "", "", "");
break;
}
} else if (p_match_pattern->type != GDScriptParser::Node::DICTIONARY) {
for (int i = 0; i < p_match_pattern->dictionary.size(); i++) {
// Don't count the ".." symbol
if (p_match_pattern->dictionary[i].value_pattern && p_match_pattern->dictionary[i].value_pattern->pattern_type == GDScriptParser::PatternNode::PT_REST) {
continue;
}
if (p_match_pattern->dictionary[i].value_pattern) {
// Test key and value type, key and value given
if (p_match_pattern->dictionary[i].key->datatype != correct_type_key || (has_value && p_match_pattern->dictionary[i].value_pattern->datatype != correct_type_value)) {
incorrect_type_present = true;
other_type_found = Pair(p_match_pattern->dictionary[i].key->datatype, p_match_pattern->dictionary[i].value_pattern->datatype);
break;
}
} else {
// Only test key type, value is not given
if (p_match_pattern->dictionary[i].key->datatype != correct_type_key) {
incorrect_key_present = true;
other_type_found = Pair(p_match_pattern->dictionary[i].key->datatype, GDScriptParser::DataType());
}
}
}
}
if (incorrect_type_present || incorrect_key_present) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::Type::DICTIONARY), p_match_test->get_datatype().to_string(), "dict_typed", "[" + other_type_found.first.to_string() + (incorrect_key_present ? "" : ", " + other_type_found.second.to_string()) + "]", "");
}
break;
}
if (p_match_pattern->pattern_type == GDScriptParser::PatternNode::PT_DICTIONARY) {
if (p_match_test->type == GDScriptParser::Node::Type::IDENTIFIER) {
Pair<GDScriptParser::DataType, GDScriptParser::DataType> other_type_found;
bool incorrect_type_present = false;
bool incorrect_key_present = false;
bool has_value = false;
GDScriptParser::DataType correct_type_key;
GDScriptParser::DataType correct_type_value;
if (p_match_test->get_datatype().container_element_types.size() == 2) {
// Both dict key and value specified
correct_type_key = p_match_test->get_datatype().container_element_types[0];
correct_type_value = p_match_test->get_datatype().container_element_types[1];
has_value = true;
} else {
break; // dictionary has no type
}
for (int i = 0; i < p_match_pattern->dictionary.size(); i++) {
// Don't count the ".." symbol
if (p_match_pattern->dictionary[i].value_pattern && p_match_pattern->dictionary[i].value_pattern->pattern_type == GDScriptParser::PatternNode::PT_REST) {
continue;
}
if (p_match_pattern->dictionary[i].value_pattern) {
// Test key and value type, key and value given
if (p_match_pattern->dictionary[i].key->datatype != correct_type_key || (has_value && p_match_pattern->dictionary[i].value_pattern->datatype != correct_type_value)) {
incorrect_type_present = true;
other_type_found = Pair(p_match_pattern->dictionary[i].key->datatype, p_match_pattern->dictionary[i].value_pattern->datatype);
break;
}
} else {
// Only test key type, value is not given
if (p_match_pattern->dictionary[i].key->datatype != correct_type_key) {
incorrect_key_present = true;
other_type_found = Pair(p_match_pattern->dictionary[i].key->datatype, GDScriptParser::DataType());
}
}
}
if (incorrect_type_present || incorrect_key_present) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::Type::DICTIONARY), p_match_test->get_datatype().to_string(), "dict_typed", "[" + other_type_found.first.to_string() + (incorrect_key_present ? "" : ", " + other_type_found.second.to_string()) + "]", "");
}
break;
} else if (p_match_test->type == GDScriptParser::Node::Type::DICTIONARY) {
GDScriptParser::DictionaryNode *dict_node_match = dynamic_cast<GDScriptParser::DictionaryNode *>(p_match_test);
bool open_ended = false;
if (p_match_pattern->dictionary.size() == 0) {
break;
}
// Create vectors of the types present in the pattern and the matching expression
List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>> match_vector;
List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>> pattern_vector;
List<GDScriptParser::DataType> pattern_vector_keys;
for (int i = 0; i < p_match_pattern->dictionary.size(); i++) {
if (p_match_pattern->dictionary[i].value_pattern && p_match_pattern->dictionary[i].value_pattern->pattern_type == GDScriptParser::PatternNode::PT_REST) {
open_ended = true;
continue;
}
if (p_match_pattern->dictionary[i].value_pattern) {
pattern_vector.push_front(Pair(p_match_pattern->dictionary[i].key->datatype, p_match_pattern->dictionary[i].value_pattern->datatype));
} else {
pattern_vector_keys.push_front(p_match_pattern->dictionary[i].key->datatype);
}
}
// Check sizes
if ((!open_ended && dict_node_match->elements.size() != p_match_pattern->dictionary.size()) || (open_ended && dict_node_match->elements.size() < p_match_pattern->dictionary.size() - 1)) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::DICTIONARY), p_match_test->get_datatype().to_string(), "size", String::num(p_match_pattern->dictionary.size() - (open_ended ? 1 : 0)), String::num(dict_node_match->elements.size()));
break;
}
// Create match vector
for (int i = 0; i < dict_node_match->elements.size(); i++) {
match_vector.push_front(Pair(dict_node_match->elements[i].key ? dict_node_match->elements[i].key->datatype : GDScriptParser::DataType(), dict_node_match->elements[i].value ? dict_node_match->elements[i].value->datatype : GDScriptParser::DataType()));
}
// Match keys with values within pattern
int vec_size = pattern_vector.size();
List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>>::Element *pattern_to_match = pattern_vector.front();
for (int i = 0; i < vec_size; i++) {
List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>>::Element *j = match_vector.find(pattern_to_match->get());
if (j != nullptr) {
j->erase();
List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>>::Element *temp = pattern_to_match->next();
pattern_to_match->erase();
pattern_to_match = temp;
if (match_vector.is_empty() || pattern_vector.is_empty()) {
break;
}
} else {
pattern_to_match = pattern_to_match->next();
}
if (pattern_to_match == nullptr) {
break;
}
}
// Match keys without values within pattern
List<GDScriptParser::DataType>::Element *pattern_keys_to_match = pattern_vector_keys.front();
bool found = false;
vec_size = pattern_vector_keys.size();
for (int i = 0; i < vec_size; i++) {
found = false;
GDScriptParser::DataType pattern_to_match_dt = pattern_keys_to_match->get();
for (List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>>::Element *elem_match = match_vector.front(); elem_match != nullptr; elem_match = elem_match->next()) {
if (elem_match->get().first == pattern_to_match_dt) {
elem_match->erase();
List<GDScriptParser::DataType>::Element *temp = pattern_keys_to_match->next();
pattern_keys_to_match->erase();
pattern_keys_to_match = temp;
found = true;
break;
}
}
if (!found) {
pattern_keys_to_match = pattern_keys_to_match->next();
}
if (pattern_keys_to_match == nullptr || match_vector.is_empty() || pattern_vector_keys.is_empty()) {
break;
}
}
if (pattern_vector.is_empty() && pattern_vector_keys.is_empty() && open_ended) {
break; // All pattern types are within the match vector
}
if (!match_vector.is_empty()) {
// Anything remaining in the match vector is not present in the pattern vector, the match cannot succeed
String missing_values;
for (List<Pair<GDScriptParser::DataType, GDScriptParser::DataType>>::Element *elem = match_vector.front(); elem != nullptr; elem = elem->next()) {
missing_values += "[" + elem->get().first.to_string() + ", " + elem->get().second.to_string() + "]";
}
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::Type::DICTIONARY), p_match_test->get_datatype().to_string(), "dict", missing_values, "");
}
}
}
break;
case Variant::ARRAY:
if (p_match_pattern->get_datatype() != p_match_test->get_datatype()) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "", "", "");
break;
}
if (p_match_pattern->pattern_type == GDScriptParser::PatternNode::Type::PT_DICTIONARY || p_match_pattern->get_datatype().builtin_type == Variant::Type::DICTIONARY) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::DICTIONARY), p_match_test->get_datatype().to_string(), "", "", "");
break;
}
if (p_match_pattern->pattern_type == GDScriptParser::PatternNode::Type::PT_BIND || p_match_pattern->pattern_type == GDScriptParser::PatternNode::Type::PT_REST || p_match_pattern->pattern_type == GDScriptParser::PatternNode::Type::PT_WILDCARD) {
break;
}
if (p_match_test->type != GDScriptParser::Node::ARRAY && p_match_test->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT && p_match_test->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED && p_match_pattern->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT && p_match_pattern->datatype.type_source != GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED) {
break; // Types must be provided
}
// If array type is provided, check all elements of pattern are that type
if (p_match_pattern->pattern_type != GDScriptParser::PatternNode::PT_ARRAY && (p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_EXPLICIT || p_match_test->datatype.type_source == GDScriptParser::DataType::TypeSource::ANNOTATED_INFERRED)) {
if (p_match_pattern->get_datatype().container_element_types.size() == 0) {
break;
}
GDScriptParser::DataType array_type;
if (p_match_test->datatype.container_element_types.size() > 0) {
array_type = p_match_test->datatype.container_element_types[0];
} else if (p_match_test->type == GDScriptParser::Node::Type::ARRAY) {
GDScriptParser::ArrayNode *arr_node_match = dynamic_cast<GDScriptParser::ArrayNode *>(p_match_test);
if (arr_node_match->elements.size() == 0) {
break;
}
array_type = arr_node_match->elements[0]->get_datatype();
bool array_mismatch_found = false;
for (int i = 1; i < arr_node_match->elements.size(); i++) {
if (array_type != arr_node_match->elements[i]->get_datatype()) {
// Multiple types within array, cannot be compatible with typed array
array_mismatch_found = true;
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "array_typed_match", "", "");
break;
}
}
if (array_mismatch_found) {
break;
}
}
if (p_match_pattern->get_datatype().container_element_types.size() == 0) {
break;
}
GDScriptParser::DataType incorrect_type;
if (p_match_pattern->get_datatype().container_element_types[0] != array_type) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::Type::ARRAY) + "[" + p_match_pattern->get_datatype().container_element_types[0].to_string() + "]", Variant::get_type_name(Variant::Type::ARRAY) + "[" + array_type.to_string() + "]", "", "", "");
}
break;
}
if (p_match_pattern->pattern_type == GDScriptParser::PatternNode::PT_ARRAY) {
bool mismatched_types = false;
if (p_match_test->type == GDScriptParser::Node::Type::IDENTIFIER) {
if (p_match_test->get_datatype().container_element_types.size() == 0) {
break;
}
GDScriptParser::DataType pattern_array_type = p_match_test->get_datatype().container_element_types[0];
for (int i = 0; i < p_match_pattern->array.size(); i++) {
if (pattern_array_type != p_match_pattern->array[i]->get_datatype()) {
mismatched_types = true;
break;
}
}
if (mismatched_types) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::ARRAY) + "[" + p_match_pattern->get_datatype().to_string() + "]", p_match_test->get_datatype().to_string(), "", "", "");
}
} else if (p_match_test->type == GDScriptParser::Node::Type::ARRAY) {
GDScriptParser::ArrayNode *arr_node_match = dynamic_cast<GDScriptParser::ArrayNode *>(p_match_test);
String all_container_types_match;
String all_container_types_pattern;
bool first_element = true;
bool open_ended = false;
Vector<GDScriptParser::DataType> pattern_vector;
// Create Vector of all types in the pattern array
for (int i = 0; i < p_match_pattern->array.size(); i++) {
if (p_match_pattern->array[i]->pattern_type == GDScriptParser::PatternNode::PT_REST) {
open_ended = true;
continue;
}
pattern_vector.append(p_match_pattern->array[i]->get_datatype());
if (!first_element) {
all_container_types_pattern += ", ";
} else {
first_element = false;
}
all_container_types_pattern += p_match_pattern->array[i]->get_datatype().to_string();
}
// Check sizes
if ((!open_ended && arr_node_match->elements.size() != p_match_pattern->array.size()) || (open_ended && arr_node_match->elements.size() < p_match_pattern->array.size() - 1)) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, p_match_pattern->get_datatype().to_string(), p_match_test->get_datatype().to_string(), "size", String::num(p_match_pattern->array.size() - (open_ended ? 1 : 0)), String::num(arr_node_match->elements.size()));
break;
}
// Check all pattern types are within the match array, in the same order
first_element = true;
for (int i = 0; i < p_match_pattern->array.size(); i++) {
if (arr_node_match->elements[i]->get_datatype() != pattern_vector[i]) {
mismatched_types = true;
}
if (!first_element) {
all_container_types_match += ", ";
} else {
first_element = false;
}
all_container_types_match += arr_node_match->elements[i]->datatype.to_string();
}
if (mismatched_types) {
parser->push_warning(p_match_pattern, GDScriptWarning::MISMATCHED_TYPE, Variant::get_type_name(Variant::ARRAY) + "[" + all_container_types_pattern + "]", p_match_test->get_datatype().to_string() + "[" + all_container_types_match + "]", "", "", "");
}
}
break;
}
}
}
#endif
}
void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) {

View File

@ -161,6 +161,21 @@ String GDScriptWarning::get_message() const {
return vformat(R"*(The default value is using "%s" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.)*", symbols[0]);
case ONREADY_WITH_EXPORT:
return R"("@onready" will set the default value after "@export" takes effect and will override it.)";
case MISMATCHED_TYPE:
CHECK_SYMBOLS(5);
if (symbols[2] == "size") {
return vformat(R"(The match expression will not match this pattern. The pattern type is %s of size %s but the match expression type is %s of size %s.)", symbols[0], symbols[3], symbols[1], symbols[4]);
} else if (symbols[2] == "array_typed") {
return vformat(R"(The match expression will not match this pattern. The pattern type is %s containing %s but the match expression type is %s.)", symbols[0], symbols[3], symbols[1]);
} else if (symbols[2] == "array_typed_match") {
return vformat(R"(The match expression will not match this pattern. The pattern type is %s but the match expression type is %s containing multiple types.)", symbols[0], symbols[1]);
} else if (symbols[2] == "dict") {
return vformat(R"(The match expression will not match this pattern. The pattern type is %s missing %s but the match expression type is %s containing those terms.)", symbols[0], symbols[3], symbols[1]);
} else if (symbols[2] == "dict_typed") {
return vformat(R"(The match expression will not match this pattern. The pattern type is %s including %s but the match expression type is %s.)", symbols[0], symbols[3], symbols[1]);
} else {
return vformat(R"(The match expression will not match this pattern. The pattern type is %s but the match expression type is %s.)", symbols[0], symbols[1]);
}
#ifndef DISABLE_DEPRECATED
// Never produced. These warnings migrated from 3.x by mistake.
case PROPERTY_USED_AS_FUNCTION: // There is already an error.
@ -242,6 +257,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
"NATIVE_METHOD_OVERRIDE",
"GET_NODE_DEFAULT_WITHOUT_ONREADY",
"ONREADY_WITH_EXPORT",
"MISMATCHED_TYPE",
#ifndef DISABLE_DEPRECATED
"PROPERTY_USED_AS_FUNCTION",
"CONSTANT_USED_AS_FUNCTION",

View File

@ -91,6 +91,7 @@ public:
NATIVE_METHOD_OVERRIDE, // The script method overrides a native one, this may not work as intended.
GET_NODE_DEFAULT_WITHOUT_ONREADY, // A class variable uses `get_node()` (or the `$` notation) as its default value, but does not use the @onready annotation.
ONREADY_WITH_EXPORT, // The `@onready` annotation will set the value after `@export` which is likely not intended.
MISMATCHED_TYPE, // The match expression type is not the same as the match pattern type
#ifndef DISABLE_DEPRECATED
PROPERTY_USED_AS_FUNCTION, // Function not found, but there's a property with the same name.
CONSTANT_USED_AS_FUNCTION, // Function not found, but there's a constant with the same name.
@ -145,6 +146,7 @@ public:
ERROR, // NATIVE_METHOD_OVERRIDE // May not work as expected.
ERROR, // GET_NODE_DEFAULT_WITHOUT_ONREADY // May not work as expected.
ERROR, // ONREADY_WITH_EXPORT // May not work as expected.
WARN, // MISMATCHED_TYPE
#ifndef DISABLE_DEPRECATED
WARN, // PROPERTY_USED_AS_FUNCTION
WARN, // CONSTANT_USED_AS_FUNCTION

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7260,6 +7260,10 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_PASS);
}
void RenderingDevice::make_current() {
render_thread_id = Thread::get_caller_id();
}
RenderingDevice::~RenderingDevice() {
finalize();

View File

@ -1496,6 +1496,8 @@ public:
static RenderingDevice *get_singleton();
void make_current();
RenderingDevice();
~RenderingDevice();

View File

@ -370,6 +370,8 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const {
void RenderingServerDefault::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
server_thread = Thread::get_caller_id();
server_task_id = p_pump_task_id;
// This is needed because the main RD is created on the main thread.
RenderingDevice::get_singleton()->make_current();
}
void RenderingServerDefault::_thread_exit() {