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

Ensure MSBuildPanel buttons are instantiated #51322

Merged
merged 1 commit into from
Aug 7, 2021

Conversation

raulsntos
Copy link
Member

@raulsntos raulsntos commented Aug 6, 2021

After #51220, MSBuildPanel was throwing a NullReferenceException on the _Notification method since the method can get called before the _Ready method where the buttons are instantiated so it was trying to set the icon of a null button. This PR initializes the panel in the constructor instead of using the _Ready method to make sure the buttons are never null.

An alternative implementation would be to leave the initialization in the _Ready method and check if the buttons are null in the _Notification method, but it doesn't seem like we need to wait for _Ready to do any of the initialization that MSBuildPanel does so it can be done in the constructor.

Bugsquad edit: Fixes #51344.

@raulsntos raulsntos requested a review from a team as a code owner August 6, 2021 16:35
@Calinou Calinou added bug cherrypick:3.3 cherrypick:3.x Considered for cherry-picking into a future 3.x release topic:editor topic:dotnet labels Aug 6, 2021
@Calinou Calinou added this to the 4.0 milestone Aug 6, 2021
@YuriSizov
Copy link
Contributor

An alternative implementation would be to leave the initialization in the _Ready method and check if the buttons are null in the _Notification method, but it doesn't seem like we need to wait for _Ready to do any of the initialization that MSBuildPanel does so it can be done in the constructor.

Indeed your current solution is correct (at least as far as we usually do it in Godot's codebase). Weird that I didn't experience the issue, or at least didn't notice it, but this change makes sense.

@YuriSizov YuriSizov removed the cherrypick:3.x Considered for cherry-picking into a future 3.x release label Aug 6, 2021
Copy link
Contributor

@neikeq neikeq left a comment

Choose a reason for hiding this comment

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

As far as I remember, we do initialization on _Ready because the constructor is always called after hot-reload. If we were to do initialization in the constructor we would be adding extra child buttons every time assemblies were hot-reloaded.

@YuriSizov
Copy link
Contributor

YuriSizov commented Aug 6, 2021

Is it a C# specific thing? Neither C++ side nor GDScript would do that (unless it was terminated improperly).

Also, why would it hot reload at all? 🙃

@neikeq
Copy link
Contributor

neikeq commented Aug 6, 2021

Is it a C# specific thing? Neither C++ side nor GDScript would do that (unless it was terminated improperly).

I don't know if GDScript calls _init every time a script is reloaded. But GDScript doesn't need to reload all script, only the ones that change.

Also, why would it hot reload at all? 🙃

Because we need to destroy the domain, start a new one and reload assemblies back. So we need to reload everything if something changes.

@YuriSizov
Copy link
Contributor

But shouldn't all the UI nodes be removed from the tree and destroyed when you do a complete reload? _Ready is way too late to add child nodes generally. _Ready should indicate that child nodes are also ready, and this way it's not possible.

@neikeq
Copy link
Contributor

neikeq commented Aug 6, 2021

No, they are not removed on reload regardless of the language.
Regarding the constructor and _Ready, I want to improve this as I don't like it either. But right now this is how it works, so there's no point in discussing it in the scope of this PR.

@raulsntos
Copy link
Member Author

As far as I remember, we do initialization on _Ready because the constructor is always called after hot-reload. If we were to do initialization in the constructor we would be adding extra child buttons every time assemblies were hot-reloaded.

That makes sense. I was under the impression the game assembly was the only one that needed to be reloaded.

Regarding the constructor and _Ready, I want to improve this as I don't like it either. But right now this is how it works, so there's no point in discussing it in the scope of this PR.

That would be nice.

I have updated the PR to use _Ready and check if the buttons are null instead.

if (errorsBtn != null)
errorsBtn.Icon = GetThemeIcon("StatusError", "EditorIcons");
if (warningsBtn != null)
warningsBtn.Icon = GetThemeIcon("NodeWarning", "EditorIcons");
Copy link
Contributor

Choose a reason for hiding this comment

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

Null conditional operator ?. would be shorter and more readable. But it's nothing important.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't use it on an assignment: The left-hand side of an assignment must be a variable, property or indexer.

@akien-mga akien-mga merged commit 35b08b7 into godotengine:master Aug 7, 2021
@akien-mga
Copy link
Member

Thanks!

@raulsntos raulsntos deleted the fix-msbuild-exception branch August 8, 2021 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unhandled Exception on opening of any project and build for 3.4 Beta 3 Mono
5 participants