diff options
Diffstat (limited to 'modules/gdscript/gdscript_analyzer.cpp')
-rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index e3d3c44dd1..9d39cbf1a5 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -2469,9 +2469,15 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig GDScriptParser::DataType assignee_type = p_assignment->assignee->get_datatype(); - if (assignee_type.is_constant || (p_assignment->assignee->type == GDScriptParser::Node::SUBSCRIPT && static_cast<GDScriptParser::SubscriptNode *>(p_assignment->assignee)->base->is_constant)) { + if (assignee_type.is_constant) { push_error("Cannot assign a new value to a constant.", p_assignment->assignee); return; + } else if (p_assignment->assignee->type == GDScriptParser::Node::SUBSCRIPT && static_cast<GDScriptParser::SubscriptNode *>(p_assignment->assignee)->base->is_constant) { + const GDScriptParser::DataType &base_type = static_cast<GDScriptParser::SubscriptNode *>(p_assignment->assignee)->base->datatype; + if (base_type.kind != GDScriptParser::DataType::SCRIPT && base_type.kind != GDScriptParser::DataType::CLASS) { // Static variables. + push_error("Cannot assign a new value to a constant.", p_assignment->assignee); + return; + } } else if (assignee_type.is_read_only) { push_error("Cannot assign a new value to a read-only property.", p_assignment->assignee); return; @@ -3366,7 +3372,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod base = *p_base; } - const StringName &name = p_identifier->name; + StringName name = p_identifier->name; if (base.kind == GDScriptParser::DataType::ENUM) { if (base.is_meta_type) { @@ -3461,12 +3467,18 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod get_class_node_current_scope_classes(base_class, &script_classes); } + bool is_constructor = base.is_meta_type && p_identifier->name == SNAME("new"); + for (GDScriptParser::ClassNode *script_class : script_classes) { if (p_base == nullptr && script_class->identifier && script_class->identifier->name == name) { reduce_identifier_from_base_set_class(p_identifier, script_class->get_datatype()); return; } + if (is_constructor) { + name = "_init"; + } + if (script_class->has_member(name)) { resolve_class_member(script_class, name, p_identifier); @@ -3516,7 +3528,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod } break; case GDScriptParser::ClassNode::Member::FUNCTION: { - if (is_base && !base.is_meta_type) { + if (is_base && (!base.is_meta_type || member.function->is_static)) { p_identifier->set_datatype(make_callable_type(member.function->info)); return; } @@ -3545,6 +3557,10 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod const StringName &native = base.native_type; if (class_exists(native)) { + if (is_constructor) { + name = "_init"; + } + MethodInfo method_info; if (ClassDB::has_property(native, name)) { StringName getter_name = ClassDB::get_property_getter(native, name); @@ -4518,7 +4534,16 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va result.builtin_type = p_value.get_type(); result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; // Constant has explicit type. - if (p_value.get_type() == Variant::OBJECT) { + if (p_value.get_type() == Variant::ARRAY) { + const Array &array = p_value; + if (array.get_typed_script()) { + result.set_container_element_type(type_from_metatype(make_script_meta_type(array.get_typed_script()))); + } else if (array.get_typed_class_name()) { + result.set_container_element_type(type_from_metatype(make_native_meta_type(array.get_typed_class_name()))); + } else if (array.get_typed_builtin() != Variant::NIL) { + result.set_container_element_type(type_from_metatype(make_builtin_meta_type((Variant::Type)array.get_typed_builtin()))); + } + } else if (p_value.get_type() == Variant::OBJECT) { // Object is treated as a native type, not a builtin type. result.kind = GDScriptParser::DataType::NATIVE; @@ -4945,6 +4970,17 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator } GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, const GDScriptParser::DataType &p_b, bool &r_valid, const GDScriptParser::Node *p_source) { + if (p_operation == Variant::OP_AND || p_operation == Variant::OP_OR) { + // Those work for any type of argument and always return a boolean. + // They don't use the Variant operator since they have short-circuit semantics. + r_valid = true; + GDScriptParser::DataType result; + result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + result.kind = GDScriptParser::DataType::BUILTIN; + result.builtin_type = Variant::BOOL; + return result; + } + Variant::Type a_type = p_a.builtin_type; Variant::Type b_type = p_b.builtin_type; @@ -4963,11 +4999,21 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator } } - Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type); + GDScriptParser::DataType result; bool hard_operation = p_a.is_hard_type() && p_b.is_hard_type(); + + if (p_operation == Variant::OP_ADD && a_type == Variant::ARRAY && b_type == Variant::ARRAY) { + if (p_a.has_container_element_type() && p_b.has_container_element_type() && p_a.get_container_element_type() == p_b.get_container_element_type()) { + r_valid = true; + result = p_a; + result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED; + return result; + } + } + + Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type); bool validated = op_eval != nullptr; - GDScriptParser::DataType result; if (validated) { r_valid = true; result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED; |