From 854b14ba244cb9cdf4df02fd32816381066f2f5c Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Wed, 1 Oct 2025 00:44:45 +1000 Subject: [PATCH] fix objectdb leaks on exit --- .../Features/Problems/DiagnosticMetadataContainer.cs | 9 +++++++-- .../Features/Problems/ProblemsPanel.cs | 2 +- .../SolutionExplorer/SharpIdeFileGodotContainer.cs | 2 +- .../SolutionExplorer/SolutionExplorerPanel.cs | 9 +-------- src/SharpIDE.Godot/IdeWindow.cs | 12 +++++++++++- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/SharpIDE.Godot/Features/Problems/DiagnosticMetadataContainer.cs b/src/SharpIDE.Godot/Features/Problems/DiagnosticMetadataContainer.cs index a921e21..e23720c 100644 --- a/src/SharpIDE.Godot/Features/Problems/DiagnosticMetadataContainer.cs +++ b/src/SharpIDE.Godot/Features/Problems/DiagnosticMetadataContainer.cs @@ -4,12 +4,17 @@ using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence; namespace SharpIDE.Godot.Features.Problems; -public partial class DiagnosticMetadataContainer(Diagnostic diagnostic) : GodotObject +// public partial class GenericContainer(T item) : RefCounted +// { +// public T Item { get; } = item; +// } + +public partial class DiagnosticMetadataContainer(Diagnostic diagnostic) : RefCounted { public Diagnostic Diagnostic { get; } = diagnostic; } -public partial class ProjectContainer(SharpIdeProjectModel project) : GodotObject +public partial class ProjectContainer(SharpIdeProjectModel project) : RefCounted { public SharpIdeProjectModel Project { get; } = project; } \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs b/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs index ced383b..e2383fc 100644 --- a/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs +++ b/src/SharpIDE.Godot/Features/Problems/ProblemsPanel.cs @@ -35,7 +35,7 @@ public partial class ProblemsPanel : Control .Subscribe(s => { GD.Print($"ProblemsPanel: Solution changed to {s?.Name ?? "null"}"); - _projects.Clear(); + _projects.RemoveRange(_projects); _projects.AddRange(s!.AllProjects); }).AddTo(this); BindToTree(_projects); diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/SharpIdeFileGodotContainer.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/SharpIdeFileGodotContainer.cs index 25c96e8..24cfc06 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/SharpIdeFileGodotContainer.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/SharpIdeFileGodotContainer.cs @@ -3,7 +3,7 @@ using SharpIDE.Application.Features.SolutionDiscovery; namespace SharpIDE.Godot.Features.SolutionExplorer; -public partial class SharpIdeFileGodotContainer : GodotObject +public partial class SharpIdeFileGodotContainer : RefCounted { public required SharpIdeFile File { get; init; } } diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs index 2c2127a..746c7be 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs @@ -161,13 +161,6 @@ public partial class SolutionExplorerPanel : MarginContainer fileItem.SetText(0, file.Name); fileItem.SetIcon(0, CsharpFileIcon); var container = new SharpIdeFileGodotContainer { File = file }; - // TODO: Handle ObjectDB instances leaked at exit fileItem.SetMetadata(0, container); } - - - // Called every frame. 'delta' is the elapsed time since the previous frame. - public override void _Process(double delta) - { - } -} \ No newline at end of file +} diff --git a/src/SharpIDE.Godot/IdeWindow.cs b/src/SharpIDE.Godot/IdeWindow.cs index f0b16b2..b072c21 100644 --- a/src/SharpIDE.Godot/IdeWindow.cs +++ b/src/SharpIDE.Godot/IdeWindow.cs @@ -1,7 +1,7 @@ -using Ardalis.GuardClauses; using Godot; using Microsoft.Build.Locator; using Microsoft.Extensions.Hosting; +using SharpIDE.Application.Features.Events; using SharpIDE.Godot.Features.SlnPicker; namespace SharpIDE.Godot; @@ -26,6 +26,16 @@ public partial class IdeWindow : Control PickSolution(true); } + // public override void _ExitTree() + // { + // GodotGlobalEvents.Instance = null!; + // GlobalEvents.Instance = null!; + // GC.Collect(); + // GC.WaitForPendingFinalizers(); + // GC.Collect(); + // PrintOrphanNodes(); + // } + public void PickSolution(bool fullscreen = false) { if (_slnPicker is not null) throw new InvalidOperationException("Solution picker is already active");