|
@@ -646,41 +646,51 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (member.variable->datatype_specifier != nullptr) {
|
|
|
- datatype = specified_type;
|
|
|
+ // Check if initalizer is an unset identifier (ie: a variable within scope, but declared below)
|
|
|
+ if (member.variable->initializer && !member.variable->initializer->get_datatype().is_set()) {
|
|
|
+ if (member.variable->initializer->type == GDScriptParser::Node::IDENTIFIER) {
|
|
|
+ GDScriptParser::IdentifierNode *initializer_identifier = static_cast<GDScriptParser::IdentifierNode *>(member.variable->initializer);
|
|
|
+ push_error(vformat(R"(Identifier "%s" must be declared above current variable.)", initializer_identifier->name), member.variable->initializer);
|
|
|
+ } else {
|
|
|
+ ERR_PRINT("Parser bug (please report): tried to assign unset node without an identifier.");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (member.variable->datatype_specifier != nullptr) {
|
|
|
+ datatype = specified_type;
|
|
|
|
|
|
- if (member.variable->initializer != nullptr) {
|
|
|
- if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true, member.variable->initializer)) {
|
|
|
- // Try reverse test since it can be a masked subtype.
|
|
|
- if (!is_type_compatible(member.variable->initializer->get_datatype(), datatype, true, member.variable->initializer)) {
|
|
|
- push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", member.variable->initializer->get_datatype().to_string(), datatype.to_string()), member.variable->initializer);
|
|
|
- } else {
|
|
|
- // TODO: Add warning.
|
|
|
+ if (member.variable->initializer != nullptr) {
|
|
|
+ if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true, member.variable->initializer)) {
|
|
|
+ // Try reverse test since it can be a masked subtype.
|
|
|
+ if (!is_type_compatible(member.variable->initializer->get_datatype(), datatype, true, member.variable->initializer)) {
|
|
|
+ push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", member.variable->initializer->get_datatype().to_string(), datatype.to_string()), member.variable->initializer);
|
|
|
+ } else {
|
|
|
+ // TODO: Add warning.
|
|
|
+ mark_node_unsafe(member.variable->initializer);
|
|
|
+ member.variable->use_conversion_assign = true;
|
|
|
+ }
|
|
|
+ } else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) {
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ parser->push_warning(member.variable->initializer, GDScriptWarning::NARROWING_CONVERSION);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ if (member.variable->initializer->get_datatype().is_variant()) {
|
|
|
+ // TODO: Warn unsafe assign.
|
|
|
mark_node_unsafe(member.variable->initializer);
|
|
|
member.variable->use_conversion_assign = true;
|
|
|
}
|
|
|
- } else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) {
|
|
|
-#ifdef DEBUG_ENABLED
|
|
|
- parser->push_warning(member.variable->initializer, GDScriptWarning::NARROWING_CONVERSION);
|
|
|
-#endif
|
|
|
}
|
|
|
- if (member.variable->initializer->get_datatype().is_variant()) {
|
|
|
- // TODO: Warn unsafe assign.
|
|
|
- mark_node_unsafe(member.variable->initializer);
|
|
|
- member.variable->use_conversion_assign = true;
|
|
|
+ } else if (member.variable->infer_datatype) {
|
|
|
+ if (member.variable->initializer == nullptr) {
|
|
|
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because there's no default value.)", member.variable->identifier->name), member.variable->identifier);
|
|
|
+ } else if (!datatype.is_set() || datatype.has_no_type()) {
|
|
|
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value doesn't have a set type.)", member.variable->identifier->name), member.variable->initializer);
|
|
|
+ } else if (datatype.is_variant()) {
|
|
|
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is Variant. Use explicit "Variant" type if this is intended.)", member.variable->identifier->name), member.variable->initializer);
|
|
|
+ } else if (datatype.builtin_type == Variant::NIL) {
|
|
|
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is "null".)", member.variable->identifier->name), member.variable->initializer);
|
|
|
}
|
|
|
+ datatype.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
|
|
}
|
|
|
- } else if (member.variable->infer_datatype) {
|
|
|
- if (member.variable->initializer == nullptr) {
|
|
|
- push_error(vformat(R"(Cannot infer the type of "%s" variable because there's no default value.)", member.variable->identifier->name), member.variable->identifier);
|
|
|
- } else if (!datatype.is_set() || datatype.has_no_type()) {
|
|
|
- push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value doesn't have a set type.)", member.variable->identifier->name), member.variable->initializer);
|
|
|
- } else if (datatype.is_variant()) {
|
|
|
- push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is Variant. Use explicit "Variant" type if this is intended.)", member.variable->identifier->name), member.variable->initializer);
|
|
|
- } else if (datatype.builtin_type == Variant::NIL) {
|
|
|
- push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is "null".)", member.variable->identifier->name), member.variable->initializer);
|
|
|
- }
|
|
|
- datatype.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
|
|
}
|
|
|
|
|
|
datatype.is_constant = false;
|