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

Annotations in GDScript #20318

Closed
vnen opened this issue Jul 21, 2018 · 45 comments
Closed

Annotations in GDScript #20318

vnen opened this issue Jul 21, 2018 · 45 comments

Comments

@vnen
Copy link
Member

vnen commented Jul 21, 2018

Around a year ago there was a PR adding annotations for GDScript (#9469). It was rejected mainly because there was no direct use for it (no data in the parse tree, only third-party tools would made use of it).

This proposal is to add some use for annotations in a way that make GDScript more extensible without hacking more keywords into it.

What annotations could be used for?

Advantages
Every time a new keyword is added, it requires changes to the GDScript tokenizer and parser to handle it. In particular the export parsing is quite convoluted and it's mixed with other class-related parsing.

With annotations, less work would be done to add a particular attribute (like export, setget, onready), instead it would only need to check which annotations are present.

DIsadvantages
Adding annotation support would require more changes to the parser than any keyword alone. It may also influence people to suggest new features as "just an annotation".

Syntax
I don't have any particular preference for syntax, but I imagine something like Python decorators. It might be confusing for Python users though, since annotations are not the same as decorators.

@onready
var my_sprite = $Sprite

For passing arguments, it could work like functions:

@export_hint(ENUM)
@export_hint_string("Attack,Defense")
export var my_enum : int = 0

Maybe without parentheses:

@export_hint ENUM
@export_hint_string "Attack,Defense"
export var my_enum : int = 0

Or maybe use named parameters (and avoid the keyword):

@export type=String hint=MULTILINE
var my_text = ""

Or something else.

Custom annotations
Unknown annotations will simply be ignored (maybe with a warning). So third-party tools can parse the annotations to offer other capabilities, like documentation generation.

It's also possible to add an introspection API: get_method_annotations(), get_property_annotations() or something like that. This way plugins that, say, expect scripts can use annotations to decide which method to call instead of using a hard-coded name.

@LikeLakers2
Copy link
Contributor

LikeLakers2 commented Jul 21, 2018

Just so I'm understanding the custom annotations correctly, I could have something like this:

@description "Adds two numbers and returns the result."
@parameter name=num1 type=float description="The first number"
@parameter name=num2 type=float description="The second number"
@returns type=float description="num1 and num2 added together"
func add(num1, num2):
	return num1 + num2

And I could call a function, say get_annotations("add"), which would return these annotations? Even if these annotations aren't recognized by Godot as some built-in keyword/annotation?

@vnen
Copy link
Member Author

vnen commented Jul 21, 2018

@LikeLakers2 yes, that is the gist of it.

@groud
Copy link
Member

groud commented Jul 21, 2018

I like it, I dont know for the implementation behind but in the GDscript code it would look a lot cleaner than what it looks like now. Especially for the setget example.

@isaacremnant
Copy link
Contributor

This is very useful, but it should allow single line statements for readability. For example,
@onready var a = $A should be allowed. Otherwise, this adds a ton of newlines and would in this case waste the useful of onready.

Something like

@onready
    var a = $A
    var b = $B
    var c = $C

would be useful to apply the same annotation to several statements.

Also, a colon could be used to indicate where the annotation ends and where the affected statement(s) begin, to be consistent with the rest of GDScript.

@Zylann
Copy link
Contributor

Zylann commented Jul 22, 2018

If annotations can be parsed with a clear begin and end, then no need for semicolons and can then be put on the same line if needed (if they use '()' for example, or are argument-less)

I don't think vnen intended to remove old shortcut keywords though?

Also having highlighter handle these can help.

@ghost
Copy link

ghost commented Sep 21, 2018

Late to the party here, but very interested in how this might provide categories for export vars and create tool/debug script divisions?

@akien-mga
Copy link
Member

Tentatively putting on the 3.2 roadmap, I'd really like to see this implemented sooner than later to provide usability enhancements to the editor.

@girng
Copy link

girng commented Dec 14, 2018

unpopular opinion incoming:

why is gdscript's syntax being modified so heavily? it was originally designed to be simple, easy to learn and intuitive. i fear with all these new additions (typed gds, annotations) it will become very confusing for new developers. for example, if a new person to godot were to watch a tutorial and see the code that's in LikeLakers2's post, i'd imagine that would make their head explode. if anything they'd have to ask bunch of questions about it / how it works, etc.

i totally understand everyone's love for gds and how the contributors want to make it better, etc. i just feel like there might be a possible disconnect between actual game devs, and the contributors (not saying contributors are not game devs, just saying how some features are not really needed). not everyone needs to utilize these features. i just fear that gds might stray further and further away from its simplicity, that's all. it's already more than enough...

also, having 3 lines for a export keyword is very cumbersome, compared to just specifying everything in one line. for example: onready var my_sprite = $Sprite is so much more cleaner (to me anyway)

and regards to point #4, this can be done in the editor AFAIK. also, imo, having annotations all over the place in code to 'disable certain warnings' could lead to very messy code

@bojidar-bg
Copy link
Contributor

why is gdscript's syntax being modified so heavily? it was originally designed to be simple, easy to learn and intuitive. i fear with all these new additions (typed gds, annotations) it will become very confusing for new developers.

Most (if not all) GDScript syntax changes are compatible with old code. The main goal is to increase productivity of developers using GDScript, e.g.:

  • match statements allow for switch-case statements (which were quite requested) and even improve upon that by allowing people to match arrays and dictionaries with ease.
  • onready variables (which were new in 2.x) concretize a pattern which was often used, namely initializing variables in _ready.
  • Typed GDScript allows developers to finally rest knowing that no wrong-type errors will happen, and lets them benefit from better autocomplete at the same time. It is optional, so newcomers don't need to learn it for their first game.

i just feel like there might be a possible disconnect between actual game devs, and the contributors.

This is an open community. Game devs are welcome to come and express their opinion, just as you did. At any rate, quite a bit of time will pass before annotations become a reality.

[...] i just fear that gds might stray further and further away from its simplicity, that's all. it's already more than enough...

If it were already good enough, we wouldn't receive feature requests for it.

also, having 3 lines for a export keyword is very cumbersome, compared to just specifying everything in one line. for example: onready var my_sprite = $Sprite is so much more cleaner

The syntax is not finalized yet. It is quite probable that it won't replace onready and export keywords immediately.

@samdze
Copy link
Contributor

samdze commented Jan 18, 2019

I really like the idea, very like attributes in C#.

Classes and signals annotations could be interesting as well.

Inspector plugins that automatically come in action whether a property, method or class have a particular custom annotation would be a breeze.
As for the syntax I'd prefer something that could be optionally written on a single line too, but it's not so crucial.

How the process of defining custom annotations could be? I would prefer that they were not freely defined every time in the code, but that they were created by the user with a univocal definition, just like classes.

@GryphonClaw
Copy link
Contributor

I think this needs more looking into, I think it'd be great to add to the language (as optional syntax etc etc) so as to not confuse complete newbies trying to jump in.

I think the following syntax might be ok to look at:

@export type=String, hint=MULTILINE

adding the comma between the "parameters" I think would make it a little more consistent with the current syntax like so:

export (String, MULTILINE) var my_var

the first version is a little more verbose, but I think it also makes it more explicit and with autocomplete it shouldn't hurt too much :)

More syntax discussions should happen going forward. Overall I like the idea.

@hubbyist
Copy link

Annotations are a good way of configuration injection. But seperating configuration and code may be a more clean approach IMO. May be adding them like as header files be more helpfull.

@willnationsdev
Copy link
Contributor

From @bojidar-bg's comment...

At any rate, quite a bit of time will pass before annotations become a reality.

Can someone explain what the "blocking" issue is that would delay this implementation? Is it just familiarity with GDScript / manpower, or are there specific features that need to be implemented ahead of time to support annotations?

@bojidar-bg
Copy link
Contributor

Well, quite a bit of time has passed since my comment, so I think that already proves it?

Main blocker for annotation support would be getting core developers agree on the syntax and semantics. Afterwards, implementation should be relatively easy.

@sleepcircle
Copy link

all i can say is that i'm glad i learned gdscript before these things got implemented because

@export_hint(ENUM)
@export_hint_string("Attack,Defense")
export var my_enum : int = 0

would have been very daunting and difficult to parse for me, as a beginner

@bojidar-bg
Copy link
Contributor

@sleepcircle We will try to keep GDScript simple in all cases. So, no need to be sarcastic here: the code you cited was just a proposal, not the future syntax.

@sleepcircle
Copy link

I'm sorry, I wasn't trying to be sarcastic. I was just assuming, since the majority seemed to approve of these additions, that they were inevitable.

@chillen
Copy link

chillen commented Mar 19, 2020

Just wanted to throw my $0.02 as a game dev instructor. Warning: Unnecessarily long comment that doesn't contribute much, just my experience from teaching programming for 5 years about how new developers will perceive this. Skip if not interested!

I think it's important when coming up with new language idioms like annotations that you should piggyback every affordance you can. For example with connect, it works nicely now as it makes sense to a new developer that you call a function that takes in parameters and has some side-effects.

If @ was used for metadata exclusively, then any time a new developer sees an @ they recognize it as metadata that doesn't affect their code logic. If it were to affect logic, it is important that we aren't adding new idioms that are sometimes used as x and sometimes used as y.

Right now, to modify a variable, there are var prefixes, suffixes, and alternatives. There are some things I'll list that aren't necessarily "variable modifiers", but new developers might see them this way

  • Prefixes: onready, export(...)
    • These each have a different type of behaviour. onready affects runtime variable loading, export is kind of an editor hint/metadata. Having them used in the same place feels like their behaviour should be connected somehow, when it really isn't
  • Alternatives: class_name, extends, signal, enum, const, func
    • These alternative formats feel fine, but differentiating an "enum" and "const" from say, ints or strings seems like an odd choice
  • Suffixes: setget
    • Setget in its own category is all right, but it is similar to export in that it is more a sugar keyword for developers and not-so-much a logic shift. I can see people having different opinions here, though
  • Somewhere in-between: typing var x : int = 5
    • This in-between typing feels odd, especially when "enum" and "const" are alternative keywords to var to represent the same thing. Definitely an argument that const is similar to setget in that it modifies the developer's experience moreso than a tool for game logic itself.

So now let's look at the addition of annotations.

Annotations would be a brand-new concept/idiom that would need to be taught to new developers. Ideally, new developers should be able to get up to speed and making things knowing as few idioms as possible so that they can organically pick up new idioms as they become useful to them. Think of it like a tech-tree.

  • (Tier 1) They can make a game knowing only func, var, and a few basic programming concepts like function calls, conditionals, and loops
  • (Tier 2) Then they move on to learn useful sugar/functionality, like signals, const, enum
  • (Tier 3) They learn shortcuts, like setget, onready
  • (Tier 3.1) They learn developer-only sugar, that won't change their game, but change their process, with things like exports, editor descriptions, tools, and typing
  • (Tier 4) Purely documentation and project structure

I feel like Tier 3-4 are the prime targets for annotations. There are two elevator pitches I'd give to my students for the two different implementations:

  • Purely metadata: "To help with your documentation and collaboration, learn about annotations to add some metadata to your scripts. They're more powerful than just using comments."
  • Dev shorthands/sugar: "If you're looking to reduce your code or make it more readable, have a look at annotations. They let you describe variables and functions while providing some editor tools and shortcuts."

I've taught a number of devs Godot, and I think making annotations at least a Tier 3 option, and at most Tier 4. I'd rather not have to show them an @ symbol until they're already building entire, reasonably complex games and are looking to improve their process.

This means my opinion lands on us using annotations exclusively for dev shorthands that are not important for game functionality/have alternative implementations or purely for documentation, as it's easy to tell people "learn annotations once you're building larger projects that need documentation".

Specific points from the thread:

  • They should be all right for exports, since exports aren't critical to any game
  • Onready is a handy shortcut early on, but not necessary since new devs can start by initiating in _ready and the prospect of nested annotations means writing onready way fewer times
  • setget is such a weird syntax already, and already its own idiom as the only suffix, that it could totally be in there
  • Connect: As I lead with, it's already perfect with the function call idiom. Having multiple ways to connect could conflate the tutorial/sample code space. Perhaps allowing people to write their own annotations would be better than standardizing this, so that devs working on closed projects can build a library of annotations that won't necessarily conflate the public space
  • Types: Types are in a weird spot right now, where some type modifiers are alternatives and some type modifiers are in-between. Maybe having them as annotations works: @type(const int) @type(enum), which would unify all of them as a developer-oriented sugar

Again, not a huge contribution, but food-for-thought when thinking about what functionality should be blanketed under annotations. I think they're a great idea, but unclear precisely where they fit in. Sorry for the length, I'm always a little too verbose.

@Shadowblitz16
Copy link

Shadowblitz16 commented Mar 29, 2020

I dislike this.
I don't want to have a bunch of annotations for every field, property and method

I would rather have more keywords

if people don't like a ton of keywords we can remove some of them

export MyClass : Node2D # export replaces class_name, : replaces extends 

signal mySignal #signal is kept

group(MyHeader, "res://icon.png" )
export var my_property : Array(int) setget _set_my_property, _get_my_property # : replaces export type

var test = 0 # no need for onready. variables declared outside of _ready automatically try to be onready vars

#others are kept

@realkotob
Copy link
Contributor

I agree with the original proposal entirely.

I don't disagree with the above comments, but the pros severely outweigh the cons.

@willnationsdev
Copy link
Contributor

@Shadowblitz16 Many of these suggestions are confusing to people here, for the following reasons...

export MyClass : Node2D # export replaces class_name, : replaces extends 

export, class_name, :, and extends each configure 4 completely separate data points and systems. You cannot simply switch them around without impacting other things irrecoverably.

  • export configures the generated PropertyInfo object that is sent to the Inspector to build the editor GUI.
  • class_name registers the script as a global class in the ScriptServer. It technically has nothing to do with the type system. It's part of GDScript's "static typing" only insofar as it just happens to create a global instance of the script at parse-time rather than run-time.
  • : is used for optional type hints. Unless you convince people to make GDScript statically typed at all times and/or propose an alternative type hint syntax, there's no way to repurpose the colon token.
  • extends is used for the inherited class (as you know). This is a pretty common syntax in other languages, and all documentation and tutorials already follow this method. There isn't going to be a strong incentive to switch away from this and create more work for purely a cosmetic reason.
group(MyHeader, "res://icon.png")

It's unclear to me what this would even do. I mean, it seems like the node will be added to the "MyHeader" group (which could make sense), but what is the icon for? Groups do not have icons associated with them.

export var my_property : Array(int) setget _set_my_property, _get_my_property # : replaces export type

As has been stated earlier, these things all affect different systems, not the same system. Furthermore, there may be times that you want a value's type or its initialization to be flexible. For example, in dynamic GDScript, you can do something like this:

onready export(NodePath) var the_node = get_node(the_node)
var test = 0 # no need for onready. variables declared outside of _ready automatically try to be onready vars

Initializing data prior to the ready notification wouldn't make sense. Scripts are associated with the Object class, not the Node class. Script properties are initialized during construction. That doesn't change even when you get to the Node class's constructor. The _ready() notification happens much later after instantiation. Having the default timing of variable initialization be different between Objects and Nodes would be extremely confusing and lead to a lot of unpredictable behavior for those learning and using Godot.


I don't mean to shoot down your suggestions, but rather just explain why people are not seeing the justification for these suggested changes.

@Shadowblitz16
Copy link

Shadowblitz16 commented Apr 1, 2020

@willnationsdev its ok I understand
what about doing both Annotations and extra Keywords
this way users can use Annotations if they like and Keywords if they don't want to have dozens of Annotations per field

Edit: note C# as attributes that allows you to combine them like so..
[Attribute1(), Attribute2()]
however while this might help reduce the line count its still is a bit ugly

@Calinou
Copy link
Member

Calinou commented Apr 1, 2020

@Shadowblitz16 We'd prefer to have only one obvious way to do things when possible. Having two different syntaxes would be contrary to that goal.

@Shadowblitz16
Copy link

Shadowblitz16 commented Apr 2, 2020

@Calinou I think gdscript should be left as it is then if people can't compromise.
1 - it breaks backwards compatibility unnecessarily
2 - it creates bigger files and less readable code
3 - it forces people change to a new system they are not used to.
4 - it forces people to use a system that they might not want to

@groud
Copy link
Member

groud commented Apr 2, 2020

1 - it breaks backwards compatibility unnecessarily
2 - it creates bigger files and less readable code
3 - it forces people change to a new system they are not used to.
4 - it forces people to use a system that they might not want to

Honestly, those are quite bad arguments. 3 out those 4 points is inherent to any big changes in an API, and the first out of them could be worked around by still keeping compatibility with the older keyword-based system for a while (likely with a deprecation warning).

Edit: we could also provide an automatic conversion tool I guess.

For point 2, while I think everyone will agree on the fact annotations can lead to files with more lines, most people here disagree on the fact it creates less readable code.

@Shadowblitz16
Copy link

Shadowblitz16 commented Apr 2, 2020

@groud this is using an annotations for unnecessary things
1 - why do we need to deprecation something that works?
2 - its less readable if you have to scroll down 5 lines to see a field

  • export is basically a public keyword to the editor
  • onready is basically a var declaration before the script runs

both are not suited to be annotations

member definitions are the only thing I can really see this being good for and they would have to be collapsible in this case they aren't.

@groud
Copy link
Member

groud commented Apr 2, 2020

@groud this is using an annotations for unnecessary things

A lot of use cases have been presented in this thread. Whether it is for documentation, introspection, more complex plugins... there a ton of use cases for annotations that cannot be covered by keywords.

1 - why do we need to deprecation something that works?

There are plenty of reasons to do something like that. Any feature might need to evolve to allow a cleaner API, more flexibility, etc... And once a new version is widely used, it's better to remove compatibility with previous version when possible, as this definitely has a maintenance cost.

2 - its less readable if you have to scroll down 5 lines to see a field

No need to exaggerate. The goal of discussing such proposal is to allow a syntax smart enough to avoid such problems. IMHO, the export hints could be integrated as arguments to the export annotations (provided we could have a named arguments system I guess). In such situations, the system could take even less space than before.

Also, we could also imagine having the annotations on the same lines as the field. I don't think this could cause problems.

export is basically a public keyword to the editor
onready is basically a var declaration before the script runs
both are not suited to be annotations

Well, you likely have preconceived ideas about what annotations are for. I do think those use case perfectly fit an annotation system (and it looks like a lot of people do). But indeed, I guess each situations should be discussed case by case.

@mnn
Copy link

mnn commented Apr 2, 2020

I don't see the "lines" argument to be particularly good. Even if the annotations don't directly allow multiple statements per line (or a "prefix" form), you can still use ; as a delimiter.

@onready var my_sprite = $Sprite
@onready; var my_sprite = $Sprite


@export_hint_string("Attack,Defense")
@export_hint(ENUM) export var my_enum : int = 0

@export_hint_string("Attack,Defense")
@export_hint(ENUM); export var my_enum : int = 0


@export_hint_string "Attack,Defense";
@export_hint ENUM export var my_enum : int = 0

@export_hint_string "Attack,Defense"
@export_hint ENUM; export var my_enum : int = 0


@export type=String hint=MULTILINE; var my_text = ""

# more options

@export(type = String, hint = MULTILINE) var my_text = ""
@export(type = String, hint = MULTILINE); var my_text = ""

@export(String, hint = MULTILINE) var my_text = ""

# I personally prefer this one (positional and named args supported, default/optional args too)
@export(String, MULTILINE) var my_text = ""
@export(String, hint = MULTILINE) var my_text = ""
@export(type = String, hint = MULTILINE) var my_text = ""
@export(int, ENUM, "Attack,Defense") var my_enum:= 0

Edit: Oh, I was too slow, @groud already addressed the lines argument. Well, at least those few code examples added something to this thread.

@Shadowblitz16
Copy link

Shadowblitz16 commented Apr 3, 2020

that's your guys opinion.
I personally think the @ is ugly

EDIT:
so how would member declaration work?
doing so would be horriable

@description "Adds two numbers and returns the result."
@parameter name=num1 type=float description="The first number"
@parameter name=num2 type=float description="The second number"
@returns type=float description="num1 and num2 added together"
func add(num1, num2):
	return num1 + num2

unless it was able to be collapsed from the beginning of @description to the beginning of func

@mnn
Copy link

mnn commented Apr 3, 2020

I believe annotations are not meant to replace types (as your example seems to do). If you don't want documentation annotations, you won't be forced to use them:

func add(num1: float, num2: float) -> float: return num1 + num2

This confusion probably stems from the less than ideal situation with export hints where, as far as I know, you can't use real types (and the problem of not having generic types which surprisingly export hints support for some types like an array).

I personally think the @ is ugly
so how would member declaration work?
doing so would be horriable

In other languages this purpose usually serve comments, not annotations and usually are on par or more verbose than what was suggested. In a C language family (most popular languages) the @ is pretty common for annotations (e.g. Java, JavaScript, TypeScript, Scala and from what I read Python as well).

TypeScript (I believe the types in docs are not required and tools can use actual types):

/** Adds two numbers and returns the result.
 * @param num1 {float} The first number
 * @param num2 {float} The second number
 * @return {float} num1 and num2 added together
  **/
const add = (num1: number, num2: number): number => num1 + num2;

func-like flavor:

@description("Adds two numbers and returns the result.")
@parameter(num1, "The first number", type=float)
@parameter(num2, "The second number", type=float)
@returns("num1 and num2 added together", type=float)
func add(num1: float, num2: float) -> float:
	return num1 + num2

without duplicate types:

@description("Adds two numbers and returns the result.")
@parameter(num1, "The first number")
@parameter(num2, "The second number")
@returns("num1 and num2 added together")
func add(num1: float, num2: float) -> float:
	return num1 + num2

paren-less flavor:

@description "Adds two numbers and returns the result."
@parameter num1 "The first number"
@parameter num2 "The second number"
@returns "num1 and num2 added together"
func add(num1: float, num2: float) -> float:
	return num1 + num2

I like this syntax best for doc comments. I am still not convinced about using annotations for documentation purposes, since for non-doc annotations I would prefer func-like syntax.

I used annotation names from the previous example, @parameter could be simply @param as in other languages, @description could be @desc, @descr or @func.

In GodoDoc I am using syntax based on TypeScript (TypeDoc which itself is based on JSDoc and Javadoc) and, in my opinion, it seems to work quite well:

## Same as [[bool_]], but `on_false`/`on_true` are functions.
## Only selected function will be called and its return value will be returned from `bool_lazy`.
## @typeparam T {any} Return type
## @param cond {bool} Condition
## @param on_false {FuncLike<T>} Function to call and return its result when `cond` is `false`
## @param on_true {FuncLike<T>} Function to call and return its result when `cond` is `true`
## @return {T}
func bool_lazy_(cond: bool, on_false, on_true): return GGI.bool_lazy_(cond, on_false, on_true)
var bool_lazy = funcref(self, "bool_lazy_")

unless it was able to be collapsed from the beginning of @description to the beginning of func

Yes, generally folding and an options for default folding would be a nice addition to the editor (folding based on a type of a block, e.g. you could enable in settings that inner classes would be collapsed by default).

@Zylann
Copy link
Contributor

Zylann commented Apr 3, 2020

I like the ability to put an annotation in front or above, for this the @annotation(a, b) is nice, with brackets optional if no params given. Being able to put in front allows the same speed of writing as today's keyword, given export and onready are very common with properties.

However in terms of usage, I dislike documentation too. I'm used to annotations having an effect on the program (even if indirect), while documentation would often triplicate their amount for comment-like usage, would then appear everywhere and highlighted the same as functional annotations... it's not fit for something that ubiquitous. Basically, I like the same usage of annotations as can be found in C#, which leads to far less annotations having to be written on top of members (they are pretty rare usually, not everyone has to write 5 lines as some examples have shown). If the argument is about Godot having no API to specify script docs, then that's the problem, not to be solved solely with annotations IMO. At least, I guess one could use that optionally, but I wouldn't want to be forced to do it this way, which I find inconvenient for full-scale documentation. (besides, scripts are not only GDScript, and edge case of using _get_property_list makes this even more awkward)

@groud
Copy link
Member

groud commented Apr 3, 2020

I think I fully agree with you Zylann. I would personnally allow such syntax for export (or onready) like keywords:

# No parenthesis when there are no parameters
@export var myvar
# With parenthesis for parameters
@export(ENUM, "Up,Down,Left,Right") var myvar2
# Being able to write the annoation on the line before
@export(ENUM, "Up,Down,Left,Right") 
var myvar2

Regarding the documentation part, I would simplify the syntax even more (taking @mnn 's example):

@description "Adds two numbers and returns the result."
@parameter "The first number" # No need to name the args if they are ordered
@parameter "The second number"
@returns "num1 and num2 added together"
func add(num1: float, num2: float) -> float:
	return num1 + num2

However, I agree it is mandatory to develop another system so that the documentation can be written elsewhere. In a json, XML or rst file I'd say. In-code documentation does not fit every project, and I agree adding a lot of annotation just for documentation might be annoying and can make the code harder to read in some cases.

@willnationsdev
Copy link
Contributor

Linking for relevance: godotengine/godot-proposals#177

@MWFIAE
Copy link

MWFIAE commented Apr 11, 2020

Pretty late to the party, but as dev who heavily relies on metadata and reflection to develop plugins I would really love to see annotations become a thing in godot.

While I do think it makes some stuff more beatiful (like the export and onready stuff) my main argument would be for custom plugins that can utilize annotations to their fullest extend.

@Xrayez
Copy link
Contributor

Xrayez commented Apr 25, 2020

Regarding onready keyword and its limitations.

I think it's safe to say that most people use onready to initialize node references early on. Except that it might not be feasible without issues in the long run, because when you instance some scenes which are _ready dependent, you may stumble upon an issue of referencing null:

func explode():
    var bomb = preload("res://explosion.tscn").instance()
    # Oops, forgot to `add_child(bomb)` earlier
    bomb.fuse.wait_time = 5.0 # ERROR: fuse is `null`
    add_child(bomb)
    # ... because `fuse` is a $Timer node 
    # which is only initialized once added to the scene tree.

Of course you need to add_child() the instanced scene before trying to set the fuse, but what if other nodes/objects need to be aware of the exact fuse before the scene is added to the scene tree?

After some time I've found a solution as described in #33620 (comment). As you may notice there, onready is just NOTIFICATION_READY, while what I actually needed was NOTIFICATION_INSTANCED and initialize my references even earlier. The only problem is that there's no oninstanced keyword, and I guess you may figure out what I'm leading to. 🙂

So, I guess it would be nice to remake onready keyword as an annotation indeed, while also supporting some other corner cases (like mine, as always!) with @oninstanced functionality without bloating the scripting language, as well as adding support for other notifications pertaining to initialization (_init, _enter_tree, etc).

Related proposal: godotengine/godot-proposals#260.

@vnen
Copy link
Member Author

vnen commented May 12, 2020

Opened a proposal with more specific details: godotengine/godot-proposals#828

@vnen
Copy link
Member Author

vnen commented May 25, 2020

Superseded by the above proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests