-
-
Notifications
You must be signed in to change notification settings - Fork 22.7k
GDScript: Replace abstract
keyword with @abstract
annotation
#107717
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
base: master
Are you sure you want to change the base?
Conversation
be946d4
to
7767d3f
Compare
Hey! This PR feels more complete than #107713 because it has an explanation. I understand that it's "too late" to be trying to stop the moving train but still I would like to express my thoughts. I'm all for UX, consistency, minimalism, readability and legibility but I must say these reasons don't really justify the change IMO. I agree with the fact that From readability standpoint (keyword vs annotation) I think it really depends on the user, on how they perceive code and how they write it. What I really want to say is this. This is my opinion and a view of how I perceive annotations in GDScript:
That was what I wanted to say. If annotations are moving towards becoming a more generic system (allowing users to create their own like decorators in JS, attributes in C#, annotations in Java, etc.) then I'm all for it. |
I have always assumed annotations are used for anything that affect the editor in some way and keywords were for things that affect the code. So this change seems confusing to me. I shall give some quick (vague) examples:
I think having abstract as an annotation deviates from this and is a little confusing. |
I somewhat disagree with the above comments, I don't think it's fair to say that annotations are exclusive to the editor.
My only gripe with the reasoning outlined here is that, following the "Reasons For", doesn't this also apply to the I do think this reason
is quite valuable, simplicity of the underlying code is immensely valuable, especially in a project where open contributions are encouraged and things like this can improve coprehensibility. |
Honestly, to me I already accepted that the difference between keyword and annotations in GDScript currently is too arbitrary anyway, so I'm like... whatever. I'd normally prefer keyword, but if virtual and override will be annotations, I prefer consistency more. However, if there's ever a GDScript 3.0 (5.0?) on Godot 5, please make the annotation system more meaningful, with annotations only for things that need it, have a more clearly defined reason for annotations to exist. I think everything in the language where its presence/absence check is mandatory (i.e. that breaks forward-compatibility) should be a keyword, even if it has Then make annotations some extensible system allowing custom classes and some hook system to modify the compilation generically like a preprocessor (but syntax-based, not text-based like C). This would allow some GDScript features be introduced by addons, reducing some implementation weight on core devs. Core features could be introduced as inbuilt annotations when they can be forward-compatible, and as keyword otherwise. It would also facilitate testing these features by many users without recompiling the engine. |
virtual and override have not yet been introduced, and according to the link you sent me in a previous discussion here, they will be decided upon on a case by case basis. It seems that contributors could not decide upon a consensus, so we all have to suffer the consequences of a mish mash design. Although it already seems like there's a pattern for what an annotation is or is not, so why not continue with that. I guess that's unfortunately one of the issues with open source development. |
Co-authored-by: Danil Alexeev <dalexeev12@yandex.ru>
7767d3f
to
bdeb83d
Compare
@dalexeev Dang, we worked on the same thing. I said in the GDScript meeting that I would work on this. Un-un-bumped, and I updated my PR to match the more detailed documentation in your PR. You and I took different approaches, though. I initially dismissed the approach in your PR because it's pretty much only a syntax change, and still keeps the "special case" code in the language parser. The approach in this PR is to make it behave like other annotations, which for functions, does involve moving the body-or-not check to the analyzer stage. @romgerman @romgerman @jordedwards The plan is also to replace |
abstract
keyword with @abstract
annotation
@aaronfranke gotcha, sorry for not clarifying before assuming static was treated differently |
I think Both are modifiers, both apply to both classes and methods, and both are language-level features, that don't interact with other parts of the engine (like most annotations do, as @produno said). I understand the team's reluctance to add more keywords to the language, 3.X went too far into that direction and the ones that were turned into annotations in 4.0 are a good change. But I think this is going too far into the other direction. |
Here's how I've always interpreted the responsibilities of keywords and annotations:
As such, I fundamentally disagree with abstract, static, virtual, or override being annotations. I know that GDScript is developed specifically for Godot. But, I believe that the past language and implementation division of keywords and annotations was wise, even if it was unintentional. |
Based on vnen and my thought, the most reason why we treat some modifiers as annotations is because of the frustrating system of adding new keywords. Every time you add a keyword, you have to change a lot of files, even the core files of gdscript module. Don't believe it? Check the source file and see how these keywords work. Meanwhile, the handle of keywords is much more difficult than annotations, which just require registration and implementation method during their definitions. Adding more keywords means higher unreadability of the source code, increasing the difficulty of maintaining the engine module. Maybe we can dig deeper on this issue in GDScript 3.0 in the future and overhaul the whole keyword system to make it much more simpler to handle. As for I admit that it is still ambiguous for most of us when a syntax element is a keyword and when it is presented as an annotation. But for modifiers in the middle of the both, we have to discuss more and reach a clear and determined consensus on this question. |
All keywords modify some behavior in some way. Otherwise, they would just be white space. So, the very idea of modifiers as a distinct category is vague. I much prefer the distinction between language features (provided by keywords) and engine features (exposed to the language through annotations). Annotations act as an extension system for the language, enabling context-specific features (i.e., those from an engine or game) to be injected into the language. Naturally, adding an extension is easier than modifying core files. If keyword implementation could be streamlined, that's a separate matter. And, indeed, if keyword implementation is difficult, and a conversion is to be made, it makes far more sense to convert from annotation to keyword rather than from keyword to annotation. One could implement a language feature as a prototype annotation and then replace it with a keyword when it's ready. |
In fear of flogging a dead horse, I shall make one last comment. As an end user, and selfishly so, I do not care how complex something is to implement and maintain. All I care about is the end user experience being as good as it possibly can be. I don't think usability should be sacrificed for less complexity, or at least, if such an integral part of the experience is difficult to maintain, then I guess that's an issue within itself. (Of course I understand this is not the case for everything.) That said, I will respect the decision of the maintainers. I will just have nightmares of annotations littering my codebase. |
I'll note something that I think has not been said yet. To me, the main motivation to make
Making it a keyword forces parsers to resolve it immediately when building the syntax tree. This can bring problems, such as missing syntax highlighting, broken autocomplete, or unhelpful error messages while editing the code. To provide the best user experience, the language grammar needs to be agnostic to contextual details, such as whether a function needs a body. That type of question is better answered during type and variable resolution. I think some people feel strongly about |
Beyond a few early adopters using 4.5.dev5 I don't see any usability issues with changing this from a keyword to an annotation, so there isn't really a trade off between code complexity etc. and user experience I can see (and while we should reduce friction as much as possible the development versions are unstable and that should be well known, so some friction is to be expected) |
If the parser and variable resolution can't elegantly handle an The usability issues, or friction, of an |
Y'all should just have been using ANTLR4 to make the parser instead of coding it by hand... |
To @Ivorforce's point, here is an example of how error messages change as of this PR. In master, this code: abstract abstract class A:
pass gives the error @abstract @abstract class A:
pass gives the error The error gives a hint to how this simplifies the parsing of the language: it only has to keep track of annotations and apply them later, instead of having to check for every possible thing that can come after |
If Imagine if someone said "the implementation workflow and error reporting for the |
At this point, it would already work exactly like an annotation (minus the forwards compatibility), and we'd just be arguing over whether we want the leading |
|
This seems to be an internal issue in the scripting system. This shouldn't lead to compromises in language consistency. |
Yes, it's important. Indeed, I posit that the average user arguing for it being a keyword—myself included—doesn't actually care how it's implemented in the backend as long as it is typed like a keyword. So, omission of the If I wanted to write an abstract class in Godot, my first instinct would be to type
Quirky implementation details don't need to bleed into user space. |
I think the discussion is going in the wrong direction. We decided to replace the You can think of annotations as attributes on class members. A class consists of different kinds of members (variables, functions, signals, constants, etc.). Each member can have additional attributes, which are specified in annotations. This makes sense from the grammar of the language. Declarator keywords ( We discussed several options for the separation criterion between keywords and annotations:
|
Ok, even though I don't personally like it, that is sound logic. Maybe we're just too used to keywords in other languages. |
I'm glad there is a discussion. It's important because this is not something that can be easily reverted back. But I agree that there are enough subtleties for everybody to make this topic endless. I'm okay with the change. not important but funny
But then
It seems like the parser is a problem if every reasoning consists of "well if it weren't for parser". |
This was requested by @vnen and discussed in the GDScript meeting on 2025-06-17. Meeting notes:
This effectively restores the code to an earlier version of PR #67777, except that it includes abstract functions as added by PR #106409.
Why?
Disclaimer: I am in favor of this PR, so this list is probably biased.
Reasons For
@abstract
is a modifier that modifies aclass
,class_name
, orfunc
. It can't be used by itself.@override
and@virtual
which go well with@abstract
.Reasons Against
abstract
from other languages, thenabstract
would be less friction. (possibly? only slightly?)static
.static
is planned to be replaced with@static
. Since removingstatic
would break compatibility, we might add@static
before removingstatic
so both work for awhile.master
branch and already usingabstract
.Neutral
: pass
except that abstract functions explicitly cannot have a body and so: pass
is forbidden there and non-abstract functions must have a body.Godot isn't a democracy, but you can react with 👍 and 👎 to show your support for or against this change.