mirror of
https://github.com/godotengine/godot.git
synced 2025-02-17 22:43:01 +08:00
GDScript: Fix typing of iterator in for loop
This commit is contained in:
parent
3c9bf4bc21
commit
40613ebd21
@ -1253,7 +1253,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
|
|||||||
return _data._int > 0;
|
return _data._int > 0;
|
||||||
} break;
|
} break;
|
||||||
case FLOAT: {
|
case FLOAT: {
|
||||||
r_iter = 0;
|
r_iter = 0.0;
|
||||||
return _data._float > 0.0;
|
return _data._float > 0.0;
|
||||||
} break;
|
} break;
|
||||||
case VECTOR2: {
|
case VECTOR2: {
|
||||||
@ -1457,7 +1457,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
|
|||||||
return true;
|
return true;
|
||||||
} break;
|
} break;
|
||||||
case FLOAT: {
|
case FLOAT: {
|
||||||
int64_t idx = r_iter;
|
double idx = r_iter;
|
||||||
idx++;
|
idx++;
|
||||||
if (idx >= _data._float) {
|
if (idx >= _data._float) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1722,21 +1722,52 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
|
|||||||
if (list_resolved) {
|
if (list_resolved) {
|
||||||
variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
||||||
variable_type.kind = GDScriptParser::DataType::BUILTIN;
|
variable_type.kind = GDScriptParser::DataType::BUILTIN;
|
||||||
variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else?
|
variable_type.builtin_type = Variant::INT;
|
||||||
p_for->variable->set_datatype(variable_type);
|
|
||||||
} else if (p_for->list) {
|
} else if (p_for->list) {
|
||||||
resolve_node(p_for->list, false);
|
resolve_node(p_for->list, false);
|
||||||
if (p_for->list->datatype.has_container_element_type()) {
|
GDScriptParser::DataType list_type = p_for->list->get_datatype();
|
||||||
variable_type = p_for->list->datatype.get_container_element_type();
|
if (!list_type.is_hard_type()) {
|
||||||
variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
mark_node_unsafe(p_for->list);
|
||||||
} else if (p_for->list->datatype.is_typed_container_type()) {
|
}
|
||||||
variable_type = p_for->list->datatype.get_typed_container_type();
|
if (list_type.is_variant()) {
|
||||||
variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
|
||||||
} else {
|
|
||||||
// Last resort
|
|
||||||
// TODO: Must other cases be handled? Must we mark as unsafe?
|
|
||||||
variable_type.type_source = GDScriptParser::DataType::UNDETECTED;
|
|
||||||
variable_type.kind = GDScriptParser::DataType::VARIANT;
|
variable_type.kind = GDScriptParser::DataType::VARIANT;
|
||||||
|
mark_node_unsafe(p_for->list);
|
||||||
|
} else if (list_type.has_container_element_type()) {
|
||||||
|
variable_type = list_type.get_container_element_type();
|
||||||
|
variable_type.type_source = list_type.type_source;
|
||||||
|
} else if (list_type.is_typed_container_type()) {
|
||||||
|
variable_type = list_type.get_typed_container_type();
|
||||||
|
variable_type.type_source = list_type.type_source;
|
||||||
|
} else if (list_type.builtin_type == Variant::INT || list_type.builtin_type == Variant::FLOAT || list_type.builtin_type == Variant::STRING) {
|
||||||
|
variable_type.type_source = list_type.type_source;
|
||||||
|
variable_type.kind = GDScriptParser::DataType::BUILTIN;
|
||||||
|
variable_type.builtin_type = list_type.builtin_type;
|
||||||
|
} else if (list_type.builtin_type == Variant::VECTOR2I || list_type.builtin_type == Variant::VECTOR3I) {
|
||||||
|
variable_type.type_source = list_type.type_source;
|
||||||
|
variable_type.kind = GDScriptParser::DataType::BUILTIN;
|
||||||
|
variable_type.builtin_type = Variant::INT;
|
||||||
|
} else if (list_type.builtin_type == Variant::VECTOR2 || list_type.builtin_type == Variant::VECTOR3) {
|
||||||
|
variable_type.type_source = list_type.type_source;
|
||||||
|
variable_type.kind = GDScriptParser::DataType::BUILTIN;
|
||||||
|
variable_type.builtin_type = Variant::FLOAT;
|
||||||
|
} else if (list_type.builtin_type == Variant::OBJECT) {
|
||||||
|
GDScriptParser::DataType return_type;
|
||||||
|
List<GDScriptParser::DataType> par_types;
|
||||||
|
int default_arg_count = 0;
|
||||||
|
bool is_static = false;
|
||||||
|
bool is_vararg = false;
|
||||||
|
if (get_function_signature(p_for->list, false, list_type, CoreStringNames::get_singleton()->_iter_get, return_type, par_types, default_arg_count, is_static, is_vararg)) {
|
||||||
|
variable_type = return_type;
|
||||||
|
variable_type.type_source = list_type.type_source;
|
||||||
|
} else if (!list_type.is_hard_type()) {
|
||||||
|
variable_type.kind = GDScriptParser::DataType::VARIANT;
|
||||||
|
} else {
|
||||||
|
push_error(vformat(R"(Unable to iterate on object of type "%s".)", list_type.to_string()), p_for->list);
|
||||||
|
}
|
||||||
|
} else if (list_type.builtin_type == Variant::ARRAY || list_type.builtin_type == Variant::DICTIONARY || !list_type.is_hard_type()) {
|
||||||
|
variable_type.kind = GDScriptParser::DataType::VARIANT;
|
||||||
|
} else {
|
||||||
|
push_error(vformat(R"(Unable to iterate on value of type "%s".)", list_type.to_string()), p_for->list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p_for->variable) {
|
if (p_for->variable) {
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
const constant_float = 1.0
|
||||||
|
|
||||||
|
func test():
|
||||||
|
for x in constant_float:
|
||||||
|
if x is String:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "float" so it can't be of type "String".
|
@ -0,0 +1,6 @@
|
|||||||
|
const constant_int = 1
|
||||||
|
|
||||||
|
func test():
|
||||||
|
for x in constant_int:
|
||||||
|
if x is String:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "int" so it can't be of type "String".
|
@ -0,0 +1,6 @@
|
|||||||
|
enum { enum_value = 1 }
|
||||||
|
|
||||||
|
func test():
|
||||||
|
for x in enum_value:
|
||||||
|
if x is String:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "int" so it can't be of type "String".
|
@ -0,0 +1,6 @@
|
|||||||
|
func test():
|
||||||
|
var hard_float := 1.0
|
||||||
|
|
||||||
|
for x in hard_float:
|
||||||
|
if x is String:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "float" so it can't be of type "String".
|
@ -0,0 +1,6 @@
|
|||||||
|
func test():
|
||||||
|
var hard_int := 1
|
||||||
|
|
||||||
|
for x in hard_int:
|
||||||
|
if x is String:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "int" so it can't be of type "String".
|
@ -0,0 +1,14 @@
|
|||||||
|
class Iterator:
|
||||||
|
func _iter_init(_count):
|
||||||
|
return true
|
||||||
|
func _iter_next(_count):
|
||||||
|
return false
|
||||||
|
func _iter_get(_count) -> StringName:
|
||||||
|
return &'custom'
|
||||||
|
|
||||||
|
func test():
|
||||||
|
var hard_iterator := Iterator.new()
|
||||||
|
|
||||||
|
for x in hard_iterator:
|
||||||
|
if x is int:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "StringName" so it can't be of type "int".
|
@ -0,0 +1,6 @@
|
|||||||
|
func test():
|
||||||
|
var hard_string := 'a'
|
||||||
|
|
||||||
|
for x in hard_string:
|
||||||
|
if x is int:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "String" so it can't be of type "int".
|
@ -0,0 +1,3 @@
|
|||||||
|
func test():
|
||||||
|
for x in true:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Unable to iterate on value of type "bool".
|
@ -0,0 +1,4 @@
|
|||||||
|
func test():
|
||||||
|
for x in 1:
|
||||||
|
if x is String:
|
||||||
|
pass
|
@ -0,0 +1,2 @@
|
|||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Expression is of type "int" so it can't be of type "String".
|
@ -0,0 +1,15 @@
|
|||||||
|
func test():
|
||||||
|
var variant_int: Variant = 1
|
||||||
|
var weak_int = 1
|
||||||
|
|
||||||
|
for x in variant_int:
|
||||||
|
if x is String:
|
||||||
|
print('never')
|
||||||
|
print(x)
|
||||||
|
|
||||||
|
for x in weak_int:
|
||||||
|
if x is String:
|
||||||
|
print('never')
|
||||||
|
print(x)
|
||||||
|
|
||||||
|
print('ok')
|
@ -0,0 +1,4 @@
|
|||||||
|
GDTEST_OK
|
||||||
|
0
|
||||||
|
0
|
||||||
|
ok
|
@ -0,0 +1,51 @@
|
|||||||
|
const constant_float = 1.0
|
||||||
|
const constant_int = 1
|
||||||
|
enum { enum_value = 1 }
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
func _iter_init(_count):
|
||||||
|
return true
|
||||||
|
func _iter_next(_count):
|
||||||
|
return false
|
||||||
|
func _iter_get(_count) -> StringName:
|
||||||
|
return &'custom'
|
||||||
|
|
||||||
|
func test():
|
||||||
|
var hard_float := 1.0
|
||||||
|
var hard_int := 1
|
||||||
|
var hard_string := '0'
|
||||||
|
var hard_iterator := Iterator.new()
|
||||||
|
|
||||||
|
var variant_float: Variant = hard_float
|
||||||
|
var variant_int: Variant = hard_int
|
||||||
|
var variant_string: Variant = hard_string
|
||||||
|
var variant_iterator: Variant = hard_iterator
|
||||||
|
|
||||||
|
for i in 1.0:
|
||||||
|
print(typeof(i) == TYPE_FLOAT)
|
||||||
|
for i in 1:
|
||||||
|
print(typeof(i) == TYPE_INT)
|
||||||
|
for i in 'a':
|
||||||
|
print(typeof(i) == TYPE_STRING)
|
||||||
|
for i in Iterator.new():
|
||||||
|
print(typeof(i) == TYPE_STRING_NAME)
|
||||||
|
|
||||||
|
for i in hard_float:
|
||||||
|
print(typeof(i) == TYPE_FLOAT)
|
||||||
|
for i in hard_int:
|
||||||
|
print(typeof(i) == TYPE_INT)
|
||||||
|
for i in hard_string:
|
||||||
|
print(typeof(i) == TYPE_STRING)
|
||||||
|
for i in hard_iterator:
|
||||||
|
print(typeof(i) == TYPE_STRING_NAME)
|
||||||
|
|
||||||
|
for i in variant_float:
|
||||||
|
print(typeof(i) == TYPE_FLOAT)
|
||||||
|
for i in variant_int:
|
||||||
|
print(typeof(i) == TYPE_INT)
|
||||||
|
for i in variant_string:
|
||||||
|
print(typeof(i) == TYPE_STRING)
|
||||||
|
for i in variant_iterator:
|
||||||
|
print(typeof(i) == TYPE_STRING_NAME)
|
||||||
|
|
||||||
|
print('ok')
|
@ -0,0 +1,14 @@
|
|||||||
|
GDTEST_OK
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
ok
|
Loading…
Reference in New Issue
Block a user