Fix constants scope in extended or inner GDScript classes#69587
Conversation
|
Generally makes sense - haven't be able to dig deeply. Is it possible to both have an outer class as well as a base class? If so, both ought to be checked right? Right now it's prioritizing the outer class over the base class. So something like: class_name OuterClass
class A:
const myvar = preload(...)
class B extends A:
func my_func(p : myvar):
print(myVar)
print(A.myVar)Would this work, or would class |
Gonna test this at once. |
|
i think you'll need 2 loops, one for checking base class, and one for checking each bases outer classes (because you don't want the outer-most script's base, you want the bases base (thats confusing, sorry)) |
b2ac34a to
d09600d
Compare
|
I updated the logic! It now checks for outer classes and their extended classes, without the need of adding one more loop. I prioritized the outer classes first, as this was the logic as for now. This code now works: # `base.gd` declares `A`
extends "base.gd"
const OuterDeclared: = "OuterDeclared"
static func test(a: A) -> void:
print(A) # prints <GDScript #...>
# `base_inner.gd` declares `B`
class InnerBaseClass extends "base_inner.gd":
static func test_a(a: A) -> void:
print(OuterDeclared) # prints "OuterDeclared"
print(A) # prints <GDScript #...>
static func test_b(b: B) -> void:
print(B) # prints <GDScript #...> |
d09600d to
c1c8cb2
Compare
There was a problem hiding this comment.
i think ideally this would just call reduce_identifier_from_base recursively on outer classes, and check if the passed base is part of the current classes hierarchy to see if it can access its self, but maybe thats just ideally
it would make the logic of searching a tree much simpler
There was a problem hiding this comment.
I don't really visualize how to use reduce_identifier_from_base there as you do, if you could show an example.
There was a problem hiding this comment.
i think it wouldn't have the information to avoid inf recursion, so looping is probably a better idea
There was a problem hiding this comment.
i don't know how to request changes, but i'm pretty sure this should be a loop inside the next if statement, collecting this outer class's bases outer classes (the terminology is so confusing), same in resolve_datatype
|
Look at these amazing MSPaint skills! But in all seriousness, inner classes need to check outer classes (blue) as well as base classes (red). I was thinking about this and it isn't really a tree - I think @adamscott is right that we need to worry about checking things twice, and about the possibility of cyclic dependencies. In that sense, having a |
c1c8cb2 to
35eca64
Compare
|
I updated the branch. Replaced |
There was a problem hiding this comment.
this should be moved outside of the base class loop and also collect the base classes of the base
There was a problem hiding this comment.
i think maybe this and the next loop should be instead something like this:
GDScriptParser::ClassNode *outer_base_class = script_class->base_type.class_type;
if (outer_base_class != nullptr) {
script_classes.append(outer_base_class);
GDScriptParser::ClassNode *outer_base_outer_class = outer_base_class->outer;
while (outer_base_outer_class != nullptr) {
script_classes.append(outer_base_outer_class );
outer = outer_base_outer_class ->outer;
}
}There was a problem hiding this comment.
wait no, the bases of each outer need to be searched first...
i think i'm back to thinking recursion is the least complicated way to do this, and just have checked_script_classes as a member of the analyzer or passed into reduce_identifier_from_base
There was a problem hiding this comment.
@rune-scape If you want to make a PR with your recursive changes and add me as a co-author, go for it! You seem to have an idea to fix this.
333b5a7 to
c112c6b
Compare
modules/gdscript/gdscript_cache.cpp
Outdated
There was a problem hiding this comment.
For some reason, without this, the tests will result in a heap-use-after-free error with the address sanitizer.
There was a problem hiding this comment.
That is so confusing! I don't see why these changes would do that.
Could it be a regression from elsewhere that shows up for you if you've rebased from master?
There was a problem hiding this comment.
i'm suspicious of this part, but the rest looks great!
There was a problem hiding this comment.
I'll create a new PR for that part, it doesn't belong in this PR.
7ae904e to
60ca361
Compare
|
Does this supersedes #57510? |
|
@trollodel Didn't know that there was an existing PR about the same issue. I searched the issue tracker before starting, didn't think about searching the pull requests too. Sorry. |
I would say yes. I just tested your PR and it doesn't pass, unfortunately, my added unit test. |
There was a problem hiding this comment.
The name implies you are getting all classes that are defined in scripts, but nothing else. Something about the name script_classes makes it a little hard for me to understand what it does. Would it make more sense to say something like get_context_classes or get_outer_and_base_classes or something more in line with its intent? Those names are terrible too :P
If nothing else, perhaps some comments explaining exactly what the function does would be nice for future readers :)
It also seems like it doesn't really check for native/builtin classes? Should it?
There was a problem hiding this comment.
I'll name the function get_class_node_current_scope_classes().
And no, no need for native/builtin classes, as checks are already made for those.
There was a problem hiding this comment.
I love the name!!!! That's perfect.
And just making sure: native/builtin class checks are already made going all the way up outer-class & extends hierarchy? Because maybe we're looking for an enum, say, somewhere in Object, and you might need to follow up a few GDScript classes before you get there?
60ca361 to
d41655a
Compare
@adamscott ok. I want to test this PR in my personal project, if I'll find some time for that. But your tests are bigger than mine, so it's probably good. |
|
@trollodel it's always frustrating when this happens - so I personally really appreciate everyone's graciousness here <3 There's a couple active GDScript contributors right now, which didn't use to be the case and explains why your PR wasn't reviewed at the time. Please feel free to hop on RocketChat or tag any of us for GDScript PRs. We've been trying to review each other's PRs and make sure GDScript changes move along, and you'd be very welcome if you wanted to join these efforts again <3 |
|
@anvilfolk Thanks for your words, but I don't feel frustrated (quite the contrary TBH).
I'm already in the GDScript channel on RC, but I don't have anything to say or PR stalled now. |
82b2454 to
8a0dd2e
Compare
|
Updated the PR to use lists instead of vectors |
|
I just realized something that I hadn't realized before, so I thought I would make it clear here - especially since I think the PR doesn't fall into this trap! :) The treatment of outer classes and base classes is meant to be different. You should look for instance members in the base class only. Searching for types, constants, class members, etc, should be done on both base class and outer class, recursively in some smart order. So here's my understanding of how things are working from a bird's eye view: I was worried that this was was doing base&outer class recursion for I feel like it's likely that there is some amount of duplication of work between Last comment is that I just realized how deeply important the order of |
I'm doing things that I didn't even knew I was doing. 🙃 |
There was a problem hiding this comment.
Just to be sure @anvilfolk, this prioritizes the node base type over its outer class
There was a problem hiding this comment.
Yes, you are right! And it should prioritize all base classes before even the first outer class.
And then it prioritizes the first outer class's base classes (all the way up) before moving on to first outer class's outer class, and so forth.
It gets pretty confusing, but honestly if somebody is looking this deep into the class hierarchy for names that are reused everywhere, they should just refactor their code, hehehe :)
There was a problem hiding this comment.
It should also add native/builtin classes and everything from what I can tell! :)
8154042 to
35cce21
Compare
modules/gdscript/gdscript_cache.cpp
Outdated
There was a problem hiding this comment.
i'm suspicious of this part, but the rest looks great!
35cce21 to
d20b3b1
Compare
|
Removed all the |
|
@akien-mga The PR doesn't build because I split off the code that made this PR build to #69865. Once #69865 merged, it should fix the current sanitizers issues. |
d20b3b1 to
fc5cabb
Compare
fc5cabb to
65a49ba
Compare
|
Thanks! |
|
Congraaaats! |


This PR depends on #69865Merged, thanksEspecially when checking the typing, the gdscript parser doesn't seem to pass through the code to set the right
script_class->outervalue for a givenGDScriptParser::ClassNode. It is available though insidescript_class->base_type.class_typeinGDScriptAnalyzer::resolve_datatype().So this PR usesscript_class->base_type.class_typeif thescript_class->outeris anullptr.Edit: I updated the logic! It now checks for outer classes and their extended classes, without the need of adding one more loop. I prioritized the outer classes first, as this was the logic as for now.
This code now works:
It makes the constants of base class available as typing inside the extended classes.
Fixes #69586