-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
GDScript: Allow quoteless strings as arguments in some annotations #76512
GDScript: Allow quoteless strings as arguments in some annotations #76512
Conversation
For some annotation, strings arguments are validated. In such cases, we allow not found or not constant identifiers to be used as a string, because invalid values will raise error messages removing the problem of typos. It also allows type names to be used as strings if the argument supports it. This commit applies it to `@rpc`, `@warning_ignore`, and `@export_node_path` (the latter now validated the arguments to be valid Node types). Incidentally, this also improve completion for `@export_node_path` by also adding custom nodes to the list.
Sorry, but I don't understand what problem this solves. There is an explanation in #71634 why this is inconsistent and confusing. There is no reason to prevent using a constant as an annotation argument (except for the Strings in annotations have no performance impact, unlike method/signal strings in 3.x. Moreover, you are not replacing strings with something else, but only hiding the quotes in some cases, forcing the identifier to be treated as a string. The It also contradicts the If we had a |
One of the big things in Godot 4.0 was the lesser reliance of strings (mostly signals and methods, which now can be used without strings). The main point of it is validating at compile time instead of trying to figure out why something does not work only to realize you made a typo. Once constant expressions (and thus constant identifiers) was supported, it made sense to require quotes because otherwise typos would be a big problem. With this PR, we have actual validation in some cases, so the quotes are not necessary. Being quoteless might not mean much, but at a glance it is more obvious that the value is significant and just any arbitrary string. I actually remember some backlash for that change by requiring quotes on some annotations that accept only a handful of possible values. It is not pretty.
But this does not "prevent using a constant as an annotation argument". You can still use constants. The only difference is that if the name does not exist it is treated as a string. Which is fine because it's validated. The only argument against this, which would be option 4 in that discussion, is the following:
Yes, this would be the case but that's why this PR introduces this behavior only for annotations that limits the string argument to a known list, which means the particular example wouldn't happen, since Sure, you can still do something like this: const call_local = "call_remote"
@rpc(call_local)
func foo():
pass And that would be pretty odd. But that's a very far fetched example, I doubt it would cause problems in actual projects. If anything, this could be made a warning as well.
This has nothing to do with performance, it is about usability. Signals/Callables are probably less performant because it has to construct in the extra object and in the end is still just storing a string to pass to the connect/call.
The point is not replacing, just providing a better interface for the users. It does not matter if it's a string in the end, what is important is the presentation.
Well, I don't think we have to wait until a proper It does not make sense to accept an arbitrary string to something that has to be the name of a class that inherits |
PS: About |
It's hard for me to argue with your authority, but for me this still does not solve any real problem and does not increase convenience. It's just a "let's remove the quotes in a few random places because they look ugly" argument. This makes things inconsistent and confusing (even if it seems minor at first glance).
String completion and validation is possible and already available for
In the case of methods and signals, we achieved this in a different way: we added new
It's still an inconsistency, even with these restrictions. But most importantly, I don’t understand why this is needed, apart from saving a couple of characters and subjective preferences. I would prefer consistency and uniformity wherever a significant gain in convenience has not been proven. Also, in my opinion, this is bad because of the addition of unnecessary context: the same identifier is interpreted differently depending on the place where it is placed (in one place it is a "quoteless string", in another it is a real identifier). Imagine that we don't have a separate Lua-style dictionary, and we treat unknown identifiers in keys as strings, or generally treat non-existent identifiers as strings (old PHP versions have this behavior).
If annotations were a "thing in itself" (like the |
The benefit is cosmetic but I believe it's a benefit nevertheless. Consistency is not that important, especially not in detriment of other improvements. As an illustration: Having Also, even if in the future we introduce a core |
In my opinion, language behavior should not be based on highlighting in the editor. In the future, we may add highlighting for "strings with special meaning" if we deem it important. To me, expression consistency (no conflicts between string literals and identifiers) is more important than highlighting in the editor. The only place in GDScript where "quoteless" strings also exist is in the keys of Lua-style dictionaries. But unlike this PR, there is no conflict, it's part of the syntax, "quoteless" string cannot appear in the main flow of an expression. This is generic behavior, with no special cases. If I give abstract examples of dictionaries, you can easily figure out where the key is an identifier, and where is a string: {x: 1, y: 2} # x and y are identifiers x and y (variables, constants, etc.).
{x = 1, y = 2} # x and y are strings "x" and "y". But if I give an abstract example of an annotation, you can't tell if an argument is an identifier or a string without knowing what the annotation is and what the argument is: @a(x, y) # x and y are identifiers or strings? I expressed my opinion and concerns. Let's take this to the next PR review meeting. |
Well, an "abstract example" wouldn't fall in the rules from this PR, since I add only for a few cases where the arguments are validated and not for any arbitrary string, so I don't think this is a fair comparison. In this abstract example I would say they are identifiers, because they do not have obvious meaning and by default annotations do not allow quoteless strings. OTOH, with a concrete example: @warning_ignore(return_value_discarded) It's pretty clear what the argument means. You wouldn't really question if this is an identifier. Another way to see this: |
Moved the 4.1 milestone to 4.2, and added it to the list of PRs to team review. |
I tried to be objective, but I would recommend re-reading the thread before the meeting, if possible. This summary is just an attempt to help with the discussion. SummaryPros
Cons
|
Discussed in a GDScript meeting. Mixed reception, the group don't really support the idea of "exceptions" for some annotations (quoteless strings), but not others. And there's already validation for wrong values some annotations, ie. Thanks for the PR nonetheless, @vnen ! |
For some annotation, strings arguments are validated. In such cases, we allow not found or not constant identifiers to be used as a string, because invalid values will raise error messages removing the problem of typos.
It also allows type names to be used as strings if the argument supports it.
This commit applies it to
@rpc
,@warning_ignore
, and@export_node_path
(the latter now validated the arguments to be valid Node types).Incidentally, this also improve completion for
@export_node_path
byalso adding custom nodes to the list.