Browse Source

Fixes #2913 - remove Disposed views from Responder.instances when Debugging (#2914)

* fix issue #2913

* remove disposed instances from responder.instances (optional)

* Ensures only clear Instances if they really was disposed.

* Fix unit tests.

* Update RunStateTests.cs

Minor format change to trigger new Unittest execution

* Fixes Pos/Dim static fields not being disposing.

---------

Co-authored-by: John Züchler <[email protected]>
Co-authored-by: BDisp <[email protected]>
usr 1 year ago
parent
commit
a8d2f8d733

+ 15 - 41
Terminal.Gui/Core/PosDim.cs

@@ -118,8 +118,6 @@ namespace Terminal.Gui {
 			return new PosFactor (n / 100);
 			return new PosFactor (n / 100);
 		}
 		}
 
 
-		static PosAnchorEnd endNoMargin;
-
 		internal class PosAnchorEnd : Pos {
 		internal class PosAnchorEnd : Pos {
 			int n;
 			int n;
 
 
@@ -137,6 +135,10 @@ namespace Terminal.Gui {
 			{
 			{
 				return $"Pos.AnchorEnd(margin={n})";
 				return $"Pos.AnchorEnd(margin={n})";
 			}
 			}
+
+			public override int GetHashCode () => n.GetHashCode ();
+
+			public override bool Equals (object other) => other is PosAnchorEnd anchorEnd && anchorEnd.n == n;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -158,11 +160,6 @@ namespace Terminal.Gui {
 			if (margin < 0)
 			if (margin < 0)
 				throw new ArgumentException ("Margin must be positive");
 				throw new ArgumentException ("Margin must be positive");
 
 
-			if (margin == 0) {
-				if (endNoMargin == null)
-					endNoMargin = new PosAnchorEnd (0);
-				return endNoMargin;
-			}
 			return new PosAnchorEnd (margin);
 			return new PosAnchorEnd (margin);
 		}
 		}
 
 
@@ -178,8 +175,6 @@ namespace Terminal.Gui {
 			}
 			}
 		}
 		}
 
 
-		static PosCenter pCenter;
-
 		/// <summary>
 		/// <summary>
 		/// Returns a <see cref="Pos"/> object that can be used to center the <see cref="View"/>
 		/// Returns a <see cref="Pos"/> object that can be used to center the <see cref="View"/>
 		/// </summary>
 		/// </summary>
