summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/classes/ProjectSettings.xml4
-rw-r--r--editor/filesystem_dock.cpp16
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp1
-rw-r--r--modules/gdscript/gdscript_parser.cpp4
-rw-r--r--modules/gdscript/gdscript_warning.cpp2
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd13
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out8
-rw-r--r--scene/gui/popup.cpp12
-rw-r--r--scene/gui/tree.cpp26
-rw-r--r--scene/gui/tree.h1
13 files changed, 82 insertions, 11 deletions
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 926d981f68..5ac4c96d93 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -554,10 +554,10 @@
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass member variable that would shadow a variable that is inherited from a parent class.
</member>
<member name="debug/gdscript/warnings/standalone_expression" type="int" setter="" getter="" default="1">
- When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
+ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that may have no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
</member>
<member name="debug/gdscript/warnings/standalone_ternary" type="int" setter="" getter="" default="1">
- When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively 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.
+ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a ternary expression that may have no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement.
</member>
<member name="debug/gdscript/warnings/static_called_on_instance" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a static method from an instance of a class instead of from the class directly.
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index b05cafa694..5f311ae445 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -79,6 +79,15 @@ Control *FileSystemList::make_custom_tooltip(const String &p_text) const {
}
void FileSystemList::_line_editor_submit(const String &p_text) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
emit_signal(SNAME("item_edited"));
@@ -127,6 +136,7 @@ bool FileSystemList::edit_selected() {
line_editor->set_text(name);
line_editor->select(0, name.rfind("."));
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
line_editor->grab_focus();
@@ -138,8 +148,12 @@ String FileSystemList::get_edit_text() {
}
void FileSystemList::_text_editor_popup_modal_close() {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
- return;
+ return; // ESC pressed, app focus lost, or forced close from code.
}
_line_editor_submit(line_editor->get_text());
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 7449657c06..3fbff3ef19 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -59,6 +59,7 @@ class FileSystemTree : public Tree {
class FileSystemList : public ItemList {
GDCLASS(FileSystemList, ItemList);
+ bool popup_edit_commited = true;
VBoxContainer *popup_editor_vb = nullptr;
Popup *popup_editor = nullptr;
LineEdit *line_editor = nullptr;
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 38d5c59e0e..a2680c932f 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -3394,6 +3394,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}
#ifdef DEBUG_ENABLED
+ // FIXME: No warning for built-in constructors and utilities due to early return.
if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL &&
!(p_call->is_super && p_call->function_name == GDScriptLanguage::get_singleton()->strings._init)) {
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 9be9307b8a..76f02e44e9 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -1877,6 +1877,10 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case Node::CALL:
// Fine.
break;
+ case Node::PRELOAD:
+ // `preload` is a function-like keyword.
+ push_warning(expression, GDScriptWarning::RETURN_VALUE_DISCARDED, "preload");
+ break;
case Node::LAMBDA:
// Standalone lambdas can't be used, so make this an error.
push_error("Standalone lambdas cannot be accessed. Consider assigning it to a variable.", expression);
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index 48a0abe617..611a9ad2d9 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -74,7 +74,7 @@ String GDScriptWarning::get_message() const {
case UNREACHABLE_PATTERN:
return "Unreachable pattern (pattern after wildcard or bind).";
case STANDALONE_EXPRESSION:
- return "Standalone expression (the line has no effect).";
+ return "Standalone expression (the line may have no effect).";
case STANDALONE_TERNARY:
return "Standalone ternary operator: the return value is being discarded.";
case INCOMPATIBLE_TERNARY:
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd
index 00598e4d50..f8f70b8cc3 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd
@@ -4,3 +4,4 @@ func i_return_int() -> int:
func test():
i_return_int()
+ preload("../../utils.notest.gd") # `preload` is a function-like keyword.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
index f2db4e9307..107051df6c 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
@@ -3,3 +3,7 @@ GDTEST_OK
>> Line: 6
>> RETURN_VALUE_DISCARDED
>> The function "i_return_int()" returns a value that will be discarded if not used.
+>> WARNING
+>> Line: 7
+>> RETURN_VALUE_DISCARDED
+>> The function "preload()" returns a value that will be discarded if not used.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
index dc4223ec2d..74f42b012b 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
+++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
@@ -6,3 +6,16 @@ func test():
Vector3.ZERO
[true, false]
float(125)
+ # The following statements should not produce `STANDALONE_EXPRESSION`:
+ var _a = 1
+ _a = 2 # Assignment is a local (or global) side effect.
+ @warning_ignore("redundant_await")
+ await 3 # The `await` operand is usually a coroutine or a signal.
+ absi(4) # A call (in general) can have side effects.
+ @warning_ignore("return_value_discarded")
+ preload("../../utils.notest.gd") # A static initializer may have side effects.
+ """
+ Python-like "comment".
+ """
+ @warning_ignore("standalone_ternary")
+ 1 if 2 else 3 # Produces `STANDALONE_TERNARY` instead.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
index a2c67a6e51..72c659c952 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
@@ -2,16 +2,16 @@ GDTEST_OK
>> WARNING
>> Line: 3
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
>> WARNING
>> Line: 4
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
>> WARNING
>> Line: 6
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
>> WARNING
>> Line: 7
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 1d45a10d2a..38204af6d5 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -37,6 +37,7 @@
void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
if (get_flag(FLAG_POPUP) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) {
+ hide_reason = HIDE_REASON_CANCELED; // ESC pressed, mark as canceled unconditionally.
_close_pressed();
}
Window::_input_from_window(p_event);
@@ -104,13 +105,18 @@ void Popup::_notification(int p_what) {
case NOTIFICATION_WM_CLOSE_REQUEST: {
if (!is_in_edited_scene_root()) {
- hide_reason = HIDE_REASON_UNFOCUSED;
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
if (!is_in_edited_scene_root() && get_flag(FLAG_POPUP)) {
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
} break;
@@ -119,7 +125,9 @@ void Popup::_notification(int p_what) {
void Popup::_parent_focused() {
if (popped_up && get_flag(FLAG_POPUP)) {
- hide_reason = HIDE_REASON_UNFOCUSED;
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 133515754b..fc5b942918 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -3152,8 +3152,12 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
void Tree::_text_editor_popup_modal_close() {
+ if (popup_edit_commited) {
+ return; // Already processed by LineEdit/TextEdit commit.
+ }
+
if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
- return;
+ return; // ESC pressed, app focus lost, or forced close from code.
}
if (value_editor->has_point(value_editor->get_local_mouse_position())) {
@@ -3172,9 +3176,18 @@ void Tree::_text_editor_popup_modal_close() {
}
void Tree::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
if (p_event->is_action_pressed("ui_text_newline_blank", true)) {
accept_event();
} else if (p_event->is_action_pressed("ui_text_newline")) {
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
_apply_multiline_edit();
accept_event();
@@ -3205,6 +3218,15 @@ void Tree::_apply_multiline_edit() {
}
void Tree::_line_editor_submit(String p_text) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
if (!popup_edited_item) {
@@ -4072,6 +4094,7 @@ bool Tree::edit_selected(bool p_force_edit) {
if (!popup_editor->is_embedded()) {
popup_editor->set_content_scale_factor(popup_scale);
}
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
@@ -4091,6 +4114,7 @@ bool Tree::edit_selected(bool p_force_edit) {
if (!popup_editor->is_embedded()) {
popup_editor->set_content_scale_factor(popup_scale);
}
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 311055a2f8..e9c93c6e03 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -479,6 +479,7 @@ private:
VBoxContainer *popup_editor_vb = nullptr;
+ bool popup_edit_commited = true;
Popup *popup_editor = nullptr;
LineEdit *line_editor = nullptr;
TextEdit *text_editor = nullptr;