Skip to content

Stop FileAccess::fix_path from emitting errors for invalid UIDs #107402

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

Merged
merged 1 commit into from
Jun 12, 2025

Conversation

mihe
Copy link
Contributor

@mihe mihe commented Jun 11, 2025

Fixes #101962.

This is mostly a quick hack to prompt a discussion about a more proper fix, and maybe serve as a hold-over, but...

This adds a ResourceUID::has_id check to FileAccess::fix_path, before it tries to call ResourceUID::text_to_id, and instead just clears the output string if it's not a known UID, same as what this error check is already doing inadvertently by returning an empty String when it can't find the UID:

ERR_FAIL_COND_V_MSG(!cache, String(), vformat("Unrecognized UID: \"%s\".", id_to_text(p_id)));

Without this, you could otherwise pass perfectly reasonable (or not) but non-existent uid:// paths to FileAccess::fix_path and it would emit the above mentioned error about Unrecognized UID, which is exactly what happens in places like the LSP server, where it runs every string literal in the GDScript file through FileAccess::file_exists, which in turn calls FileAccess::fix_path, as seen here:

} else if (token.type == GDScriptTokenizer::Token::LITERAL) {
const Variant &const_val = token.literal;
if (const_val.get_type() == Variant::STRING) {
String scr_path = const_val;
if (scr_path.is_relative_path()) {
scr_path = get_path().get_base_dir().path_join(scr_path).simplify_path();
}
bool exists = fs->file_exists(scr_path);

I feel like the proper fix is to change FileAccess::fix_path to instead return a bool, to indicate a failure to fix/resolve the path, like when trying to fix/resolve a non-existent UID, but since that would/should require changing quite a lot of call sites I settled for this for now.

The fact that the LSP server is running every GDScript string literal through FileAccess::file_exists is maybe a bit questionable as well, but that seems like more of a performance concern than anything else. FileAccess::file_exists should not throw errors on non-existent UIDs.

@mihe mihe added this to the 4.5 milestone Jun 11, 2025
@mihe mihe requested a review from a team as a code owner June 11, 2025 12:02
@akien-mga akien-mga requested a review from KoBeWi June 11, 2025 12:23
@akien-mga
Copy link
Member

CC @HolonProduction as this seems LSP related.

@HolonProduction
Copy link
Member

CC @HolonProduction as this seems LSP related.

The fact that the LSP runs every string through this, could probably be improved given that we have more fine grained knowledge about were a path is expected in the completion context, but it would require an architecture change to have this info available outside of completion.

Even if we'd do that, we'd still need a way to resolve the path, which fails silently, since even if a path is expected there could be a user error. So having this fail silently (or providing a silent alternative) seems necessary to me. Can't say anything about this specific implementation though.

Also a learning from the current situation of Variant::get and typed dictionaries: if we make this fail silently, please add a documentation comment to make this contract explicit! Otherwise we'll just get regressions in the future because this behavior changes.

@akien-mga akien-mga merged commit 94d7a54 into godotengine:master Jun 12, 2025
20 checks passed
@akien-mga
Copy link
Member

Thanks!

@mihe mihe deleted the lsp-uid-bug branch June 13, 2025 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unrecognized UID: "uid://a"
4 participants