public void InitializedWithConstant(string code)
            {
                var testCode = @"
namespace RoslynSandbox
{
    internal class Foo
    {
        private const int Value = 2;

        internal Foo()
        {
            var value = 1;
            var temp = value;
        }
    }
}";

                testCode = testCode.AssertReplace("1", code);
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause("var temp = value;").Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(code, actual);
                }
            }
示例#2
0
        public static void One(string mutation)
        {
            var code = @"
namespace N
{
    public class C
    {
        public C()
        {
            this.Value = 1;
        }

        public int Value { get; }
    }
}";

            code = code.AssertReplace("this.Value = 1", mutation);
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var property      = semanticModel.GetDeclaredSymbol(syntaxTree.FindPropertyDeclaration("Value"));

            using var walker = MutationWalker.For(property, semanticModel, CancellationToken.None);
            Assert.AreEqual(mutation, walker.All().Single().ToString());
            Assert.AreEqual(true, walker.TrySingle(out var single));
            Assert.AreEqual(mutation, single.ToString());
        }
示例#3
0
        public void AutoPropertyGetOnlyAssignedInCtor(string code, string expected)
        {
            var syntaxTree    = CSharpSyntaxTree.ParseText(@"
public sealed class Foo
{
    public Foo()
    {
        var temp1 = this.Bar;
        this.Bar = 2;
        var temp2 = this.Bar;
    }

    public int Bar { get; } = 1;

    public void Meh()
    {
        var temp3 = this.Bar;
    }
}");
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindEqualsValueClause(code).Value;

            using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
            {
                var actual = string.Join(", ", pooled);
                Assert.AreEqual(expected, actual);
            }
        }
            public void FieldPublicCtorFactory(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    public int value = 1;

    public Foo(int ctorArg)
    {
        var temp1 = this.value;
        this.value = ctorArg;
        var temp2 = this.value;
    }

    internal static Foo Create()
    {
        return new Foo(2);
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
            public void LocalAssignedWithOutParameterGeneric()
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo<T>
{
    internal Foo()
    {
        T value;
        Assign(out value);
        var temp = value;
    }

    internal void Assign(out T outValue)
    {
        outValue = default(T);
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause("var temp = value;").Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
#pragma warning disable GU0006 // Use nameof.
                    Assert.AreEqual("value", actual);
#pragma warning restore GU0006 // Use nameof.
                }
            }
示例#6
0
        public static void Out()
        {
            var code          = @"
namespace N
{
    public class C
    {
        private int value;

        public C()
        {
            Update(out this.value);
        }

        private static void Update(out int field)
        {
            field = 1;
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var field         = (IFieldSymbol)semanticModel.GetDeclaredSymbol(syntaxTree.Find <VariableDeclaratorSyntax>("value"));

            using var walker = MutationWalker.For(field, semanticModel, CancellationToken.None);
            Assert.AreEqual("out this.value", walker.All().Single().ToString());
            Assert.AreEqual(true, walker.TrySingle(out var single));
            Assert.AreEqual("out this.value", single.ToString());
        }
示例#7
0
        public void Single(string mutation)
        {
            var testCode = @"
namespace RoslynSandbox
{
    public class Foo
    {
        private int value;

        public Foo()
        {
            this.value = 1;
        }
    }
}";

            testCode = testCode.AssertReplace("this.value = 1", mutation);
            var syntaxTree       = CSharpSyntaxTree.ParseText(testCode);
            var compilation      = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel    = compilation.GetSemanticModel(syntaxTree);
            var classDeclaration = syntaxTree.FindClassDeclaration("Foo");

            using (var walker = MutationWalker.Borrow(classDeclaration, Scope.Instance, semanticModel, CancellationToken.None))
            {
                Assert.AreEqual(mutation, walker.All().Single().ToString());
                Assert.AreEqual(true, walker.TrySingle(out var single));
                Assert.AreEqual(mutation, single.ToString());
            }
        }
        public static void OneRefOrOut(string modifier)
        {
            var code = @"
namespace N
{
    public class C
    {
        private int value;

        public C()
        {
            Mutate(out this.value);
        }

        private static void Mutate(out int i)
        {
            i = 1;
        }
    }
}";

            code = code.AssertReplace("out", modifier);
            var syntaxTree       = CSharpSyntaxTree.ParseText(code);
            var compilation      = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
            var semanticModel    = compilation.GetSemanticModel(syntaxTree);
            var classDeclaration = syntaxTree.FindClassDeclaration("C");

            using var walker = MutationWalker.Borrow(classDeclaration, SearchScope.Type, semanticModel, CancellationToken.None);
            CollectionAssert.IsEmpty(walker.PrefixUnaries);
            CollectionAssert.IsEmpty(walker.PostfixUnaries);
            CollectionAssert.AreEqual(new[] { $"{modifier} this.value" }, walker.RefOrOutArguments.Select(x => x.ToString()));
            CollectionAssert.AreEqual(new[] { "i = 1" }, walker.Assignments.Select(x => x.ToString()));
            CollectionAssert.AreEqual(new[] { "i = 1", $"{modifier} this.value" }, walker.All().Select(x => x.ToString()));
        }
示例#9
0
        public static void One(string mutation)
        {
            var code = @"
namespace N
{
    public class C
    {
        public C()
        {
            var value = 0;
            value = 1;
        }
    }
}";

            code = code.AssertReplace("value = 1", mutation);
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var symbol        = (ILocalSymbol)semanticModel.GetDeclaredSymbol(syntaxTree.Find <VariableDeclaratorSyntax>("value"));

            using var walker = MutationWalker.For(symbol, semanticModel, CancellationToken.None);
            Assert.AreEqual(mutation, walker.All().Single().ToString());
            Assert.AreEqual(true, walker.TrySingle(out var single));
            Assert.AreEqual(mutation, single.ToString());
        }
示例#10
0
            public void Ref()
            {
                var testCode      = @"
namespace RoslynSandbox
{
    public class Foo
    {
        private int value;

        public Foo()
        {
            Update(ref this.value);
        }

        private static void Update(ref int field)
        {
            field++;
        }
    }
}";
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var field         = (IFieldSymbol)semanticModel.GetDeclaredSymbol(syntaxTree.Find <VariableDeclaratorSyntax>("value"));

                using (var walker = MutationWalker.For(field, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual("ref this.value", walker.All().Single().ToString());
                    Assert.AreEqual(true, walker.TrySingle(out var single));
                    Assert.AreEqual("ref this.value", single.ToString());
                }
            }
        public static void One(string mutation)
        {
            var code = @"
namespace N
{
    public class C
    {
        private int value;

        public C()
        {
            this.value = 1;
        }
    }
}";

            code = code.AssertReplace("this.value = 1", mutation);
            var syntaxTree       = CSharpSyntaxTree.ParseText(code);
            var compilation      = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
            var semanticModel    = compilation.GetSemanticModel(syntaxTree);
            var classDeclaration = syntaxTree.FindClassDeclaration("C");

            using var walker = MutationWalker.Borrow(classDeclaration, SearchScope.Instance, semanticModel, CancellationToken.None);
            Assert.AreEqual(mutation, walker.All().Single().ToString());
            Assert.AreEqual(true, walker.TrySingle(out var single));
            Assert.AreEqual(mutation, single.ToString());
        }
示例#12
0
        public void BackingFieldPrivateSetSimple()
        {
            var syntaxTree    = CSharpSyntaxTree.ParseText(@"
namespace RoslynSandbox
{
    public sealed class Foo
    {
        private int bar;

        public int Bar
        {
            get { return this.bar; }
            private set { this.bar = value; }
        }

        public void Meh()
        {
            var temp = this.bar;
        }
    }
}");
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindEqualsValueClause("var temp = this.bar").Value;

            using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
            {
                var actual = string.Join(", ", pooled);
                Assert.AreEqual(string.Empty, actual);
            }
        }
            public void FieldCtorArgThenIdMethod(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    private readonly int value;

    internal Foo(int arg)
    {
        var temp1 = this.value;
        this.value = Id(arg);
        var temp2 = this.value;
    }

    internal void Bar(int arg)
    {
        var temp3 = this.value;
    }

    private static T Id(T genericArg) => genericArg;
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
示例#14
0
        internal static bool TryGetSingle(IPropertySymbol property, SemanticModel semanticModel, CancellationToken cancellationToken, out ExpressionSyntax expression)
        {
            expression = null;
            if (property.IsGetOnly() &&
                property.TrySingleDeclaration(cancellationToken, out PropertyDeclarationSyntax declaration))
            {
                using (var walker = MutationWalker.For(property, semanticModel, cancellationToken))
                {
                    if (walker.IsEmpty)
                    {
                        expression = declaration.Initializer?.Value;
                        return(expression != null);
                    }

                    if (declaration.Initializer == null &&
                        walker.TrySingle(out var node) &&
                        node.Parent is AssignmentExpressionSyntax assignment)
                    {
                        expression = assignment.Right;
                        return(expression != null);
                    }

                    return(false);
                }
            }

            return(false);
        }
示例#15
0
        internal static bool TryGetSingle(ILocalSymbol local, SemanticModel semanticModel, CancellationToken cancellationToken, out ExpressionSyntax expression)
        {
            expression = null;
            if (local.TrySingleDeclaration(cancellationToken, out VariableDeclarationSyntax declaration) &&
                declaration.Variables.TrySingle(out var variable))
            {
                using (var walker = MutationWalker.For(local, semanticModel, cancellationToken))
                {
                    if (walker.IsEmpty)
                    {
                        expression = variable.Initializer?.Value;
                        return(expression != null);
                    }

                    if (variable.Initializer == null &&
                        walker.TrySingle(out var node) &&
                        node.Parent is AssignmentExpressionSyntax assignment)
                    {
                        expression = assignment.Right;
                        return(expression != null);
                    }

                    return(false);
                }
            }

            return(false);
        }
            public void InitializedInChainedWithLiteralGeneric(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo<T>
{
    internal Foo()
    {
        this.Value = 2;
    }

    internal Foo(string text)
        : this()
    {
        this.Value = 3;
        var temp1 = this.Value;
        this.Value = 4;
    }

    public int Value { get; set; } = 1;

    internal void Bar()
    {
        var temp2 = this.Value;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
            public void LocalAssignedWithRefParameter(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    internal Foo()
    {
        int value;
        var temp1 = value;
        Assign(ref value);
        var temp2 = value;
    }

    internal void Assign(ref int value)
    {
        value = 1;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
            public void FieldInitializedlWithLiteralAndAssignedInCtor(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    private readonly int value = 1;
    private readonly int temp1 = this.value;

    internal Foo()
    {
        var temp1 = this.value;
        var temp2 = this.temp1;
        this.value = 2;
        var temp3 = this.value;
        var temp4 = this.temp1;
    }

    internal void Bar()
    {
        var temp5 = this.value;
        var temp6 = this.temp1;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
示例#19
0
            public void Single(string mutation)
            {
                var testCode = @"
namespace RoslynSandbox
{
    public class Foo
    {
        public Foo()
        {
            this.Value = 1;
        }

        public int Value { get; }
    }
}";

                testCode = testCode.AssertReplace("this.Value = 1", mutation);
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var property      = semanticModel.GetDeclaredSymbol(syntaxTree.FindPropertyDeclaration("Value"));

                using (var walker = MutationWalker.For(property, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual(mutation, walker.All().Single().ToString());
                    Assert.AreEqual(true, walker.TrySingle(out var single));
                    Assert.AreEqual(mutation, single.ToString());
                }
            }
            public void InitializedListOfIntIndexerAfterAddItem(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
namespace RoslynSandbox
{
    using System.Collections.Generic;

    internal class Foo
    {
        internal Foo()
        {
            var ints = new List<int> { 1, 2 };
            var temp1 = ints[0];
            ints.Add(3);
            var temp2 = ints[0];
        }
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code)
                                    .Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
示例#21
0
        public void BackingFieldPublicSetInitializedAndPropertyAssignedInCtorWeirdSetter(string code, string expected)
        {
            var syntaxTree    = CSharpSyntaxTree.ParseText(@"
namespace RoslynSandbox
{
    public sealed class Foo
    {
        private int bar = 1;

        public Foo()
        {
            var temp1 = this.bar;
            var temp2 = this.Bar;
            this.Bar = 2;
            var temp3 = this.bar;
            var temp4 = this.Bar;
        }

        public int Bar
        {
            get { return this.bar; }
            set
            {
                if (true)
                {
                    this.bar = value;
                }
                else
                {
                    this.bar = value;
                }

                this.bar = value / 2;
                this.bar = 3;
            }
        }

        public void Meh()
        {
            var temp5 = this.bar;
            var temp6 = this.Bar;
        }
    }
}");
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindEqualsValueClause(code).Value;

            using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
            {
                var actual = string.Join(", ", pooled);
                Assert.AreEqual(expected, actual);
            }
        }
            public void AutoPropertyChainedCtor(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    internal Foo()
    {
        var temp1 = this.Value;
        this.Value = 2;
        var temp2 = this.Value;
        this.Bar(3);
        var temp3 = this.Value;
    }

    internal Foo(string text)
        : this()
    {
        var temp4 = this.Value;
        this.Value = 4;
        var temp5 = this.Value;
        this.Value = 5;
        var temp6 = this.Value;
        this.Bar(6);
        var temp7 = this.Value;
        this.Bar(7);
        var temp8 = this.Value;
    }

    public int Value { get; set; } = 1;

    internal void Bar(int arg)
    {
        var temp9 = this.Value;
        this.Value = 8;
        var temp10 = this.Value;
        this.Value = arg;
        var temp11 = this.Value;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
            public void AssignedInLock()
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
namespace RoslynSandbox
{
    using System;

    public class Foo : IDisposable
    {
        private readonly object gate;

        public IDisposable disposable;
        private bool disposed;

        public void Dispose()
        {
            if (this.disposed)
            {
                return;
            }

            var toDispose = (IDisposable)null;
            lock (this.gate)
            {
                if (this.disposed)
                {
                    return;
                }

                this.disposed = true;
                toDispose = this.disposable;
                this.disposable = null;
            }

            var temp = toDispose;
        }
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause("var temp = toDispose;").Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual("(IDisposable)null, this.disposable", actual);
                }
            }
            public void FieldImplicitBaseWhenSubclassHasCtor(string code, object expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class FooBase
{
    protected readonly int value = 1;

    internal FooBase()
    {
        var temp1 = this.value;
        this.value = 2;
        var temp2 = this.value;
    }
}

internal class Foo : FooBase
{
    internal Foo()
    {
        var temp3 = this.value;
        this.value = 3;
        var temp4 = this.value;
        this.value = 4;
        var temp5 = this.value;
    }

    internal void Bar(int arg)
    {
        var temp6 = this.value;
        this.value = 5;
        var temp7 = this.value;
        this.value = arg;
        var temp8 = this.value;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
            public void FieldCtorCallingProtectedInitializeMethod(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    public int value = 1;

    internal Foo()
    {
        var temp1 = this.value;
        this.Initialize(2);
        var temp4 = this.value;
        this.value = 3;
        var temp5 = this.value;
        this.Initialize(4);
        var temp6 = this.value;
    }

    internal void Bar(int arg)
    {
        var temp7 = this.value;
        this.value = 5;
        var temp8 = this.value;
        this.value = arg;
        var temp9 = this.value;
    }

    protected void Initialize(int initArg)
    {
        var temp2 = this.value;
        this.value = initArg;
        var temp3 = this.value;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
            public void InitializedInExplicitBaseCtorWithLiteral(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class FooBase
{
    protected readonly int value = 1;
    
    public FooBase()
    {
        this.value = -1;
    }

    public FooBase(int value)
    {
        this.value = value;
    }
}

internal class Foo : FooBase
{
    internal Foo()
        :base(2)
    {
        this.value = 3;
        var temp1 = this.value;
        this.value = 4;
    }

    internal void Bar()
    {
        var temp2 = this.value;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }
        private static bool IsPreferUsing(ILocalSymbol local, InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context)
        {
            return(local.TrySingleDeclaration(context.CancellationToken, out var declaration) &&
                   declaration is VariableDeclaratorSyntax declarator &&
                   declaration.TryFirstAncestor(out LocalDeclarationStatementSyntax localDeclarationStatement) &&
                   invocation.TryFirstAncestor(out ExpressionStatementSyntax expressionStatement) &&
                   (DeclarationIsAssignment() || IsTrivialTryFinally()) &&
                   !IsMutated());

            bool DeclarationIsAssignment()
            {
                return(localDeclarationStatement.Parent == expressionStatement.Parent &&
                       Disposable.IsCreation(declarator.Initializer?.Value, context.SemanticModel, context.CancellationToken) == Result.Yes);
            }

            bool IsTrivialTryFinally()
            {
                return(expressionStatement.Parent is BlockSyntax block &&
                       block.Statements.Count == 1 &&
                       block.Parent is FinallyClauseSyntax finallyClause &&
                       finallyClause.Parent is TryStatementSyntax tryStatement &&
                       !tryStatement.Catches.Any());
            }

            bool IsMutated()
            {
                using (var walker = MutationWalker.For(local, context.SemanticModel, context.CancellationToken))
                {
                    if (declarator.Initializer?.Value.IsKind(SyntaxKind.NullLiteralExpression) == true &&
                        walker.TrySingle(out var mutation) &&
                        mutation.TryFirstAncestor(out ExpressionStatementSyntax statement) &&
                        statement.Parent is BlockSyntax block &&
                        block.Statements[0] == statement &&
                        block.Parent is TryStatementSyntax)
                    {
                        return(false);
                    }

                    return(walker.All().Any());
                }
            }
        }
            public void AssignedWithArgGenericMethod()
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo
{
    internal Foo<T>(T meh)
    {
        var temp = meh;
        var value = temp;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause("var value = temp").Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual("meh", actual);
                }
            }
            public void InitializedWithDefaultGeneric()
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
internal class Foo<T>
{
    internal Foo()
    {
        var value = default(T);
        var temp = value;
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause("var temp = value;").Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual("default(T)", actual);
                }
            }
            public void FieldAssignedWithRefParameterArgument(string code, string expected)
            {
                var syntaxTree    = CSharpSyntaxTree.ParseText(@"
namespace RoslynSandbox
{
    internal class Foo
    {
        private int value = 1;

        public Foo()
        {
            var temp1 = this.value;
            this.Assign(ref this.value, 2);
            var temp2 = this.value;
        }

        internal void Bar()
        {
            var temp3 = this.value;
            this.Assign(ref this.value, 3);
            var temp4 = this.value;
        }

        private void Assign(ref int refValue, int arg)
        {
            refValue = arg;
        }
    }
}");
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindEqualsValueClause(code).Value;

                using (var pooled = MutationWalker.Borrow(value, semanticModel, CancellationToken.None))
                {
                    var actual = string.Join(", ", pooled);
                    Assert.AreEqual(expected, actual);
                }
            }