@@ -198,9 +193,7 @@ namespace Terminal.Gui {
 		/// </example>
 		/// </example>
 		public static Pos Center ()
 		public static Pos Center ()
 		{
 		{
-			if (pCenter == null)
-				pCenter = new PosCenter ();
-			return pCenter;
+			return new PosCenter ();
 		}
 		}
 
 
 		internal class PosAbsolute : Pos {
 		internal class PosAbsolute : Pos {
@@ -269,8 +262,6 @@ namespace Terminal.Gui {
 
 
 		}
 		}
 
 
-		static PosCombine posCombine;
-
 		/// <summary>
 		/// <summary>
 		/// Adds a <see cref="Terminal.Gui.Pos"/> to a <see cref="Terminal.Gui.Pos"/>, yielding a new <see cref="Pos"/>.
 		/// Adds a <see cref="Terminal.Gui.Pos"/> to a <see cref="Terminal.Gui.Pos"/>, yielding a new <see cref="Pos"/>.
 		/// </summary>
 		/// </summary>
@@ -280,12 +271,11 @@ namespace Terminal.Gui {
 		public static Pos operator + (Pos left, Pos right)
 		public static Pos operator + (Pos left, Pos right)
 		{
 		{
 			if (left is PosAbsolute && right is PosAbsolute) {
 			if (left is PosAbsolute && right is PosAbsolute) {
-				posCombine = null;
 				return new PosAbsolute (left.Anchor (0) + right.Anchor (0));
 				return new PosAbsolute (left.Anchor (0) + right.Anchor (0));
 			}
 			}
 			PosCombine newPos = new PosCombine (true, left, right);
 			PosCombine newPos = new PosCombine (true, left, right);
 			SetPosCombine (left, newPos);
 			SetPosCombine (left, newPos);
-			return posCombine = newPos;
+			return newPos;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -297,21 +287,18 @@ namespace Terminal.Gui {
 		public static Pos operator - (Pos left, Pos right)
 		public static Pos operator - (Pos left, Pos right)
 		{
 		{
 			if (left is PosAbsolute && right is PosAbsolute) {
 			if (left is PosAbsolute && right is PosAbsolute) {
-				posCombine = null;
 				return new PosAbsolute (left.Anchor (0) - right.Anchor (0));
 				return new PosAbsolute (left.Anchor (0) - right.Anchor (0));
 			}
 			}
 			PosCombine newPos = new PosCombine (false, left, right);
 			PosCombine newPos = new PosCombine (false, left, right);
 			SetPosCombine (left, newPos);
 			SetPosCombine (left, newPos);
-			return posCombine = newPos;
+			return newPos;
 		}
 		}
 
 
 		static void SetPosCombine (Pos left, PosCombine newPos)
 		static void SetPosCombine (Pos left, PosCombine newPos)
 		{
 		{
-			if (posCombine?.ToString () != newPos.ToString ()) {
-				var view = left as PosView;
-				if (view != null) {
-					view.Target.SetNeedsLayout ();
-				}
+			var view = left as PosView;
+			if (view != null) {
+				view.Target.SetNeedsLayout ();
 			}
 			}
 		}
 		}
 
 
@@ -554,8 +541,6 @@ namespace Terminal.Gui {
 			public override bool Equals (object other) => other is DimFill fill && fill.margin == margin;
 			public override bool Equals (object other) => other is DimFill fill && fill.margin == margin;
 		}
 		}
 
 
-		static DimFill zeroMargin;
-
 		/// <summary>
 		/// <summary>
 		/// Initializes a new instance of the <see cref="Dim"/> class that fills the dimension, but leaves the specified number of colums for a margin.
 		/// Initializes a new instance of the <see cref="Dim"/> class that fills the dimension, but leaves the specified number of colums for a margin.
 		/// </summary>
 		/// </summary>
@@ -563,11 +548,6 @@ namespace Terminal.Gui {
 		/// <param name="margin">Margin to use.</param>
 		/// <param name="margin">Margin to use.</param>
 		public static Dim Fill (int margin = 0)
 		public static Dim Fill (int margin = 0)
 		{
 		{
-			if (margin == 0) {
-				if (zeroMargin == null)
-					zeroMargin = new DimFill (0);
-				return zeroMargin;
-			}
 			return new DimFill (margin);
 			return new DimFill (margin);
 		}
 		}
 
 
@@ -618,8 +598,6 @@ namespace Terminal.Gui {
 
 
 		}
 		}
 
 
-		static DimCombine dimCombine;
-
 		/// <summary>
 		/// <summary>
 		/// Adds a <see cref="Terminal.Gui.Dim"/> to a <see cref="Terminal.Gui.Dim"/>, yielding a new <see cref="Dim"/>.
 		/// Adds a <see cref="Terminal.Gui.Dim"/> to a <see cref="Terminal.Gui.Dim"/>, yielding a new <see cref="Dim"/>.
 		/// </summary>
 		/// </summary>
@@ -629,12 +607,11 @@ namespace Terminal.Gui {
 		public static Dim operator + (Dim left, Dim right)
 		public static Dim operator + (Dim left, Dim right)
 		{
 		{
 			if (left is DimAbsolute && right is DimAbsolute) {
 			if (left is DimAbsolute && right is DimAbsolute) {
-				dimCombine = null;
 				return new DimAbsolute (left.Anchor (0) + right.Anchor (0));
 				return new DimAbsolute (left.Anchor (0) + right.Anchor (0));
 			}
 			}
 			DimCombine newDim = new DimCombine (true, left, right);
 			DimCombine newDim = new DimCombine (true, left, right);
 			SetDimCombine (left, newDim);
 			SetDimCombine (left, newDim);
-			return dimCombine = newDim;
+			return newDim;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -646,21 +623,18 @@ namespace Terminal.Gui {
 		public static Dim operator - (Dim left, Dim right)
 		public static Dim operator - (Dim left, Dim right)
 		{
 		{
 			if (left is DimAbsolute && right is DimAbsolute) {
 			if (left is DimAbsolute && right is DimAbsolute) {
-				dimCombine = null;
 				return new DimAbsolute (left.Anchor (0) - right.Anchor (0));
 				return new DimAbsolute (left.Anchor (0) - right.Anchor (0));
 			}
 			}
 			DimCombine newDim = new DimCombine (false, left, right);
 			DimCombine newDim = new DimCombine (false, left, right);
 			SetDimCombine (left, newDim);
 			SetDimCombine (left, newDim);
-			return dimCombine = newDim;
+			return newDim;
 		}
 		}
 
 
 		static void SetDimCombine (Dim left, DimCombine newPos)
 		static void SetDimCombine (Dim left, DimCombine newPos)
 		{
 		{
-			if (dimCombine?.ToString () != newPos.ToString ()) {
-				var view = left as DimView;
-				if (view != null) {
-					view.Target.SetNeedsLayout ();
-				}
+			var view = left as DimView;
+			if (view != null) {
+				view.Target.SetNeedsLayout ();
 			}
 			}
 		}
 		}
 
 

+ 6 - 2
Terminal.Gui/Core/Responder.cs

@@ -15,7 +15,7 @@
 
 
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Diagnostics;
+using System.Linq;
 using System.Reflection;
 using System.Reflection;
 
 
 namespace Terminal.Gui {
 namespace Terminal.Gui {
@@ -255,7 +255,7 @@ namespace Terminal.Gui {
 			}
 			}
 			return m.GetBaseDefinition ().DeclaringType != m.DeclaringType;
 			return m.GetBaseDefinition ().DeclaringType != m.DeclaringType;
 		}
 		}
-		
+
 		/// <summary>
 		/// <summary>
 		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 		/// </summary>
 		/// </summary>
@@ -291,6 +291,10 @@ namespace Terminal.Gui {
 			GC.SuppressFinalize (this);
 			GC.SuppressFinalize (this);
 #if DEBUG_IDISPOSABLE
 #if DEBUG_IDISPOSABLE
 			WasDisposed = true;
 			WasDisposed = true;
+
+			foreach (var instance in Instances.Where (x => x.WasDisposed).ToList ()) {
+				Instances.Remove (instance);
+			}
 #endif
 #endif
 		}
 		}
 	}
 	}

+ 4 - 0
Terminal.Gui/Core/View.cs

@@ -2934,6 +2934,10 @@ namespace Terminal.Gui {
 		/// <inheritdoc/>
 		/// <inheritdoc/>
 		protected override void Dispose (bool disposing)
 		protected override void Dispose (bool disposing)
 		{
 		{
+			height = null;
+			width = null;
+			x = null;
+			y = null;
 			for (var i = InternalSubviews.Count - 1; i >= 0; i--) {
 			for (var i = InternalSubviews.Count - 1; i >= 0; i--) {
 				var subview = InternalSubviews [i];
 				var subview = InternalSubviews [i];
 				Remove (subview);
 				Remove (subview);

+ 1 - 2
UnitTests/Application/ApplicationTests.cs

@@ -91,8 +91,7 @@ namespace Terminal.Gui.ApplicationTests {
 			Application.Shutdown ();
 			Application.Shutdown ();
 
 
 #if DEBUG_IDISPOSABLE
 #if DEBUG_IDISPOSABLE
-			Assert.Single (Responder.Instances);
-			Assert.True (Responder.Instances [0].WasDisposed);
+			Assert.Empty (Responder.Instances);
 #endif
 #endif
 		}
 		}
 
 

+ 1 - 0
UnitTests/Application/RunStateTests.cs

@@ -63,6 +63,7 @@ namespace Terminal.Gui.ApplicationTests {
 		void Init ()
 		void Init ()
 		{
 		{
 			Application.Init (new FakeDriver ());
 			Application.Init (new FakeDriver ());
+			
 			Assert.NotNull (Application.Driver);
 			Assert.NotNull (Application.Driver);
 			Assert.NotNull (Application.MainLoop);
 			Assert.NotNull (Application.MainLoop);
 			Assert.NotNull (SynchronizationContext.Current);
 			Assert.NotNull (SynchronizationContext.Current);

+ 2 - 6
UnitTests/TopLevels/MdiTests.cs

@@ -32,9 +32,7 @@ namespace Terminal.Gui.TopLevelTests {
 			Application.Shutdown ();
 			Application.Shutdown ();
 
 
 #if DEBUG_IDISPOSABLE
 #if DEBUG_IDISPOSABLE
-			Assert.Equal (2, Responder.Instances.Count);
-			Assert.True (Responder.Instances [0].WasDisposed);
-			Assert.True (Responder.Instances [1].WasDisposed);
+			Assert.Empty (Responder.Instances);
 #endif
 #endif
 		}
 		}
 
 
@@ -49,9 +47,7 @@ namespace Terminal.Gui.TopLevelTests {
 
 
 			Application.Shutdown ();
 			Application.Shutdown ();
 #if DEBUG_IDISPOSABLE
 #if DEBUG_IDISPOSABLE
-			Assert.Equal (2, Responder.Instances.Count);
-			Assert.True (Responder.Instances [0].WasDisposed);
-			Assert.True (Responder.Instances [1].WasDisposed);
+			Assert.Empty (Responder.Instances);
 #endif
 #endif
 		}
 		}