Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly change global class paths on move or rename in the filesystem dock #85037

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
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
35 changes: 31 additions & 4 deletions editor/filesystem_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1563,10 +1563,37 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
}

void FileSystemDock::_update_resource_paths_after_move(const HashMap<String, String> &p_renames, const HashMap<String, ResourceUID::ID> &p_uids) const {
// Update the paths in ResourceUID, so that UIDs remain valid.
for (const KeyValue<String, ResourceUID::ID> &pair : p_uids) {
if (p_renames.has(pair.key)) {
ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]);
for (const KeyValue<String, String> &pair : p_renames) {
// Update UID path.
const HashMap<String, ResourceUID::ID>::ConstIterator I = p_uids.find(pair.key);
if (I) {
ResourceUID::get_singleton()->set_id(I->value, pair.value);
}

int index = -1;
EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->find_file(pair.key, &index);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is nearly 100% copied from EditorFileSystem._update_script_classes. I wonder if we can instead extract the necessary part of the method to a new method and call if from both locations?

The code in EditorFileSystem also handles the case when the file does not exist, which looks good to have in place as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did consider this, but the differences are enough that trying to extract it into a single function would be more annoying than useful. It's not like its a lot of code.

The "file" should be guaranteed to exist, because it is a EditorFileSystemDirectory fetched before a fs rescan is called, it uses data from before the move/rename operation. Can you think of a case where this would break?

Copy link
Contributor

Choose a reason for hiding this comment

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

It makes the maintenance easier, as right now only EditorFileSystem._update_script_classes is responsible for updating script classes.
With your PR, there will be 2 places and if something needs to be fixed in the logic, one place may be forgotten.

Is there really a difference? I only see the order of ScriptServer::remove_global_class_by_path(path) and ClassDB::is_parent_class(type, "Script"), but that is also handled below at the language check. All other differences can be handled easily.

No, but for FS operations generally, it is always better to check and be safe as you can never be 100% sure.
Your code right now can fail or even crash if the index is not found and therefore -1.

const StringName &type = efd->get_file_type(index);
if (!ClassDB::is_parent_class(type, "Script")) {
continue;
}

// Update paths for global classes.
if (!efd->get_file_script_class_name(index).is_empty()) {
String lang;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
if (ScriptServer::get_language(i)->handles_global_class_type(type)) {
lang = ScriptServer::get_language(i)->get_name();
Jordyfel marked this conversation as resolved.
Show resolved Hide resolved
break;
}
}
if (lang.is_empty()) {
continue; // No language found that can handle this global class.
}

ScriptServer::remove_global_class_by_path(pair.key);
ScriptServer::add_global_class(efd->get_file_script_class_name(index), efd->get_file_script_class_extends(index), lang, pair.value);
EditorNode::get_editor_data().script_class_set_icon_path(efd->get_file_script_class_name(index), efd->get_file_script_class_icon_path(index));
EditorNode::get_editor_data().script_class_set_name(pair.value, efd->get_file_script_class_name(index));
}
}

Expand Down