Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
779da28
Add refactor rename symbol functionality
adamscott Dec 9, 2024
dc724eb
Fix issues with pre-commit
adamscott Sep 23, 2025
4f390c7
Set vformat content to one-line
adamscott Sep 30, 2025
26f1a98
Fix issue where argument index would be incremented twice
adamscott Sep 30, 2025
ba44159
Add comment to reflect absence of refactor rename
adamscott Sep 30, 2025
53cb6ef
Fix what seems to be an oversight
adamscott Sep 30, 2025
3a3409e
Rename `get_word_pos` to `get_word_pos_at_pos`
adamscott Sep 30, 2025
3124368
Better separate before/after
adamscott Sep 30, 2025
0ccb157
Add WIP of test cases for refactor
adamscott Sep 30, 2025
11a11d3
Remove commented code
adamscott Sep 30, 2025
f337dd8
WIP adding refactor test
adamscott Sep 30, 2025
c6d39d7
Fix issue caused by godotengine/godot#107469
adamscott Oct 1, 2025
c85e33d
Add .global.gd extension to refactor global class files
adamscott Oct 1, 2025
8e478df
Add refactor exception
adamscott Oct 1, 2025
641b06e
Fix refactor test issues with global classes
adamscott Oct 1, 2025
d8ba8f5
Actually add a true test
adamscott Oct 1, 2025
df377d0
Fix use of designated initializers
adamscott Oct 1, 2025
ed26808
Add missing logic
adamscott Oct 2, 2025
f7e03d6
Fix some detection issue and add new internal test
adamscott Oct 2, 2025
2f7a99b
Fix variable shadowing
adamscott Oct 2, 2025
ac18385
Fix issue where default font was not loaded
adamscott Oct 2, 2025
09b0adf
Add `load_scenes()`
adamscott Oct 2, 2025
c394870
Loop through scene state instead of instantiating
adamscott Oct 2, 2025
bb5d86e
Add goto next and checks for .godot
adamscott Oct 2, 2025
7451662
Fix issue with existing extension signals
adamscott Oct 3, 2025
1f1c1d9
Huge overhaul of the testing
adamscott Oct 3, 2025
1e0f4e4
Remove superfluous file_access import
adamscott Oct 3, 2025
96c5dc2
Add new output values for cfg to test if the refactor failed
adamscott Oct 3, 2025
92a8ba0
Fix missing parsing_type default value
adamscott Oct 3, 2025
a87afcf
Add missing space in fail condition message
adamscott Oct 3, 2025
5c90e3c
Add new test (will fail, need to fix issue)
adamscott Oct 3, 2025
493b656
Add check for new symbol if defined in test
adamscott Oct 3, 2025
db54dc4
Add separate project dir logic from `init_language()`
adamscott Oct 3, 2025
ab3af2b
Move included files after `TOOLS_ENABLED`
adamscott Oct 3, 2025
09e0e1e
Move refactor_rename_helper.py to misc/scripts
adamscott Oct 3, 2025
2357e6f
Remove superfluous newline
adamscott Oct 3, 2025
a55b15b
Remove refactor.to for the moment and fix match values
adamscott Oct 3, 2025
a01a493
Add OUTSIDE_REFACTOR macro for rename_symbol_from_base
adamscott Oct 3, 2025
5ac0596
Fix shadowing issue
adamscott Oct 4, 2025
e55fc62
Fix text_server.h path
adamscott Oct 5, 2025
7a1280b
Replace old code with function call
adamscott Oct 6, 2025
38a61e8
Add `operator!=` to refactor matches
adamscott Oct 6, 2025
25e7124
Fix enum matching issue
adamscott Oct 6, 2025
72c8aa6
WIP to fix issue with enum refactor
adamscott Oct 6, 2025
358886f
Add new add_match signature
adamscott Oct 9, 2025
7cd933d
Add deep parameter
adamscott Oct 9, 2025
be4a9d7
Add missing info
adamscott Oct 9, 2025
48b1223
Add new test and try to simplify symbol match loop
adamscott Oct 9, 2025
6690896
Simplify from class loop nodes logic
adamscott Oct 9, 2025
d42de79
Make process_code return an error
adamscott Oct 9, 2025
0d72e1e
Add member_variable rename tests
adamscott Oct 9, 2025
6527af5
Fix issue with matchmap_to_string
adamscott Oct 9, 2025
05edbd1
Add two external script signal tests
adamscott Oct 9, 2025
964fe6a
Add inner script signal test
adamscott Oct 9, 2025
a5a79fe
Fix issues with enum and signal matching
adamscott Oct 9, 2025
17b89ac
Fix font used
adamscott Oct 22, 2025
f71676c
Fix shadowing of variable
adamscott Oct 22, 2025
e37a56d
Make GDScriptCache clearable multiple times
adamscott Oct 23, 2025
fde6c6c
Fix refactor popup popping issues
adamscott Oct 25, 2025
e21bc08
Fix issues with local variables
adamscott Oct 25, 2025
53f04af
Add additionnal local_variable internal test
adamscott Oct 25, 2025
9118d38
Add lambda test for local variable rename
adamscott Oct 25, 2025
704218f
Add a test for renaming literals
adamscott Oct 27, 2025
d5bd8cb
Add test output for `refactor_result_type`
adamscott Oct 27, 2025
2dc08fa
Add `refactor_result_type` to existing tests
adamscott Oct 27, 2025
10342dc
Simplify `refactor_rename_symbol_code()` macros
adamscott Oct 27, 2025
a7814b8
Make use of SUBCASE (makes it easy to filter tests)
adamscott Oct 27, 2025
9b41a61
Add support to (try to) "rename" `void`
adamscott Oct 27, 2025
2447098
Add rename Node
adamscott Oct 27, 2025
854bf25
Fix enum indent
adamscott Oct 27, 2025
eb7f997
WIP to get symbol directly from language
adamscott Oct 28, 2025
2367c47
Fix isues with mismatch in extents tracking stack
adamscott Oct 28, 2025
f0b4542
Rename to `AwaitNode::keyword`
adamscott Oct 28, 2025
45494c2
Add token in `GDScriptParser::Node`
adamscott Oct 28, 2025
d81cdcc
Add missing empty.gd uid
adamscott Oct 28, 2025
3cbf0b5
Make refactor match on beginning of token
adamscott Oct 28, 2025
9d300cb
Add REFACTOR_RENAME_TYPE_CONTROL_FLOW
adamscott Oct 28, 2025
67f3ced
Add break, continue, and class_name tests
adamscott Oct 28, 2025
0d3bda9
Add annotation support and test
adamscott Oct 28, 2025
8a2ca7b
WIP for adding tokens in `GDScriptParser::Node`
adamscott Oct 29, 2025
3af2627
Add tokens to parse_grouping()
adamscott Oct 29, 2025
fc65c5e
Add token to `parse_cast()`
adamscott Oct 29, 2025
baeee33
Add token to `parse_call()`
adamscott Oct 29, 2025
ccd0213
Add tokens to `parse_get_node()` and `parse_preload()`
adamscott Oct 29, 2025
f87ba92
Remove commented code
adamscott Oct 29, 2025
2daa0e4
Parse successfully `{Array,Break,Continue}Node` tokens
adamscott Oct 30, 2025
6f82bce
Remove tokens in `GDScriptParser::Node`
adamscott Oct 30, 2025
1ff2802
Cleanup registration of refactor context
adamscott Oct 31, 2025
15eb740
Fix `CodeArea::*_or_together` methods
adamscott Oct 31, 2025
2d42099
Remove null error from `GDScriptParser::refactor_rename_is_node_more_…
adamscott Oct 31, 2025
89713c1
Fix GDScriptTokenizer::CodeArea::contains(const Pair<int,int>)
adamscott Oct 31, 2025
3a942ea
Fix variable parsing
adamscott Oct 31, 2025
14b74d2
Fix refactor context token fetching code
adamscott Oct 31, 2025
b7bc5fd
Fix function refactor
adamscott Oct 31, 2025
258d080
Fix renaming "Node"
adamscott Oct 31, 2025
84118d6
Add rename_extends test
adamscott Oct 31, 2025
a3bd51a
Fix renaming void
adamscott Oct 31, 2025
849c783
Fix rename class_name
adamscott Oct 31, 2025
827efbf
Fix tests/type/rename_int.cfg
adamscott Oct 31, 2025
da7b71d
Fix tests/variable/local_variable/lambda.cfg
adamscott Oct 31, 2025
36883e6
Fix tests/signal/external_script.cfg
adamscott Oct 31, 2025
9d704cf
WIP to rethink the context concept
adamscott Oct 31, 2025
1819e71
Remove literal as refactor context
adamscott Oct 31, 2025
8b0f4bb
Fix parse_type()
adamscott Oct 31, 2025
520c923
Fix "extends" issue.
adamscott Oct 31, 2025
533d479
Fix rename string line issue
adamscott Oct 31, 2025
f19479f
Add new `LineColumn` type (`Pair<int, int>`)
adamscott Nov 3, 2025
e5cbea9
Fix issues with enum (detects correctly enum names/values)
adamscott Nov 3, 2025
734272a
Remove superfluous print line
adamscott Nov 3, 2025
7255e7e
Fix attribute and enum matching
adamscott Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 237 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ class ScriptLanguage : public Object {
virtual bool overrides_external_editor() { return false; }
virtual ScriptNameCasing preferred_file_name_casing() const { return SCRIPT_NAME_CASING_SNAKE_CASE; }

// Code completion.
// Keep enums in sync with:
// scene/gui/code_edit.h - CodeEdit::CodeCompletionKind
enum CodeCompletionKind {
Expand Down Expand Up @@ -339,6 +340,242 @@ class ScriptLanguage : public Object {

virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<CodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }

// Refactoring.
// Keep enums in sync with:
// scene/gui/code_edit.h - CodeEdit::RefactorKind
enum RefactorKind {
REFACTOR_KIND_RENAME_SYMBOL,
};

enum RefactorRenameSymbolResultType {
REFACTOR_RENAME_SYMBOL_RESULT_NONE,
REFACTOR_RENAME_SYMBOL_RESULT_CONTROL_FLOW,
REFACTOR_RENAME_SYMBOL_RESULT_LITERAL,
REFACTOR_RENAME_SYMBOL_RESULT_KEYWORD,
REFACTOR_RENAME_SYMBOL_RESULT_SYMBOL,
REFACTOR_RENAME_SYMBOL_RESULT_NATIVE,
REFACTOR_RENAME_SYMBOL_RESULT_NOT_EXPOSED,
REFACTOR_RENAME_SYMBOL_RESULT_SCRIPT,
REFACTOR_RENAME_SYMBOL_RESULT_GLOBAL_CLASS_NAME,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_NAME,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_CONSTANT,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_PROPERTY,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_METHOD,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_SIGNAL,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_ENUM,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_ENUM_VALUE,
REFACTOR_RENAME_SYMBOL_RESULT_CLASS_ANNOTATION,
REFACTOR_RENAME_SYMBOL_RESULT_LOCAL_CONSTANT,
REFACTOR_RENAME_SYMBOL_RESULT_LOCAL_VARIABLE,
REFACTOR_RENAME_SYMBOL_RESULT_LOCAL_FOR_VARIABLE,
REFACTOR_RENAME_SYMBOL_RESULT_LOCAL_PATTERN_BIND,
REFACTOR_RENAME_SYMBOL_RESULT_MAX,
};

struct RefactorRenameSymbolResult {
struct Match {
int start_line = -1;
int start_column = -1;
int end_line = -1;
int end_column = -1;

Match() {}
Match(int p_start_line, int p_start_column, int p_end_line, int p_end_column) {
start_line = p_start_line;
start_column = p_start_column;
end_line = p_end_line;
end_column = p_end_column;
}

_FORCE_INLINE_ bool operator==(const Match &r) const {
return start_line == r.start_line &&
start_column == r.start_column &&
end_line == r.end_line &&
end_column == r.end_column;
}

_FORCE_INLINE_ bool operator!=(const Match &r) const {
return !(operator==(r));
}

String to_string() const {
return vformat("Match{(%s,%s)=>(%s,%s)}", start_line, start_column, end_line, end_column);
}

struct Compare {
_FORCE_INLINE_ bool operator()(const Match &l, const Match &r) const {
if (l.start_line != r.start_line) {
return l.start_line < r.start_line;
}
if (l.start_column != r.start_column) {
return l.start_column < r.start_column;
}
return false;
}
};
};

String symbol;
String new_symbol;
String code;
Vector2i start;
Vector2i sentinel;
Vector2i end;
Error error = FAILED;
bool outside_refactor = false;
RefactorRenameSymbolResultType type = RefactorRenameSymbolResultType::REFACTOR_RENAME_SYMBOL_RESULT_NONE;
HashMap<String, LocalVector<Match>> matches;

private:
void _deep_copy(const RefactorRenameSymbolResult &p_result) {
symbol = p_result.symbol;
new_symbol = p_result.new_symbol;
code = p_result.code;
outside_refactor = p_result.outside_refactor;
error = p_result.error;
type = p_result.type;
matches.clear();
for (const KeyValue<String, LocalVector<Match>> &KV : p_result.matches) {
for (const Match &match : KV.value) {
matches[KV.key].push_back(match);
}
}
}

public:
String to_string() const {
String matches_string;
for (const KeyValue<String, LocalVector<Match>> &KV : matches) {
LocalVector<String> match_entries;
for (const Match &match : KV.value) {
match_entries.push_back(match.to_string());
}
matches_string += vformat("\t\t%s: %s,\n", KV.key, String(", ").join(PackedStringArray(match_entries)));
}
matches_string = matches_string.trim_suffix("\n");

return vformat("(RefactorRenameSymbolResult{\n\"%s\" -> \"%s\",\n\t(\n%s\n\t)\n})",
symbol, new_symbol, matches_string);
}

void add_match(const String &p_path, Match p_match) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void add_match(const String &p_path, Match p_match) {
void add_match(const String &p_path, const Match &p_match) {

matches[p_path].push_back(p_match);
matches[p_path].sort_custom<RefactorRenameSymbolResult::Match::Compare>();
}
void add_match(const String &p_path, int p_start_line, int p_start_column, int p_end_line, int p_end_column) {
add_match(p_path, { p_start_line, p_start_column, p_end_line, p_end_column });
}

Dictionary to_dictionary() {
Dictionary result;
result["symbol"] = symbol;
result["new_symbol"] = new_symbol;
result["code"] = code;
result["outside_refactor"] = outside_refactor;
result["error"] = error;
result["type"] = type;

Dictionary dictionary_matches;
for (KeyValue<String, LocalVector<Match>> &KV : matches) {
TypedArray<Dictionary> dictionary_matches_entries;
for (Match &match : KV.value) {
Dictionary dictionary_match;
dictionary_match["start_line"] = match.start_line;
dictionary_match["start_column"] = match.start_column;
dictionary_match["end_line"] = match.end_line;
dictionary_match["end_column"] = match.end_column;
dictionary_matches_entries.push_back(dictionary_match);
}
dictionary_matches[KV.key] = dictionary_matches_entries;
}
result["matches"] = dictionary_matches;

return result;
}

RefactorRenameSymbolResult get_undo() {
RefactorRenameSymbolResult undo_result;
undo_result.symbol = new_symbol;
undo_result.new_symbol = symbol;
undo_result.code = code;
undo_result.outside_refactor = outside_refactor;
undo_result.error = error;
undo_result.type = type;

for (const KeyValue<String, LocalVector<Match>> &KV : matches) {
int last_line = 0;
int offset = 0;
for (const Match &match : KV.value) {
if (last_line < match.start_line) {
offset = 0;
last_line = match.start_line;
}
Match new_match = {
match.start_line,
match.start_column + offset,
match.end_line,
match.end_column,
};
offset += new_symbol.length() - symbol.length();
undo_result.matches[KV.key].push_back(new_match);
}
}

return undo_result;
}

bool has_failed() const {
return error != OK || outside_refactor;
}

void reset(bool p_keep_context = false) {
matches.clear();
outside_refactor = false;
error = FAILED;
type = REFACTOR_RENAME_SYMBOL_RESULT_NONE;
if (!p_keep_context) {
symbol = "";
new_symbol = "";
code = "";
}
}

void operator=(const RefactorRenameSymbolResult &p_result) {
_deep_copy(p_result);
}

RefactorRenameSymbolResult(const RefactorRenameSymbolResult &p_result) {
_deep_copy(p_result);
}

RefactorRenameSymbolResult(const Dictionary &p_result) {
ERR_FAIL_COND(!p_result.has("symbol") || !p_result.has("new_symbol") || !p_result.has("code") || !p_result.has("error") || !p_result.has("outside_refactor") || !p_result.has("type") || !p_result.has("matches"));
symbol = p_result["symbol"];
new_symbol = p_result["new_symbol"];
code = p_result["code"];
outside_refactor = p_result["outside_refactor"];
error = (Error)(int)p_result["error"];
type = (RefactorRenameSymbolResultType)(int)p_result["type"];
matches.clear();
Dictionary dictionary_matches = p_result["matches"];
for (const String key : dictionary_matches.keys()) {
TypedArray<Dictionary> dictionary_match_entries = dictionary_matches[key];
for (int i = 0; i < dictionary_match_entries.size(); i++) {
Dictionary dictionar_match_entry = dictionary_match_entries[i];
matches[key].push_back({ dictionar_match_entry["start_line"],
dictionar_match_entry["start_column"],
dictionar_match_entry["end_line"],
dictionar_match_entry["end_column"] });
Comment on lines +563 to +568
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (int i = 0; i < dictionary_match_entries.size(); i++) {
Dictionary dictionar_match_entry = dictionary_match_entries[i];
matches[key].push_back({ dictionar_match_entry["start_line"],
dictionar_match_entry["start_column"],
dictionar_match_entry["end_line"],
dictionar_match_entry["end_column"] });
for (Dictionary dictionary_match_entry : dictionary_match_entries) {
matches[key].push_back({ dictionary_match_entry["start_line"],
dictionary_match_entry["start_column"],
dictionary_match_entry["end_line"],
dictionary_match_entry["end_column"] });

}
}
}

RefactorRenameSymbolResult() = default;
};

virtual Error refactor_rename_symbol_code(const String &p_code, const String &p_path, Object *p_owner, const HashMap<String, String> &p_unsaved_scripts_source_code, RefactorRenameSymbolResult &r_result) { return ERR_UNAVAILABLE; }

// Lookup.
enum LookupResultType {
LOOKUP_RESULT_SCRIPT_LOCATION, // Use if none of the options below apply.
LOOKUP_RESULT_CLASS,
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/CodeEdit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,12 @@
Emitted when the user requests code completion. This signal will not be sent if [method _request_code_completion] is overridden or [member code_completion_enabled] is [code]false[/code].
</description>
</signal>
<signal name="refactor_requested">
<param index="0" name="type" type="int" />
<description>
Emitted when the user requests a refactor.
</description>
</signal>
Comment on lines +607 to +612
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my god, this is particularly egregious. In its current state (prone to future changes), it should not be exposed at all, let alone without its corresponding enum.

CC @KoBeWi because of #69012 (comment). We somehow still can't choose to keep signals unexposed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeEdit has code_completion_requested too, so it's not completely out of place.

...if not the fact that this signal is only emitted externally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like signals can be hidden from docs as of recently.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that means they're completely hidden from the API, though. Things like autocompletion may recommend them, the Node dock may display them. GDExtension may have them exposed anyway, though the leading underscore is a deterrent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only concern with this PR is still this specific signal. @adamscott , can you consider a workaround as KoBeWi also discussed in #69012 (comment)?
It would be an admittedly rare, but not unique case to use Object.add_user_signal() for this purpose.

add_user_signal(MethodInfo("_editor_region_rect_enabled"));

add_user_signal(MethodInfo("_fold_line_updated"));

Copy link
Contributor

@kitbdev kitbdev Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could also just be removed, like I suggest here #102380 (comment)
There's no need for it in CodeEdit.

<signal name="symbol_hovered">
<param index="0" name="symbol" type="String" />
<param index="1" name="line" type="int" />
Expand Down
29 changes: 28 additions & 1 deletion editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "core/os/time.h"
#include "core/string/print_string.h"
#include "core/string/translation_server.h"
#include "core/templates/local_vector.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include "core/templates/local_vector.h"

#include "core/version.h"
#include "editor/editor_string_names.h"
#include "editor/inspector/editor_context_menu_plugin.h"
Expand Down Expand Up @@ -1605,7 +1606,9 @@ void EditorNode::edit_resource(const Ref<Resource> &p_resource) {
}

void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) {
editor_data.apply_changes_in_editors();
if (!p_resource->has_meta("__resource_saved_in_bulk")) {
editor_data.apply_changes_in_editors();
}

if (saving_resources_in_path.has(p_resource)) {
return;
Expand Down Expand Up @@ -1743,6 +1746,25 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
file->popup_file_dialog();
}

void EditorNode::save_resource_bulk(const LocalVector<Ref<Resource>> &p_resource_bulk) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my attempt to reduce the save time. I need to check if it's still needed, though

LocalVector<String> paths;
for (const Ref<Resource> &resource : p_resource_bulk) {
paths.push_back(resource->get_path());
resource->set_meta("__resource_saved_in_bulk", true);
save_resource(resource);
}

for (const Ref<Resource> &resource : p_resource_bulk) {
resource->remove_meta("__resource_saved_in_bulk");
singleton->editor_folding.save_resource_folding(resource, resource->get_path());
emit_signal(SNAME("resource_saved"), resource);
editor_data.notify_resource_saved(resource);
}

EditorFileSystem::get_singleton()->update_files(PackedStringArray(paths));
editor_data.apply_changes_in_editors();
}

void EditorNode::_menu_option(int p_option) {
_menu_option_confirm(p_option, false);
}
Expand Down Expand Up @@ -7305,6 +7327,11 @@ void EditorNode::_set_renderer_name_save_and_restart() {
}

void EditorNode::_resource_saved(Ref<Resource> p_resource, const String &p_path) {
if (p_resource->has_meta("__resource_saved_in_bulk")) {
singleton->saving_resources_in_path.erase(p_resource);
return;
}

if (singleton->saving_resources_in_path.has(p_resource)) {
// This is going to be handled by save_resource_in_path when the time is right.
return;
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#pragma once

#include "core/object/script_language.h"
#include "core/string/string_name.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include "core/string/string_name.h"

#include "core/templates/safe_refcount.h"
#include "editor/editor_data.h"
#include "editor/plugins/editor_plugin.h"
Expand Down Expand Up @@ -810,6 +811,8 @@ class EditorNode : public Node {
void save_resource(const Ref<Resource> &p_resource);
void save_resource_as(const Ref<Resource> &p_resource, const String &p_at_path = String());

void save_resource_bulk(const LocalVector<Ref<Resource>> &p_bulk);

void show_about() { _menu_option_confirm(HELP_ABOUT, false); }

void push_item(Object *p_object, const String &p_property = "", bool p_inspector_only = false);
Expand Down
Loading
Loading