Exemple #1
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());
                }
            }
Exemple #2
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());
        }
        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());
        }
Exemple #4
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());
                }
            }
Exemple #5
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());
        }
Exemple #6
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);
        }
Exemple #7
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);
        }
        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 static void ObjectInitializer()
        {
            var code          = @"
namespace N
{
    public class C
    {
        public int Value { get; private set; }

        public static C Create() => new C { Value = 1 };
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            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("Value = 1", walker.All().Single().ToString());
            Assert.AreEqual(true, walker.TrySingle(out var single));
            Assert.AreEqual("Value = 1", single.ToString());
        }
Exemple #10
0
        public static void IgnoresBang()
        {
            var code          = @"
namespace N
{
    public class C
    {
        public C()
        {
            string? value = null;
            var x = value!;
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
            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(true, walker.IsEmpty);
        }
Exemple #11
0
        public static void ObjectInitializer()
        {
            var code          = @"
namespace N
{
    public class C
    {
        private int value;

        public static C Create() => new C { value = 1 };
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            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("value = 1", walker.All().Single().ToString());
                Assert.AreEqual(true, walker.TrySingle(out var single));
                Assert.AreEqual("value = 1", single.ToString());
            }
        }
        private static bool IsUsedAfter(ILocalSymbol local, InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, out IReadOnlyList <Location> locations)
        {
            if (local.TrySingleDeclaration(context.CancellationToken, out var declaration) &&
                declaration.TryFirstAncestor(out BlockSyntax block))
            {
                List <Location> temp = null;
                using (var walker = IdentifierNameWalker.Borrow(block))
                {
                    foreach (var identifierName in walker.IdentifierNames)
                    {
                        if (identifierName.Identifier.ValueText == local.Name &&
                            invocation.IsExecutedBefore(identifierName) == ExecutedBefore.Yes &&
                            context.SemanticModel.TryGetSymbol(identifierName, context.CancellationToken, out ILocalSymbol candidate) &&
                            local.Equals(candidate) &&
                            !IsAssigned(identifierName) &&
                            !IsReassigned(identifierName))
                        {
                            if (temp == null)
                            {
                                temp = new List <Location>();
                            }

                            temp.Add(identifierName.GetLocation());
                        }
                    }

                    locations = temp;
                    return(locations != null);
                }
            }

            locations = null;
            return(false);

            bool IsAssigned(IdentifierNameSyntax identifier)
            {
                switch (identifier.Parent)
                {
                case AssignmentExpressionSyntax assignment:
                    return(assignment.Left == identifier);

                case ArgumentSyntax argument when argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword):
                    return(true);
                }

                return(false);
            }

            bool IsReassigned(ExpressionSyntax location)
            {
                using (var walker = MutationWalker.For(local, context.SemanticModel, context.CancellationToken))
                {
                    foreach (var mutation in walker.All())
                    {
                        if (mutation.TryFirstAncestorOrSelf(out ExpressionSyntax expression) &&
                            invocation.IsExecutedBefore(expression) != ExecutedBefore.No &&
                            expression.IsExecutedBefore(location) != ExecutedBefore.No)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }