summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp47
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp6
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h1
-rw-r--r--modules/gdscript/gdscript_codegen.h1
-rw-r--r--modules/gdscript/gdscript_compiler.cpp19
-rw-r--r--modules/gdscript/gdscript_disassembler.cpp8
-rw-r--r--modules/gdscript/gdscript_editor.cpp2
-rw-r--r--modules/gdscript/gdscript_function.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp31
-rw-r--r--modules/gdscript/gdscript_vm.cpp13
-rw-r--r--modules/gdscript/gdscript_warning.cpp4
-rw-r--r--modules/gdscript/gdscript_warning.h1
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.gd16
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/features/variable_declaration.gd21
-rw-r--r--modules/gdscript/tests/scripts/parser/features/variable_declaration.out6
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.gd3
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.out4
29 files changed, 218 insertions, 32 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index fc0bef3ba2..06db46173c 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -171,7 +171,7 @@ Error GDScriptAnalyzer::check_native_member_name_conflict(const StringName &p_me
}
if (class_exists(p_member_name)) {
- push_error(vformat(R"(The class "%s" shadows a native class.)", p_member_name), p_member_node);
+ push_error(vformat(R"(The member "%s" shadows a native class.)", p_member_name), p_member_node);
return ERR_PARSE_ERROR;
}
@@ -218,6 +218,17 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
p_class->fqcn = p_class->outer->fqcn + "::" + String(p_class->identifier->name);
}
+ if (p_class->identifier) {
+ StringName class_name = p_class->identifier->name;
+ if (class_exists(class_name)) {
+ push_error(vformat(R"(Class "%s" hides a native class.)", class_name), p_class->identifier);
+ } else if (ScriptServer::is_global_class(class_name) && (ScriptServer::get_global_class_path(class_name) != parser->script_path || p_class != parser->head)) {
+ push_error(vformat(R"(Class "%s" hides a global script class.)", class_name), p_class->identifier);
+ } else if (ProjectSettings::get_singleton()->has_autoload(class_name) && ProjectSettings::get_singleton()->get_autoload(class_name).is_singleton) {
+ push_error(vformat(R"(Class "%s" hides an autoload singleton.)", class_name), p_class->identifier);
+ }
+ }
+
GDScriptParser::DataType result;
// Set datatype for class.
@@ -681,8 +692,9 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
specified_type.is_meta_type = false;
}
- GDScriptParser::DataType datatype = member.constant->get_datatype();
+ GDScriptParser::DataType datatype;
if (member.constant->initializer) {
+ datatype = member.constant->initializer->get_datatype();
if (member.constant->initializer->type == GDScriptParser::Node::ARRAY) {
GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(member.constant->initializer);
const_fold_array(array);
@@ -2516,14 +2528,29 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
while (outer != nullptr) {
if (outer->has_member(name)) {
const GDScriptParser::ClassNode::Member &member = outer->get_member(name);
- if (member.type == GDScriptParser::ClassNode::Member::CONSTANT) {
- // TODO: Make sure loops won't cause problem. And make special error message for those.
- // For out-of-order resolution:
- reduce_expression(member.constant->initializer);
- p_identifier->set_datatype(member.get_datatype());
- p_identifier->is_constant = true;
- p_identifier->reduced_value = member.constant->initializer->reduced_value;
- return;
+ switch (member.type) {
+ case GDScriptParser::ClassNode::Member::CONSTANT: {
+ // TODO: Make sure loops won't cause problem. And make special error message for those.
+ // For out-of-order resolution:
+ reduce_expression(member.constant->initializer);
+ p_identifier->set_datatype(member.get_datatype());
+ p_identifier->is_constant = true;
+ p_identifier->reduced_value = member.constant->initializer->reduced_value;
+ return;
+ } break;
+ case GDScriptParser::ClassNode::Member::ENUM_VALUE: {
+ p_identifier->set_datatype(member.get_datatype());
+ p_identifier->is_constant = true;
+ p_identifier->reduced_value = member.enum_value.value;
+ return;
+ } break;
+ case GDScriptParser::ClassNode::Member::ENUM: {
+ p_identifier->set_datatype(member.get_datatype());
+ p_identifier->is_constant = false;
+ return;
+ } break;
+ default:
+ break;
}
}
outer = outer->outer;
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index bed67b55f0..1127488db8 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -864,6 +864,12 @@ void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_
function->default_arguments.push_back(opcodes.size());
}
+void GDScriptByteCodeGenerator::write_store_global(const Address &p_dst, int p_global_index) {
+ append(GDScriptFunction::OPCODE_STORE_GLOBAL, 1);
+ append(p_dst);
+ append(p_global_index);
+}
+
void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
append(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL, 1);
append(p_dst);
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index ce1a043b28..dcc11ebdce 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -454,6 +454,7 @@ public:
virtual void write_assign_true(const Address &p_target) override;
virtual void write_assign_false(const Address &p_target) override;
virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
+ virtual void write_store_global(const Address &p_dst, int p_global_index) override;
virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) override;
virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override;
virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h
index 7713d13bc8..e6ecc92d55 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -115,6 +115,7 @@ public:
virtual void write_assign_true(const Address &p_target) = 0;
virtual void write_assign_false(const Address &p_target) = 0;
virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
+ virtual void write_store_global(const Address &p_dst, int p_global_index) = 0;
virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) = 0;
virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0;
virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 736f6eae79..b0d0b02443 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -35,6 +35,8 @@
#include "gdscript_cache.h"
#include "gdscript_utility_functions.h"
+#include "core/config/project_settings.h"
+
bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
if (codegen.function_node && codegen.function_node->is_static) {
return false;
@@ -316,10 +318,21 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
}
}
+ // Try globals.
if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
- int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
- Variant global = GDScriptLanguage::get_singleton()->get_global_array()[idx];
- return codegen.add_constant(global); // TODO: Get type.
+ // If it's an autoload singleton, we postpone to load it at runtime.
+ // This is so one autoload doesn't try to load another before it's compiled.
+ OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+ if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
+ GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
+ int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
+ gen->write_store_global(global, idx);
+ return global;
+ } else {
+ int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
+ Variant global = GDScriptLanguage::get_singleton()->get_global_array()[idx];
+ return codegen.add_constant(global);
+ }
}
// Try global classes.
diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp
index 1acb9ceddc..9287df2ea0 100644
--- a/modules/gdscript/gdscript_disassembler.cpp
+++ b/modules/gdscript/gdscript_disassembler.cpp
@@ -914,6 +914,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
incr += 5;
} break;
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
+ case OPCODE_STORE_GLOBAL: {
+ text += "store global ";
+ text += DADDR(1);
+ text += " = ";
+ text += String::num_int64(_code_ptr[ip + 2]);
+
+ incr += 3;
+ } break;
case OPCODE_STORE_NAMED_GLOBAL: {
text += "store named global ";
text += DADDR(1);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index f809a4dab8..f79e5726ce 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1733,7 +1733,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
}
}
- if (is_function_parameter && p_context.current_function && p_context.current_class) {
+ if (is_function_parameter && p_context.current_function && p_context.current_function->source_lambda == nullptr && p_context.current_class) {
// Check if it's override of native function, then we can assume the type from the signature.
GDScriptParser::DataType base_type = p_context.current_class->base_type;
while (base_type.is_set()) {
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index b21cb47910..9d076a8e4c 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -348,6 +348,7 @@ public:
OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
OPCODE_ITERATE_PACKED_COLOR_ARRAY,
OPCODE_ITERATE_OBJECT,
+ OPCODE_STORE_GLOBAL,
OPCODE_STORE_NAMED_GLOBAL,
OPCODE_TYPE_ADJUST_BOOL,
OPCODE_TYPE_ADJUST_INT,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 6c3d4367e4..19584ce194 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -337,12 +337,29 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_
tokenizer.set_cursor_position(cursor_line, cursor_column);
script_path = p_script_path;
current = tokenizer.scan();
- // Avoid error as the first token.
- while (current.type == GDScriptTokenizer::Token::ERROR) {
- push_error(current.literal);
+ // Avoid error or newline as the first token.
+ // The latter can mess with the parser when opening files filled exclusively with comments and newlines.
+ while (current.type == GDScriptTokenizer::Token::ERROR || current.type == GDScriptTokenizer::Token::NEWLINE) {
+ if (current.type == GDScriptTokenizer::Token::ERROR) {
+ push_error(current.literal);
+ }
current = tokenizer.scan();
}
+#ifdef DEBUG_ENABLED
+ // Warn about parsing an empty script file:
+ if (current.type == GDScriptTokenizer::Token::TK_EOF) {
+ // Create a dummy Node for the warning, pointing to the very beginning of the file
+ Node *nd = alloc_node<PassNode>();
+ nd->start_line = 1;
+ nd->start_column = 0;
+ nd->end_line = 1;
+ nd->leftmost_column = 0;
+ nd->rightmost_column = 0;
+ push_warning(nd, GDScriptWarning::EMPTY_FILE);
+ }
+#endif
+
push_multiline(false); // Keep one for the whole parsing.
parse_program();
pop_multiline();
@@ -2369,8 +2386,12 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
}
#ifdef DEBUG_ENABLED
- if (has_operator && source_variable != nullptr && source_variable->assignments == 0) {
- push_warning(assignment, GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, source_variable->identifier->name);
+ if (source_variable != nullptr) {
+ if (has_operator && source_variable->assignments == 0) {
+ push_warning(assignment, GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, source_variable->identifier->name);
+ }
+
+ source_variable->assignments += 1;
}
#endif
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 882256b7e3..64fd7eca8a 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -322,6 +322,7 @@ void (*type_init_function_table[])(Variant *) = {
&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
&&OPCODE_ITERATE_OBJECT, \
+ &&OPCODE_STORE_GLOBAL, \
&&OPCODE_STORE_NAMED_GLOBAL, \
&&OPCODE_TYPE_ADJUST_BOOL, \
&&OPCODE_TYPE_ADJUST_INT, \
@@ -3116,6 +3117,18 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
DISPATCH_OPCODE;
+ OPCODE(OPCODE_STORE_GLOBAL) {
+ CHECK_SPACE(3);
+ int global_idx = _code_ptr[ip + 2];
+ GD_ERR_BREAK(global_idx < 0 || global_idx >= GDScriptLanguage::get_singleton()->get_global_array_size());
+
+ GET_INSTRUCTION_ARG(dst, 0);
+ *dst = GDScriptLanguage::get_singleton()->get_global_array()[global_idx];
+
+ ip += 3;
+ }
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
CHECK_SPACE(3);
int globalname_idx = _code_ptr[ip + 2];
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index ad41b60a4e..7a483a16ba 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -145,6 +145,9 @@ String GDScriptWarning::get_message() const {
case REDUNDANT_AWAIT: {
return R"("await" keyword not needed in this case, because the expression isn't a coroutine nor a signal.)";
}
+ case EMPTY_FILE: {
+ return "Empty script file.";
+ }
case WARNING_MAX:
break; // Can't happen, but silences warning
}
@@ -190,6 +193,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
"ASSERT_ALWAYS_TRUE",
"ASSERT_ALWAYS_FALSE",
"REDUNDANT_AWAIT",
+ "EMPTY_FILE",
};
static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h
index 4b295b5eb8..8de46b08c1 100644
--- a/modules/gdscript/gdscript_warning.h
+++ b/modules/gdscript/gdscript_warning.h
@@ -68,6 +68,7 @@ public:
ASSERT_ALWAYS_TRUE, // Expression for assert argument is always true.
ASSERT_ALWAYS_FALSE, // Expression for assert argument is always false.
REDUNDANT_AWAIT, // await is used but expression is synchronous (not a signal nor a coroutine).
+ EMPTY_FILE, // A script file is empty.
WARNING_MAX,
};
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index 6225e5d1eb..c383830c82 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -415,6 +415,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
TestResult result;
result.status = GDTEST_OK;
result.output = String();
+ result.passed = false;
Error err = OK;
@@ -496,7 +497,12 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
}
return result;
}
-
+ // Script files matching this pattern are allowed to not contain a test() function.
+ if (source_file.match("*.notest.gd")) {
+ enable_stdout();
+ result.passed = check_output(result.output);
+ return result;
+ }
// Test running.
const Map<StringName, GDScriptFunction *>::Element *test_function_element = script->get_member_functions().find(GDScriptTestRunner::test_function_name);
if (test_function_element == nullptr) {
diff --git a/modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.gd b/modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.gd
new file mode 100644
index 0000000000..135b6c3d85
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.gd
@@ -0,0 +1,16 @@
+extends Node
+
+const NO_TYPE_CONST = 0
+const TYPE_CONST: int = 1
+const GUESS_TYPE_CONST := 2
+
+class Test:
+ var a = NO_TYPE_CONST
+ var b = TYPE_CONST
+ var c = GUESS_TYPE_CONST
+
+func test():
+ var test_instance = Test.new()
+ prints("a", test_instance.a, test_instance.a == NO_TYPE_CONST)
+ prints("b", test_instance.b, test_instance.b == TYPE_CONST)
+ prints("c", test_instance.c, test_instance.c == GUESS_TYPE_CONST)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.out b/modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.out
new file mode 100644
index 0000000000..a96bb84246
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/constants_from_parent.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+a 0 true
+b 1 true
+c 2 true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd
new file mode 100644
index 0000000000..5f57c5b8c2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd
@@ -0,0 +1,14 @@
+extends Node
+
+enum Named { VALUE_A, VALUE_B, VALUE_C = 42 }
+
+class Test:
+ var a = Named.VALUE_A
+ var b = Named.VALUE_B
+ var c = Named.VALUE_C
+
+func test():
+ var test_instance = Test.new()
+ prints("a", test_instance.a, test_instance.a == Named.VALUE_A)
+ prints("b", test_instance.b, test_instance.b == Named.VALUE_B)
+ prints("c", test_instance.c, test_instance.c == Named.VALUE_C)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out b/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out
new file mode 100644
index 0000000000..c160839da3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+a 0 true
+b 1 true
+c 42 true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.gd
new file mode 100644
index 0000000000..26edce353d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.gd
@@ -0,0 +1,14 @@
+extends Node
+
+enum { VALUE_A, VALUE_B, VALUE_C = 42 }
+
+class Test:
+ var a = VALUE_A
+ var b = VALUE_B
+ var c = VALUE_C
+
+func test():
+ var test_instance = Test.new()
+ prints("a", test_instance.a, test_instance.a == VALUE_A)
+ prints("b", test_instance.b, test_instance.b == VALUE_B)
+ prints("c", test_instance.c, test_instance.c == VALUE_C)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.out b/modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.out
new file mode 100644
index 0000000000..c160839da3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_value_from_parent.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+a 0 true
+b 1 true
+c 42 true
diff --git a/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd b/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd
index 3b48f10ca7..38567d35c6 100644
--- a/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd
+++ b/modules/gdscript/tests/scripts/parser/features/variable_declaration.gd
@@ -1,12 +1,19 @@
-var a # No init.
-var b = 42 # Init.
+var m1 # No init.
+var m2 = 22 # Init.
+var m3: String # No init, typed.
+var m4: String = "44" # Init, typed.
func test():
- var c # No init, local.
- var d = 23 # Init, local.
+ var loc5 # No init, local.
+ var loc6 = 66 # Init, local.
+ var loc7: String # No init, typed.
+ var loc8: String = "88" # Init, typed.
- a = 1
- c = 2
+ m1 = 11
+ m3 = "33"
- prints(a, b, c, d)
+ loc5 = 55
+ loc7 = "77"
+
+ prints(m1, m2, m3, m4, loc5, loc6, loc7, loc8)
print("OK")
diff --git a/modules/gdscript/tests/scripts/parser/features/variable_declaration.out b/modules/gdscript/tests/scripts/parser/features/variable_declaration.out
index 2e0a63c024..7817dd3169 100644
--- a/modules/gdscript/tests/scripts/parser/features/variable_declaration.out
+++ b/modules/gdscript/tests/scripts/parser/features/variable_declaration.out
@@ -1,7 +1,3 @@
GDTEST_OK
->> WARNING
->> Line: 5
->> UNASSIGNED_VARIABLE
->> The variable 'c' was used but never assigned a value.
-1 42 2 23
+11 22 33 44 55 66 77 88
OK
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.gd b/modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.gd
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.gd
@@ -0,0 +1 @@
+
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.out b/modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.out
new file mode 100644
index 0000000000..20eec212ba
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file.notest.out
@@ -0,0 +1,4 @@
+>> WARNING
+>> Line: 1
+>> EMPTY_FILE
+>> Empty script file.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.gd b/modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.gd
new file mode 100644
index 0000000000..15cd95ff2b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.gd
@@ -0,0 +1 @@
+#a comment
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.out b/modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.out
new file mode 100644
index 0000000000..20eec212ba
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file_comment.notest.out
@@ -0,0 +1,4 @@
+>> WARNING
+>> Line: 1
+>> EMPTY_FILE
+>> Empty script file.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.gd b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.gd
new file mode 100644
index 0000000000..b28b04f643
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.gd
@@ -0,0 +1,3 @@
+
+
+
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.out b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.out
new file mode 100644
index 0000000000..20eec212ba
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline.notest.out
@@ -0,0 +1,4 @@
+>> WARNING
+>> Line: 1
+>> EMPTY_FILE
+>> Empty script file.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.gd b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.gd
new file mode 100644
index 0000000000..ecdba44d21
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.gd
@@ -0,0 +1,4 @@
+#a comment, followed by a bunch of newlines
+
+
+
diff --git a/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.out b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.out
new file mode 100644
index 0000000000..20eec212ba
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment.notest.out
@@ -0,0 +1,4 @@
+>> WARNING
+>> Line: 1
+>> EMPTY_FILE
+>> Empty script file.