diff --git a/MetadataProcessor.Shared/Tables/nanoMethodDefinitionTable.cs b/MetadataProcessor.Shared/Tables/nanoMethodDefinitionTable.cs
index 70df0509..2ee60fb0 100644
--- a/MetadataProcessor.Shared/Tables/nanoMethodDefinitionTable.cs
+++ b/MetadataProcessor.Shared/Tables/nanoMethodDefinitionTable.cs
@@ -242,6 +242,13 @@ public static uint GetFlags(MethodDefinition method)
flag |= (method.IsStatic ? MD_StaticConstructor : MD_Constructor);
}
+ if(method.Name == "Finalize"
+ && method.ReturnType.FullName == "System.Void"
+ && method.Parameters.Count == 0)
+ {
+ flag |= MD_Finalizer;
+ }
+
if (method.IsSynchronized)
{
flag |= MD_Synchronized;
diff --git a/MetadataProcessor.Tests/Core/Tables/nanoMethodDefinitionTableTests.cs b/MetadataProcessor.Tests/Core/Tables/nanoMethodDefinitionTableTests.cs
index d673e4d2..e2e19b0e 100644
--- a/MetadataProcessor.Tests/Core/Tables/nanoMethodDefinitionTableTests.cs
+++ b/MetadataProcessor.Tests/Core/Tables/nanoMethodDefinitionTableTests.cs
@@ -5,6 +5,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mono.Cecil;
+using System.Linq;
namespace nanoFramework.Tools.MetadataProcessor.Tests.Core.Tables
{
@@ -12,12 +13,18 @@ namespace nanoFramework.Tools.MetadataProcessor.Tests.Core.Tables
public class nanoMethodDefinitionTableTests
{
private TypeDefinition _testDelegatesClassTypeDefinition;
+ private TypeDefinition _destructorTestClassTypeDefinition;
+ private TypeDefinition _destructorAnotherTestClassTypeDefinition;
+ private TypeDefinition _destructorAnotherBaseClassTypeDefinition;
[TestInitialize]
public void Setup()
{
var nanoTablesContext = TestObjectHelper.GetTestNFAppNanoTablesContext();
_testDelegatesClassTypeDefinition = TestObjectHelper.GetTestNFAppTestingDelegatesTypeDefinition(nanoTablesContext.AssemblyDefinition);
+ _destructorTestClassTypeDefinition = TestObjectHelper.GetTestNFAppDestructorsTestClassTypeDefinition(nanoTablesContext.AssemblyDefinition);
+ _destructorAnotherTestClassTypeDefinition = TestObjectHelper.GetTestNFAppDestructorsTestAnotherClassTypeDefinition(nanoTablesContext.AssemblyDefinition);
+ _destructorAnotherBaseClassTypeDefinition = TestObjectHelper.GetTestNFAppDestructorsTestAnotherClassBaseTypeDefinition(nanoTablesContext.AssemblyDefinition);
}
#region delegate method flags
@@ -75,5 +82,45 @@ public void TestDelegateEndInvokeMethodReturnsDelegateEndInvokeFlag()
}
#endregion
+
+ #region finalizer method flags
+
+ [DataRow("DestructorsTestClass")]
+ [DataRow("DestructorsTestAnotherClass")]
+ [DataRow("DestructorsTestAnotherClassBase")]
+ [TestMethod]
+ public void TestFinalizerMethodReturnsFinalizerFlag(string className)
+ {
+ // Arrange
+ MethodDefinition methodDefinition = null;
+
+ if (className == "DestructorsTestClass")
+ {
+ methodDefinition = _destructorTestClassTypeDefinition.Methods.First(m => m.Name == "Finalize");
+ }
+ else if (className == "DestructorsTestAnotherClass")
+ {
+ methodDefinition = _destructorAnotherTestClassTypeDefinition.Methods.First(m => m.Name == "Finalize");
+ }
+ else if (className == "DestructorsTestAnotherClassBase")
+ {
+ methodDefinition = _destructorAnotherBaseClassTypeDefinition.Methods.First(m => m.Name == "Finalize");
+ }
+ else
+ {
+ Assert.Fail("Invalid class name.");
+ }
+
+ Assert.IsNotNull(methodDefinition, "Finalizer method not found.");
+
+ // Act
+ uint flags = nanoMethodDefinitionTable.GetFlags(methodDefinition);
+
+ // Assert
+ const uint expectedFlag = 0x00004000; // MD_Finalizer
+ Assert.IsTrue((flags & expectedFlag) == expectedFlag, "Expected flag not set for Finalizer method.");
+ }
+
+ #endregion
}
}
diff --git a/MetadataProcessor.Tests/TestNFApp/TestNFApp.nfproj b/MetadataProcessor.Tests/TestNFApp/TestNFApp.nfproj
index 601594f3..04374fb8 100644
--- a/MetadataProcessor.Tests/TestNFApp/TestNFApp.nfproj
+++ b/MetadataProcessor.Tests/TestNFApp/TestNFApp.nfproj
@@ -32,6 +32,7 @@
+
diff --git a/MetadataProcessor.Tests/TestNFApp/TestingDestructors.cs b/MetadataProcessor.Tests/TestNFApp/TestingDestructors.cs
new file mode 100644
index 00000000..dd34d0d5
--- /dev/null
+++ b/MetadataProcessor.Tests/TestNFApp/TestingDestructors.cs
@@ -0,0 +1,133 @@
+//
+// Copyright (c) .NET Foundation and Contributors
+// See LICENSE file in the project root for full license information.
+//
+
+using System;
+
+namespace TestNFApp
+{
+ public class TestingDestructors
+ {
+ public TestingDestructors()
+ {
+ Console.WriteLine("Test Destructors class 3");
+
+ if (DestructorsTestClass.TestMethod())
+ {
+ Console.WriteLine("Test Destructors class 3 passed!");
+ }
+ else
+ {
+ Console.WriteLine("Test Destructors class 3 failed!");
+ }
+
+ Console.WriteLine("Test Destructors class 4");
+ if (DestructorsTestAnotherClass.TestMethod())
+ {
+ Console.WriteLine("Test Destructors class 4 passed!");
+ }
+ else
+ {
+ Console.WriteLine("Test Destructors class 4 failed!");
+ }
+
+ Console.WriteLine("Test destructors completed!");
+ }
+ }
+
+ public class DestructorsTestClass
+ {
+ static int intI = 1;
+
+ ~DestructorsTestClass()
+ {
+ // Calling Destructor for Test Class 3
+ intI = 2;
+
+ Console.WriteLine("Calling Destructor for Test Class 3");
+ }
+
+ public static bool TestMethod()
+ {
+ DestructorsTestClass mc = new DestructorsTestClass();
+ mc = null;
+
+ // should be calling GC
+ // nanoFramework.Runtime.Native.GC.Run(true);
+
+ int sleepTime = 5000;
+ int slept = 0;
+
+ while (intI != 2 && slept < sleepTime)
+ {
+ System.Threading.Thread.Sleep(10);
+ slept += 10;
+ }
+
+ // Thread has slept for
+ Console.WriteLine($"Thread has slept for {slept}");
+
+ if (intI == 2)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ public class DestructorsTestAnotherClassBase
+ {
+ public static int intI = 2;
+
+ ~DestructorsTestAnotherClassBase()
+ {
+ intI = intI * 2;
+
+ Console.WriteLine("Calling Destructor for Test Class 4 Base");
+ }
+ }
+
+ public class DestructorsTestAnotherClass : DestructorsTestAnotherClassBase
+ {
+ ~DestructorsTestAnotherClass()
+ {
+ intI = intI + 2;
+
+ Console.WriteLine("Calling Destructor for Test Class 4");
+ }
+
+ public static bool TestMethod()
+ {
+ DestructorsTestAnotherClass mc = new DestructorsTestAnotherClass();
+
+ mc = null;
+
+ // should be calling GC
+ // nanoFramework.Runtime.Native.GC.Run(true);
+
+ int sleepTime = 5000;
+ int slept = 0;
+
+ while (intI != 8 && slept < sleepTime)
+ {
+ System.Threading.Thread.Sleep(10);
+ slept += 10;
+ }
+
+ Console.WriteLine($"Thread has slept for {slept}");
+
+ if (intI == 8)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/MetadataProcessor.Tests/TestObjectHelper.cs b/MetadataProcessor.Tests/TestObjectHelper.cs
index 863e875d..d4366e9b 100644
--- a/MetadataProcessor.Tests/TestObjectHelper.cs
+++ b/MetadataProcessor.Tests/TestObjectHelper.cs
@@ -385,6 +385,46 @@ internal static TypeDefinition GetTestNFAppTestingDelegatesTypeDefinition(Assemb
return ret;
}
+ internal static TypeDefinition GetTestNFAppTestingDestructorsTypeDefinition(AssemblyDefinition assemblyDefinition)
+ {
+ TypeDefinition ret = null;
+
+ var module = assemblyDefinition.Modules[0];
+ ret = module.Types.First(i => i.FullName == "TestNFApp.TestingDestructors");
+
+ return ret;
+ }
+
+ internal static TypeDefinition GetTestNFAppDestructorsTestClassTypeDefinition(AssemblyDefinition assemblyDefinition)
+ {
+ TypeDefinition ret = null;
+
+ var module = assemblyDefinition.Modules[0];
+ ret = module.Types.First(i => i.FullName == "TestNFApp.DestructorsTestClass");
+
+ return ret;
+ }
+
+ internal static TypeDefinition GetTestNFAppDestructorsTestAnotherClassBaseTypeDefinition(AssemblyDefinition assemblyDefinition)
+ {
+ TypeDefinition ret = null;
+
+ var module = assemblyDefinition.Modules[0];
+ ret = module.Types.First(i => i.FullName == "TestNFApp.DestructorsTestAnotherClassBase");
+
+ return ret;
+ }
+
+ internal static TypeDefinition GetTestNFAppDestructorsTestAnotherClassTypeDefinition(AssemblyDefinition assemblyDefinition)
+ {
+ TypeDefinition ret = null;
+
+ var module = assemblyDefinition.Modules[0];
+ ret = module.Types.First(i => i.FullName == "TestNFApp.DestructorsTestAnotherClass");
+
+ return ret;
+ }
+
internal static MethodDefinition GetMethodDefinition(
TypeDefinition typeDefinition,
string delegateName,
@@ -393,5 +433,12 @@ internal static MethodDefinition GetMethodDefinition(
var delegateType = typeDefinition.NestedTypes.First(nt => nt.Name == delegateName);
return delegateType.Methods.First(m => m.Name == methodName);
}
+
+ internal static MethodDefinition GetMethodDefinition(
+ TypeDefinition typeDefinition,
+ string methodName)
+ {
+ return typeDefinition.Methods.First(m => m.Name == methodName);
+ }
}
}