mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
GDScript: Add support for variadic functions
This commit is contained in:
parent
3b963ab8b6
commit
ee121ef80e
33 changed files with 416 additions and 65 deletions
|
@ -1798,6 +1798,33 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
|
|||
}
|
||||
}
|
||||
|
||||
if (p_function->is_vararg()) {
|
||||
resolve_parameter(p_function->rest_parameter);
|
||||
if (p_function->rest_parameter->datatype_specifier != nullptr) {
|
||||
GDScriptParser::DataType specified_type = p_function->rest_parameter->get_datatype();
|
||||
if (specified_type.kind != GDScriptParser::DataType::BUILTIN || specified_type.builtin_type != Variant::ARRAY) {
|
||||
push_error(vformat(R"(The rest parameter type must be "Array", but "%s" is specified.)", specified_type.to_string()), p_function->rest_parameter->datatype_specifier);
|
||||
} else if ((specified_type.has_container_element_type(0) && !specified_type.get_container_element_type(0).is_variant())) {
|
||||
push_error(R"(Typed arrays are currently not supported for the rest parameter.)", p_function->rest_parameter->datatype_specifier);
|
||||
}
|
||||
} else {
|
||||
GDScriptParser::DataType inferred_type;
|
||||
inferred_type.type_source = GDScriptParser::DataType::INFERRED;
|
||||
inferred_type.kind = GDScriptParser::DataType::BUILTIN;
|
||||
inferred_type.builtin_type = Variant::ARRAY;
|
||||
p_function->rest_parameter->set_datatype(inferred_type);
|
||||
#ifdef DEBUG_ENABLED
|
||||
parser->push_warning(p_function->rest_parameter, GDScriptWarning::UNTYPED_DECLARATION, "Parameter", p_function->rest_parameter->identifier->name);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (p_function->rest_parameter->usages == 0 && !String(p_function->rest_parameter->identifier->name).begins_with("_") && !p_function->is_abstract) {
|
||||
parser->push_warning(p_function->rest_parameter->identifier, GDScriptWarning::UNUSED_PARAMETER, function_visible_name, p_function->rest_parameter->identifier->name);
|
||||
}
|
||||
is_shadowing(p_function->rest_parameter->identifier, "function parameter", true);
|
||||
#endif // DEBUG_ENABLED
|
||||
}
|
||||
|
||||
if (!p_is_lambda && function_name == GDScriptLanguage::get_singleton()->strings._init) {
|
||||
// Constructor.
|
||||
GDScriptParser::DataType return_type = parser->current_class->get_datatype();
|
||||
|
@ -1864,15 +1891,23 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
|
|||
}
|
||||
}
|
||||
|
||||
int par_count_diff = p_function->parameters.size() - parameters_types.size();
|
||||
valid = valid && par_count_diff >= 0;
|
||||
valid = valid && default_value_count >= default_par_count + par_count_diff;
|
||||
int parent_min_argc = parameters_types.size() - default_par_count;
|
||||
int parent_max_argc = (method_flags & METHOD_FLAG_VARARG) ? INT_MAX : parameters_types.size();
|
||||
int current_min_argc = p_function->parameters.size() - default_value_count;
|
||||
int current_max_argc = p_function->is_vararg() ? INT_MAX : p_function->parameters.size();
|
||||
|
||||
// `[current_min_argc..current_max_argc]` must include `[parent_min_argc..parent_max_argc]`.
|
||||
valid = valid && current_min_argc <= parent_min_argc && parent_max_argc <= current_max_argc;
|
||||
|
||||
if (valid) {
|
||||
int i = 0;
|
||||
for (const GDScriptParser::DataType &parent_par_type : parameters_types) {
|
||||
if (i >= p_function->parameters.size()) {
|
||||
break;
|
||||
}
|
||||
const GDScriptParser::DataType ¤t_par_type = p_function->parameters[i]->datatype;
|
||||
i++;
|
||||
// Check parameter type contravariance.
|
||||
GDScriptParser::DataType current_par_type = p_function->parameters[i++]->get_datatype();
|
||||
if (parent_par_type.is_variant() && parent_par_type.is_hard_type()) {
|
||||
// `is_type_compatible()` returns `true` if one of the types is `Variant`.
|
||||
// Don't allow narrowing a hard `Variant`.
|
||||
|
@ -1902,6 +1937,12 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
|
|||
|
||||
j++;
|
||||
}
|
||||
if (method_flags & METHOD_FLAG_VARARG) {
|
||||
if (!parameters_types.is_empty()) {
|
||||
parent_signature += ", ";
|
||||
}
|
||||
parent_signature += "...";
|
||||
}
|
||||
parent_signature += ") -> ";
|
||||
|
||||
const String return_type = parent_return_type.to_string_strict();
|
||||
|
@ -5853,6 +5894,9 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
|
|||
r_default_arg_count++;
|
||||
}
|
||||
}
|
||||
if (found_function->is_vararg()) {
|
||||
r_method_flags.set_flag(METHOD_FLAG_VARARG);
|
||||
}
|
||||
r_return_type = p_is_constructor ? p_base_type : found_function->get_datatype();
|
||||
r_return_type.is_meta_type = false;
|
||||
r_return_type.is_coroutine = found_function->is_coroutine;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue