Skip to content

Commit 82b36cc

Browse files
committed
Merge pull request godotengine#90756 from vnen/gdscript-warning-enum-without-default
GDScript: Warn when enum variable has no default
2 parents 01eb81b + f9048fc commit 82b36cc

File tree

7 files changed

+38
-0
lines changed

7 files changed

+38
-0
lines changed

doc/classes/ProjectSettings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@
488488
<member name="debug/gdscript/warnings/enable" type="bool" setter="" getter="" default="true">
489489
If [code]true[/code], enables specific GDScript warnings (see [code]debug/gdscript/warnings/*[/code] settings). If [code]false[/code], disables all GDScript warnings.
490490
</member>
491+
<member name="debug/gdscript/warnings/enum_variable_without_default" type="int" setter="" getter="" default="1">
492+
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a variable has an enum type but no explicit default value, but only if the enum does not contain [code]0[/code] as a valid value.
493+
</member>
491494
<member name="debug/gdscript/warnings/exclude_addons" type="bool" setter="" getter="" default="true">
492495
If [code]true[/code], scripts in the [code]res://addons[/code] folder will not generate warnings.
493496
</member>

modules/gdscript/gdscript_analyzer.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,6 +1957,18 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
19571957
} else {
19581958
parser->push_warning(p_assignable, GDScriptWarning::UNTYPED_DECLARATION, declaration_type, p_assignable->identifier->name);
19591959
}
1960+
} else if (specified_type.kind == GDScriptParser::DataType::ENUM && p_assignable->initializer == nullptr) {
1961+
// Warn about enum variables without default value. Unless the enum defines the "0" value, then it's fine.
1962+
bool has_zero_value = false;
1963+
for (const KeyValue<StringName, int64_t> &kv : specified_type.enum_values) {
1964+
if (kv.value == 0) {
1965+
has_zero_value = true;
1966+
break;
1967+
}
1968+
}
1969+
if (!has_zero_value) {
1970+
parser->push_warning(p_assignable, GDScriptWarning::ENUM_VARIABLE_WITHOUT_DEFAULT, p_assignable->identifier->name);
1971+
}
19601972
}
19611973
#endif
19621974

modules/gdscript/gdscript_warning.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ String GDScriptWarning::get_message() const {
126126
case INT_AS_ENUM_WITHOUT_MATCH:
127127
CHECK_SYMBOLS(3);
128128
return vformat(R"(Cannot %s %s as Enum "%s": no enum member has matching value.)", symbols[0], symbols[1], symbols[2]);
129+
case ENUM_VARIABLE_WITHOUT_DEFAULT:
130+
CHECK_SYMBOLS(1);
131+
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]);
129132
case EMPTY_FILE:
130133
return "Empty script file.";
131134
case DEPRECATED_KEYWORD:
@@ -221,6 +224,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
221224
"NARROWING_CONVERSION",
222225
"INT_AS_ENUM_WITHOUT_CAST",
223226
"INT_AS_ENUM_WITHOUT_MATCH",
227+
"ENUM_VARIABLE_WITHOUT_DEFAULT",
224228
"EMPTY_FILE",
225229
"DEPRECATED_KEYWORD",
226230
"RENAMED_IN_GODOT_4_HINT",

modules/gdscript/gdscript_warning.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class GDScriptWarning {
7878
NARROWING_CONVERSION, // Float value into an integer slot, precision is lost.
7979
INT_AS_ENUM_WITHOUT_CAST, // An integer value was used as an enum value without casting.
8080
INT_AS_ENUM_WITHOUT_MATCH, // An integer value was used as an enum value without matching enum member.
81+
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.
8182
EMPTY_FILE, // A script file is empty.
8283
DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced.
8384
RENAMED_IN_GODOT_4_HINT, // A variable or function that could not be found has been renamed in Godot 4.
@@ -129,6 +130,7 @@ class GDScriptWarning {
129130
WARN, // NARROWING_CONVERSION
130131
WARN, // INT_AS_ENUM_WITHOUT_CAST
131132
WARN, // INT_AS_ENUM_WITHOUT_MATCH
133+
WARN, // ENUM_VARIABLE_WITHOUT_DEFAULT
132134
WARN, // EMPTY_FILE
133135
WARN, // DEPRECATED_KEYWORD
134136
WARN, // RENAMED_IN_GODOT_4_HINT
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
enum HasZero { A = 0, B = 1 }
2+
enum HasNoZero { A = 1, B = 2 }
3+
var has_zero: HasZero # No warning, because the default `0` is valid.
4+
var has_no_zero: HasNoZero # Warning, because there is no `0` in the enum.
5+
6+
7+
func test():
8+
print(has_zero)
9+
print(has_no_zero)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
GDTEST_OK
2+
>> WARNING
3+
>> Line: 4
4+
>> ENUM_VARIABLE_WITHOUT_DEFAULT
5+
>> The variable "has_no_zero" has an enum type and does not set an explicit default value. The default will be set to "0".
6+
0
7+
0

modules/gdscript/tests/scripts/runtime/features/member_info.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var test_var_hard_int: int
2323
var test_var_hard_variant_type: Variant.Type
2424
@export var test_var_hard_variant_type_exported: Variant.Type
2525
var test_var_hard_node_process_mode: Node.ProcessMode
26+
@warning_ignore("enum_variable_without_default")
2627
var test_var_hard_my_enum: MyEnum
2728
var test_var_hard_array: Array
2829
var test_var_hard_array_int: Array[int]

0 commit comments

Comments
 (0)