diff options
Diffstat (limited to 'modules/gdscript')
11 files changed, 70 insertions, 11 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index b198338ff0..cd19887d82 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1957,6 +1957,18 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi } else { parser->push_warning(p_assignable, GDScriptWarning::UNTYPED_DECLARATION, declaration_type, p_assignable->identifier->name); } + } else if (specified_type.kind == GDScriptParser::DataType::ENUM && p_assignable->initializer == nullptr) { + // Warn about enum variables without default value. Unless the enum defines the "0" value, then it's fine. + bool has_zero_value = false; + for (const KeyValue<StringName, int64_t> &kv : specified_type.enum_values) { + if (kv.value == 0) { + has_zero_value = true; + break; + } + } + if (!has_zero_value) { + parser->push_warning(p_assignable, GDScriptWarning::ENUM_VARIABLE_WITHOUT_DEFAULT, p_assignable->identifier->name); + } } #endif diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 2940af585d..5b1639e250 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -1455,10 +1455,11 @@ GDScriptTokenizer::Token GDScriptTokenizerText::scan() { if (_peek() != '\n') { return make_error("Expected new line after \"\\\"."); } - continuation_lines.push_back(line); _advance(); newline(false); line_continuation = true; + _skip_whitespace(); // Skip whitespace/comment lines after `\`. See GH-89403. + continuation_lines.push_back(line); return scan(); // Recurse to get next token. } diff --git a/modules/gdscript/gdscript_tokenizer_buffer.cpp b/modules/gdscript/gdscript_tokenizer_buffer.cpp index db523ea941..e53bc5bc41 100644 --- a/modules/gdscript/gdscript_tokenizer_buffer.cpp +++ b/modules/gdscript/gdscript_tokenizer_buffer.cpp @@ -285,9 +285,9 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code, // Remove continuation lines from map. for (int line : tokenizer.get_continuation_lines()) { - if (rev_token_lines.has(line + 1)) { - token_lines.erase(rev_token_lines[line + 1]); - token_columns.erase(rev_token_lines[line + 1]); + if (rev_token_lines.has(line)) { + token_lines.erase(rev_token_lines[line]); + token_columns.erase(rev_token_lines[line]); } } diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 708966a0a8..48a0abe617 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -126,6 +126,9 @@ String GDScriptWarning::get_message() const { case INT_AS_ENUM_WITHOUT_MATCH: CHECK_SYMBOLS(3); return vformat(R"(Cannot %s %s as Enum "%s": no enum member has matching value.)", symbols[0], symbols[1], symbols[2]); + case ENUM_VARIABLE_WITHOUT_DEFAULT: + CHECK_SYMBOLS(1); + return vformat(R"(The variable "%s" has an enum type and does not set an explicit default value. The default will be set to "0".)", symbols[0]); case EMPTY_FILE: return "Empty script file."; case DEPRECATED_KEYWORD: @@ -221,6 +224,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "NARROWING_CONVERSION", "INT_AS_ENUM_WITHOUT_CAST", "INT_AS_ENUM_WITHOUT_MATCH", + "ENUM_VARIABLE_WITHOUT_DEFAULT", "EMPTY_FILE", "DEPRECATED_KEYWORD", "RENAMED_IN_GODOT_4_HINT", diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index 93c232a0f8..3ad9488138 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -78,6 +78,7 @@ public: NARROWING_CONVERSION, // Float value into an integer slot, precision is lost. INT_AS_ENUM_WITHOUT_CAST, // An integer value was used as an enum value without casting. INT_AS_ENUM_WITHOUT_MATCH, // An integer value was used as an enum value without matching enum member. + ENUM_VARIABLE_WITHOUT_DEFAULT, // A variable with an enum type does not have a default value. The default will be set to `0` instead of the first enum value. EMPTY_FILE, // A script file is empty. DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced. RENAMED_IN_GODOT_4_HINT, // A variable or function that could not be found has been renamed in Godot 4. @@ -129,6 +130,7 @@ public: WARN, // NARROWING_CONVERSION WARN, // INT_AS_ENUM_WITHOUT_CAST WARN, // INT_AS_ENUM_WITHOUT_MATCH + WARN, // ENUM_VARIABLE_WITHOUT_DEFAULT WARN, // EMPTY_FILE WARN, // DEPRECATED_KEYWORD WARN, // RENAMED_IN_GODOT_4_HINT diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index a0329eb8d2..e3d16eaf42 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -300,14 +300,23 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) { #endif String out_file = next.get_basename() + ".out"; - if (!is_generating && !dir->file_exists(out_file)) { - ERR_FAIL_V_MSG(false, "Could not find output file for " + next); - } - GDScriptTest test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); - if (binary_tokens) { - test.set_tokenizer_mode(GDScriptTest::TOKENIZER_BUFFER); + ERR_FAIL_COND_V_MSG(!is_generating && !dir->file_exists(out_file), false, "Could not find output file for " + next); + + if (next.ends_with(".bin.gd")) { + // Test text mode first. + GDScriptTest text_test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); + tests.push_back(text_test); + // Test binary mode even without `--use-binary-tokens`. + GDScriptTest bin_test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); + bin_test.set_tokenizer_mode(GDScriptTest::TOKENIZER_BUFFER); + tests.push_back(bin_test); + } else { + GDScriptTest test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); + if (binary_tokens) { + test.set_tokenizer_mode(GDScriptTest::TOKENIZER_BUFFER); + } + tests.push_back(test); } - tests.push_back(test); } } diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd new file mode 100644 index 0000000000..13e3edf93f --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd @@ -0,0 +1,9 @@ +enum HasZero { A = 0, B = 1 } +enum HasNoZero { A = 1, B = 2 } +var has_zero: HasZero # No warning, because the default `0` is valid. +var has_no_zero: HasNoZero # Warning, because there is no `0` in the enum. + + +func test(): + print(has_zero) + print(has_no_zero) diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.out b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.out new file mode 100644 index 0000000000..ae40e0bc8c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.out @@ -0,0 +1,7 @@ +GDTEST_OK +>> WARNING +>> Line: 4 +>> ENUM_VARIABLE_WITHOUT_DEFAULT +>> The variable "has_no_zero" has an enum type and does not set an explicit default value. The default will be set to "0". +0 +0 diff --git a/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.gd b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.gd new file mode 100644 index 0000000000..cb0bc94d2e --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.gd @@ -0,0 +1,12 @@ +# GH-89403 + +func test(): + var x := 1 + if x == 0 \ + # Comment. + # Comment. + and (x < 1 or x > 2) \ + # Comment. + and x != 3: + pass + print("Ok") diff --git a/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.out b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.out new file mode 100644 index 0000000000..0e9f482af4 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.out @@ -0,0 +1,2 @@ +GDTEST_OK +Ok diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.gd b/modules/gdscript/tests/scripts/runtime/features/member_info.gd index d7485f49e6..42b29eee43 100644 --- a/modules/gdscript/tests/scripts/runtime/features/member_info.gd +++ b/modules/gdscript/tests/scripts/runtime/features/member_info.gd @@ -23,6 +23,7 @@ var test_var_hard_int: int var test_var_hard_variant_type: Variant.Type @export var test_var_hard_variant_type_exported: Variant.Type var test_var_hard_node_process_mode: Node.ProcessMode +@warning_ignore("enum_variable_without_default") var test_var_hard_my_enum: MyEnum var test_var_hard_array: Array var test_var_hard_array_int: Array[int] |
