Merge pull request #70702 from vnen/gdscript-error-on-assign-void
GDScript: Error when assigning return value of void function
This commit is contained in:
commit
4e360ac612
26 changed files with 108 additions and 53 deletions
|
@ -65,11 +65,13 @@ static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...) const, Variant *b
|
||||||
|
|
||||||
template <class T, class... P>
|
template <class T, class... P>
|
||||||
static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
|
static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
|
||||||
|
VariantInternal::clear(&r_ret);
|
||||||
call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
|
call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class... P>
|
template <class T, class... P>
|
||||||
static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
|
static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
|
||||||
|
VariantInternal::clear(&r_ret);
|
||||||
call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
|
call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -464,9 +464,6 @@
|
||||||
<member name="debug/gdscript/warnings/unused_variable" type="int" setter="" getter="" default="1">
|
<member name="debug/gdscript/warnings/unused_variable" type="int" setter="" getter="" default="1">
|
||||||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable is unused.
|
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local variable is unused.
|
||||||
</member>
|
</member>
|
||||||
<member name="debug/gdscript/warnings/void_assignment" type="int" setter="" getter="" default="1">
|
|
||||||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when assigning the result of a function that returns [code]void[/code] to a variable.
|
|
||||||
</member>
|
|
||||||
<member name="debug/settings/crash_handler/message" type="String" setter="" getter="" default=""Please include this when reporting the bug to the project developer."">
|
<member name="debug/settings/crash_handler/message" type="String" setter="" getter="" default=""Please include this when reporting the bug to the project developer."">
|
||||||
Message to be displayed before the backtrace when the engine crashes. By default, this message is only used in exported projects due to the editor-only override applied to this setting.
|
Message to be displayed before the backtrace when the engine crashes. By default, this message is only used in exported projects due to the editor-only override applied to this setting.
|
||||||
</member>
|
</member>
|
||||||
|
|
|
@ -1751,12 +1751,6 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
|
||||||
|
|
||||||
type = p_variable->initializer->get_datatype();
|
type = p_variable->initializer->get_datatype();
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (p_variable->initializer->type == GDScriptParser::Node::CALL && type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
|
|
||||||
parser->push_warning(p_variable->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_variable->initializer)->function_name);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p_variable->infer_datatype) {
|
if (p_variable->infer_datatype) {
|
||||||
type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
|
||||||
|
|
||||||
|
@ -1846,12 +1840,6 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant
|
||||||
}
|
}
|
||||||
|
|
||||||
type = p_constant->initializer->get_datatype();
|
type = p_constant->initializer->get_datatype();
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (p_constant->initializer->type == GDScriptParser::Node::CALL && type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL) {
|
|
||||||
parser->push_warning(p_constant->initializer, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_constant->initializer)->function_name);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_constant->datatype_specifier != nullptr) {
|
if (p_constant->datatype_specifier != nullptr) {
|
||||||
|
@ -2335,9 +2323,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (p_assignment->assigned_value->type == GDScriptParser::Node::CALL && assigned_value_type.is_hard_type() && assigned_value_type.kind == GDScriptParser::DataType::BUILTIN && assigned_value_type.builtin_type == Variant::NIL) {
|
if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
|
||||||
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_assignment->assigned_value)->function_name);
|
|
||||||
} else if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
|
|
||||||
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION);
|
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2652,6 +2638,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
|
||||||
} else if (GDScriptUtilityFunctions::function_exists(function_name)) {
|
} else if (GDScriptUtilityFunctions::function_exists(function_name)) {
|
||||||
MethodInfo function_info = GDScriptUtilityFunctions::get_function_info(function_name);
|
MethodInfo function_info = GDScriptUtilityFunctions::get_function_info(function_name);
|
||||||
|
|
||||||
|
if (!p_is_root && function_info.return_val.type == Variant::NIL && ((function_info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) == 0)) {
|
||||||
|
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
|
||||||
|
}
|
||||||
|
|
||||||
if (all_is_constant && GDScriptUtilityFunctions::is_function_constant(function_name)) {
|
if (all_is_constant && GDScriptUtilityFunctions::is_function_constant(function_name)) {
|
||||||
// Can call on compilation.
|
// Can call on compilation.
|
||||||
Vector<const Variant *> args;
|
Vector<const Variant *> args;
|
||||||
|
@ -2695,6 +2685,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
|
||||||
} else if (Variant::has_utility_function(function_name)) {
|
} else if (Variant::has_utility_function(function_name)) {
|
||||||
MethodInfo function_info = info_from_utility_func(function_name);
|
MethodInfo function_info = info_from_utility_func(function_name);
|
||||||
|
|
||||||
|
if (!p_is_root && function_info.return_val.type == Variant::NIL && ((function_info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) == 0)) {
|
||||||
|
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
|
||||||
|
}
|
||||||
|
|
||||||
if (all_is_constant && Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH) {
|
if (all_is_constant && Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH) {
|
||||||
// Can call on compilation.
|
// Can call on compilation.
|
||||||
Vector<const Variant *> args;
|
Vector<const Variant *> args;
|
||||||
|
@ -2837,6 +2831,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
|
||||||
mark_lambda_use_self();
|
mark_lambda_use_self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!p_is_root && return_type.is_hard_type() && return_type.kind == GDScriptParser::DataType::BUILTIN && return_type.builtin_type == Variant::NIL) {
|
||||||
|
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", p_call->function_name), p_call);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) {
|
if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) {
|
||||||
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
|
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
|
||||||
|
|
|
@ -538,20 +538,20 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
// Construct a built-in type.
|
// Construct a built-in type.
|
||||||
Variant::Type vtype = GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(call->callee)->name);
|
Variant::Type vtype = GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(call->callee)->name);
|
||||||
|
|
||||||
gen->write_construct(result, vtype, arguments);
|
gen->write_construct(return_addr, vtype, arguments);
|
||||||
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) {
|
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) {
|
||||||
// Variant utility function.
|
// Variant utility function.
|
||||||
gen->write_call_utility(result, call->function_name, arguments);
|
gen->write_call_utility(return_addr, call->function_name, arguments);
|
||||||
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptUtilityFunctions::function_exists(call->function_name)) {
|
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptUtilityFunctions::function_exists(call->function_name)) {
|
||||||
// GDScript utility function.
|
// GDScript utility function.
|
||||||
gen->write_call_gdscript_utility(result, GDScriptUtilityFunctions::get_function(call->function_name), arguments);
|
gen->write_call_gdscript_utility(return_addr, GDScriptUtilityFunctions::get_function(call->function_name), arguments);
|
||||||
} else {
|
} else {
|
||||||
// Regular function.
|
// Regular function.
|
||||||
const GDScriptParser::ExpressionNode *callee = call->callee;
|
const GDScriptParser::ExpressionNode *callee = call->callee;
|
||||||
|
|
||||||
if (call->is_super) {
|
if (call->is_super) {
|
||||||
// Super call.
|
// Super call.
|
||||||
gen->write_super_call(result, call->function_name, arguments);
|
gen->write_super_call(return_addr, call->function_name, arguments);
|
||||||
} else {
|
} else {
|
||||||
if (callee->type == GDScriptParser::Node::IDENTIFIER) {
|
if (callee->type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
// Self function call.
|
// Self function call.
|
||||||
|
@ -563,22 +563,22 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
|
|
||||||
if (_have_exact_arguments(method, arguments)) {
|
if (_have_exact_arguments(method, arguments)) {
|
||||||
// Exact arguments, use ptrcall.
|
// Exact arguments, use ptrcall.
|
||||||
gen->write_call_ptrcall(result, self, method, arguments);
|
gen->write_call_ptrcall(return_addr, self, method, arguments);
|
||||||
} else {
|
} else {
|
||||||
// Not exact arguments, but still can use method bind call.
|
// Not exact arguments, but still can use method bind call.
|
||||||
gen->write_call_method_bind(result, self, method, arguments);
|
gen->write_call_method_bind(return_addr, self, method, arguments);
|
||||||
}
|
}
|
||||||
} else if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") {
|
} else if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") {
|
||||||
GDScriptCodeGenerator::Address self;
|
GDScriptCodeGenerator::Address self;
|
||||||
self.mode = GDScriptCodeGenerator::Address::CLASS;
|
self.mode = GDScriptCodeGenerator::Address::CLASS;
|
||||||
if (within_await) {
|
if (within_await) {
|
||||||
gen->write_call_async(result, self, call->function_name, arguments);
|
gen->write_call_async(return_addr, self, call->function_name, arguments);
|
||||||
} else {
|
} else {
|
||||||
gen->write_call(return_addr, self, call->function_name, arguments);
|
gen->write_call(return_addr, self, call->function_name, arguments);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (within_await) {
|
if (within_await) {
|
||||||
gen->write_call_self_async(result, call->function_name, arguments);
|
gen->write_call_self_async(return_addr, call->function_name, arguments);
|
||||||
} else {
|
} else {
|
||||||
gen->write_call_self(return_addr, call->function_name, arguments);
|
gen->write_call_self(return_addr, call->function_name, arguments);
|
||||||
}
|
}
|
||||||
|
@ -589,18 +589,18 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
if (subscript->is_attribute) {
|
if (subscript->is_attribute) {
|
||||||
// May be static built-in method call.
|
// May be static built-in method call.
|
||||||
if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
|
if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
|
||||||
gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
|
gen->write_call_builtin_type_static(return_addr, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
|
||||||
} else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") &&
|
} else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") &&
|
||||||
ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
|
ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
|
||||||
// It's a static native method call.
|
// It's a static native method call.
|
||||||
gen->write_call_native_static(result, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
|
gen->write_call_native_static(return_addr, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
|
||||||
} else {
|
} else {
|
||||||
GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
|
GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
|
||||||
if (r_error) {
|
if (r_error) {
|
||||||
return GDScriptCodeGenerator::Address();
|
return GDScriptCodeGenerator::Address();
|
||||||
}
|
}
|
||||||
if (within_await) {
|
if (within_await) {
|
||||||
gen->write_call_async(result, base, call->function_name, arguments);
|
gen->write_call_async(return_addr, base, call->function_name, arguments);
|
||||||
} else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
|
} else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
|
||||||
// Native method, use faster path.
|
// Native method, use faster path.
|
||||||
StringName class_name;
|
StringName class_name;
|
||||||
|
@ -613,16 +613,16 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
MethodBind *method = ClassDB::get_method(class_name, call->function_name);
|
MethodBind *method = ClassDB::get_method(class_name, call->function_name);
|
||||||
if (_have_exact_arguments(method, arguments)) {
|
if (_have_exact_arguments(method, arguments)) {
|
||||||
// Exact arguments, use ptrcall.
|
// Exact arguments, use ptrcall.
|
||||||
gen->write_call_ptrcall(result, base, method, arguments);
|
gen->write_call_ptrcall(return_addr, base, method, arguments);
|
||||||
} else {
|
} else {
|
||||||
// Not exact arguments, but still can use method bind call.
|
// Not exact arguments, but still can use method bind call.
|
||||||
gen->write_call_method_bind(result, base, method, arguments);
|
gen->write_call_method_bind(return_addr, base, method, arguments);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gen->write_call(return_addr, base, call->function_name, arguments);
|
gen->write_call(return_addr, base, call->function_name, arguments);
|
||||||
}
|
}
|
||||||
} else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
|
} else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
|
||||||
gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments);
|
gen->write_call_builtin_type(return_addr, base, base.type.builtin_type, call->function_name, arguments);
|
||||||
} else {
|
} else {
|
||||||
gen->write_call(return_addr, base, call->function_name, arguments);
|
gen->write_call(return_addr, base, call->function_name, arguments);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1533,8 +1533,28 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
Callable::CallError err;
|
Callable::CallError err;
|
||||||
if (call_ret) {
|
if (call_ret) {
|
||||||
GET_INSTRUCTION_ARG(ret, argc + 1);
|
GET_INSTRUCTION_ARG(ret, argc + 1);
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
Variant::Type base_type = base->get_type();
|
||||||
|
Object *base_obj = base->get_validated_object();
|
||||||
|
StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
|
||||||
|
#endif
|
||||||
base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
|
base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (ret->get_type() == Variant::NIL) {
|
||||||
|
if (base_type == Variant::OBJECT) {
|
||||||
|
if (base_obj) {
|
||||||
|
MethodBind *method = ClassDB::get_method(base_class, *methodname);
|
||||||
|
if (*methodname == CoreStringNames::get_singleton()->_free || (method && !method->has_return())) {
|
||||||
|
err_text = R"(Trying to get a return value of a method that returns "void")";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Variant::has_builtin_method(base_type, *methodname) && !Variant::has_builtin_method_return_value(base_type, *methodname)) {
|
||||||
|
err_text = R"(Trying to get a return value of a method that returns "void")";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!call_async && ret->get_type() == Variant::OBJECT) {
|
if (!call_async && ret->get_type() == Variant::OBJECT) {
|
||||||
// Check if getting a function state without await.
|
// Check if getting a function state without await.
|
||||||
bool was_freed = false;
|
bool was_freed = false;
|
||||||
|
|
|
@ -80,10 +80,6 @@ String GDScriptWarning::get_message() const {
|
||||||
case STANDALONE_EXPRESSION: {
|
case STANDALONE_EXPRESSION: {
|
||||||
return "Standalone expression (the line has no effect).";
|
return "Standalone expression (the line has no effect).";
|
||||||
} break;
|
} break;
|
||||||
case VOID_ASSIGNMENT: {
|
|
||||||
CHECK_SYMBOLS(1);
|
|
||||||
return "Assignment operation, but the function '" + symbols[0] + "()' returns void.";
|
|
||||||
} break;
|
|
||||||
case NARROWING_CONVERSION: {
|
case NARROWING_CONVERSION: {
|
||||||
return "Narrowing conversion (float is converted to int and loses precision).";
|
return "Narrowing conversion (float is converted to int and loses precision).";
|
||||||
} break;
|
} break;
|
||||||
|
@ -202,7 +198,6 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
|
||||||
"UNREACHABLE_CODE",
|
"UNREACHABLE_CODE",
|
||||||
"UNREACHABLE_PATTERN",
|
"UNREACHABLE_PATTERN",
|
||||||
"STANDALONE_EXPRESSION",
|
"STANDALONE_EXPRESSION",
|
||||||
"VOID_ASSIGNMENT",
|
|
||||||
"NARROWING_CONVERSION",
|
"NARROWING_CONVERSION",
|
||||||
"INCOMPATIBLE_TERNARY",
|
"INCOMPATIBLE_TERNARY",
|
||||||
"UNUSED_SIGNAL",
|
"UNUSED_SIGNAL",
|
||||||
|
|
|
@ -57,7 +57,6 @@ public:
|
||||||
UNREACHABLE_CODE, // Code after a return statement.
|
UNREACHABLE_CODE, // Code after a return statement.
|
||||||
UNREACHABLE_PATTERN, // Pattern in a match statement after a catch all pattern (wildcard or bind).
|
UNREACHABLE_PATTERN, // Pattern in a match statement after a catch all pattern (wildcard or bind).
|
||||||
STANDALONE_EXPRESSION, // Expression not assigned to a variable.
|
STANDALONE_EXPRESSION, // Expression not assigned to a variable.
|
||||||
VOID_ASSIGNMENT, // Function returns void but it's assigned to a variable.
|
|
||||||
NARROWING_CONVERSION, // Float value into an integer slot, precision is lost.
|
NARROWING_CONVERSION, // Float value into an integer slot, precision is lost.
|
||||||
INCOMPATIBLE_TERNARY, // Possible values of a ternary if are not mutually compatible.
|
INCOMPATIBLE_TERNARY, // Possible values of a ternary if are not mutually compatible.
|
||||||
UNUSED_SIGNAL, // Signal is defined but never emitted.
|
UNUSED_SIGNAL, // Signal is defined but never emitted.
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
func test():
|
||||||
|
var builtin := []
|
||||||
|
print(builtin.reverse()) # Built-in type method.
|
|
@ -0,0 +1,2 @@
|
||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Cannot get return value of call to "reverse()" because it returns "void".
|
|
@ -0,0 +1,5 @@
|
||||||
|
func foo() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func test():
|
||||||
|
print(foo()) # Custom method.
|
|
@ -0,0 +1,2 @@
|
||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Cannot get return value of call to "foo()" because it returns "void".
|
|
@ -0,0 +1,2 @@
|
||||||
|
func test():
|
||||||
|
print(print_debug()) # GDScript utility function.
|
|
@ -0,0 +1,2 @@
|
||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Cannot get return value of call to "print_debug()" because it returns "void".
|
|
@ -0,0 +1,3 @@
|
||||||
|
func test():
|
||||||
|
var obj := Node.new()
|
||||||
|
print(obj.free()) # Native type method.
|
|
@ -0,0 +1,2 @@
|
||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Cannot get return value of call to "free()" because it returns "void".
|
|
@ -0,0 +1,2 @@
|
||||||
|
func test():
|
||||||
|
print(print()) # Built-in utility function.
|
|
@ -0,0 +1,2 @@
|
||||||
|
GDTEST_ANALYZER_ERROR
|
||||||
|
Cannot get return value of call to "print()" because it returns "void".
|
|
@ -1,6 +0,0 @@
|
||||||
func i_return_void() -> void:
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
func test():
|
|
||||||
var __ = i_return_void()
|
|
|
@ -1,5 +0,0 @@
|
||||||
GDTEST_OK
|
|
||||||
>> WARNING
|
|
||||||
>> Line: 6
|
|
||||||
>> VOID_ASSIGNMENT
|
|
||||||
>> Assignment operation, but the function 'i_return_void()' returns void.
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
func test():
|
||||||
|
var obj
|
||||||
|
obj = Node.new()
|
||||||
|
print(obj.free())
|
|
@ -0,0 +1,6 @@
|
||||||
|
GDTEST_RUNTIME_ERROR
|
||||||
|
>> SCRIPT ERROR
|
||||||
|
>> on function: test()
|
||||||
|
>> runtime/errors/use_return_value_of_free_call.gd
|
||||||
|
>> 4
|
||||||
|
>> Trying to get a return value of a method that returns "void"
|
|
@ -0,0 +1,4 @@
|
||||||
|
func test():
|
||||||
|
var value
|
||||||
|
value = []
|
||||||
|
print(value.reverse())
|
|
@ -0,0 +1,6 @@
|
||||||
|
GDTEST_RUNTIME_ERROR
|
||||||
|
>> SCRIPT ERROR
|
||||||
|
>> on function: test()
|
||||||
|
>> runtime/errors/use_return_value_of_void_builtin_method_call.gd
|
||||||
|
>> 4
|
||||||
|
>> Trying to get a return value of a method that returns "void"
|
|
@ -0,0 +1,4 @@
|
||||||
|
func test():
|
||||||
|
var obj
|
||||||
|
obj = RefCounted.new()
|
||||||
|
print(obj.notify_property_list_changed())
|
|
@ -0,0 +1,6 @@
|
||||||
|
GDTEST_RUNTIME_ERROR
|
||||||
|
>> SCRIPT ERROR
|
||||||
|
>> on function: test()
|
||||||
|
>> runtime/errors/use_return_value_of_void_native_method_call.gd
|
||||||
|
>> 4
|
||||||
|
>> Trying to get a return value of a method that returns "void"
|
|
@ -15,10 +15,10 @@ func test():
|
||||||
var string_array: Array[String] = []
|
var string_array: Array[String] = []
|
||||||
var stringname_array: Array[StringName] = []
|
var stringname_array: Array[StringName] = []
|
||||||
|
|
||||||
assert(!string_array.push_back(&"abc"))
|
string_array.push_back(&"abc")
|
||||||
print("Array[String] insert converted: ", typeof(string_array[0]) == TYPE_STRING)
|
print("Array[String] insert converted: ", typeof(string_array[0]) == TYPE_STRING)
|
||||||
|
|
||||||
assert(!stringname_array.push_back("abc"))
|
stringname_array.push_back("abc")
|
||||||
print("Array[StringName] insert converted: ", typeof(stringname_array[0]) == TYPE_STRING_NAME)
|
print("Array[StringName] insert converted: ", typeof(stringname_array[0]) == TYPE_STRING_NAME)
|
||||||
|
|
||||||
print("StringName in Array[String]: ", &"abc" in string_array)
|
print("StringName in Array[String]: ", &"abc" in string_array)
|
||||||
|
@ -28,8 +28,8 @@ func test():
|
||||||
assert(!packed_string_array.push_back("abc"))
|
assert(!packed_string_array.push_back("abc"))
|
||||||
print("StringName in PackedStringArray: ", &"abc" in packed_string_array)
|
print("StringName in PackedStringArray: ", &"abc" in packed_string_array)
|
||||||
|
|
||||||
assert(!string_array.push_back("abc"))
|
string_array.push_back("abc")
|
||||||
print("StringName finds String in Array: ", string_array.find(&"abc"))
|
print("StringName finds String in Array: ", string_array.find(&"abc"))
|
||||||
|
|
||||||
assert(!stringname_array.push_back(&"abc"))
|
stringname_array.push_back(&"abc")
|
||||||
print("String finds StringName in Array: ", stringname_array.find("abc"))
|
print("String finds StringName in Array: ", stringname_array.find("abc"))
|
||||||
|
|
Loading…
Reference in a new issue