Skip to content

Commit

Permalink
Merge pull request #90756 from vnen/gdscript-warning-enum-without-def…
Browse files Browse the repository at this point in the history
…ault

GDScript: Warn when enum variable has no default
  • Loading branch information
akien-mga committed Apr 17, 2024
2 parents 01eb81b + f9048fc commit 82b36cc
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 0 deletions.
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@
<member name="debug/gdscript/warnings/enable" type="bool" setter="" getter="" default="true">
If [code]true[/code], enables specific GDScript warnings (see [code]debug/gdscript/warnings/*[/code] settings). If [code]false[/code], disables all GDScript warnings.
</member>
<member name="debug/gdscript/warnings/enum_variable_without_default" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a 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.
</member>
<member name="debug/gdscript/warnings/exclude_addons" type="bool" setter="" getter="" default="true">
If [code]true[/code], scripts in the [code]res://addons[/code] folder will not generate warnings.
</member>
Expand Down
12 changes: 12 additions & 0 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions modules/gdscript/gdscript_warning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions modules/gdscript/gdscript_warning.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class GDScriptWarning {
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.
Expand Down Expand Up @@ -129,6 +130,7 @@ class GDScriptWarning {
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
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 82b36cc

Please sign in to comment.