Example #1
0
        private static bool TryGetParameterName(ISymbol member, TypeDeclarationSyntax typeDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken, out string parameterName)
        {
            parameterName = null;
            using (var walker = AssignmentExecutionWalker.For(member, typeDeclaration, Scope.Member, semanticModel, cancellationToken))
            {
                foreach (var assignment in walker.Assignments)
                {
                    if (assignment.Right is IdentifierNameSyntax identifierName &&
                        assignment.TryFirstAncestor <ConstructorDeclarationSyntax>(out var ctor) &&
                        ctor.TryFindParameter(identifierName.Identifier.ValueText, out _))
                    {
                        if (parameterName == null)
                        {
                            parameterName = identifierName.Identifier.ValueText;
                        }
                        else if (parameterName != identifierName.Identifier.ValueText)
                        {
                            parameterName = null;
                            return(false);
                        }
                    }
                }
            }

            return(parameterName != null);
        }
Example #2
0
        public static void FieldPrivateCtorCalledByInitializer(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C
    {
        public static readonly C Default = new C();
        private readonly int value;

        private C()
        {
            this.value = 1;
        }
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var field         = semanticModel.GetDeclaredSymbolSafe(syntaxTree.FindFieldDeclaration("private readonly int value"), CancellationToken.None);
            var bar           = syntaxTree.FindTypeDeclaration("C");

            Assert.AreEqual(true, AssignmentExecutionWalker.FirstFor(field, bar, scope, semanticModel, CancellationToken.None, out var result));
            Assert.AreEqual("this.value = 1", result.ToString());
            Assert.AreEqual(true, AssignmentExecutionWalker.SingleFor(field, bar, scope, semanticModel, CancellationToken.None, out result));
            Assert.AreEqual("this.value = 1", result.ToString());
            using (var walker = AssignmentExecutionWalker.For(field, bar, scope, semanticModel, CancellationToken.None))
            {
                Assert.AreEqual("this.value = 1", walker.Assignments.Single().ToString());
            }
        }
Example #3
0
        public static void FieldWithCtorArg(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C
    {
        private readonly int value;

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

            Assert.AreEqual(true, AssignmentExecutionWalker.FirstFor(field, ctor, scope, semanticModel, CancellationToken.None, out var result));
            Assert.AreEqual("this.value = arg", result.ToString());
            Assert.AreEqual(true, AssignmentExecutionWalker.SingleFor(field, ctor, scope, semanticModel, CancellationToken.None, out result));
            Assert.AreEqual("this.value = arg", result.ToString());
            using (var walker = AssignmentExecutionWalker.For(field, ctor, scope, semanticModel, CancellationToken.None))
            {
                Assert.AreEqual("this.value = arg", walker.Assignments.Single().ToString());
            }
        }
Example #4
0
 private static bool TryGetParameterName(ISymbol member, TypeDeclarationSyntax typeDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out string?parameterName)
 {
     using (var walker = AssignmentExecutionWalker.For(member, typeDeclaration, SearchScope.Member, semanticModel, cancellationToken))
     {
         foreach (var assignment in walker.Assignments)
         {
             if (assignment.Right is IdentifierNameSyntax {
                 Identifier: { } identifier
             } &&
Example #5
0
            public void FieldWithCtorArgViaProperty(Scope scope)
            {
                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.FindMemberAccessExpression("this.number");
                var ctor          = syntaxTree.FindConstructorDeclaration("Foo(int arg)");
                AssignmentExpressionSyntax result;
                var field = semanticModel.GetSymbolSafe(value, CancellationToken.None);

                if (scope != Scope.Member)
                {
                    Assert.AreEqual(true, AssignmentExecutionWalker.FirstFor(field, ctor, scope, semanticModel, CancellationToken.None, out result));
                    Assert.AreEqual("this.number = value", result.ToString());
                    Assert.AreEqual(true, AssignmentExecutionWalker.SingleFor(field, ctor, scope, semanticModel, CancellationToken.None, out result));
                    Assert.AreEqual("this.number = value", result.ToString());
                    using (var walker = AssignmentExecutionWalker.For(field, ctor, scope, semanticModel, CancellationToken.None))
                    {
                        Assert.AreEqual("this.number = value", walker.Assignments.Single().ToString());
                    }
                }
                else
                {
                    Assert.AreEqual(false, AssignmentExecutionWalker.FirstFor(field, ctor, scope, semanticModel, CancellationToken.None, out result));
                }
            }
Example #6
0
        public static void FieldInPropertyExpressionBody(SearchScope scope)
        {
            var code          = @"
namespace N
{
    internal class C
    {
        private int number;

        internal C()
        {
            var i = this.Number;
        }

        public int Number => this.number = 3;
    }
}";
            var syntaxTree    = CSharpSyntaxTree.ParseText(code);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var value         = syntaxTree.FindMemberAccessExpression("this.number");
            var ctor          = syntaxTree.FindConstructorDeclaration("C()");
            AssignmentExpressionSyntax result;
            var field = semanticModel.GetSymbolSafe(value, CancellationToken.None);

            if (scope != SearchScope.Member)
            {
                Assert.AreEqual(true, AssignmentExecutionWalker.FirstFor(field, ctor, scope, semanticModel, CancellationToken.None, out result));
                Assert.AreEqual("this.number = 3", result.ToString());
                Assert.AreEqual(true, AssignmentExecutionWalker.SingleFor(field, ctor, scope, semanticModel, CancellationToken.None, out result));
                Assert.AreEqual("this.number = 3", result.ToString());
                using (var walker = AssignmentExecutionWalker.For(field, ctor, scope, semanticModel, CancellationToken.None))
                {
                    Assert.AreEqual("this.number = 3", walker.Assignments.Single().ToString());
                }
            }
            else
            {
                Assert.AreEqual(false, AssignmentExecutionWalker.FirstFor(field, ctor, scope, semanticModel, CancellationToken.None, out _));
            }
        }
Example #7
0
        internal static bool IsValueValidForRegisteredType(ExpressionSyntax value, ITypeSymbol registeredType, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <SyntaxNode>?visited = null)
        {
            switch (value)
            {
            case ConditionalExpressionSyntax conditional:
                return(IsValueValidForRegisteredType(conditional.WhenTrue, registeredType, semanticModel, cancellationToken, visited) &&
                       IsValueValidForRegisteredType(conditional.WhenFalse, registeredType, semanticModel, cancellationToken, visited));

            case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.CoalesceExpression):
                return(IsValueValidForRegisteredType(binary.Left, registeredType, semanticModel, cancellationToken, visited) &&
                       IsValueValidForRegisteredType(binary.Right, registeredType, semanticModel, cancellationToken, visited));
            }

            if (registeredType.TypeKind == TypeKind.Enum)
            {
                return(semanticModel.TryGetType(value, cancellationToken, out var valueType) &&
                       valueType.MetadataName == registeredType.MetadataName &&
                       Equals(valueType.ContainingType, registeredType.ContainingType) &&
                       NamespaceSymbolComparer.Equals(valueType.ContainingNamespace, registeredType.ContainingNamespace));
            }

            if (semanticModel.IsRepresentationPreservingConversion(value, registeredType))
            {
                return(true);
            }

            if (semanticModel.TryGetSymbol(value, cancellationToken, out var symbol))
            {
                if (symbol is IFieldSymbol field)
                {
                    if (field.TrySingleDeclaration(cancellationToken, out var fieldDeclaration))
                    {
                        if (fieldDeclaration.Declaration is { } variableDeclaration&&
                            variableDeclaration.Variables.TryLast(out var variable) &&
                            variable.Initializer is { } initializer&&
                            !IsValueValidForRegisteredType(initializer.Value, registeredType, semanticModel, cancellationToken, visited))
                        {
                            return(false);
                        }

                        return(IsAssignedValueOfRegisteredType(symbol, fieldDeclaration));
                    }

                    return(field.Type == KnownSymbols.Object);
                }

                if (symbol is IPropertySymbol property)
                {
                    if (property.TrySingleDeclaration(cancellationToken, out PropertyDeclarationSyntax? propertyDeclaration))
                    {
                        if (propertyDeclaration.Initializer is { } initializer&&
                            !IsValueValidForRegisteredType(initializer.Value, registeredType, semanticModel, cancellationToken, visited))
                        {
                            return(false);
                        }

                        if (property.SetMethod == null &&
                            property.GetMethod is { } getMethod)
                        {
                            return(IsReturnValueOfRegisteredType(getMethod));
                        }

                        return(IsAssignedValueOfRegisteredType(symbol, propertyDeclaration));
                    }

                    return(property.Type == KnownSymbols.Object);
                }

                if (symbol is IMethodSymbol method)
                {
                    return(IsReturnValueOfRegisteredType(method));
                }
            }

            return(false);

            bool IsAssignedValueOfRegisteredType(ISymbol memberSymbol, MemberDeclarationSyntax declaration)
            {
                if (declaration.TryFirstAncestor(out TypeDeclarationSyntax? typeDeclaration))
                {
                    using (var walker = AssignmentExecutionWalker.For(memberSymbol, typeDeclaration, SearchScope.Type, semanticModel, cancellationToken))
                    {
                        foreach (var assignment in walker.Assignments)
                        {
                            if (!IsValueValidForRegisteredType(assignment.Right, registeredType, semanticModel, cancellationToken, visited))
                            {
                                return(false);
                            }
                        }
                    }
                }

                return(true);
            }

            bool IsReturnValueOfRegisteredType(IMethodSymbol method)
            {
                if (method.TrySingleMethodDeclaration(cancellationToken, out var target))
                {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                    using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                    {
                        if (visited.Add(target))
                        {
                            using (var walker = ReturnValueWalker.Borrow(target))
                            {
                                foreach (var returnValue in walker.ReturnValues)
                                {
                                    if (!IsValueValidForRegisteredType(returnValue, registeredType, semanticModel, cancellationToken, visited))
                                    {
                                        return(false);
                                    }
                                }
                            }
                        }

                        return(true);
                    }
                }

                return(method.ReturnType == KnownSymbols.Object);
            }
        }