コード例 #1
0
        private static bool TryGetAssignedFieldOrProperty(ArgumentSyntax argument, IMethodSymbol method, SemanticModel semanticModel, CancellationToken cancellationToken, out ISymbol member)
        {
            member = null;
            if (method == null)
            {
                return(false);
            }

            if (method.TrySingleDeclaration(cancellationToken, out BaseMethodDeclarationSyntax methodDeclaration) &&
                methodDeclaration.TryFindParameter(argument, out var parameter))
            {
                var parameterSymbol = semanticModel.GetDeclaredSymbolSafe(parameter, cancellationToken);
                if (AssignmentExecutionWalker.FirstWith(parameterSymbol, methodDeclaration.Body, Scope.Member, semanticModel, cancellationToken, out var assignment))
                {
                    member = semanticModel.GetSymbolSafe(assignment.Left, cancellationToken);
                    if (member is IFieldSymbol ||
                        member is IPropertySymbol)
                    {
                        return(true);
                    }
                }

                if (methodDeclaration is ConstructorDeclarationSyntax ctor &&
                    ctor.Initializer is ConstructorInitializerSyntax initializer &&
                    initializer.ArgumentList != null &&
                    initializer.ArgumentList.Arguments.TrySingle(x => x.Expression is IdentifierNameSyntax identifier && identifier.Identifier.ValueText == parameter.Identifier.ValueText, out var chainedArgument))
                {
                    var chained = semanticModel.GetSymbolSafe(ctor.Initializer, cancellationToken);
                    return(TryGetAssignedFieldOrProperty(chainedArgument, chained, semanticModel, cancellationToken, out member));
                }
            }

            return(false);
        }
