@ -1139,7 +1139,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
# endif // TOOLS_ENABLED
}
if ( p_function - > identifier - > name = = " _init " ) {
if ( p_function - > identifier - > name = = GDScriptLanguage : : get_singleton ( ) - > strings . _init ) {
// Constructor.
GDScriptParser : : DataType return_type = parser - > current_class - > get_datatype ( ) ;
return_type . is_meta_type = false ;
@ -1153,6 +1153,57 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
} else {
GDScriptParser : : DataType return_type = resolve_datatype ( p_function - > return_type ) ;
p_function - > set_datatype ( return_type ) ;
# ifdef DEBUG_ENABLED
// Check if the function signature matches the parent. If not it's an error since it breaks polymorphism.
// Not for the constructor which can vary in signature.
GDScriptParser : : DataType base_type = parser - > current_class - > base_type ;
GDScriptParser : : DataType parent_return_type ;
List < GDScriptParser : : DataType > parameters_types ;
int default_par_count = 0 ;
bool is_static = false ;
bool is_vararg = false ;
if ( get_function_signature ( p_function , false , base_type , p_function - > identifier - > name , parent_return_type , parameters_types , default_par_count , is_static , is_vararg ) ) {
bool valid = p_function - > is_static = = is_static ;
valid = valid & & parent_return_type = = p_function - > get_datatype ( ) ;
int par_count_diff = p_function - > parameters . size ( ) - parameters_types . size ( ) ;
valid = valid & & par_count_diff > = 0 ;
valid = valid & & p_function - > default_arg_values . size ( ) > = default_par_count + par_count_diff ;
int i = 0 ;
for ( const GDScriptParser : : DataType & par_type : parameters_types ) {
valid = valid & & par_type = = p_function - > parameters [ i + + ] - > get_datatype ( ) ;
}
if ( ! valid ) {
// Compute parent signature as a string to show in the error message.
String parent_signature = parent_return_type . is_hard_type ( ) ? parent_return_type . to_string ( ) : " Variant " ;
if ( parent_signature = = " null " ) {
parent_signature = " void " ;
}
parent_signature + = " " + p_function - > identifier - > name . operator String ( ) + " ( " ;
int j = 0 ;
for ( const GDScriptParser : : DataType & par_type : parameters_types ) {
if ( j > 0 ) {
parent_signature + = " , " ;
}
String parameter = par_type . to_string ( ) ;
if ( parameter = = " null " ) {
parameter = " Variant " ;
}
parent_signature + = parameter ;
if ( j = = parameters_types . size ( ) - default_par_count ) {
parent_signature + = " = default " ;
}
j + + ;
}
parent_signature + = " ) " ;
push_error ( vformat ( R " (The function signature doesn't match the parent. Parent signature is " % s " .) " , parent_signature ) , p_function ) ;
}
}
# endif
}
parser - > current_function = previous_function ;
@ -2416,7 +2467,9 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
GDScriptParser : : DataType return_type ;
List < GDScriptParser : : DataType > par_types ;
if ( get_function_signature ( p_call , base_type , p_call - > function_name , return_type , par_types , default_arg_count , is_static , is_vararg ) ) {
bool is_constructor = ( base_type . is_meta_type | | ( p_call - > callee & & p_call - > callee - > type = = GDScriptParser : : Node : : IDENTIFIER ) ) & & p_call - > function_name = = SNAME ( " new " ) ;
if ( get_function_signature ( p_call , is_constructor , base_type , p_call - > function_name , return_type , par_types , default_arg_count , is_static , is_vararg ) ) {
// If the function require typed arrays we must make literals be typed.
for ( const KeyValue < int , GDScriptParser : : ArrayNode * > & E : arrays ) {
int index = E . key ;
@ -3576,7 +3629,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo
return result ;
}
bool GDScriptAnalyzer : : get_function_signature ( GDScriptParser : : Call Node * p_source , GDScriptParser : : DataType p_base_type , const StringName & p_function , GDScriptParser : : DataType & r_return_type , List < GDScriptParser : : DataType > & r_par_types , int & r_default_arg_count , bool & r_static , bool & r_vararg ) {
bool GDScriptAnalyzer : : get_function_signature ( GDScriptParser : : Node * p_source , bool p_is_constructor , GDScriptParser : : DataType p_base_type , const StringName & p_function , GDScriptParser : : DataType & r_return_type , List < GDScriptParser : : DataType > & r_par_types , int & r_default_arg_count , bool & r_static , bool & r_vararg ) {
r_static = false ;
r_vararg = false ;
r_default_arg_count = 0 ;
@ -3616,8 +3669,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source
return false ;
}
bool is_constructor = ( p_base_type . is_meta_type | | ( p_source - > callee & & p_source - > callee - > type = = GDScriptParser : : Node : : IDENTIFIER ) ) & & p_function = = StaticCString : : create ( " new " ) ;
if ( is_constructor ) {
if ( p_is_constructor ) {
function_name = " _init " ;
r_static = true ;
}
@ -3638,7 +3690,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source
}
if ( found_function ! = nullptr ) {
r_static = is_constructor | | found_function - > is_static ;
r_static = p_ is_constructor | | found_function - > is_static ;
for ( int i = 0 ; i < found_function - > parameters . size ( ) ; i + + ) {
r_par_types . push_back ( found_function - > parameters [ i ] - > get_datatype ( ) ) ;
if ( found_function - > parameters [ i ] - > default_value ! = nullptr ) {
@ -3664,7 +3716,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source
}
// If the base is a script, it might be trying to access members of the Script class itself.
if ( p_base_type . is_meta_type & & ! is_constructor & & ( p_base_type . kind = = GDScriptParser : : DataType : : SCRIPT | | p_base_type . kind = = GDScriptParser : : DataType : : CLASS ) ) {
if ( p_base_type . is_meta_type & & ! p_ is_constructor & & ( p_base_type . kind = = GDScriptParser : : DataType : : SCRIPT | | p_base_type . kind = = GDScriptParser : : DataType : : CLASS ) ) {
MethodInfo info ;
StringName script_class = p_base_type . kind = = GDScriptParser : : DataType : : SCRIPT ? p_base_type . script_type - > get_class_name ( ) : StringName ( GDScript : : get_class_static ( ) ) ;
@ -3684,7 +3736,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source
}
# endif
if ( is_constructor) {
if ( p_ is_constructor) {
// Native types always have a default constructor.
r_return_type = p_base_type ;
r_return_type . type_source = GDScriptParser : : DataType : : ANNOTATED_EXPLICIT ;