public void Emit_NoWork_EmitsDisposeStub()
        {
            // Arrange
            var expectedText =
                @"using System;

namespace TestNamespace
{
    partial class TestClass
    {
        public void Dispose()
        {
        }
    }
}
";

            DisposeWork work = new DisposeWork
            {
                NamespaceName = "TestNamespace",
                ClassName     = "TestClass"
            };

            var writer = new Writer(work);

            // Act
            var actualText = writer.Emit();

            // Assert
            Assert.Equal(expectedText, actualText);
        }
        public void Emit_ClassAccessibility_EmitsDisposeStub(string declaredAccessibility)
        {
            // Arrange
            var space        = declaredAccessibility.Length > 0 ? " " : "";
            var expectedText =
                $@"using System;

namespace TestNamespace
{{
    {declaredAccessibility}{space}partial class TestClass
    {{
        public void Dispose()
        {{
        }}
    }}
}}
";

            DisposeWork work = new DisposeWork
            {
                NamespaceName         = "TestNamespace",
                ClassName             = "TestClass",
                DeclaredAccessibility = declaredAccessibility
            };

            var writer = new Writer(work);

            // Act
            var actualText = writer.Emit();

            // Assert
            Assert.Equal(expectedText, actualText);
        }
        public void HasWork_NonZeroDisposableMembers_ReturnsTrue()
        {
            var work = new DisposeWork()
            {
                DisposableMemberNames = new [] { "Test1", "Test2" }
            };

            Assert.True(work.HasWork);
        }
        public void HasWork_ImplementsUnmanagedTrue_ReturnsTrue()
        {
            var work = new DisposeWork()
            {
                ImplementUnmanaged = true
            };

            Assert.True(work.HasWork);
        }
        public void Emit_DisposableMembersWithUnmanaged_AutoDisposesAndCallsUnmanaged()
        {
            // Arrange
            var expectedText =
                @"using System;

namespace TestNamespace
{
    partial class TestClass
    {
        private bool _isDisposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool isDisposing)
        {
            if (_isDisposed)
            {
                return;
            }

            if (disposing)
            {
                Disposable1.Dispose();
                Disposable2.Dispose();
            }

            DisposeUnmanaged();

            _isDisposed = true;
        }

        ~TestClass() => Dispose(false);
    }
}
";

            DisposeWork work = new DisposeWork
            {
                NamespaceName         = "TestNamespace",
                ClassName             = "TestClass",
                ImplementUnmanaged    = true,
                DisposableMemberNames = new [] { "Disposable1", "Disposable2" }
            };

            var writer = new Writer(work);

            // Act
            var actualText = writer.Emit();

            // Assert
            Assert.Equal(expectedText, actualText);
        }
        public void Emit_BothExplicitDisposers_CallsBothDisposers()
        {
            // Arrange
            var expectedText =
                @"using System;

namespace TestNamespace
{
    partial class TestClass
    {
        private bool _isDisposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool isDisposing)
        {
            if (_isDisposed)
            {
                return;
            }

            if (disposing)
            {
                DisposeManaged();
            }

            DisposeUnmanaged();

            _isDisposed = true;
        }

        ~TestClass() => Dispose(false);
    }
}
";

            DisposeWork work = new DisposeWork
            {
                NamespaceName      = "TestNamespace",
                ClassName          = "TestClass",
                ImplementManaged   = true,
                ImplementUnmanaged = true
            };

            var writer = new Writer(work);

            // Act
            var actualText = writer.Emit();

            // Assert
            Assert.Equal(expectedText, actualText);
        }
        public void Emit_MultipleAutoDisposedMembers_EmitsManagedDisposeOfMembers()
        {
            // Arrange
            var expectedText =
                @"using System;

namespace TestNamespace
{
    partial class TestClass
    {
        private bool _isDisposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool isDisposing)
        {
            if (_isDisposed)
            {
                return;
            }

            if (disposing)
            {
                Member1.Dispose();
                Member2.Dispose();
                Member3.Dispose();
            }

            _isDisposed = true;
        }
    }
}
";

            DisposeWork work = new DisposeWork
            {
                NamespaceName         = "TestNamespace",
                ClassName             = "TestClass",
                DisposableMemberNames = new[] { "Member1", "Member2", "Member3" }
            };

            var writer = new Writer(work);

            // Act
            var actualText = writer.Emit();

            // Assert
            Assert.Equal(expectedText, actualText);
        }
        public void HasWork_DefaultClass_ReturnsFalse()
        {
            var work = new DisposeWork();

            Assert.False(work.HasWork);
        }