コード例 #2
0
        public static void FieldCtorArgInNested(SearchScope scope)
        {
            var code          = @"
namespace N
{
    using System.IO;

    internal class C
    {
        private StreamReader reader;

        internal C(Stream stream)
        {
            this.reader = new StreamReader(stream);
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindParameter("stream");
            var ctor          = syntaxTree.FindConstructorDeclaration("C(Stream stream)");
            var symbol        = semanticModel.GetDeclaredSymbol(value, CancellationToken.None);

            Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
            Assert.AreEqual("this.reader = new StreamReader(stream)", result.ToString());
            using var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None);
            Assert.AreEqual("this.reader = new StreamReader(stream)", walker.Assignments.Single().ToString());
        }
コード例 #3
0
        public static void GenericFieldTypedCtorArg(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C<T>
    {
        private readonly T value;

        internal C(T arg)
        {
            this.value = arg;
        }

         public static C<int> Create(int n) => new C<int>(n);
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var argument      = syntaxTree.FindArgument("n");

            Assert.AreEqual(true, semanticModel.TryGetSymbol(argument.Parent.Parent, CancellationToken.None, out IMethodSymbol method));
            Assert.AreEqual(true, method.TryFindParameter(argument, out var symbol));
            var ctor = syntaxTree.FindConstructorDeclaration("C(T arg)");

            Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
            Assert.AreEqual("this.value = arg", result.ToString());
            using var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None);
            Assert.AreEqual("this.value = arg", walker.Assignments.Single().ToString());
        }
コード例 #4
0
        public static void GenericFieldCtorArg(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C<T>
    {
        private readonly T value;

        internal C(T arg)
        {
            this.value = arg;
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindParameter("arg");
            var ctor          = syntaxTree.FindConstructorDeclaration("C(T arg)");

            Assert.AreEqual(true, semanticModel.TryGetSymbol(value, CancellationToken.None, out var symbol));
            Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
            Assert.AreEqual("this.value = arg", result.ToString());
            using var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None);
            Assert.AreEqual("this.value = arg", walker.Assignments.Single().ToString());
        }
コード例 #5
0
        public static void FieldCtorArgViaLocal(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C
    {
        private readonly int value;

        internal C(int arg)
        {
            var temp = arg;
            this.value = temp;
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var ctor          = syntaxTree.FindConstructorDeclaration("C(int arg)");
            var symbol        = semanticModel.GetDeclaredSymbol(syntaxTree.FindParameter("int arg"), CancellationToken.None);

            Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
            Assert.AreEqual("this.value = temp", result.ToString());
            using var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None);
            Assert.AreEqual("this.value = temp", walker.Assignments.Single().ToString());
        }
コード例 #6
0
            public void FieldCtorArg(Search search)
            {
                var testCode      = @"
namespace RoslynSandbox
{
    internal class Foo
    {
        private readonly int value;

        internal Foo(int arg)
        {
            this.value = arg;
        }
    }
}";
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindAssignmentExpression("this.value = arg").Right;
                var ctor          = syntaxTree.FindConstructorDeclaration("Foo(int arg)");
                var arg           = semanticModel.GetSymbolSafe(value, CancellationToken.None);

                Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(arg, ctor, search, semanticModel, CancellationToken.None, out var result));
                Assert.AreEqual("this.value = arg", result?.ToString());
            }
コード例 #7
0
            public void FieldCtorArg(Scope scope)
            {
                var testCode      = @"
namespace RoslynSandbox
{
    internal class C
    {
        private readonly int value;

        internal C(int arg)
        {
            this.value = arg;
        }
    }
}";
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindParameter("arg");
                var ctor          = syntaxTree.FindConstructorDeclaration("C(int arg)");

                Assert.AreEqual(true, semanticModel.TryGetSymbol(value, CancellationToken.None, out var symbol));
                Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out AssignmentExpressionSyntax result));
                Assert.AreEqual("this.value = arg", result.ToString());
                using (var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual("this.value = arg", walker.Assignments.Single().ToString());
                }
            }
コード例 #8
0
        public static void FieldWithCtorArgViaProperty(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C
    {
        private int number;

        internal C(int arg)
        {
            this.Number = arg;
        }

        public int Number
        {
            get { return this.number; }
            set { this.number = value; }
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindParameter("arg");
            var ctor          = syntaxTree.FindConstructorDeclaration("C(int arg)");
            var symbol        = semanticModel.GetDeclaredSymbolSafe(value, CancellationToken.None);

            if (scope == SearchScope.Member)
            {
                Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
                Assert.AreEqual("this.Number = arg", result.ToString());
                using (var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual("this.Number = arg", string.Join(", ", walker.Assignments));
                }
            }
            else
            {
                Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
                Assert.AreEqual("this.number = value", result.ToString());
                using (var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual("this.number = value", string.Join(", ", walker.Assignments));
                }
            }
        }
コード例 #9
0
        public static void ChainedCtorArg(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C
    {
        private readonly int value;

        public C(int arg)
            : this(arg, 1)
        {
        }

        internal C(int chainedArg, int _)
        {
            this.value = chainedArg;
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var ctor          = syntaxTree.FindConstructorDeclaration("C(int arg)");
            var symbol        = semanticModel.GetDeclaredSymbolSafe(syntaxTree.FindParameter("arg"), CancellationToken.None);

            if (scope != SearchScope.Member)
            {
                Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out var result));
                Assert.AreEqual("this.value = chainedArg", result.ToString());
                using (var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual("this.value = chainedArg", walker.Assignments.Single().ToString());
                }
            }
            else
            {
                Assert.AreEqual(false, AssignmentExecutionWalker.FirstWith(symbol, ctor, scope, semanticModel, CancellationToken.None, out _));
                using (var walker = AssignmentExecutionWalker.With(symbol, ctor, scope, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual(0, walker.Assignments.Count);
                }
            }
        }
コード例 #10
0
        internal static bool IsAssignedToFieldOrProperty(ISymbol symbol, SyntaxNode scope, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <ISymbol> visited = null)
        {
            if (AssignmentExecutionWalker.FirstWith(symbol, scope, Scope.Instance, semanticModel, cancellationToken, out var assignment) &&
                semanticModel.TryGetSymbol(assignment.Left, cancellationToken, out ISymbol left))
            {
                if (left.IsEither <IParameterSymbol, ILocalSymbol>())
                {
                    using (visited = visited.IncrementUsage())
                    {
                        return(visited.Add(left) &&
                               IsAssignedToFieldOrProperty(left, scope, semanticModel, cancellationToken, visited));
                    }
                }

                return(left.IsEitherKind(SymbolKind.Field, SymbolKind.Property, SymbolKind.ArrayType));
            }

            return(false);
        }
コード例 #11
0
            public void FieldWithCtorArgViaProperty(Search search)
            {
                var testCode      = @"
namespace RoslynSandbox
{
    internal class Foo
    {
        private int number;

        internal Foo(int arg)
        {
            this.Number = arg;
        }

        public int Number
        {
            get { return this.number; }
            set { this.number = value; }
        }
    }
}";
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindParameter("arg");
                var ctor          = syntaxTree.FindConstructorDeclaration("Foo(int arg)");
                AssignmentExpressionSyntax result;
                var symbol = semanticModel.GetDeclaredSymbolSafe(value, CancellationToken.None);

                if (search == Search.Recursive)
                {
                    Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, Search.Recursive, semanticModel, CancellationToken.None, out result));
                    Assert.AreEqual("this.Number = arg", result?.ToString());
                }
                else
                {
                    Assert.AreEqual(false, AssignmentExecutionWalker.FirstForSymbol(symbol, ctor, Search.TopLevel, semanticModel, CancellationToken.None, out result));
                }
            }
コード例 #12
0
            public void ChainedCtorArg(Search search)
            {
                var testCode      = @"
namespace RoslynSandbox
{
    internal class Foo
    {
        private readonly int value;

        public Foo(int arg)
            : this(arg, 1)
        {
        }

        internal Foo(int chainedArg, int _)
        {
            this.value = chainedArg;
        }
    }
}";
                var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
                var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var value         = syntaxTree.FindParameter("arg");
                var ctor          = syntaxTree.FindConstructorDeclaration("Foo(int arg)");
                AssignmentExpressionSyntax result;
                var symbol = semanticModel.GetDeclaredSymbolSafe(value, CancellationToken.None);

                if (search == Search.Recursive)
                {
                    Assert.AreEqual(true, AssignmentExecutionWalker.FirstWith(symbol, ctor, Search.Recursive, semanticModel, CancellationToken.None, out result));
                    Assert.AreEqual("this.value = chainedArg", result?.ToString());
                }
                else
                {
                    Assert.AreEqual(false, AssignmentExecutionWalker.FirstWith(symbol, ctor, Search.TopLevel, semanticModel, CancellationToken.None, out result));
                }
            }