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

GDScript: Fix conflict between property and group names #78254

Merged

Conversation

@dalexeev dalexeev requested a review from a team as a code owner June 15, 2023 05:03
@dalexeev
Copy link
Member Author

dalexeev commented Jun 15, 2023

See also #73870, #73905 and #73933.

I think #73870 can be safely reintroduced after this PR (but it requires testing). Although this is optional (since no valid identifier starts with @group_), but without this check, the following curious thing is possible:

extends Node

@export_group("Resource")

func _ready() -> void:
    set("@group_0_Resource", 123)
    print(get("@group_0_Resource")) # 123
    set("lalala", 123)
    print(get("lalala")) # <null>

СС @vnen

@dalexeev dalexeev force-pushed the gds-fix-property-group-name-conflict branch from 78efb95 to bf8f996 Compare June 15, 2023 05:36
@YuriSizov
Copy link
Contributor

Groups and categories are also properties, they just have special flags that make them behave differently. So the error that the user is facing is not a bug but a design limitation. While we can work around it somewhat with this PR, I think we should instead err and report name collisions in the parser. That would be more correct in terms of what the engine expects from the user input.

@dalexeev
Copy link
Member Author

dalexeev commented Jun 15, 2023

But you can achieve this with _get_property_list() and the Inspector handles this correctly (see test case output). @group_* is the key of the internal HashMap (which, unlike the property list, does not support repetitions), not the real name of the property. I don't think it makes sense to not allow it.

{ "name": "prop_1", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
{ "name": "prop_1", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 128 }
{ "name": "prop_2", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }

Also, #73843 is a bug anyway.

@YuriSizov
Copy link
Contributor

YuriSizov commented Jun 15, 2023

Well, the inspector is pretty dumb, it just displays things :) But this structure of properties is still an error, because it implies you have 2 properties with the same name and different configurations. If anything, we should validate this more strictly in ClassDB as well.

@adamscott
Copy link
Member

Will postpone this issue to 4.2, as there seem to be a discussion on if this is an issue by itself.

@adamscott adamscott modified the milestones: 4.1, 4.2 Jun 19, 2023
@dalexeev
Copy link
Member Author

dalexeev commented Jun 20, 2023

I would suggest simply not counting entries with group usage flags as properties. So they can be repeated, unlike regular properties. Even the structure matches this: an array of dictionaries, not a dictionary of dictionaries.

1. We already have such entries in native classes.

{ "name": "RefCounted", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 128 }
{ "name": "Resource", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 128 }
{ "name": "Resource", "class_name": &"", "type": 0, "hint": 0, "hint_string": "resource_", "usage": 64 }
{ "name": "resource_local_to_scene", "class_name": &"", "type": 1, "hint": 0, "hint_string": "", "usage": 6 }
{ "name": "resource_path", "class_name": &"", "type": 4, "hint": 0, "hint_string": "", "usage": 4 }
{ "name": "resource_name", "class_name": &"", "type": 4, "hint": 0, "hint_string": "", "usage": 6 }

2. Group ending entries use the empty string, which of course will be repeated if you have multiple group endings.

@export_group("A")
@export_subgroup("1")
@export var a1: int
@export_subgroup("2")
@export var a2: int

@export_group("B")
@export_subgroup("1")
@export var b1: int
@export_subgroup("2")
@export var b2: int

3. I think it is logical that subgroups in several groups can be repeated. At the same time, the property list is flat.

{ "name": "A", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 64 }
{ "name": "1", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 256 }
{ "name": "a1", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
{ "name": "2", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 256 }
{ "name": "a2", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
{ "name": "B", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 64 }
{ "name": "1", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 256 }
{ "name": "b1", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
{ "name": "2", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 256 }
{ "name": "b2", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }

4. As I mentioned above, otherwise we would need to disallow category/group/subgroup names in GDScript that match Variant types, native classes, and user-defined classes (otherwise groups shadow them, in the current implementation). I think it doesn't make sense, for users the group names are just text.

Copy link
Member

@adamscott adamscott left a comment

Choose a reason for hiding this comment

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

Discussed in the GDScript weekly meeting. We agree with @dalexeev, the group names should not count as properties for the check of name collision. So we approve this PR.

@YuriSizov YuriSizov merged commit efbff13 into godotengine:master Jul 31, 2023
@YuriSizov
Copy link
Contributor

Thanks!

@dalexeev dalexeev deleted the gds-fix-property-group-name-conflict branch July 31, 2023 19:11
@dalexeev dalexeev added the cherrypick:4.1 Considered for cherry-picking into a future 4.1.x release label Aug 1, 2023
@dalexeev
Copy link
Member Author

dalexeev commented Aug 1, 2023

This PR is relatively small and fixes many issues. So in my opinion it's worth considering for cherry-pick. I've added the label beforehand, but note that the production team makes the final decisions on cherry-picks.

@YuriSizov
Copy link
Contributor

Cherry-picked for 4.1.2. This seems to be isolated and simple enough indeed.

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