| 2075 | } |
| 2076 | |
| 2077 | void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assignable, const char *p_kind) { |
| 2078 | GDScriptParser::DataType type; |
| 2079 | type.kind = GDScriptParser::DataType::VARIANT; |
| 2080 | |
| 2081 | bool is_constant = p_assignable->type == GDScriptParser::Node::CONSTANT; |
| 2082 | |
| 2083 | #ifdef DEBUG_ENABLED |
| 2084 | if (p_assignable->identifier != nullptr && p_assignable->identifier->suite != nullptr && p_assignable->identifier->suite->parent_block != nullptr) { |
| 2085 | if (p_assignable->identifier->suite->parent_block->has_local(p_assignable->identifier->name)) { |
| 2086 | const GDScriptParser::SuiteNode::Local &local = p_assignable->identifier->suite->parent_block->get_local(p_assignable->identifier->name); |
| 2087 | parser->push_warning(p_assignable->identifier, GDScriptWarning::CONFUSABLE_LOCAL_DECLARATION, local.get_name(), p_assignable->identifier->name); |
| 2088 | } |
| 2089 | } |
| 2090 | #endif // DEBUG_ENABLED |
| 2091 | |
| 2092 | GDScriptParser::DataType specified_type; |
| 2093 | bool has_specified_type = p_assignable->datatype_specifier != nullptr; |
| 2094 | if (has_specified_type) { |
| 2095 | specified_type = type_from_metatype(resolve_datatype(p_assignable->datatype_specifier)); |
| 2096 | type = specified_type; |
| 2097 | } |
| 2098 | |
| 2099 | if (p_assignable->initializer != nullptr) { |
| 2100 | reduce_expression(p_assignable->initializer); |
| 2101 | |
| 2102 | if (p_assignable->initializer->type == GDScriptParser::Node::ARRAY) { |
| 2103 | GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(p_assignable->initializer); |
| 2104 | if (has_specified_type && specified_type.has_container_element_type(0)) { |
| 2105 | update_array_literal_element_type(array, specified_type.get_container_element_type(0)); |
| 2106 | } |
| 2107 | } else if (p_assignable->initializer->type == GDScriptParser::Node::DICTIONARY) { |
| 2108 | GDScriptParser::DictionaryNode *dictionary = static_cast<GDScriptParser::DictionaryNode *>(p_assignable->initializer); |
| 2109 | if (has_specified_type && specified_type.has_container_element_types()) { |
| 2110 | update_dictionary_literal_element_type(dictionary, specified_type.get_container_element_type_or_variant(0), specified_type.get_container_element_type_or_variant(1)); |
| 2111 | } |
| 2112 | } |
| 2113 | |
| 2114 | if (is_constant && !p_assignable->initializer->is_constant) { |
| 2115 | bool is_initializer_value_reduced = false; |
| 2116 | Variant initializer_value = make_expression_reduced_value(p_assignable->initializer, is_initializer_value_reduced); |
| 2117 | if (is_initializer_value_reduced) { |
| 2118 | p_assignable->initializer->is_constant = true; |
| 2119 | p_assignable->initializer->reduced_value = initializer_value; |
| 2120 | } else { |
| 2121 | push_error(vformat(R"(Assigned value for %s "%s" isn't a constant expression.)", p_kind, p_assignable->identifier->name), p_assignable->initializer); |
| 2122 | } |
| 2123 | } |
| 2124 | |
| 2125 | if (has_specified_type && p_assignable->initializer->is_constant) { |
| 2126 | update_const_expression_builtin_type(p_assignable->initializer, specified_type, "assign"); |
| 2127 | } |
| 2128 | GDScriptParser::DataType initializer_type = p_assignable->initializer->get_datatype(); |
| 2129 | |
| 2130 | if (p_assignable->infer_datatype) { |
| 2131 | if (!initializer_type.is_set() || initializer_type.has_no_type() || !initializer_type.is_hard_type()) { |
| 2132 | push_error(vformat(R"(Cannot infer the type of "%s" %s because the value doesn't have a set type.)", p_assignable->identifier->name, p_kind), p_assignable->initializer); |
| 2133 | } else if (initializer_type.kind == GDScriptParser::DataType::BUILTIN && initializer_type.builtin_type == Variant::NIL && !is_constant) { |
| 2134 | push_error(vformat(R"(Cannot infer the type of "%s" %s because the value is "null".)", p_assignable->identifier->name, p_kind), p_assignable->initializer); |
nothing calls this directly
no test coverage detected