From 14bad75206963dd944db5e8f2f3ef24d90fc4867 Mon Sep 17 00:00:00 2001 From: jordi Date: Tue, 22 Mar 2022 21:44:30 -0500 Subject: [PATCH] Add enum values (Ignore, Warn, Error) to GDScript warnings --- doc/classes/ProjectSettings.xml | 118 ++++++++++++++------------ modules/gdscript/gdscript.cpp | 10 ++- modules/gdscript/gdscript_parser.cpp | 8 +- modules/gdscript/gdscript_warning.cpp | 16 ++++ modules/gdscript/gdscript_warning.h | 10 +++ 5 files changed, 103 insertions(+), 59 deletions(-) diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 44b16de0cfb..a6dcd5f942f 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -334,18 +334,20 @@ Specifies the maximum amount of log files allowed (used for rotation). - + + If [code]enabled[/code], prints a warning or an error when an [code]assert[/code] call always returns false. - + + If [code]enabled[/code], prints a warning or an error when an [code]assert[/code] call always returns true. - - If [code]true[/code], enables warnings when a constant is used as a function. + + If [code]enabled[/code], prints a warning or an error when a constant is used as a function. - - If [code]true[/code], enables warnings when deprecated keywords are used. + + If [code]enabled[/code], prints a warning or an error when deprecated keywords are used. - - If [code]true[/code], enables warnings when an empty file is parsed. + + If [code]enabled[/code], prints a warning or an error when an empty file is parsed. If [code]true[/code], enables specific GDScript warnings (see [code]debug/gdscript/warnings/*[/code] settings). If [code]false[/code], disables all GDScript warnings. @@ -353,82 +355,88 @@ If [code]true[/code], scripts in the [code]res://addons[/code] folder will not generate warnings. - - If [code]true[/code], enables warnings when using a function as if it was a property. + + If [code]enabled[/code], prints a warning or an error when using a function as if it was a property. - - If [code]true[/code], enables warnings when a ternary operator may emit values with incompatible types. + + If [code]enabled[/code], prints a warning or an error when a ternary operator may emit values with incompatible types. - + + If [code]enabled[/code], prints a warning or an error when trying to assign an integer to a variable that expects an enum value. - - If [code]true[/code], enables warnings when dividing an integer by another integer (the decimal part will be discarded). + + If [code]enabled[/code], prints a warning or an error when dividing an integer by another integer (the decimal part will be discarded). - - If [code]true[/code], enables warnings when passing a floating-point value to a function that expects an integer (it will be converted and lose precision). + + If [code]enabled[/code], prints a warning or an error when passing a floating-point value to a function that expects an integer (it will be converted and lose precision). - - If [code]true[/code], enables warnings when using a property as if it was a function. + + If [code]enabled[/code], prints a warning or an error when using a property as if it was a function. - + + If [code]enabled[/code], prints a warning or an error when a function that is not a coroutine is called with await. - - If [code]true[/code], enables warnings when calling a function without using its return value (by assigning it to a variable or using it as a function argument). Such return values are sometimes used to denote possible errors using the [enum Error] enum. + + If [code]enabled[/code], prints a warning or an error when calling a function without using its return value (by assigning it to a variable or using it as a function argument). Such return values are sometimes used to denote possible errors using the [enum Error] enum. - - If [code]true[/code], enables warnings when defining a local or subclass member variable, signal, or enum that would have the same name as a built-in function or global class name, which possibly shadow it. + + If [code]enabled[/code], prints a warning or an error when defining a local or subclass member variable, signal, or enum that would have the same name as a built-in function or global class name, which possibly shadow it. - - If [code]true[/code], enables warnings when defining a local or subclass member variable that would shadow a variable at an upper level (such as a member variable). + + If [code]enabled[/code], prints a warning or an error when defining a local or subclass member variable that would shadow a variable at an upper level (such as a member variable). - + - - If [code]true[/code], enables warnings when calling an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement. + + If [code]enabled[/code], prints a warning or an error when calling an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement. - - If [code]true[/code], enables warnings when calling a ternary expression that has no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement. + + If [code]enabled[/code], prints a warning or an error when calling a ternary expression that has no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement. If [code]true[/code], all warnings will be reported as if they were errors. - - If [code]true[/code], enables warnings when using a variable that wasn't previously assigned. + + If [code]enabled[/code], prints a warning or an error when using a variable that wasn't previously assigned. - - If [code]true[/code], enables warnings when assigning a variable using an assignment operator like [code]+=[/code] if the variable wasn't previously assigned. + + If [code]enabled[/code], prints a warning or an error when assigning a variable using an assignment operator like [code]+=[/code] if the variable wasn't previously assigned. - - If [code]true[/code], enables warnings when unreachable code is detected (such as after a [code]return[/code] statement that will always be executed). + + If [code]enabled[/code], prints a warning or an error when unreachable code is detected (such as after a [code]return[/code] statement that will always be executed). - + + If [code]enabled[/code], prints a warning or an error when an unreachable [code]match[/code] pattern is detected. - - If [code]true[/code], enables warnings when using an expression whose type may not be compatible with the function parameter expected. + + If [code]enabled[/code], prints a warning or an error when using an expression whose type may not be compatible with the function parameter expected. - - If [code]true[/code], enables warnings when performing an unsafe cast. + + If [code]enabled[/code], prints a warning or an error when performing an unsafe cast. - - If [code]true[/code], enables warnings when calling a method whose presence is not guaranteed at compile-time in the class. + + If [code]enabled[/code], prints a warning or an error when calling a method whose presence is not guaranteed at compile-time in the class. - - If [code]true[/code], enables warnings when accessing a property whose presence is not guaranteed at compile-time in the class. + + If [code]enabled[/code], prints a warning or an error when accessing a property whose presence is not guaranteed at compile-time in the class. - + + If [code]enabled[/code], prints a warning or an error when a local constant is never used. - + + If [code]enabled[/code], prints a warning or an error when a function parameter is never used. - + + If [code]enabled[/code], prints a warning or an error when a class variable is never used. - - If [code]true[/code], enables warnings when a signal is unused. + + If [code]enabled[/code], prints a warning or an error when a signal is unused. - - If [code]true[/code], enables warnings when a local variable is unused. + + If [code]enabled[/code], prints a warning or an error when a local variable is unused. - - If [code]true[/code], enables warnings when assigning the result of a function that returns [code]void[/code] to a variable. + + If [code]enabled[/code], prints a warning or an error when assigning the result of a function that returns [code]void[/code] to a variable. Message to be displayed before the backtrace when the engine crashes. diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 3a0e320e9b7..096e09ef9cd 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -2213,9 +2213,13 @@ GDScriptLanguage::GDScriptLanguage() { GLOBAL_DEF("debug/gdscript/warnings/treat_warnings_as_errors", false); GLOBAL_DEF("debug/gdscript/warnings/exclude_addons", true); for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) { - String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower(); - bool default_enabled = !warning.begins_with("unsafe_"); - GLOBAL_DEF("debug/gdscript/warnings/" + warning, default_enabled); + GDScriptWarning::Code code = (GDScriptWarning::Code)i; + Variant default_enabled = GDScriptWarning::get_default_value(code); + String path = GDScriptWarning::get_settings_path_from_code(code); + GLOBAL_DEF(path, default_enabled); + + PropertyInfo property_info = GDScriptWarning::get_property_info(code); + ProjectSettings::get_singleton()->set_custom_property_info(path, property_info); } #endif // DEBUG_ENABLED } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 67d778f9323..9a7da12273b 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -205,7 +205,8 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_ if (ignored_warnings.has(warn_name)) { return; } - if (!GLOBAL_GET("debug/gdscript/warnings/" + warn_name)) { + int warn_level = (int)GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(p_code)); + if (!warn_level) { return; } @@ -217,6 +218,11 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_ warning.leftmost_column = p_source->leftmost_column; warning.rightmost_column = p_source->rightmost_column; + if (warn_level == GDScriptWarning::WarnLevel::ERROR) { + push_error(warning.get_message(), p_source); + return; + } + List::Element *before = nullptr; for (List::Element *E = warnings.front(); E; E = E->next()) { if (E->get().start_line > warning.start_line) { diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index ad96e366405..1cae7bdfac0 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -163,6 +163,18 @@ String GDScriptWarning::get_message() const { #undef CHECK_SYMBOLS } +int GDScriptWarning::get_default_value(Code p_code) { + if (get_name_from_code(p_code).to_lower().begins_with("unsafe_")) { + return WarnLevel::IGNORE; + } + return WarnLevel::WARN; +} + +PropertyInfo GDScriptWarning::get_property_info(Code p_code) { + // Making this a separate function in case a warning needs different PropertyInfo in the future. + return PropertyInfo(Variant::INT, get_settings_path_from_code(p_code), PROPERTY_HINT_ENUM, "Ignore,Warn,Error"); +} + String GDScriptWarning::get_name() const { return get_name_from_code(code); } @@ -210,6 +222,10 @@ String GDScriptWarning::get_name_from_code(Code p_code) { return names[(int)p_code]; } +String GDScriptWarning::get_settings_path_from_code(Code p_code) { + return "debug/gdscript/warnings/" + get_name_from_code(p_code).to_lower(); +} + GDScriptWarning::Code GDScriptWarning::get_code_from_name(const String &p_name) { for (int i = 0; i < WARNING_MAX; i++) { if (get_name_from_code((Code)i) == p_name) { diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index 82efe3568ff..f47f31aedfe 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -33,11 +33,18 @@ #ifdef DEBUG_ENABLED +#include "core/object/object.h" #include "core/string/ustring.h" #include "core/templates/vector.h" class GDScriptWarning { public: + enum WarnLevel { + IGNORE, + WARN, + ERROR + }; + enum Code { UNASSIGNED_VARIABLE, // Variable used but never assigned. UNASSIGNED_VARIABLE_OP_ASSIGN, // Variable never assigned but used in an assignment operation (+=, *=, etc). @@ -81,7 +88,10 @@ public: String get_name() const; String get_message() const; + static int get_default_value(Code p_code); + static PropertyInfo get_property_info(Code p_code); static String get_name_from_code(Code p_code); + static String get_settings_path_from_code(Code p_code); static Code get_code_from_name(const String &p_name); };