diff options
Diffstat (limited to 'modules')
240 files changed, 2863 insertions, 75 deletions
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index fc876a81cf..ed05e51e53 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -87,8 +87,8 @@ RID BulletPhysicsServer3D::shape_create(ShapeType p_shape) { ShapeBullet *shape = nullptr; switch (p_shape) { - case SHAPE_PLANE: { - shape = bulletnew(PlaneShapeBullet); + case SHAPE_WORLD_BOUNDARY: { + shape = bulletnew(WorldBoundaryShapeBullet); } break; case SHAPE_SPHERE: { shape = bulletnew(SphereShapeBullet); diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 40e785d699..88ffb9ec67 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -110,7 +110,7 @@ btEmptyShape *ShapeBullet::create_shape_empty() { return bulletnew(btEmptyShape); } -btStaticPlaneShape *ShapeBullet::create_shape_plane(const btVector3 &planeNormal, btScalar planeConstant) { +btStaticPlaneShape *ShapeBullet::create_shape_world_boundary(const btVector3 &planeNormal, btScalar planeConstant) { return bulletnew(btStaticPlaneShape(planeNormal, planeConstant)); } @@ -164,32 +164,32 @@ btRayShape *ShapeBullet::create_shape_ray(real_t p_length, bool p_slips_on_slope return r; } -/* PLANE */ +/* World boundary */ -PlaneShapeBullet::PlaneShapeBullet() : +WorldBoundaryShapeBullet::WorldBoundaryShapeBullet() : ShapeBullet() {} -void PlaneShapeBullet::set_data(const Variant &p_data) { +void WorldBoundaryShapeBullet::set_data(const Variant &p_data) { setup(p_data); } -Variant PlaneShapeBullet::get_data() const { +Variant WorldBoundaryShapeBullet::get_data() const { return plane; } -PhysicsServer3D::ShapeType PlaneShapeBullet::get_type() const { - return PhysicsServer3D::SHAPE_PLANE; +PhysicsServer3D::ShapeType WorldBoundaryShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_WORLD_BOUNDARY; } -void PlaneShapeBullet::setup(const Plane &p_plane) { +void WorldBoundaryShapeBullet::setup(const Plane &p_plane) { plane = p_plane; notifyShapeChanged(); } -btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *WorldBoundaryShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btVector3 btPlaneNormal; G_TO_B(plane.normal, btPlaneNormal); - return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d)); + return prepare(WorldBoundaryShapeBullet::create_shape_world_boundary(btPlaneNormal, plane.d)); } /* Sphere */ diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index 5080d13d99..0822399b5e 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -81,7 +81,7 @@ public: public: static class btEmptyShape *create_shape_empty(); - static class btStaticPlaneShape *create_shape_plane(const btVector3 &planeNormal, btScalar planeConstant); + static class btStaticPlaneShape *create_shape_world_boundary(const btVector3 &planeNormal, btScalar planeConstant); static class btSphereShape *create_shape_sphere(btScalar radius); static class btBoxShape *create_shape_box(const btVector3 &boxHalfExtents); static class btCapsuleShape *create_shape_capsule(btScalar radius, btScalar height); @@ -93,11 +93,11 @@ public: static class btRayShape *create_shape_ray(real_t p_length, bool p_slips_on_slope); }; -class PlaneShapeBullet : public ShapeBullet { +class WorldBoundaryShapeBullet : public ShapeBullet { Plane plane; public: - PlaneShapeBullet(); + WorldBoundaryShapeBullet(); virtual void set_data(const Variant &p_data); virtual Variant get_data() const; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 06db46173c..ceb6d5a5f0 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -253,6 +253,9 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, int extends_index = 0; if (!p_class->extends_path.is_empty()) { + if (p_class->extends_path.is_relative_path()) { + p_class->extends_path = class_type.script_path.get_base_dir().plus_file(p_class->extends_path).simplify_path(); + } Ref<GDScriptParserRef> parser = get_parser_for(p_class->extends_path); if (parser.is_null()) { push_error(vformat(R"(Could not resolve super class path "%s".)", p_class->extends_path), p_class); @@ -1184,12 +1187,28 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { } } - if (!list_resolved) { + GDScriptParser::DataType variable_type; + if (list_resolved) { + variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + variable_type.kind = GDScriptParser::DataType::BUILTIN; + variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else? + p_for->variable->set_datatype(variable_type); + } else { resolve_node(p_for->list); + if (p_for->list->datatype.has_container_element_type()) { + variable_type = p_for->list->datatype.get_container_element_type(); + variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + } else if (p_for->list->datatype.is_typed_container_type()) { + variable_type = p_for->list->datatype.get_typed_container_type(); + variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + } else { + // Last resort + // TODO: Must other cases be handled? Must we mark as unsafe? + variable_type.type_source = GDScriptParser::DataType::UNDETECTED; + variable_type.kind = GDScriptParser::DataType::VARIANT; + } } - - // TODO: If list is a typed array, the variable should be an element. - // Also applicable for constant range() (so variable is int or float). + p_for->variable->set_datatype(variable_type); resolve_suite(p_for->loop); p_for->set_datatype(p_for->loop->get_datatype()); @@ -1477,8 +1496,7 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame } if (p_parameter->datatype_specifier != nullptr) { - resolve_datatype(p_parameter->datatype_specifier); - result = p_parameter->datatype_specifier->get_datatype(); + result = resolve_datatype(p_parameter->datatype_specifier); result.is_meta_type = false; if (p_parameter->default_value != nullptr) { @@ -1490,6 +1508,10 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame } } + if (result.builtin_type == Variant::Type::NIL && result.type_source == GDScriptParser::DataType::ANNOTATED_INFERRED && p_parameter->datatype_specifier == nullptr) { + push_error(vformat(R"(Could not infer the type of the variable "%s" because the initial value is "null".)", p_parameter->identifier->name), p_parameter->default_value); + } + p_parameter->set_datatype(result); } @@ -1760,6 +1782,15 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig identifier->variable_source->set_datatype(id_type); } } break; + case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER: { + GDScriptParser::DataType id_type = identifier->parameter_source->get_datatype(); + if (!id_type.is_hard_type()) { + id_type = assigned_value_type; + id_type.type_source = GDScriptParser::DataType::INFERRED; + id_type.is_constant = false; + identifier->parameter_source->set_datatype(id_type); + } + } break; case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: { GDScriptParser::DataType id_type = identifier->variable_source->get_datatype(); if (!id_type.is_hard_type()) { @@ -2421,13 +2452,15 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod p_identifier->is_constant = true; p_identifier->reduced_value = result; p_identifier->set_datatype(type_from_variant(result, p_identifier)); - } else { + } else if (base.is_hard_type()) { push_error(vformat(R"(Cannot find constant "%s" on type "%s".)", name, base.to_string()), p_identifier); } } else { switch (base.builtin_type) { case Variant::NIL: { - push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier); + if (base.is_hard_type()) { + push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier); + } return; } case Variant::DICTIONARY: { @@ -2448,7 +2481,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod return; } } - push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); + if (base.is_hard_type()) { + push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); + } } } } diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 07f50d14dc..8121053245 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -51,7 +51,9 @@ GDScriptParser *GDScriptParserRef::get_parser() const { Error GDScriptParserRef::raise_status(Status p_new_status) { ERR_FAIL_COND_V(parser == nullptr, ERR_INVALID_DATA); - Error result = OK; + if (result != OK) { + return result; + } while (p_new_status > status) { switch (status) { @@ -86,14 +88,6 @@ Error GDScriptParserRef::raise_status(Status p_new_status) { } } if (result != OK) { - if (parser != nullptr) { - memdelete(parser); - parser = nullptr; - } - if (analyzer != nullptr) { - memdelete(analyzer); - analyzer = nullptr; - } return result; } } diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h index 943638d29f..9fb661d031 100644 --- a/modules/gdscript/gdscript_cache.h +++ b/modules/gdscript/gdscript_cache.h @@ -54,6 +54,7 @@ private: GDScriptParser *parser = nullptr; GDScriptAnalyzer *analyzer = nullptr; Status status = EMPTY; + Error result = OK; String path; friend class GDScriptCache; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index b0d0b02443..a8aef84db3 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -440,7 +440,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code break; case GDScriptParser::DictionaryNode::LUA_TABLE: // Lua-style: key is an identifier interpreted as StringName. - StringName key = static_cast<const GDScriptParser::IdentifierNode *>(dn->elements[i].key)->name; + StringName key = dn->elements[i].key->reduced_value.operator StringName(); element = codegen.add_constant(key); break; } @@ -964,7 +964,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code // Perform operator if any. if (assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) { - GDScriptCodeGenerator::Address value = codegen.add_temporary(); + GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype())); if (subscript->is_attribute) { gen->write_get_named(value, name, prev_base); } else { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 19584ce194..c901d9f68f 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2123,22 +2123,34 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_unary_operator(ExpressionN operation->operation = UnaryOpNode::OP_NEGATIVE; operation->variant_op = Variant::OP_NEGATE; operation->operand = parse_precedence(PREC_SIGN, false); + if (operation->operand == nullptr) { + push_error(R"(Expected expression after "-" operator.)"); + } break; case GDScriptTokenizer::Token::PLUS: operation->operation = UnaryOpNode::OP_POSITIVE; operation->variant_op = Variant::OP_POSITIVE; operation->operand = parse_precedence(PREC_SIGN, false); + if (operation->operand == nullptr) { + push_error(R"(Expected expression after "+" operator.)"); + } break; case GDScriptTokenizer::Token::TILDE: operation->operation = UnaryOpNode::OP_COMPLEMENT; operation->variant_op = Variant::OP_BIT_NEGATE; operation->operand = parse_precedence(PREC_BIT_NOT, false); + if (operation->operand == nullptr) { + push_error(R"(Expected expression after "~" operator.)"); + } break; case GDScriptTokenizer::Token::NOT: case GDScriptTokenizer::Token::BANG: operation->operation = UnaryOpNode::OP_LOGIC_NOT; operation->variant_op = Variant::OP_NOT; operation->operand = parse_precedence(PREC_LOGIC_NOT, false); + if (operation->operand == nullptr) { + push_error(vformat(R"(Expected expression after "%s" operator.)", op_type == GDScriptTokenizer::Token::NOT ? "not" : "!")); + } break; default: return nullptr; // Unreachable. @@ -2275,6 +2287,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(Expressio operation->false_expr = parse_precedence(PREC_TERNARY, false); + if (operation->false_expr == nullptr) { + push_error(R"(Expected expression after "else".)"); + } + return operation; } @@ -2472,8 +2488,13 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode switch (dictionary->style) { case DictionaryNode::LUA_TABLE: - if (key != nullptr && key->type != Node::IDENTIFIER) { - push_error("Expected identifier as LUA-style dictionary key."); + if (key != nullptr && key->type != Node::IDENTIFIER && key->type != Node::LITERAL) { + push_error("Expected identifier or string as LUA-style dictionary key."); + advance(); + break; + } + if (key != nullptr && key->type == Node::LITERAL && static_cast<LiteralNode *>(key)->value.get_type() != Variant::STRING) { + push_error("Expected identifier or string as LUA-style dictionary key."); advance(); break; } @@ -2487,7 +2508,11 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode } if (key != nullptr) { key->is_constant = true; - key->reduced_value = static_cast<IdentifierNode *>(key)->name; + if (key->type == Node::IDENTIFIER) { + key->reduced_value = static_cast<IdentifierNode *>(key)->name; + } else if (key->type == Node::LITERAL) { + key->reduced_value = StringName(static_cast<LiteralNode *>(key)->value.operator String()); + } } break; case DictionaryNode::PYTHON_DICT: @@ -2567,6 +2592,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode * subscript->base = p_previous_operand; subscript->index = parse_expression(false); + if (subscript->index == nullptr) { + push_error(R"(Expected expression after "[".)"); + } + pop_multiline(); consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected "]" after subscription index.)"); @@ -3562,6 +3591,39 @@ String GDScriptParser::DataType::to_string() const { ERR_FAIL_V_MSG("<unresolved type", "Kind set outside the enum range."); } +static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_type) { + switch (p_type) { + case Variant::PACKED_BYTE_ARRAY: + case Variant::PACKED_INT32_ARRAY: + case Variant::PACKED_INT64_ARRAY: + return Variant::INT; + case Variant::PACKED_FLOAT32_ARRAY: + case Variant::PACKED_FLOAT64_ARRAY: + return Variant::FLOAT; + case Variant::PACKED_STRING_ARRAY: + return Variant::STRING; + case Variant::PACKED_VECTOR2_ARRAY: + return Variant::VECTOR2; + case Variant::PACKED_VECTOR3_ARRAY: + return Variant::VECTOR3; + case Variant::PACKED_COLOR_ARRAY: + return Variant::COLOR; + default: + return Variant::NIL; + } +} + +bool GDScriptParser::DataType::is_typed_container_type() const { + return kind == GDScriptParser::DataType::BUILTIN && _variant_type_to_typed_array_element_type(builtin_type) != Variant::NIL; +} + +GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() const { + GDScriptParser::DataType type; + type.kind = GDScriptParser::DataType::BUILTIN; + type.builtin_type = _variant_type_to_typed_array_element_type(builtin_type); + return type; +} + /*---------- PRETTY PRINT FOR DEBUG ----------*/ #ifdef DEBUG_ENABLED diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 4902f0d4a6..a641c1052d 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -161,6 +161,10 @@ public: container_element_type = nullptr; } + bool is_typed_container_type() const; + + GDScriptParser::DataType get_typed_container_type() const; + bool operator==(const DataType &p_other) const { if (type_source == UNDETECTED || p_other.type_source == UNDETECTED) { return true; // Can be consireded equal for parsing purposes. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_left_operand.gd b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_left_operand.gd new file mode 100644 index 0000000000..9b722ea50a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_left_operand.gd @@ -0,0 +1,3 @@ +func test(): + # Error here. + print(2.2 << 4) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_left_operand.out b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_left_operand.out new file mode 100644 index 0000000000..7dee854d1a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_left_operand.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid operands to operator <<, float and int. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_right_operand.gd b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_right_operand.gd new file mode 100644 index 0000000000..4502960105 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_right_operand.gd @@ -0,0 +1,3 @@ +func test(): + # Error here. + print(2 << 4.4) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_right_operand.out b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_right_operand.out new file mode 100644 index 0000000000..1879fc1adf --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/bitwise_float_right_operand.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid operands to operator <<, int and float. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_used_as_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/constant_used_as_function.gd new file mode 100644 index 0000000000..0ad2337c15 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_used_as_function.gd @@ -0,0 +1,5 @@ +const CONSTANT = 25 + + +func test(): + CONSTANT(123) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_used_as_function.out b/modules/gdscript/tests/scripts/analyzer/errors/constant_used_as_function.out new file mode 100644 index 0000000000..f4051cd02c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_used_as_function.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Member "CONSTANT" is not a function. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd new file mode 100644 index 0000000000..7a922cd73e --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd @@ -0,0 +1,6 @@ +func test(): + var lua_dict = { + a = 1, + b = 2, + a = 3, # Duplicate isn't allowed. + } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out new file mode 100644 index 0000000000..ffdfa56645 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Key "a" was already used in this dictionary (at line 3). diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd new file mode 100644 index 0000000000..933e737ac7 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd @@ -0,0 +1,6 @@ +func test(): + var lua_dict_with_string = { + a = 1, + b = 2, + "a" = 3, # Duplicate isn't allowed. + } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out new file mode 100644 index 0000000000..ffdfa56645 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Key "a" was already used in this dictionary (at line 3). diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd new file mode 100644 index 0000000000..3b8c83e9cb --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd @@ -0,0 +1,6 @@ +func test(): + var python_dict = { + "a": 1, + "b": 2, + "a": 3, # Duplicate isn't allowed. + } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out new file mode 100644 index 0000000000..ffdfa56645 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Key "a" was already used in this dictionary (at line 3). diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_float_value.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_float_value.gd new file mode 100644 index 0000000000..cf9a0ce038 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_float_value.gd @@ -0,0 +1,7 @@ +enum Size { + # Error here. Enum values must be integers. + S = 0.0, +} + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_float_value.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_float_value.out new file mode 100644 index 0000000000..b315d20508 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_float_value.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Enum values must be integers. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_string_value.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_string_value.gd new file mode 100644 index 0000000000..cd9b8fabc4 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_string_value.gd @@ -0,0 +1,7 @@ +enum Size { + # Error here. Enum values must be integers. + S = "hello", +} + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_string_value.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_string_value.out new file mode 100644 index 0000000000..b315d20508 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_string_value.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Enum values must be integers. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_used_as_property.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_used_as_property.gd new file mode 100644 index 0000000000..4346503fc2 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_used_as_property.gd @@ -0,0 +1,6 @@ +func function(): + pass + + +func test(): + function = 25 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_used_as_property.out b/modules/gdscript/tests/scripts/analyzer/errors/function_used_as_property.out new file mode 100644 index 0000000000..5275183da2 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_used_as_property.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot assign a new value to a constant. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.gd b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.gd new file mode 100644 index 0000000000..b8c0b7a8d3 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.gd @@ -0,0 +1,3 @@ +func test(): + # Error here. Array indices must be integers. + print([0, 1][true]) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out new file mode 100644 index 0000000000..015ad756f8 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid index type "bool" for a base of type "Array". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_bool.gd b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_bool.gd new file mode 100644 index 0000000000..c159e03140 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_bool.gd @@ -0,0 +1,2 @@ +func test(): + print(true + true) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_bool.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_bool.out new file mode 100644 index 0000000000..c1dc7c7d08 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_bool.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid operands to operator +, bool and bool. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_dictionary.gd b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_dictionary.gd new file mode 100644 index 0000000000..6aec2e0796 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_dictionary.gd @@ -0,0 +1,2 @@ +func test(): + print({"hello": "world"} + {"godot": "engine"}) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_dictionary.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_dictionary.out new file mode 100644 index 0000000000..1b4451edbe --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_dictionary.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid operands "Dictionary" and "Dictionary" for "+" operator. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_mixed.gd b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_mixed.gd new file mode 100644 index 0000000000..eb2a6a0ce7 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_mixed.gd @@ -0,0 +1,2 @@ +func test(): + print("hello" + ["world"]) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_mixed.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_mixed.out new file mode 100644 index 0000000000..6d44c6c1bd --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_concatenation_mixed.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid operands "String" and "Array" for "+" operator. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_constant.gd b/modules/gdscript/tests/scripts/analyzer/errors/invalid_constant.gd new file mode 100644 index 0000000000..a7426e88da --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_constant.gd @@ -0,0 +1,5 @@ +func test(): + var i = 12 + # Constants must be made of a constant, deterministic expression. + # A constant that depends on a variable's value is not a constant expression. + const TEST = 13 + i diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_constant.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_constant.out new file mode 100644 index 0000000000..c40830f123 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_constant.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Assigned value for constant "TEST" isn't a constant expression. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/leading_number_separator.gd b/modules/gdscript/tests/scripts/analyzer/errors/leading_number_separator.gd new file mode 100644 index 0000000000..d88c02d6ee --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/leading_number_separator.gd @@ -0,0 +1,3 @@ +func test(): + # Number separators may not be placed at the beginning of a number. + var __ = _123 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/leading_number_separator.out b/modules/gdscript/tests/scripts/analyzer/errors/leading_number_separator.out new file mode 100644 index 0000000000..cfb558bf45 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/leading_number_separator.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Identifier "_123" not declared in the current scope. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/missing_argument.gd b/modules/gdscript/tests/scripts/analyzer/errors/missing_argument.gd new file mode 100644 index 0000000000..70bdadf291 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/missing_argument.gd @@ -0,0 +1,6 @@ +func args(a, b): + print(a) + print(b) + +func test(): + args(1,) diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_argument.out b/modules/gdscript/tests/scripts/analyzer/errors/missing_argument.out index fc2a891109..fc2a891109 100644 --- a/modules/gdscript/tests/scripts/parser/errors/missing_argument.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/missing_argument.out diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_used_as_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/property_used_as_function.gd new file mode 100644 index 0000000000..059d774927 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_used_as_function.gd @@ -0,0 +1,4 @@ +var property = 25 + +func test(): + property() diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_used_as_function.out b/modules/gdscript/tests/scripts/analyzer/errors/property_used_as_function.out new file mode 100644 index 0000000000..94d6c26a1a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_used_as_function.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Member "property" is not a function. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/redefine_class_constant.gd b/modules/gdscript/tests/scripts/analyzer/errors/redefine_class_constant.gd new file mode 100644 index 0000000000..91401d32fc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/redefine_class_constant.gd @@ -0,0 +1,7 @@ +# See also `parser-warnings/shadowed-constant.gd`. +const TEST = 25 + + +func test(): + # Error here (trying to set a new value to a constant). + TEST = 50 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/redefine_class_constant.out b/modules/gdscript/tests/scripts/analyzer/errors/redefine_class_constant.out new file mode 100644 index 0000000000..5275183da2 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/redefine_class_constant.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot assign a new value to a constant. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/redefine_local_constant.gd b/modules/gdscript/tests/scripts/analyzer/errors/redefine_local_constant.gd new file mode 100644 index 0000000000..97f3e55e81 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/redefine_local_constant.gd @@ -0,0 +1,5 @@ +func test(): + const TEST = 25 + + # Error here (can't assign a new value to a constant). + TEST = 50 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/redefine_local_constant.out b/modules/gdscript/tests/scripts/analyzer/errors/redefine_local_constant.out new file mode 100644 index 0000000000..5275183da2 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/redefine_local_constant.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot assign a new value to a constant. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/super_nonexistent_base_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/super_nonexistent_base_method.gd new file mode 100644 index 0000000000..722a8fcdb7 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/super_nonexistent_base_method.gd @@ -0,0 +1,11 @@ +# `class` extends RefCounted by default. +class Say: + func say(): + super() + print("say something") + + +func test(): + # RefCounted doesn't have a `say()` method, so the `super()` call in the method + # definition will cause a run-time error. + Say.new().say() diff --git a/modules/gdscript/tests/scripts/analyzer/errors/super_nonexistent_base_method.out b/modules/gdscript/tests/scripts/analyzer/errors/super_nonexistent_base_method.out new file mode 100644 index 0000000000..e3dbf81850 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/super_nonexistent_base_method.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Function "say()" not found in base RefCounted. diff --git a/modules/gdscript/tests/scripts/analyzer/features/as.gd b/modules/gdscript/tests/scripts/analyzer/features/as.gd new file mode 100644 index 0000000000..13a36147c0 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/as.gd @@ -0,0 +1,16 @@ +func test(): + var some_bool = 5 as bool + var some_int = 5 as int + var some_float = 5 as float + print(typeof(some_bool)) + print(typeof(some_int)) + print(typeof(some_float)) + + print() + + var some_bool_typed := 5 as bool + var some_int_typed := 5 as int + var some_float_typed := 5 as float + print(typeof(some_bool_typed)) + print(typeof(some_int_typed)) + print(typeof(some_float_typed)) diff --git a/modules/gdscript/tests/scripts/analyzer/features/as.out b/modules/gdscript/tests/scripts/analyzer/features/as.out new file mode 100644 index 0000000000..bcf84aa6f6 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/as.out @@ -0,0 +1,8 @@ +GDTEST_OK +1 +2 +3 + +1 +2 +3 diff --git a/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.gd b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.gd new file mode 100644 index 0000000000..f64dce26c9 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.gd @@ -0,0 +1,9 @@ +func inferred_parameter(param = null): + if param == null: + param = Node.new() + param.name = "Ok" + print(param.name) + param.free() + +func test(): + inferred_parameter() diff --git a/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out new file mode 100644 index 0000000000..0e9f482af4 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out @@ -0,0 +1,2 @@ +GDTEST_OK +Ok diff --git a/modules/gdscript/tests/scripts/parser/errors/array_consecutive_commas.gd b/modules/gdscript/tests/scripts/parser/errors/array_consecutive_commas.gd new file mode 100644 index 0000000000..b45f99fdd0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/array_consecutive_commas.gd @@ -0,0 +1,3 @@ +func test(): + # Arrays with consecutive commas are not allowed. + var array = ["arrays",,,,] diff --git a/modules/gdscript/tests/scripts/parser/errors/array_consecutive_commas.out b/modules/gdscript/tests/scripts/parser/errors/array_consecutive_commas.out new file mode 100644 index 0000000000..4ef8526065 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/array_consecutive_commas.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression as array element. diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_2_equal_signs.gd b/modules/gdscript/tests/scripts/parser/errors/assignment_2_equal_signs.gd new file mode 100644 index 0000000000..17d5e078e5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_2_equal_signs.gd @@ -0,0 +1,2 @@ +func test(): + var hello == "world" diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_2_equal_signs.out b/modules/gdscript/tests/scripts/parser/errors/assignment_2_equal_signs.out new file mode 100644 index 0000000000..b150fc0d16 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_2_equal_signs.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected end of statement after variable declaration, found "==" instead. diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_3_equal_signs.gd b/modules/gdscript/tests/scripts/parser/errors/assignment_3_equal_signs.gd new file mode 100644 index 0000000000..8b5f620889 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_3_equal_signs.gd @@ -0,0 +1,2 @@ +func test(): + var hello === "world" diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_3_equal_signs.out b/modules/gdscript/tests/scripts/parser/errors/assignment_3_equal_signs.out new file mode 100644 index 0000000000..b150fc0d16 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_3_equal_signs.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected end of statement after variable declaration, found "==" instead. diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_in_if.gd b/modules/gdscript/tests/scripts/parser/errors/assignment_in_if.gd new file mode 100644 index 0000000000..8c3a908532 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_in_if.gd @@ -0,0 +1,4 @@ +func test(): + # Error here. + if foo = 25: + print(foo) diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_in_if.out b/modules/gdscript/tests/scripts/parser/errors/assignment_in_if.out new file mode 100644 index 0000000000..e8f9130706 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_in_if.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Assignment is not allowed inside an expression. diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_in_var.gd b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var.gd new file mode 100644 index 0000000000..126a3227ea --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var.gd @@ -0,0 +1,2 @@ +func test(): + var hello = "world" = "test" diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_in_var.out b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var.out new file mode 100644 index 0000000000..e8f9130706 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Assignment is not allowed inside an expression. diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_in_var_if.gd b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var_if.gd new file mode 100644 index 0000000000..a99557fa3c --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var_if.gd @@ -0,0 +1,4 @@ +func test(): + # Error here. + if var foo = 25: + print(foo) diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_in_var_if.out b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var_if.out new file mode 100644 index 0000000000..e84f4652ac --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_in_var_if.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected conditional expression after "if". diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_without_identifier.gd b/modules/gdscript/tests/scripts/parser/errors/assignment_without_identifier.gd new file mode 100644 index 0000000000..031ea523c8 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_without_identifier.gd @@ -0,0 +1,2 @@ +func test(): + var = "world" diff --git a/modules/gdscript/tests/scripts/parser/errors/assignment_without_identifier.out b/modules/gdscript/tests/scripts/parser/errors/assignment_without_identifier.out new file mode 100644 index 0000000000..a4bd8beef1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/assignment_without_identifier.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected variable name after "var". diff --git a/modules/gdscript/tests/scripts/parser/errors/binary_complement_without_argument.gd b/modules/gdscript/tests/scripts/parser/errors/binary_complement_without_argument.gd new file mode 100644 index 0000000000..b52a6defcb --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/binary_complement_without_argument.gd @@ -0,0 +1,2 @@ +func test(): + print(~) diff --git a/modules/gdscript/tests/scripts/parser/errors/binary_complement_without_argument.out b/modules/gdscript/tests/scripts/parser/errors/binary_complement_without_argument.out new file mode 100644 index 0000000000..ceabe42d3c --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/binary_complement_without_argument.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "~" operator. diff --git a/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument.gd b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument.gd new file mode 100644 index 0000000000..b3ea1ba1f6 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument.gd @@ -0,0 +1,2 @@ +func test(): + print(not) diff --git a/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument.out b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument.out new file mode 100644 index 0000000000..6cf191ea98 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "not" operator. diff --git a/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument_using_bang.gd b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument_using_bang.gd new file mode 100644 index 0000000000..8a33079193 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument_using_bang.gd @@ -0,0 +1,2 @@ +func test(): + print(!) diff --git a/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument_using_bang.out b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument_using_bang.out new file mode 100644 index 0000000000..87fcc5e2b0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/boolean_negation_without_argument_using_bang.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "!" operator. diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd new file mode 100644 index 0000000000..d13d713454 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd @@ -0,0 +1,6 @@ +# Error here. `class_name` should be used *before* annotations, not after. +@icon("res://path/to/optional/icon.svg") +class_name HelloWorld + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out new file mode 100644 index 0000000000..0bcc8acc55 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +"class_name" should be used before annotations. diff --git a/modules/gdscript/tests/scripts/parser/errors/constant_conflicts_variable.gd b/modules/gdscript/tests/scripts/parser/errors/constant_conflicts_variable.gd new file mode 100644 index 0000000000..49fb4ffedf --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/constant_conflicts_variable.gd @@ -0,0 +1,3 @@ +func test(): + var TEST = 50 + const TEST = 25 diff --git a/modules/gdscript/tests/scripts/parser/errors/constant_conflicts_variable.out b/modules/gdscript/tests/scripts/parser/errors/constant_conflicts_variable.out new file mode 100644 index 0000000000..407f094ca0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/constant_conflicts_variable.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +There is already a variable named "TEST" declared in this scope. diff --git a/modules/gdscript/tests/scripts/parser/errors/default_value_in_function_call.gd b/modules/gdscript/tests/scripts/parser/errors/default_value_in_function_call.gd new file mode 100644 index 0000000000..2581d873dd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/default_value_in_function_call.gd @@ -0,0 +1,7 @@ +func hello(arg1): + print(arg1) + + +func test(): + # Error here. + hello(arg1 = 25) diff --git a/modules/gdscript/tests/scripts/parser/errors/default_value_in_function_call.out b/modules/gdscript/tests/scripts/parser/errors/default_value_in_function_call.out new file mode 100644 index 0000000000..e8f9130706 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/default_value_in_function_call.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Assignment is not allowed inside an expression. diff --git a/modules/gdscript/tests/scripts/parser/errors/function_conflicts_constant.gd b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_constant.gd new file mode 100644 index 0000000000..a8f7cf1810 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_constant.gd @@ -0,0 +1,5 @@ +const test = 25 + + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/function_conflicts_constant.out b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_constant.out new file mode 100644 index 0000000000..c614acd094 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_constant.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Function "test" has the same name as a previously declared constant. diff --git a/modules/gdscript/tests/scripts/parser/errors/function_conflicts_variable.gd b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_variable.gd new file mode 100644 index 0000000000..5c86710a40 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_variable.gd @@ -0,0 +1,7 @@ +func test(): + pass + + +# Error here. The difference with `variable-conflicts-function.gd` is that here, +# the function is defined *before* the variable. +var test = 25 diff --git a/modules/gdscript/tests/scripts/parser/errors/function_conflicts_variable.out b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_variable.out new file mode 100644 index 0000000000..551db61531 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/function_conflicts_variable.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Variable "test" has the same name as a previously declared function. diff --git a/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_number.gd b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_number.gd new file mode 100644 index 0000000000..081b9faf4b --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_number.gd @@ -0,0 +1,3 @@ +func test(): + # Error here. + var 23test = "is not a valid identifier" diff --git a/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_number.out b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_number.out new file mode 100644 index 0000000000..a4bd8beef1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_number.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected variable name after "var". diff --git a/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_string.gd b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_string.gd new file mode 100644 index 0000000000..fa4d6b5cac --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_string.gd @@ -0,0 +1,3 @@ +func test(): + # Error here. + var "yes" = "is not a valid identifier" diff --git a/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_string.out b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_string.out new file mode 100644 index 0000000000..a4bd8beef1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/invalid_identifier_string.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected variable name after "var". diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_argument.gd b/modules/gdscript/tests/scripts/parser/errors/missing_argument.gd deleted file mode 100644 index c56ad94095..0000000000 --- a/modules/gdscript/tests/scripts/parser/errors/missing_argument.gd +++ /dev/null @@ -1,6 +0,0 @@ -func args(a, b): - print(a) - print(b) - -func test(): - args(1,) diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_closing_expr_paren.gd b/modules/gdscript/tests/scripts/parser/errors/missing_closing_expr_paren.gd index a1077e1985..8af5f123cc 100644 --- a/modules/gdscript/tests/scripts/parser/errors/missing_closing_expr_paren.gd +++ b/modules/gdscript/tests/scripts/parser/errors/missing_closing_expr_paren.gd @@ -1,2 +1,2 @@ func test(): - var a = ("missing paren ->" + var a = ("missing paren ->" diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_colon.gd b/modules/gdscript/tests/scripts/parser/errors/missing_colon.gd index 62cb633e9e..0e5e5ce060 100644 --- a/modules/gdscript/tests/scripts/parser/errors/missing_colon.gd +++ b/modules/gdscript/tests/scripts/parser/errors/missing_colon.gd @@ -1,3 +1,3 @@ func test(): - if true # Missing colon here. - print("true") + if true # Missing colon here. + print("true") diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_expression_after_ternary_else.gd b/modules/gdscript/tests/scripts/parser/errors/missing_expression_after_ternary_else.gd new file mode 100644 index 0000000000..1f66935329 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/missing_expression_after_ternary_else.gd @@ -0,0 +1,4 @@ +func test(): + var x = 1 if false else + print("oops") + print(x) diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_expression_after_ternary_else.out b/modules/gdscript/tests/scripts/parser/errors/missing_expression_after_ternary_else.out new file mode 100644 index 0000000000..dab6b0a1ad --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/missing_expression_after_ternary_else.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "else". diff --git a/modules/gdscript/tests/scripts/parser/errors/missing_paren_after_args.gd b/modules/gdscript/tests/scripts/parser/errors/missing_paren_after_args.gd index 116b0151da..7a35bf688c 100644 --- a/modules/gdscript/tests/scripts/parser/errors/missing_paren_after_args.gd +++ b/modules/gdscript/tests/scripts/parser/errors/missing_paren_after_args.gd @@ -1,6 +1,6 @@ func args(a, b): - print(a) - print(b) + print(a) + print(b) func test(): - args(1,2 + args(1,2 diff --git a/modules/gdscript/tests/scripts/parser/errors/mistaken_decrement_operator.gd b/modules/gdscript/tests/scripts/parser/errors/mistaken_decrement_operator.gd new file mode 100644 index 0000000000..193f824702 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/mistaken_decrement_operator.gd @@ -0,0 +1,3 @@ +func test(): + var a = 0 + print(a--) diff --git a/modules/gdscript/tests/scripts/parser/errors/mistaken_decrement_operator.out b/modules/gdscript/tests/scripts/parser/errors/mistaken_decrement_operator.out new file mode 100644 index 0000000000..b6b577a277 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/mistaken_decrement_operator.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "-" operator. diff --git a/modules/gdscript/tests/scripts/parser/errors/mistaken_increment_operator.gd b/modules/gdscript/tests/scripts/parser/errors/mistaken_increment_operator.gd new file mode 100644 index 0000000000..035d27638c --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/mistaken_increment_operator.gd @@ -0,0 +1,3 @@ +func test(): + var a = 0 + print(a++) diff --git a/modules/gdscript/tests/scripts/parser/errors/mistaken_increment_operator.out b/modules/gdscript/tests/scripts/parser/errors/mistaken_increment_operator.out new file mode 100644 index 0000000000..24eb76593a --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/mistaken_increment_operator.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "+" operator. diff --git a/modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.gd b/modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.gd new file mode 100644 index 0000000000..71a03fbc0d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.gd @@ -0,0 +1,3 @@ +func test(): + # Number separators may not be placed right next to each other. + var __ = 1__23 diff --git a/modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.out b/modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.out new file mode 100644 index 0000000000..71a3c2fd6a --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Only one underscore can be used as a numeric separator. diff --git a/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.gd b/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.gd index 3875ce3936..df388a21de 100644 --- a/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.gd +++ b/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.gd @@ -1,3 +1,5 @@ extends Node + + func test(): - var a = $ # Expected some node path. + var a = $ # Expected some node path. diff --git a/modules/gdscript/tests/scripts/parser/errors/redefine_keyword.gd b/modules/gdscript/tests/scripts/parser/errors/redefine_keyword.gd new file mode 100644 index 0000000000..c289c9d976 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/redefine_keyword.gd @@ -0,0 +1,2 @@ +func test(): + var while = "it's been a while" diff --git a/modules/gdscript/tests/scripts/parser/errors/redefine_keyword.out b/modules/gdscript/tests/scripts/parser/errors/redefine_keyword.out new file mode 100644 index 0000000000..a4bd8beef1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/redefine_keyword.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected variable name after "var". diff --git a/modules/gdscript/tests/scripts/parser/errors/redefine_local_constant_with_keyword.gd b/modules/gdscript/tests/scripts/parser/errors/redefine_local_constant_with_keyword.gd new file mode 100644 index 0000000000..204259f981 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/redefine_local_constant_with_keyword.gd @@ -0,0 +1,5 @@ +func test(): + const TEST = 25 + + # Error here (can't redeclare a constant on the same scope). + const TEST = 50 diff --git a/modules/gdscript/tests/scripts/parser/errors/redefine_local_constant_with_keyword.out b/modules/gdscript/tests/scripts/parser/errors/redefine_local_constant_with_keyword.out new file mode 100644 index 0000000000..d67cc92953 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/redefine_local_constant_with_keyword.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +There is already a constant named "TEST" declared in this scope. diff --git a/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.gd b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.gd new file mode 100644 index 0000000000..c30c05e4da --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.gd @@ -0,0 +1,3 @@ +func test(): + var array = [1, 2, 3] + array[] = 4 diff --git a/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.out b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.out new file mode 100644 index 0000000000..7017c7b4aa --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "[". diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_constant.gd b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_constant.gd new file mode 100644 index 0000000000..0d8843df20 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_constant.gd @@ -0,0 +1,3 @@ +func test(): + const TEST = 25 + var TEST = 50 diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_constant.out b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_constant.out new file mode 100644 index 0000000000..d67cc92953 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_constant.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +There is already a constant named "TEST" declared in this scope. diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_function.gd b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_function.gd new file mode 100644 index 0000000000..ce2c8784d6 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_function.gd @@ -0,0 +1,6 @@ +var test = 25 + +# Error here. The difference with `variable-conflicts-function.gd` is that here, +# the function is defined *before* the variable. +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_function.out b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_function.out new file mode 100644 index 0000000000..daeaca40ec --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_function.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Function "test" has the same name as a previously declared variable. diff --git a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.gd b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.gd index 6fd2692d47..babe39068c 100644 --- a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.gd +++ b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.gd @@ -1,3 +1,5 @@ extends Node + + func test(): - $23 # Can't use number here. + $23 # Can't use number here. diff --git a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.gd b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.gd index 1836d42226..b6b1cf3e52 100644 --- a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.gd +++ b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.gd @@ -1,3 +1,5 @@ extends Node + + func test(): - $MyNode/23 # Can't use number here. + $MyNode/23 # Can't use number here. diff --git a/modules/gdscript/tests/scripts/parser/features/array.gd b/modules/gdscript/tests/scripts/parser/features/array.gd new file mode 100644 index 0000000000..828ce8d134 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/array.gd @@ -0,0 +1,16 @@ +func test(): + # Indexing from the beginning: + print([1, 2, 3][0]) + print([1, 2, 3][1]) + print([1, 2, 3][2]) + + # Indexing from the end: + print([1, 2, 3][-1]) + print([1, 2, 3][-2]) + print([1, 2, 3][-3]) + + # Float indices are currently allowed, but should probably be an error? + print([1, 2, 3][0.4]) + print([1, 2, 3][0.8]) + print([1, 2, 3][1.0]) + print([1, 2, 3][-1.0]) diff --git a/modules/gdscript/tests/scripts/parser/features/array.out b/modules/gdscript/tests/scripts/parser/features/array.out new file mode 100644 index 0000000000..cf576c59e0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/array.out @@ -0,0 +1,11 @@ +GDTEST_OK +1 +2 +3 +3 +2 +1 +1 +1 +2 +3 diff --git a/modules/gdscript/tests/scripts/parser/features/bitwise_operators.gd b/modules/gdscript/tests/scripts/parser/features/bitwise_operators.gd new file mode 100644 index 0000000000..de502c6ed1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/bitwise_operators.gd @@ -0,0 +1,50 @@ +enum Flags { + FIRE = 1 << 1, + ICE = 1 << 2, + SLIPPERY = 1 << 3, + STICKY = 1 << 4, + NONSOLID = 1 << 5, + + ALL = FIRE | ICE | SLIPPERY | STICKY | NONSOLID, +} + + +func test(): + var flags = Flags.FIRE | Flags.SLIPPERY + print(flags) + + flags = Flags.FIRE & Flags.SLIPPERY + print(flags) + + flags = Flags.FIRE ^ Flags.SLIPPERY + print(flags) + + flags = Flags.ALL & (Flags.FIRE | Flags.ICE) + print(flags) + + flags = (Flags.ALL & Flags.FIRE) | Flags.ICE + print(flags) + + flags = Flags.ALL & Flags.FIRE | Flags.ICE + print(flags) + + # Enum value must be casted to an integer. Otherwise, a parser error is emitted. + flags &= int(Flags.ICE) + print(flags) + + flags ^= int(Flags.ICE) + print(flags) + + flags |= int(Flags.STICKY | Flags.SLIPPERY) + print(flags) + + print() + + var num = 2 << 4 + print(num) + + num <<= 2 + print(num) + + num >>= 2 + print(num) diff --git a/modules/gdscript/tests/scripts/parser/features/bitwise_operators.out b/modules/gdscript/tests/scripts/parser/features/bitwise_operators.out new file mode 100644 index 0000000000..410e358a05 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/bitwise_operators.out @@ -0,0 +1,14 @@ +GDTEST_OK +10 +0 +10 +6 +6 +6 +4 +0 +24 + +32 +128 +32 diff --git a/modules/gdscript/tests/scripts/parser/features/class.gd b/modules/gdscript/tests/scripts/parser/features/class.gd new file mode 100644 index 0000000000..6652f85ad9 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class.gd @@ -0,0 +1,25 @@ +# Test non-nested/slightly nested class architecture. +class Test: + var number = 25 + var string = "hello" + + +class TestSub extends Test: + var other_string = "bye" + + +class TestConstructor: + func _init(argument = 10): + print(str("constructor with argument ", argument)) + + +func test(): + var test_instance = Test.new() + test_instance.number = 42 + + var test_sub = TestSub.new() + assert(test_sub.number == 25) # From Test. + assert(test_sub.other_string == "bye") # From TestSub. + + TestConstructor.new() + TestConstructor.new(500) diff --git a/modules/gdscript/tests/scripts/parser/features/class.out b/modules/gdscript/tests/scripts/parser/features/class.out new file mode 100644 index 0000000000..94dc2d6003 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class.out @@ -0,0 +1,3 @@ +GDTEST_OK +constructor with argument 10 +constructor with argument 500 diff --git a/modules/gdscript/tests/scripts/parser/features/class_inheritance.gd b/modules/gdscript/tests/scripts/parser/features/class_inheritance.gd new file mode 100644 index 0000000000..3f9b4ea86e --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class_inheritance.gd @@ -0,0 +1,33 @@ +# Test deeply nested class architectures. +class Test: + var depth = 1 + + class Nested: + var depth_nested = 10 + + +class Test2 extends Test: + var depth2 = 2 + + +class Test3 extends Test2: + var depth3 = 3 + + +class Test4 extends Test3: + var depth4 = 4 + + class Nested2: + var depth4_nested = 100 + + +func test(): + print(Test.new().depth) + print(Test2.new().depth) + print(Test2.new().depth2) + print(Test3.new().depth) + print(Test3.new().depth3) + print(Test4.new().depth) + print(Test4.new().depth4) + print(Test.Nested.new().depth_nested) + print(Test4.Nested2.new().depth4_nested) diff --git a/modules/gdscript/tests/scripts/parser/features/class_inheritance.out b/modules/gdscript/tests/scripts/parser/features/class_inheritance.out new file mode 100644 index 0000000000..75bdde3d94 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class_inheritance.out @@ -0,0 +1,10 @@ +GDTEST_OK +1 +1 +2 +1 +3 +1 +4 +10 +100 diff --git a/modules/gdscript/tests/scripts/parser/features/class_name.gd b/modules/gdscript/tests/scripts/parser/features/class_name.gd new file mode 100644 index 0000000000..8bd188e247 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class_name.gd @@ -0,0 +1,5 @@ +class_name HelloWorld +@icon("res://path/to/optional/icon.svg") + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/features/class_name.out b/modules/gdscript/tests/scripts/parser/features/class_name.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/class_name.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/concatenation.gd b/modules/gdscript/tests/scripts/parser/features/concatenation.gd new file mode 100644 index 0000000000..e8335c9823 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/concatenation.gd @@ -0,0 +1,4 @@ +func test(): + print(20 + 20) + print("hello" + "world") + print([1, 2] + [3, 4]) diff --git a/modules/gdscript/tests/scripts/parser/features/concatenation.out b/modules/gdscript/tests/scripts/parser/features/concatenation.out new file mode 100644 index 0000000000..23bff08f49 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/concatenation.out @@ -0,0 +1,4 @@ +GDTEST_OK +40 +helloworld +[1, 2, 3, 4] diff --git a/modules/gdscript/tests/scripts/parser/features/constants.gd b/modules/gdscript/tests/scripts/parser/features/constants.gd new file mode 100644 index 0000000000..013c9c074f --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/constants.gd @@ -0,0 +1,11 @@ +func test(): + const _TEST = 12 + 34 - 56 * 78 + const _STRING = "yes" + const _VECTOR = Vector2(5, 6) + const _ARRAY = [] + const _DICTIONARY = {"this": "dictionary"} + + # Create user constants from built-in constants. + const _HELLO = PI + TAU + const _INFINITY = INF + const _NOT_A_NUMBER = NAN diff --git a/modules/gdscript/tests/scripts/parser/features/constants.out b/modules/gdscript/tests/scripts/parser/features/constants.out new file mode 100644 index 0000000000..6093e4a6ca --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/constants.out @@ -0,0 +1,33 @@ +GDTEST_OK +>> WARNING +>> Line: 2 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_TEST' is declared but never used in the block. If this is intended, prefix it with an underscore: '__TEST' +>> WARNING +>> Line: 3 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_STRING' is declared but never used in the block. If this is intended, prefix it with an underscore: '__STRING' +>> WARNING +>> Line: 4 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_VECTOR' is declared but never used in the block. If this is intended, prefix it with an underscore: '__VECTOR' +>> WARNING +>> Line: 5 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_ARRAY' is declared but never used in the block. If this is intended, prefix it with an underscore: '__ARRAY' +>> WARNING +>> Line: 6 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_DICTIONARY' is declared but never used in the block. If this is intended, prefix it with an underscore: '__DICTIONARY' +>> WARNING +>> Line: 9 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_HELLO' is declared but never used in the block. If this is intended, prefix it with an underscore: '__HELLO' +>> WARNING +>> Line: 10 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_INFINITY' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INFINITY' +>> WARNING +>> Line: 11 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_NOT_A_NUMBER' is declared but never used in the block. If this is intended, prefix it with an underscore: '__NOT_A_NUMBER' diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary.gd b/modules/gdscript/tests/scripts/parser/features/dictionary.gd new file mode 100644 index 0000000000..99afe166c7 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dictionary.gd @@ -0,0 +1,37 @@ +func test(): + # Non-string keys are valid. + print({ 12: "world" }[12]) + + var contents = { + 0: "zero", + 0.0: "zero point zero", + null: "null", + false: "false", + []: "empty array", + Vector2i(): "zero Vector2i", + 15: { + 22: { + 4: ["nesting", "arrays"], + }, + }, + } + + print(contents[0.0]) + # Making sure declaration order doesn't affect things... + print({ 0.0: "zero point zero", 0: "zero", null: "null", false: "false", []: "empty array" }[0]) + print({ 0.0: "zero point zero", 0: "zero", null: "null", false: "false", []: "empty array" }[0.0]) + + print(contents[null]) + print(contents[false]) + print(contents[[]]) + print(contents[Vector2i()]) + print(contents[15]) + print(contents[15][22]) + print(contents[15][22][4]) + print(contents[15][22][4][0]) + print(contents[15][22][4][1]) + + # Currently fails with "invalid get index 'hello' on base Dictionary". + # Both syntaxes are valid however. + #print({ "hello": "world" }["hello"]) + #print({ "hello": "world" }.hello) diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary.out b/modules/gdscript/tests/scripts/parser/features/dictionary.out new file mode 100644 index 0000000000..54083c1afc --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dictionary.out @@ -0,0 +1,14 @@ +GDTEST_OK +world +zero point zero +zero +zero point zero +null +false +empty array +zero Vector2i +{22:{4:[nesting, arrays]}} +{4:[nesting, arrays]} +[nesting, arrays] +nesting +arrays diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd new file mode 100644 index 0000000000..fdd6de2348 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd @@ -0,0 +1,9 @@ +func test(): + var lua_dict = { + a = 1, + "b" = 2, # Using strings are allowed too. + "with spaces" = 3, # Especially useful when key has spaces... + "2" = 4, # ... or invalid identifiers. + } + + print(lua_dict) diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out new file mode 100644 index 0000000000..447d7e223c --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out @@ -0,0 +1,2 @@ +GDTEST_OK +{2:4, a:1, b:2, with spaces:3} diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.gd b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.gd new file mode 100644 index 0000000000..cce8538ddd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.gd @@ -0,0 +1,12 @@ +func test(): + # Mixing Python-style and Lua-style syntax in the same dictionary declaration + # is allowed. + var dict = { + "hello": { + world = { + "is": "beautiful", + }, + }, + } + + print(dict) diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out new file mode 100644 index 0000000000..62be807a1f --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out @@ -0,0 +1,2 @@ +GDTEST_OK +{hello:{world:{is:beautiful}}} diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd b/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd new file mode 100644 index 0000000000..8ba558e91d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd @@ -0,0 +1,20 @@ +extends Node + + +func test(): + # Create the required node structure. + var hello = Node.new() + hello.name = "Hello" + add_child(hello) + var world = Node.new() + world.name = "World" + hello.add_child(world) + + # All the ways of writing node paths below with the `$` operator are valid. + # Results are assigned to variables to avoid warnings. + var __ = $Hello + __ = $"Hello" + __ = $Hello/World + __ = $"Hello/World" + __ = $"Hello/.." + __ = $"Hello/../Hello/World" diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.out b/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/enum.gd b/modules/gdscript/tests/scripts/parser/features/enum.gd new file mode 100644 index 0000000000..bbc66f6f3d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/enum.gd @@ -0,0 +1,14 @@ +enum Size { + S = -10, + M, + L = 0, + XL = 10, + XXL, +} + +func test(): + print(Size.S) + print(Size.M) + print(Size.L) + print(Size.XL) + print(Size.XXL) diff --git a/modules/gdscript/tests/scripts/parser/features/enum.out b/modules/gdscript/tests/scripts/parser/features/enum.out new file mode 100644 index 0000000000..6f3a4a3e49 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/enum.out @@ -0,0 +1,6 @@ +GDTEST_OK +-10 +-9 +0 +10 +11 diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.gd b/modules/gdscript/tests/scripts/parser/features/export_variable.gd new file mode 100644 index 0000000000..51e7d4a8ed --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/export_variable.gd @@ -0,0 +1,11 @@ +@export var example = 99 +@export_range(0, 100) var example_range = 100 +@export_range(0, 100, 1) var example_range_step = 101 +@export_range(0, 100, 1, "or_greater") var example_range_step_or_greater = 102 + + +func test(): + print(example) + print(example_range) + print(example_range_step) + print(example_range_step_or_greater) diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.out b/modules/gdscript/tests/scripts/parser/features/export_variable.out new file mode 100644 index 0000000000..b455196359 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/export_variable.out @@ -0,0 +1,5 @@ +GDTEST_OK +99 +100 +101 +102 diff --git a/modules/gdscript/tests/scripts/parser/features/float_notation.gd b/modules/gdscript/tests/scripts/parser/features/float_notation.gd new file mode 100644 index 0000000000..b207b88820 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/float_notation.gd @@ -0,0 +1,24 @@ +func test(): + # The following floating-point notations are all valid: + print(is_equal_approx(123., 123)) + print(is_equal_approx(.123, 0.123)) + print(is_equal_approx(.123e4, 1230)) + print(is_equal_approx(123.e4, 1.23e6)) + print(is_equal_approx(.123e-1, 0.0123)) + print(is_equal_approx(123.e-1, 12.3)) + + # Same as above, but with negative numbers. + print(is_equal_approx(-123., -123)) + print(is_equal_approx(-.123, -0.123)) + print(is_equal_approx(-.123e4, -1230)) + print(is_equal_approx(-123.e4, -1.23e6)) + print(is_equal_approx(-.123e-1, -0.0123)) + print(is_equal_approx(-123.e-1, -12.3)) + + # Same as above, but with explicit positive numbers (which is redundant). + print(is_equal_approx(+123., +123)) + print(is_equal_approx(+.123, +0.123)) + print(is_equal_approx(+.123e4, +1230)) + print(is_equal_approx(+123.e4, +1.23e6)) + print(is_equal_approx(+.123e-1, +0.0123)) + print(is_equal_approx(+123.e-1, +12.3)) diff --git a/modules/gdscript/tests/scripts/parser/features/float_notation.out b/modules/gdscript/tests/scripts/parser/features/float_notation.out new file mode 100644 index 0000000000..041c4439b0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/float_notation.out @@ -0,0 +1,19 @@ +GDTEST_OK +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/modules/gdscript/tests/scripts/parser/features/for_range.gd b/modules/gdscript/tests/scripts/parser/features/for_range.gd new file mode 100644 index 0000000000..fd1d002b82 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/for_range.gd @@ -0,0 +1,39 @@ +func test(): + for i in range(5): + print(i) + + print() + + # Equivalent to the above `for` loop: + for i in 5: + print(i) + + print() + + for i in range(1, 5): + print(i) + + print() + + for i in range(1, -5, -1): + print(i) + + print() + + for i in [2, 4, 6, -8]: + print(i) + + print() + + for i in [true, false]: + print(i) + + print() + + for i in [Vector2i(10, 20), Vector2i(-30, -40)]: + print(i) + + print() + + for i in "Hello_Unicôde_world!_🦄": + print(i) diff --git a/modules/gdscript/tests/scripts/parser/features/for_range.out b/modules/gdscript/tests/scripts/parser/features/for_range.out new file mode 100644 index 0000000000..50b2c856c5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/for_range.out @@ -0,0 +1,58 @@ +GDTEST_OK +0 +1 +2 +3 +4 + +0 +1 +2 +3 +4 + +1 +2 +3 +4 + +1 +0 +-1 +-2 +-3 +-4 + +2 +4 +6 +-8 + +true +false + +(10, 20) +(-30, -40) + +H +e +l +l +o +_ +U +n +i +c +ô +d +e +_ +w +o +r +l +d +! +_ +🦄 diff --git a/modules/gdscript/tests/scripts/parser/features/in.gd b/modules/gdscript/tests/scripts/parser/features/in.gd new file mode 100644 index 0000000000..f7296017c5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/in.gd @@ -0,0 +1,14 @@ +func test(): + print("dot" in "Godot") + print(not "i" in "team") + + print(true in [true, false]) + print(not null in [true, false]) + print(null in [null]) + + print(26 in [8, 26, 64, 100]) + print(not Vector2i(10, 20) in [Vector2i(20, 10)]) + + print("apple" in { "apple": "fruit" }) + print("apple" in { "apple": null }) + print(not "apple" in { "fruit": "apple" }) diff --git a/modules/gdscript/tests/scripts/parser/features/in.out b/modules/gdscript/tests/scripts/parser/features/in.out new file mode 100644 index 0000000000..7533f6ff54 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/in.out @@ -0,0 +1,11 @@ +GDTEST_OK +true +true +true +true +true +true +true +true +true +true diff --git a/modules/gdscript/tests/scripts/parser/features/match.gd b/modules/gdscript/tests/scripts/parser/features/match.gd new file mode 100644 index 0000000000..4d05490aa5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/match.gd @@ -0,0 +1,18 @@ +func test(): + var i = "Hello" + match i: + "Hello": + print("hello") + # This will fall through to the default case below. + continue + "Good bye": + print("bye") + _: + print("default") + + var j = 25 + match j: + 26: + print("This won't match") + _: + print("This will match") diff --git a/modules/gdscript/tests/scripts/parser/features/match.out b/modules/gdscript/tests/scripts/parser/features/match.out new file mode 100644 index 0000000000..732885c7a2 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/match.out @@ -0,0 +1,4 @@ +GDTEST_OK +hello +default +This will match diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_arrays.gd b/modules/gdscript/tests/scripts/parser/features/multiline_arrays.gd new file mode 100644 index 0000000000..3b30998853 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_arrays.gd @@ -0,0 +1,7 @@ +func test(): + var __ = [ + "this", + "is", "a","multiline", + + "array", "with mixed indentation and trailing comma", + ] diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_arrays.out b/modules/gdscript/tests/scripts/parser/features/multiline_arrays.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_arrays.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_dictionaries.gd b/modules/gdscript/tests/scripts/parser/features/multiline_dictionaries.gd new file mode 100644 index 0000000000..e108cd23d4 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_dictionaries.gd @@ -0,0 +1,10 @@ +func test(): + var __ = { + "multiline": "dictionary","should": "work", + "even with": "a trailing comma", + } + + __ = { + this_also_applies = "to the", + lua_style_syntax = null, foo = null, + } diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_dictionaries.out b/modules/gdscript/tests/scripts/parser/features/multiline_dictionaries.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_dictionaries.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_if.gd b/modules/gdscript/tests/scripts/parser/features/multiline_if.gd new file mode 100644 index 0000000000..86152f4543 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_if.gd @@ -0,0 +1,14 @@ +func test(): + # Line breaks are allowed within parentheses. + if ( + 1 == 1 + and 2 == 2 and + 3 == 3 + ): + pass + + # Alternatively, backslashes can be used. + if 1 == 1 \ + and 2 == 2 and \ + 3 == 3: + pass diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_if.out b/modules/gdscript/tests/scripts/parser/features/multiline_if.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_if.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_strings.gd b/modules/gdscript/tests/scripts/parser/features/multiline_strings.gd new file mode 100644 index 0000000000..7f5bba85e7 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_strings.gd @@ -0,0 +1,15 @@ +func test(): + var __ = """ + This is a standalone string, not a multiline comment. + Writing both "double" quotes and 'simple' quotes is fine as + long as there is only ""one"" or ''two'' of those in a row, not more. + + If you have more quotes, they need to be escaped like this: \"\"\" + """ + __ = ''' + Another standalone string, this time with single quotes. + Writing both "double" quotes and 'simple' quotes is fine as + long as there is only ""one"" or ''two'' of those in a row, not more. + + If you have more quotes, they need to be escaped like this: \'\'\' + ''' diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_strings.out b/modules/gdscript/tests/scripts/parser/features/multiline_strings.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_strings.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_vector.gd b/modules/gdscript/tests/scripts/parser/features/multiline_vector.gd new file mode 100644 index 0000000000..11a40fc00e --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_vector.gd @@ -0,0 +1,17 @@ +func test(): + Vector2( + 1, + 2 + ) + + Vector3( + 3, + 3.5, + 4, # Trailing comma should work. + ) + + Vector2i(1, 2,) # Trailing comma should work. + + Vector3i(6, + 9, + 12) diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_vector.out b/modules/gdscript/tests/scripts/parser/features/multiline_vector.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/multiline_vector.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/nested_arithmetic.gd b/modules/gdscript/tests/scripts/parser/features/nested_arithmetic.gd new file mode 100644 index 0000000000..b9bd19c9c5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_arithmetic.gd @@ -0,0 +1,22 @@ +func test(): + print(+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++2.718) + + print() + + print(------------------------------------------------------------------2.718) + print(-------------------------------------------------------------------2.718) + + print() + + print(~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~999) + + print() + + print(+-+-+-----+------------+++++++---++--++--+--+---+--++2.718) + + print() + + print(2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 0.444) + print(153023902390239 % 550 % 29 % 27 % 23 % 17) + print(2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2 >> 2) + print(8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8 ^ -8 ^ 8 ^ 8 ^ 8 ^ 8 ^ 8) diff --git a/modules/gdscript/tests/scripts/parser/features/nested_arithmetic.out b/modules/gdscript/tests/scripts/parser/features/nested_arithmetic.out new file mode 100644 index 0000000000..048cfbdfae --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_arithmetic.out @@ -0,0 +1,82 @@ +GDTEST_OK +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +>> WARNING +>> Line: 19 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. +2.718 + +2.718 +-2.718 + +-1000 + +-2.718 + +36900.9009009009 +2 +8192 +-8 diff --git a/modules/gdscript/tests/scripts/parser/features/nested_array.gd b/modules/gdscript/tests/scripts/parser/features/nested_array.gd new file mode 100644 index 0000000000..3caef96391 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_array.gd @@ -0,0 +1,5 @@ +func test(): + var array = [[[[[[[[[[15]]]]]]]]]] + print(array[0][0][0][0][0][0][0][0]) + print(array[0][0][0][0][0][0][0][0][0]) + print(array[0][0][0][0][0][0][0][0][0][0]) diff --git a/modules/gdscript/tests/scripts/parser/features/nested_array.out b/modules/gdscript/tests/scripts/parser/features/nested_array.out new file mode 100644 index 0000000000..46c6ce3874 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_array.out @@ -0,0 +1,4 @@ +GDTEST_OK +[[15]] +[15] +15 diff --git a/modules/gdscript/tests/scripts/parser/features/nested_dictionary.gd b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.gd new file mode 100644 index 0000000000..d67e142156 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.gd @@ -0,0 +1,6 @@ +func test(): + var dictionary = {1: {2: {3: {4: {5: {6: {7: {8: {"key": "value"}}}}}}}}} + print(dictionary[1][2][3][4][5][6][7]) + print(dictionary[1][2][3][4][5][6][7][8]) + print(dictionary[1][2][3][4][5][6][7][8].key) + print(dictionary[1][2][3][4][5][6][7][8]["key"]) diff --git a/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out new file mode 100644 index 0000000000..4009160439 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out @@ -0,0 +1,5 @@ +GDTEST_OK +{8:{key:value}} +{key:value} +value +value diff --git a/modules/gdscript/tests/scripts/parser/features/nested_if.gd b/modules/gdscript/tests/scripts/parser/features/nested_if.gd new file mode 100644 index 0000000000..7282d08497 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_if.gd @@ -0,0 +1,57 @@ +func test(): + # 20 levels of nesting (and then some). + if true: + print("1") + if true: + print("2") + if true: + print("3") + if true: + print("4") + if true: + print("5") + if true: + print("6") + if true: + print("7") + if true: + print("8") + if true: + print("9") + if true: + print("10") + if true: + print("11") + if true: + print("12") + if true: + print("13") + if true: + print("14") + if true: + print("15") + if true: + print("16") + if true: + print("17") + if true: + print("18") + if true: + print("19") + if true: + print("20") + if false: + print("End") + if true: + if true: + if true: + if true: + if true: + if true: + if true: + if true: + if true: + if true: + if true: + if true: + print("This won't be printed") diff --git a/modules/gdscript/tests/scripts/parser/features/nested_if.out b/modules/gdscript/tests/scripts/parser/features/nested_if.out new file mode 100644 index 0000000000..c2d2e29a06 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_if.out @@ -0,0 +1,21 @@ +GDTEST_OK +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 diff --git a/modules/gdscript/tests/scripts/parser/features/nested_match.gd b/modules/gdscript/tests/scripts/parser/features/nested_match.gd new file mode 100644 index 0000000000..aaddcc7e83 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_match.gd @@ -0,0 +1,79 @@ +func test(): + # 20 levels of nesting (and then some). + var number = 1234 + match number: + 1234: + print("1") + match number: + 1234: + print("2") + match number: + 1234: + print("3") + continue + _: + print("Should also be printed") + match number: + 1234: + print("4") + match number: + _: + print("5") + match number: + false: + print("Should not be printed") + true: + print("Should not be printed") + "hello": + print("Should not be printed") + 1234: + print("6") + match number: + _: + print("7") + match number: + 1234: + print("8") + match number: + _: + print("9") + match number: + 1234: + print("10") + match number: + _: + print("11") + match number: + 1234: + print("12") + match number: + _: + print("13") + match number: + 1234: + print("14") + match number: + _: + print("15") + match number: + _: + print("16") + match number: + 1234: + print("17") + match number: + _: + print("18") + match number: + 1234: + print("19") + match number: + _: + print("20") + match number: + []: + print("Should not be printed") + _: + print("Should not be printed") + 5678: + print("Should not be printed either") diff --git a/modules/gdscript/tests/scripts/parser/features/nested_match.out b/modules/gdscript/tests/scripts/parser/features/nested_match.out new file mode 100644 index 0000000000..651d76cc59 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_match.out @@ -0,0 +1,22 @@ +GDTEST_OK +1 +2 +3 +Should also be printed +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 diff --git a/modules/gdscript/tests/scripts/parser/features/nested_parentheses.gd b/modules/gdscript/tests/scripts/parser/features/nested_parentheses.gd new file mode 100644 index 0000000000..3fef73b9be --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_parentheses.gd @@ -0,0 +1,65 @@ +func test(): + (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((print("Hello world!")))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + + print(((((((((((((((((((((((((((((((((((((((((((((((((((((((((("Hello world 2!")))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + + print( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + ( + (2)) + ((4)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) diff --git a/modules/gdscript/tests/scripts/parser/features/nested_parentheses.out b/modules/gdscript/tests/scripts/parser/features/nested_parentheses.out new file mode 100644 index 0000000000..27221a56bb --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/nested_parentheses.out @@ -0,0 +1,4 @@ +GDTEST_OK +Hello world! +Hello world 2! +6 diff --git a/modules/gdscript/tests/scripts/parser/features/number_separators.gd b/modules/gdscript/tests/scripts/parser/features/number_separators.gd new file mode 100644 index 0000000000..f5f5661cae --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/number_separators.gd @@ -0,0 +1,12 @@ +func test(): + # `_` can be used as a separator for numbers in GDScript. + # It can be placed anywhere in the number, except at the beginning. + # Currently, GDScript in the `master` branch only allows using one separator + # per number. + # Results are assigned to variables to avoid warnings. + var __ = 1_23 + __ = 123_ # Trailing number separators are OK. + __ = 12_3 + __ = 123_456 + __ = 0x1234_5678 + __ = 0b1001_0101 diff --git a/modules/gdscript/tests/scripts/parser/features/number_separators.out b/modules/gdscript/tests/scripts/parser/features/number_separators.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/number_separators.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/operator_assign.gd b/modules/gdscript/tests/scripts/parser/features/operator_assign.gd new file mode 100644 index 0000000000..b5f07675ca --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/operator_assign.gd @@ -0,0 +1,8 @@ +func test(): + var i = 0 + i += 5 + i -= 4 + i *= 10 + i %= 8 + i /= 0.25 + print(round(i)) diff --git a/modules/gdscript/tests/scripts/parser/features/operator_assign.out b/modules/gdscript/tests/scripts/parser/features/operator_assign.out new file mode 100644 index 0000000000..b0cb63ef59 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/operator_assign.out @@ -0,0 +1,2 @@ +GDTEST_OK +8 diff --git a/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd new file mode 100644 index 0000000000..9e4b360fb2 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd @@ -0,0 +1,37 @@ +# 4.0+ replacement for `setget`: +var _backing: int = 0 +var property: + get: + return _backing + 1000 + set(value): + _backing = value - 1000 + + +func test(): + print("Not using self:") + print(property) + print(_backing) + property = 5000 + print(property) + print(_backing) + _backing = -50 + print(property) + print(_backing) + property = 5000 + print(property) + print(_backing) + + # In Godot 4.0 and later, using `self` no longer makes a difference for + # getter/setter execution in GDScript. + print("Using self:") + print(self.property) + print(self._backing) + self.property = 5000 + print(self.property) + print(self._backing) + self._backing = -50 + print(self.property) + print(self._backing) + self.property = 5000 + print(self.property) + print(self._backing) diff --git a/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out new file mode 100644 index 0000000000..560e0c3bd7 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out @@ -0,0 +1,19 @@ +GDTEST_OK +Not using self: +1000 +0 +5000 +4000 +950 +-50 +5000 +4000 +Using self: +5000 +4000 +5000 +4000 +950 +-50 +5000 +4000 diff --git a/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.gd b/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.gd index 08f2eedb2d..d50776c25c 100644 --- a/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.gd +++ b/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.gd @@ -1,2 +1,5 @@ func test(): - print("A"); print("B") + print("A"); print("B") + + # Multiple semicolons and whitespace between them is also valid. + print("A"); ;;;;; ; print("B");; diff --git a/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.out b/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.out index fc03f3efe8..bd7f38f516 100644 --- a/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.out +++ b/modules/gdscript/tests/scripts/parser/features/semicolon_as_end_statement.out @@ -1,3 +1,5 @@ GDTEST_OK A B +A +B diff --git a/modules/gdscript/tests/scripts/parser/features/space_indentation.gd b/modules/gdscript/tests/scripts/parser/features/space_indentation.gd new file mode 100644 index 0000000000..0a4887c199 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/space_indentation.gd @@ -0,0 +1,4 @@ +func test(): + # 2-space indentation should work, even though the GDScript style guide recommends tabs. + if true: + pass diff --git a/modules/gdscript/tests/scripts/parser/features/space_indentation.out b/modules/gdscript/tests/scripts/parser/features/space_indentation.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/space_indentation.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/features/static_typing.gd b/modules/gdscript/tests/scripts/parser/features/static_typing.gd new file mode 100644 index 0000000000..d42632c82d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/static_typing.gd @@ -0,0 +1,13 @@ +func test(): + # The following lines are equivalent: + var _integer: int = 1 + var _integer2 : int = 1 + var _inferred := 1 + var _inferred2 : = 1 + + # Type inference is automatic for constants. + const _INTEGER = 1 + const _INTEGER_REDUNDANT_TYPED : int = 1 + const _INTEGER_REDUNDANT_TYPED2 : int = 1 + const _INTEGER_REDUNDANT_INFERRED := 1 + const _INTEGER_REDUNDANT_INFERRED2 : = 1 diff --git a/modules/gdscript/tests/scripts/parser/features/static_typing.out b/modules/gdscript/tests/scripts/parser/features/static_typing.out new file mode 100644 index 0000000000..92ce7bc0e0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/static_typing.out @@ -0,0 +1,21 @@ +GDTEST_OK +>> WARNING +>> Line: 9 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_INTEGER' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER' +>> WARNING +>> Line: 10 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_INTEGER_REDUNDANT_TYPED' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_TYPED' +>> WARNING +>> Line: 11 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_INTEGER_REDUNDANT_TYPED2' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_TYPED2' +>> WARNING +>> Line: 12 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_INTEGER_REDUNDANT_INFERRED' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_INFERRED' +>> WARNING +>> Line: 13 +>> UNUSED_LOCAL_CONSTANT +>> The local constant '_INTEGER_REDUNDANT_INFERRED2' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_INFERRED2' diff --git a/modules/gdscript/tests/scripts/parser/features/string_formatting.gd b/modules/gdscript/tests/scripts/parser/features/string_formatting.gd new file mode 100644 index 0000000000..a91837145d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/string_formatting.gd @@ -0,0 +1,18 @@ +func test(): + print("hello %s" % "world" == "hello world") + print("hello %s" % true == "hello true") + print("hello %s" % false == "hello false") + + print("hello %d" % 25 == "hello 25") + print("hello %d %d" % [25, 42] == "hello 25 42") + # Pad with spaces. + print("hello %3d" % 25 == "hello 25") + # Pad with zeroes. + print("hello %03d" % 25 == "hello 025") + + print("hello %.02f" % 0.123456 == "hello 0.12") + + # Dynamic padding: + # <https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_format_string.html#dynamic-padding> + print("hello %*.*f" % [7, 3, 0.123456] == "hello 0.123") + print("hello %0*.*f" % [7, 3, 0.123456] == "hello 000.123") diff --git a/modules/gdscript/tests/scripts/parser/features/string_formatting.out b/modules/gdscript/tests/scripts/parser/features/string_formatting.out new file mode 100644 index 0000000000..7533f6ff54 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/string_formatting.out @@ -0,0 +1,11 @@ +GDTEST_OK +true +true +true +true +true +true +true +true +true +true diff --git a/modules/gdscript/tests/scripts/parser/features/super.gd b/modules/gdscript/tests/scripts/parser/features/super.gd new file mode 100644 index 0000000000..f5ae2a74a7 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/super.gd @@ -0,0 +1,60 @@ +class Say: + var prefix = "S" + + func greet(): + prefix = "S Greeted" + print("hello") + + func say(name): + print(prefix, " say something ", name) + + +class SayAnotherThing extends Say: + # This currently crashes the engine. + #var prefix = "SAT" + + func greet(): + prefix = "SAT Greeted" + print("hi") + + func say(name): + print(prefix, " say another thing ", name) + + +class SayNothing extends Say: + # This currently crashes the engine. + #var prefix = "SN" + + func greet(): + super() + prefix = "SN Greeted" + print("howdy, see above") + + func greet_prefix_before_super(): + prefix = "SN Greeted" + super.greet() + print("howdy, see above") + + func say(name): + super(name + " super'd") + print(prefix, " say nothing... or not? ", name) + + +func test(): + var say = Say.new() + say.greet() + say.say("foo") + print() + + var say_another_thing = SayAnotherThing.new() + say_another_thing.greet() + say_another_thing.say("bar") + print() + + var say_nothing = SayNothing.new() + say_nothing.greet() + print(say_nothing.prefix) + say_nothing.greet_prefix_before_super() + print(say_nothing.prefix) + # This currently triggers a compiler bug: "compiler bug, function name not found" + #say_nothing.say("baz") diff --git a/modules/gdscript/tests/scripts/parser/features/super.out b/modules/gdscript/tests/scripts/parser/features/super.out new file mode 100644 index 0000000000..e0d4f4f098 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/super.out @@ -0,0 +1,13 @@ +GDTEST_OK +hello +S Greeted say something foo + +hi +SAT Greeted say another thing bar + +hello +howdy, see above +SN Greeted +hello +howdy, see above +S Greeted diff --git a/modules/gdscript/tests/scripts/parser/features/truthiness.gd b/modules/gdscript/tests/scripts/parser/features/truthiness.gd new file mode 100644 index 0000000000..9c67a152f5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/truthiness.gd @@ -0,0 +1,30 @@ +func test(): + # The assertions below should all evaluate to `true` for this test to pass. + assert(true) + assert(not false) + assert(500) + assert(not 0) + assert(500.5) + assert(not 0.0) + assert("non-empty string") + assert(["non-empty array"]) + assert({"non-empty": "dictionary"}) + assert(Vector2(1, 0)) + assert(Vector2i(-1, -1)) + assert(Vector3(0, 0, 0.0001)) + assert(Vector3i(0, 0, 10000)) + + # Zero position is `true` only if the Rect2's size is non-zero. + assert(Rect2(0, 0, 0, 1)) + + # Zero size is `true` only if the position is non-zero. + assert(Rect2(1, 1, 0, 0)) + + # Zero position is `true` only if the Rect2's size is non-zero. + assert(Rect2i(0, 0, 0, 1)) + + # Zero size is `true` only if the position is non-zero. + assert(Rect2i(1, 1, 0, 0)) + + # A fully black color is only truthy if its alpha component is not equal to `1`. + assert(Color(0, 0, 0, 0.5)) diff --git a/modules/gdscript/tests/scripts/parser/features/truthiness.out b/modules/gdscript/tests/scripts/parser/features/truthiness.out new file mode 100644 index 0000000000..705524857b --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/truthiness.out @@ -0,0 +1,65 @@ +GDTEST_OK +>> WARNING +>> Line: 3 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 4 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 5 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 6 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 7 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 8 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 9 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 12 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 13 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 14 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 15 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 18 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 21 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 24 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 27 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 30 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. diff --git a/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd b/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd index 38567d35c6..65013c4301 100644 --- a/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd +++ b/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd @@ -3,6 +3,7 @@ var m2 = 22 # Init. var m3: String # No init, typed. var m4: String = "44" # Init, typed. + func test(): var loc5 # No init, local. var loc6 = 66 # Init, local. diff --git a/modules/gdscript/tests/scripts/parser/features/while.gd b/modules/gdscript/tests/scripts/parser/features/while.gd new file mode 100644 index 0000000000..17dd4fbad2 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/while.gd @@ -0,0 +1,5 @@ +func test(): + var i = 0 + while i < 5: + print(i) + i += 1 diff --git a/modules/gdscript/tests/scripts/parser/features/while.out b/modules/gdscript/tests/scripts/parser/features/while.out new file mode 100644 index 0000000000..b4a50885c7 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/while.out @@ -0,0 +1,6 @@ +GDTEST_OK +0 +1 +2 +3 +4 diff --git a/modules/gdscript/tests/scripts/parser/warnings/assert_always_true.gd b/modules/gdscript/tests/scripts/parser/warnings/assert_always_true.gd new file mode 100644 index 0000000000..8feaed899f --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/assert_always_true.gd @@ -0,0 +1,5 @@ +func test(): + # These statements always evaluate to `true`, and therefore emit a warning. + assert(true) + assert(-1.234) + assert(2 + 3 == 5) diff --git a/modules/gdscript/tests/scripts/parser/warnings/assert_always_true.out b/modules/gdscript/tests/scripts/parser/warnings/assert_always_true.out new file mode 100644 index 0000000000..5132792cb7 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/assert_always_true.out @@ -0,0 +1,13 @@ +GDTEST_OK +>> WARNING +>> Line: 3 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 4 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. +>> WARNING +>> Line: 5 +>> ASSERT_ALWAYS_TRUE +>> Assert statement is redundant because the expression is always true. diff --git a/modules/gdscript/tests/scripts/parser/warnings/deprecated_operators.gd b/modules/gdscript/tests/scripts/parser/warnings/deprecated_operators.gd new file mode 100644 index 0000000000..f72b10213f --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/deprecated_operators.gd @@ -0,0 +1,8 @@ +func test(): + # `and` should be used instead. + if true && true: + pass + + # `or` should be used instead. + if false || true: + pass diff --git a/modules/gdscript/tests/scripts/parser/warnings/deprecated_operators.out b/modules/gdscript/tests/scripts/parser/warnings/deprecated_operators.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/deprecated_operators.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/warnings/incompatible_ternary.gd b/modules/gdscript/tests/scripts/parser/warnings/incompatible_ternary.gd new file mode 100644 index 0000000000..a93ecb66b1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/incompatible_ternary.gd @@ -0,0 +1,8 @@ +func test(): + # The ternary operator below returns values of different types and the + # result is assigned to a typed variable. This will cause a run-time error + # if the branch with the incompatible type is picked. Here, it won't happen + # since the `false` condition never evaluates to `true`. Instead, a warning + # will be emitted. + var __: int = 25 + __ = "hello" if false else -2 diff --git a/modules/gdscript/tests/scripts/parser/warnings/incompatible_ternary.out b/modules/gdscript/tests/scripts/parser/warnings/incompatible_ternary.out new file mode 100644 index 0000000000..7d1558c6fc --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/incompatible_ternary.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 8 +>> INCOMPATIBLE_TERNARY +>> Values of the ternary conditional are not mutually compatible. diff --git a/modules/gdscript/tests/scripts/parser/warnings/integer_division.gd b/modules/gdscript/tests/scripts/parser/warnings/integer_division.gd new file mode 100644 index 0000000000..6117425528 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/integer_division.gd @@ -0,0 +1,10 @@ +func test(): + # This should emit a warning. + var __ = 5 / 2 + + # These should not emit warnings. + __ = float(5) / 2 + __ = 5 / float(2) + __ = 5.0 / 2 + __ = 5 / 2.0 + __ = 5.0 / 2.0 diff --git a/modules/gdscript/tests/scripts/parser/warnings/integer_division.out b/modules/gdscript/tests/scripts/parser/warnings/integer_division.out new file mode 100644 index 0000000000..40eb63ffcb --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/integer_division.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 3 +>> INTEGER_DIVISION +>> Integer division, decimal part will be discarded. diff --git a/modules/gdscript/tests/scripts/parser/warnings/match_default_not_at_end.gd b/modules/gdscript/tests/scripts/parser/warnings/match_default_not_at_end.gd new file mode 100644 index 0000000000..1eb54059dd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/match_default_not_at_end.gd @@ -0,0 +1,9 @@ +func test(): + var i = 25 + # The default branch (`_`) should be at the end of the `match` statement. + # Otherwise, a warning will be emitted + match i: + _: + print("default") + 25: + print("is 25") diff --git a/modules/gdscript/tests/scripts/parser/warnings/match_default_not_at_end.out b/modules/gdscript/tests/scripts/parser/warnings/match_default_not_at_end.out new file mode 100644 index 0000000000..8630fab420 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/match_default_not_at_end.out @@ -0,0 +1,6 @@ +GDTEST_OK +>> WARNING +>> Line: 8 +>> UNREACHABLE_PATTERN +>> Unreachable pattern (pattern after wildcard or bind). +default diff --git a/modules/gdscript/tests/scripts/parser/warnings/narrowing_conversion.gd b/modules/gdscript/tests/scripts/parser/warnings/narrowing_conversion.gd new file mode 100644 index 0000000000..954e697145 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/narrowing_conversion.gd @@ -0,0 +1,5 @@ +func i_accept_ints_only(_i: int): + pass + +func test(): + i_accept_ints_only(12.345) diff --git a/modules/gdscript/tests/scripts/parser/warnings/narrowing_conversion.out b/modules/gdscript/tests/scripts/parser/warnings/narrowing_conversion.out new file mode 100644 index 0000000000..6fb592117b --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/narrowing_conversion.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 5 +>> NARROWING_CONVERSION +>> Narrowing conversion (float is converted to int and loses precision). diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd new file mode 100644 index 0000000000..00598e4d50 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd @@ -0,0 +1,6 @@ +func i_return_int() -> int: + return 4 + + +func test(): + i_return_int() diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out new file mode 100644 index 0000000000..d73c5eb7cd --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out @@ -0,0 +1 @@ +GDTEST_OK diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.gd b/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.gd new file mode 100644 index 0000000000..d565d38365 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.gd @@ -0,0 +1,8 @@ +# See also `parser-errors/redefine-class-constant.gd`. +const TEST = 25 + + +func test(): + # Warning here. This is not an error because a new constant is created, + # rather than attempting to set the value of an existing constant. + const TEST = 50 diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out new file mode 100644 index 0000000000..9c9417e11d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_constant.out @@ -0,0 +1,9 @@ +GDTEST_OK +>> WARNING +>> Line: 8 +>> UNUSED_LOCAL_CONSTANT +>> The local constant 'TEST' is declared but never used in the block. If this is intended, prefix it with an underscore: '_TEST' +>> WARNING +>> Line: 8 +>> SHADOWED_VARIABLE +>> The local constant "TEST" is shadowing an already-declared constant at line 2. diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.gd b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.gd new file mode 100644 index 0000000000..66dcf309e8 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.gd @@ -0,0 +1,8 @@ +var foo = 123 + + +func test(): + # Notice the `var` keyword. Without this keyword, no warning would be emitted + # because no new variable would be created. Instead, the class variable's value + # would be overwritten. + var foo = 456 diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out new file mode 100644 index 0000000000..82e467b368 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_class.out @@ -0,0 +1,9 @@ +GDTEST_OK +>> WARNING +>> Line: 8 +>> UNUSED_VARIABLE +>> The local variable 'foo' is declared but never used in the block. If this is intended, prefix it with an underscore: '_foo' +>> WARNING +>> Line: 8 +>> SHADOWED_VARIABLE +>> The local variable "foo" is shadowing an already-declared variable at line 1. diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.gd b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.gd new file mode 100644 index 0000000000..2c55d68be8 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.gd @@ -0,0 +1,2 @@ +func test(): + var test = "This variable has the same name as the test() function." diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out new file mode 100644 index 0000000000..26ce0465b1 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_variable_function.out @@ -0,0 +1,9 @@ +GDTEST_OK +>> WARNING +>> Line: 2 +>> UNUSED_VARIABLE +>> The local variable 'test' is declared but never used in the block. If this is intended, prefix it with an underscore: '_test' +>> WARNING +>> Line: 2 +>> SHADOWED_VARIABLE +>> The local variable "test" is shadowing an already-declared function at line 1. diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd new file mode 100644 index 0000000000..18ea260fa2 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd @@ -0,0 +1,9 @@ +func test(): + # The following statements should all be reported as standalone expressions: + "This is a standalone expression" + 1234 + 0.0 + 0.0 + Color(1, 1, 1) + Vector3.ZERO + [true, false] + float(125) diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out new file mode 100644 index 0000000000..99ec87438e --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out @@ -0,0 +1,21 @@ +GDTEST_OK +>> WARNING +>> Line: 3 +>> STANDALONE_EXPRESSION +>> Standalone expression (the line has no effect). +>> WARNING +>> Line: 4 +>> STANDALONE_EXPRESSION +>> Standalone expression (the line has no effect). +>> WARNING +>> Line: 5 +>> STANDALONE_EXPRESSION +>> Standalone expression (the line has no effect). +>> WARNING +>> Line: 7 +>> STANDALONE_EXPRESSION +>> Standalone expression (the line has no effect). +>> WARNING +>> Line: 8 +>> STANDALONE_EXPRESSION +>> Standalone expression (the line has no effect). diff --git a/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable.gd b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable.gd new file mode 100644 index 0000000000..afb5059eea --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable.gd @@ -0,0 +1,2 @@ +func test(): + var __ diff --git a/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable.out b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable.out new file mode 100644 index 0000000000..cf14502e9a --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 2 +>> UNASSIGNED_VARIABLE +>> The variable '__' was used but never assigned a value. diff --git a/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable_op_assign.gd b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable_op_assign.gd new file mode 100644 index 0000000000..d77791f4c5 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable_op_assign.gd @@ -0,0 +1,4 @@ +func test(): + var __: int + # Variable has no set value at this point (even though it's implicitly `0` here). + __ += 15 diff --git a/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable_op_assign.out b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable_op_assign.out new file mode 100644 index 0000000000..ba55a4e0f8 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unassigned_variable_op_assign.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 4 +>> UNASSIGNED_VARIABLE_OP_ASSIGN +>> Using assignment with operation but the variable '__' was not previously assigned a value. diff --git a/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return.gd b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return.gd new file mode 100644 index 0000000000..3311f342ab --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return.gd @@ -0,0 +1,7 @@ +func test(): + var i = 25 + + return + + # This will never be run due to the `return` statement above. + print(i) diff --git a/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return.out b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return.out new file mode 100644 index 0000000000..9316abd5eb --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 7 +>> UNREACHABLE_CODE +>> Unreachable code (statement after return) in function 'test()'. diff --git a/modules/gdscript/tests/scripts/parser/warnings/unused_argument.gd b/modules/gdscript/tests/scripts/parser/warnings/unused_argument.gd new file mode 100644 index 0000000000..e6e24dc6f2 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unused_argument.gd @@ -0,0 +1,12 @@ +# This should emit a warning since the unused argument is not prefixed with an underscore. +func function_with_unused_argument(p_arg1, p_arg2): + print(p_arg1) + + +# This shouldn't emit a warning since the unused argument is prefixed with an underscore. +func function_with_ignored_unused_argument(p_arg1, _p_arg2): + print(p_arg1) + + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/parser/warnings/unused_argument.out b/modules/gdscript/tests/scripts/parser/warnings/unused_argument.out new file mode 100644 index 0000000000..92f3308f85 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/unused_argument.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 2 +>> UNUSED_PARAMETER +>> The parameter 'p_arg2' is never used in the function 'function_with_unused_argument'. If this is intended, prefix it with an underscore: '_p_arg2' diff --git a/modules/gdscript/tests/scripts/parser/warnings/unused_variable.gd b/modules/gdscript/tests/scripts/parser/warnings/unused_variable.gd index 68e3bd424f..013a2e4beb 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/unused_variable.gd +++ b/modules/gdscript/tests/scripts/parser/warnings/unused_variable.gd @@ -1,2 +1,4 @@ func test(): - var unused = "not used" + var unused = "not used" + + var _unused = "not used, but no warning since the variable name starts with an underscore" diff --git a/modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd b/modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd new file mode 100644 index 0000000000..b4a42b3e3d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd @@ -0,0 +1,6 @@ +func i_return_void() -> void: + return + + +func test(): + var __ = i_return_void() diff --git a/modules/gdscript/tests/scripts/parser/warnings/void_assignment.out b/modules/gdscript/tests/scripts/parser/warnings/void_assignment.out new file mode 100644 index 0000000000..84c9598f9a --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/void_assignment.out @@ -0,0 +1,5 @@ +GDTEST_OK +>> WARNING +>> Line: 6 +>> VOID_ASSIGNMENT +>> Assignment operation, but the function 'i_return_void()' returns void. diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd new file mode 100644 index 0000000000..c6645c2c34 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(value == null) + + # bool + value = false + print(value == null) + + # int + value = 0 + print(value == null) + + # float + value = 0.0 + print(value == null) + + # String + value = "" + print(value == null) + + # Vector2 + value = Vector2() + print(value == null) + + # Vector2i + value = Vector2i() + print(value == null) + + # Rect2 + value = Rect2() + print(value == null) + + # Rect2i + value = Rect2i() + print(value == null) + + # Vector3 + value = Vector3() + print(value == null) + + # Vector3i + value = Vector3i() + print(value == null) + + # Transform2D + value = Transform2D() + print(value == null) + + # Plane + value = Plane() + print(value == null) + + # Quaternion + value = Quaternion() + print(value == null) + + # AABB + value = AABB() + print(value == null) + + # Basis + value = Basis() + print(value == null) + + # Transform3D + value = Transform3D() + print(value == null) + + # Color + value = Color() + print(value == null) + + # StringName + value = &"" + print(value == null) + + # NodePath + value = ^"" + print(value == null) + + # RID + value = RID() + print(value == null) + + # Callable + value = Callable() + print(value == null) + + # Signal + value = Signal() + print(value == null) + + # Dictionary + value = {} + print(value == null) + + # Array + value = [] + print(value == null) + + # PackedByteArray + value = PackedByteArray() + print(value == null) + + # PackedInt32Array + value = PackedInt32Array() + print(value == null) + + # PackedInt64Array + value = PackedInt64Array() + print(value == null) + + # PackedFloat32Array + value = PackedFloat32Array() + print(value == null) + + # PackedFloat64Array + value = PackedFloat64Array() + print(value == null) + + # PackedStringArray + value = PackedStringArray() + print(value == null) + + # PackedVector2Array + value = PackedVector2Array() + print(value == null) + + # PackedVector3Array + value = PackedVector3Array() + print(value == null) + + # PackedColorArray + value = PackedColorArray() + print(value == null) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out new file mode 100644 index 0000000000..639f6027b9 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out @@ -0,0 +1,35 @@ +GDTEST_OK +true +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd new file mode 100644 index 0000000000..ee622bf22f --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(value != null) + + # bool + value = false + print(value != null) + + # int + value = 0 + print(value != null) + + # float + value = 0.0 + print(value != null) + + # String + value = "" + print(value != null) + + # Vector2 + value = Vector2() + print(value != null) + + # Vector2i + value = Vector2i() + print(value != null) + + # Rect2 + value = Rect2() + print(value != null) + + # Rect2i + value = Rect2i() + print(value != null) + + # Vector3 + value = Vector3() + print(value != null) + + # Vector3i + value = Vector3i() + print(value != null) + + # Transform2D + value = Transform2D() + print(value != null) + + # Plane + value = Plane() + print(value != null) + + # Quaternion + value = Quaternion() + print(value != null) + + # AABB + value = AABB() + print(value != null) + + # Basis + value = Basis() + print(value != null) + + # Transform3D + value = Transform3D() + print(value != null) + + # Color + value = Color() + print(value != null) + + # StringName + value = &"" + print(value != null) + + # NodePath + value = ^"" + print(value != null) + + # RID + value = RID() + print(value != null) + + # Callable + value = Callable() + print(value != null) + + # Signal + value = Signal() + print(value != null) + + # Dictionary + value = {} + print(value != null) + + # Array + value = [] + print(value != null) + + # PackedByteArray + value = PackedByteArray() + print(value != null) + + # PackedInt32Array + value = PackedInt32Array() + print(value != null) + + # PackedInt64Array + value = PackedInt64Array() + print(value != null) + + # PackedFloat32Array + value = PackedFloat32Array() + print(value != null) + + # PackedFloat64Array + value = PackedFloat64Array() + print(value != null) + + # PackedStringArray + value = PackedStringArray() + print(value != null) + + # PackedVector2Array + value = PackedVector2Array() + print(value != null) + + # PackedVector3Array + value = PackedVector3Array() + print(value != null) + + # PackedColorArray + value = PackedColorArray() + print(value != null) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out new file mode 100644 index 0000000000..d1e332afba --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out @@ -0,0 +1,35 @@ +GDTEST_OK +false +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.gd b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.gd new file mode 100644 index 0000000000..7649062fda --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(null == value) + + # bool + value = false + print(null == value) + + # int + value = 0 + print(null == value) + + # float + value = 0.0 + print(null == value) + + # String + value = "" + print(null == value) + + # Vector2 + value = Vector2() + print(null == value) + + # Vector2i + value = Vector2i() + print(null == value) + + # Rect2 + value = Rect2() + print(null == value) + + # Rect2i + value = Rect2i() + print(null == value) + + # Vector3 + value = Vector3() + print(null == value) + + # Vector3i + value = Vector3i() + print(null == value) + + # Transform2D + value = Transform2D() + print(null == value) + + # Plane + value = Plane() + print(null == value) + + # Quaternion + value = Quaternion() + print(null == value) + + # AABB + value = AABB() + print(null == value) + + # Basis + value = Basis() + print(null == value) + + # Transform3D + value = Transform3D() + print(null == value) + + # Color + value = Color() + print(null == value) + + # StringName + value = &"" + print(null == value) + + # NodePath + value = ^"" + print(null == value) + + # RID + value = RID() + print(null == value) + + # Callable + value = Callable() + print(null == value) + + # Signal + value = Signal() + print(null == value) + + # Dictionary + value = {} + print(null == value) + + # Array + value = [] + print(null == value) + + # PackedByteArray + value = PackedByteArray() + print(null == value) + + # PackedInt32Array + value = PackedInt32Array() + print(null == value) + + # PackedInt64Array + value = PackedInt64Array() + print(null == value) + + # PackedFloat32Array + value = PackedFloat32Array() + print(null == value) + + # PackedFloat64Array + value = PackedFloat64Array() + print(null == value) + + # PackedStringArray + value = PackedStringArray() + print(null == value) + + # PackedVector2Array + value = PackedVector2Array() + print(null == value) + + # PackedVector3Array + value = PackedVector3Array() + print(null == value) + + # PackedColorArray + value = PackedColorArray() + print(null == value) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.out b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.out new file mode 100644 index 0000000000..639f6027b9 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.out @@ -0,0 +1,35 @@ +GDTEST_OK +true +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.gd b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.gd new file mode 100644 index 0000000000..8d5f9df1b8 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(null != value) + + # bool + value = false + print(null != value) + + # int + value = 0 + print(null != value) + + # float + value = 0.0 + print(null != value) + + # String + value = "" + print(null != value) + + # Vector2 + value = Vector2() + print(null != value) + + # Vector2i + value = Vector2i() + print(null != value) + + # Rect2 + value = Rect2() + print(null != value) + + # Rect2i + value = Rect2i() + print(null != value) + + # Vector3 + value = Vector3() + print(null != value) + + # Vector3i + value = Vector3i() + print(null != value) + + # Transform2D + value = Transform2D() + print(null != value) + + # Plane + value = Plane() + print(null != value) + + # Quaternion + value = Quaternion() + print(null != value) + + # AABB + value = AABB() + print(null != value) + + # Basis + value = Basis() + print(null != value) + + # Transform3D + value = Transform3D() + print(null != value) + + # Color + value = Color() + print(null != value) + + # StringName + value = &"" + print(null != value) + + # NodePath + value = ^"" + print(null != value) + + # RID + value = RID() + print(null != value) + + # Callable + value = Callable() + print(null != value) + + # Signal + value = Signal() + print(null != value) + + # Dictionary + value = {} + print(null != value) + + # Array + value = [] + print(null != value) + + # PackedByteArray + value = PackedByteArray() + print(null != value) + + # PackedInt32Array + value = PackedInt32Array() + print(null != value) + + # PackedInt64Array + value = PackedInt64Array() + print(null != value) + + # PackedFloat32Array + value = PackedFloat32Array() + print(null != value) + + # PackedFloat64Array + value = PackedFloat64Array() + print(null != value) + + # PackedStringArray + value = PackedStringArray() + print(null != value) + + # PackedVector2Array + value = PackedVector2Array() + print(null != value) + + # PackedVector3Array + value = PackedVector3Array() + print(null != value) + + # PackedColorArray + value = PackedColorArray() + print(null != value) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.out b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.out new file mode 100644 index 0000000000..d1e332afba --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.out @@ -0,0 +1,35 @@ +GDTEST_OK +false +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 17846eb281..6cc7ddb424 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2891,12 +2891,24 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage ERR_FAIL_COND_V_MSG(elem_variant_type == Variant::NIL, -1, "Unknown array element type."); - int hint_res = _try_get_member_export_hint(p_member, elem_type, elem_variant_type, /* allow_generics: */ false, elem_hint, elem_hint_string); + bool preset_hint = false; + if (elem_variant_type == Variant::STRING) { + MonoObject *attr = p_member->get_attribute(CACHED_CLASS(ExportAttribute)); + if (PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)) == PROPERTY_HINT_ENUM) { + r_hint_string = itos(elem_variant_type) + "/" + itos(PROPERTY_HINT_ENUM) + ":" + CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); + preset_hint = true; + } + } + + if (!preset_hint) { + int hint_res = _try_get_member_export_hint(p_member, elem_type, elem_variant_type, /* allow_generics: */ false, elem_hint, elem_hint_string); - ERR_FAIL_COND_V_MSG(hint_res == -1, -1, "Error while trying to determine information about the array element type."); + ERR_FAIL_COND_V_MSG(hint_res == -1, -1, "Error while trying to determine information about the array element type."); + + // Format: type/hint:hint_string + r_hint_string = itos(elem_variant_type) + "/" + itos(elem_hint) + ":" + elem_hint_string; + } - // Format: type/hint:hint_string - r_hint_string = itos(elem_variant_type) + "/" + itos(elem_hint) + ":" + elem_hint_string; r_hint = PROPERTY_HINT_TYPE_STRING; } else if (p_allow_generics && p_variant_type == Variant::DICTIONARY) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs index 658582960f..1dc21b6303 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs @@ -78,7 +78,8 @@ namespace Godot /// </example> /// <seealso cref="GetNode{T}(NodePath)"/> /// <param name="path">The path to the node to fetch.</param> - /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>/// ///////// <returns> + /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam> + /// <returns> /// The <see cref="Node"/> at the given <paramref name="path"/>, or <see langword="null"/> if not found. /// </returns> public T GetNodeOrNull<T>(NodePath path) where T : class @@ -97,7 +98,8 @@ namespace Godot /// <exception cref="InvalidCastException"> /// Thrown when the given the fetched node can't be casted to the given type <typeparamref name="T"/>. /// </exception> - /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>/// ///////// <returns> + /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam> + /// <returns> /// The child <see cref="Node"/> at the given index <paramref name="idx"/>. /// </returns> public T GetChild<T>(int idx) where T : class diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index daea09ba72..c82c5f4588 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -361,6 +361,7 @@ namespace Godot /// <seealso cref="XformInv(Vector2)"/> /// <param name="v">A vector to transform.</param> /// <returns>The transformed vector.</returns> + [Obsolete("Xform is deprecated. Use the multiplication operator (Transform2D * Vector2) instead.")] public Vector2 Xform(Vector2 v) { return new Vector2(Tdotx(v), Tdoty(v)) + origin; @@ -372,6 +373,7 @@ namespace Godot /// <seealso cref="Xform(Vector2)"/> /// <param name="v">A vector to inversely transform.</param> /// <returns>The inversely transformed vector.</returns> + [Obsolete("XformInv is deprecated. Use the multiplication operator (Vector2 * Transform2D) instead.")] public Vector2 XformInv(Vector2 v) { Vector2 vInv = v - origin; @@ -447,7 +449,7 @@ namespace Godot public static Transform2D operator *(Transform2D left, Transform2D right) { - left.origin = left.Xform(right.origin); + left.origin = left * right.origin; real_t x0 = left.Tdotx(right.x); real_t x1 = left.Tdoty(right.x); @@ -462,6 +464,96 @@ namespace Godot return left; } + /// <summary> + /// Returns a Vector2 transformed (multiplied) by transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="vector">A Vector2 to transform.</param> + /// <returns>The transformed Vector2.</returns> + public static Vector2 operator *(Transform2D transform, Vector2 vector) + { + return new Vector2(transform.Tdotx(vector), transform.Tdoty(vector)) + transform.origin; + } + + /// <summary> + /// Returns a Vector2 transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="vector">A Vector2 to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed Vector2.</returns> + public static Vector2 operator *(Vector2 vector, Transform2D transform) + { + Vector2 vInv = vector - transform.origin; + return new Vector2(transform.x.Dot(vInv), transform.y.Dot(vInv)); + } + + /// <summary> + /// Returns a Rect2 transformed (multiplied) by transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="rect">A Rect2 to transform.</param> + /// <returns>The transformed Rect2.</returns> + public static Rect2 operator *(Transform2D transform, Rect2 rect) + { + Vector2 pos = transform * rect.Position; + Vector2 toX = transform.x * rect.Size.x; + Vector2 toY = transform.y * rect.Size.y; + + return new Rect2(pos, rect.Size).Expand(pos + toX).Expand(pos + toY).Expand(pos + toX + toY); + } + + /// <summary> + /// Returns a Rect2 transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="rect">A Rect2 to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed Rect2.</returns> + public static Rect2 operator *(Rect2 rect, Transform2D transform) + { + Vector2 pos = rect.Position * transform; + Vector2 to1 = new Vector2(rect.Position.x, rect.Position.y + rect.Size.y) * transform; + Vector2 to2 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y + rect.Size.y) * transform; + Vector2 to3 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y) * transform; + + return new Rect2(pos, rect.Size).Expand(to1).Expand(to2).Expand(to3); + } + + /// <summary> + /// Returns a copy of the given Vector2[] transformed (multiplied) by transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="array">A Vector2[] to transform.</param> + /// <returns>The transformed copy of the Vector2[].</returns> + public static Vector2[] operator *(Transform2D transform, Vector2[] array) + { + Vector2[] newArray = new Vector2[array.Length]; + + for (int i = 0; i < array.Length; i++) + { + newArray[i] = transform * array[i]; + } + + return newArray; + } + + /// <summary> + /// Returns a copy of the given Vector2[] transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="array">A Vector2[] to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed copy of the Vector2[].</returns> + public static Vector2[] operator *(Vector2[] array, Transform2D transform) + { + Vector2[] newArray = new Vector2[array.Length]; + + for (int i = 0; i < array.Length; i++) + { + newArray[i] = array[i] * transform; + } + + return newArray; + } + public static bool operator ==(Transform2D left, Transform2D right) { return left.Equals(right); diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 905d10c9d4..bb6bc578a4 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -45,7 +45,7 @@ #include "scene/resources/primitive_meshes.h" #include "scene/resources/shape_3d.h" #include "scene/resources/sphere_shape_3d.h" -#include "scene/resources/world_margin_shape_3d.h" +#include "scene/resources/world_boundary_shape_3d.h" #ifdef TOOLS_ENABLED #include "editor/editor_node.h" diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 6691f86e60..7cd4db6f67 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -64,6 +64,7 @@ if env["builtin_harfbuzz"]: #'src/hb-gobject-structs.cc', "src/hb-icu.cc", "src/hb-map.cc", + "src/hb-ms-feature-ranges.cc", "src/hb-number.cc", "src/hb-ot-cff1-table.cc", "src/hb-ot-cff2-table.cc", diff --git a/modules/text_server_adv/script_iterator.cpp b/modules/text_server_adv/script_iterator.cpp index f9bbd25a5f..d1e849def8 100644 --- a/modules/text_server_adv/script_iterator.cpp +++ b/modules/text_server_adv/script_iterator.cpp @@ -30,6 +30,8 @@ #include "script_iterator.h" +// This implementation is derived from ICU: icu4c/source/extra/scrptrun/scrptrun.cpp + bool ScriptIterator::same_script(int32_t p_script_one, int32_t p_script_two) { return p_script_one <= USCRIPT_INHERITED || p_script_two <= USCRIPT_INHERITED || p_script_one == p_script_two; } @@ -48,7 +50,8 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length p_start = 0; } - ParenStackEntry paren_stack[128]; + int paren_size = PAREN_STACK_DEPTH; + ParenStackEntry *paren_stack = (ParenStackEntry *)memalloc(paren_size * sizeof(ParenStackEntry)); int script_start; int script_end = p_start; @@ -64,13 +67,22 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length UChar32 ch = str[script_end]; UScriptCode sc = uscript_getScript(ch, &err); if (U_FAILURE(err)) { + memfree(paren_stack); ERR_FAIL_MSG(u_errorName(err)); } if (u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) != U_BPT_NONE) { if (u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_OPEN) { - paren_stack[++paren_sp].pair_index = ch; + // If it's an open character, push it onto the stack. + paren_sp++; + if (unlikely(paren_sp >= paren_size)) { + // If the stack is full, allocate more space to handle deeply nested parentheses. This is unlikely to happen with any real text. + paren_size += PAREN_STACK_DEPTH; + paren_stack = (ParenStackEntry *)memrealloc(paren_stack, paren_size * sizeof(ParenStackEntry)); + } + paren_stack[paren_sp].pair_index = ch; paren_stack[paren_sp].script_code = script_code; } else if (paren_sp >= 0) { + // If it's a close character, find the matching open on the stack, and use that script code. Any non-matching open characters above it on the stack will be poped. UChar32 paired_ch = u_getBidiPairedBracket(ch); while (paren_sp >= 0 && paren_stack[paren_sp].pair_index != paired_ch) { paren_sp -= 1; @@ -87,11 +99,13 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length if (same_script(script_code, sc)) { if (script_code <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) { script_code = sc; + // Now that we have a final script code, fix any open characters we pushed before we knew the script code. while (start_sp < paren_sp) { paren_stack[++start_sp].script_code = script_code; } } if ((u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_CLOSE) && paren_sp >= 0) { + // If this character is a close paired character pop the matching open character from the stack. paren_sp -= 1; if (start_sp >= 0) { start_sp -= 1; @@ -109,4 +123,6 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length script_ranges.push_back(rng); } while (script_end < p_length); + + memfree(paren_stack); } diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h index 896a0e5c15..5efd40f7c4 100644 --- a/modules/text_server_adv/script_iterator.h +++ b/modules/text_server_adv/script_iterator.h @@ -43,6 +43,8 @@ #include <hb.h> class ScriptIterator { + static const int PAREN_STACK_DEPTH = 128; + public: struct ScriptRange { int start = 0; diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 7fb9707fce..890861cf82 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -117,7 +117,7 @@ void register_visual_script_types() { GDREGISTER_CLASS(VisualScriptCustomNodes); ClassDB::set_current_api(ClassDB::API_CORE); vs_custom_nodes_singleton = memnew(VisualScriptCustomNodes); - Engine::get_singleton()->add_singleton(Engine::Singleton("VisualScriptEditor", VisualScriptCustomNodes::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("VisualScriptCustomNodes", VisualScriptCustomNodes::get_singleton())); VisualScriptEditor::register_editor(); #endif diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index eee9e8f32b..0a6bcedf31 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -2546,16 +2546,11 @@ void VisualScriptEditor::goto_line(int p_line, bool p_with_error) { error_line = p_line; } - List<StringName> functions; - script->get_function_list(&functions); - for (const StringName &E : functions) { - if (script->has_node(p_line)) { - _update_graph(); - _update_members(); + if (script->has_node(p_line)) { + _update_graph(); + _update_members(); - call_deferred(SNAME("call_deferred"), "_center_on_node", E, p_line); //editor might be just created and size might not exist yet - return; - } + call_deferred(SNAME("call_deferred"), "_center_on_node", p_line); // The editor might be just created and size might not exist yet. } } @@ -3592,6 +3587,11 @@ void VisualScriptEditor::_hide_timer() { hint_text->hide(); } +void VisualScriptEditor::_toggle_scripts_pressed() { + ScriptEditor::get_singleton()->toggle_scripts_panel(); + update_toggle_scripts_button(); +} + void VisualScriptEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { @@ -3606,6 +3606,8 @@ void VisualScriptEditor::_notification(int p_what) { return; } + update_toggle_scripts_button(); + edit_variable_edit->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); edit_signal_edit->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); func_input_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); @@ -3650,6 +3652,7 @@ void VisualScriptEditor::_notification(int p_what) { } } break; case NOTIFICATION_VISIBILITY_CHANGED: { + update_toggle_scripts_button(); members_section->set_visible(is_visible_in_tree()); } break; } @@ -4232,6 +4235,15 @@ void VisualScriptEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_h void VisualScriptEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) { } +void VisualScriptEditor::update_toggle_scripts_button() { + if (is_layout_rtl()) { + toggle_scripts_button->set_icon(Control::get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Forward") : SNAME("Back"), SNAME("EditorIcons"))); + } else { + toggle_scripts_button->set_icon(Control::get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"), SNAME("EditorIcons"))); + } + toggle_scripts_button->set_tooltip(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); +} + void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node); ClassDB::bind_method("_update_graph", &VisualScriptEditor::_update_graph, DEFVAL(-1)); @@ -4333,6 +4345,16 @@ VisualScriptEditor::VisualScriptEditor() { graph->hide(); graph->connect("scroll_offset_changed", callable_mp(this, &VisualScriptEditor::_graph_ofs_changed)); + status_bar = memnew(HBoxContainer); + add_child(status_bar); + status_bar->set_h_size_flags(SIZE_EXPAND_FILL); + status_bar->set_custom_minimum_size(Size2(0, 24 * EDSCALE)); + + toggle_scripts_button = memnew(Button); + toggle_scripts_button->set_flat(true); + toggle_scripts_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_toggle_scripts_pressed)); + status_bar->add_child(toggle_scripts_button); + /// Add Buttons to Top Bar/Zoom bar. HBoxContainer *graph_hbc = graph->get_zoom_hbox(); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index ab32aae7aa..19f5aabac9 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -93,6 +93,8 @@ class VisualScriptEditor : public ScriptEditorBase { ConfirmationDialog *function_create_dialog; GraphEdit *graph; + HBoxContainer *status_bar; + Button *toggle_scripts_button; VisualScriptEditorSignalEdit *signal_editor; @@ -281,6 +283,8 @@ class VisualScriptEditor : public ScriptEditorBase { void _member_rmb_selected(const Vector2 &p_pos); void _member_option(int p_option); + void _toggle_scripts_pressed(); + protected: void _notification(int p_what); static void _bind_methods(); @@ -330,6 +334,8 @@ public: static void free_clipboard(); + void update_toggle_scripts_button() override; + VisualScriptEditor(); ~VisualScriptEditor(); }; |