コード例 #1
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());
            }
        }
コード例 #2
0
        internal static bool IsAssignedAndDisposedInSetupAndTearDown(FieldOrProperty fieldOrProperty, TypeDeclarationSyntax scope, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (AssignmentExecutionWalker.SingleFor(fieldOrProperty.Symbol, scope, Scope.Member, semanticModel, cancellationToken, out var assignment) &&
                assignment.FirstAncestor <MethodDeclarationSyntax>() is MethodDeclarationSyntax methodDeclaration)
            {
                if (Attribute.TryFind(methodDeclaration, KnownSymbol.NUnitSetUpAttribute, semanticModel, cancellationToken, out _))
                {
                    if (fieldOrProperty.ContainingType.TryFindFirstMethodRecursive(x => x.GetAttributes().Any(a => a.AttributeClass == KnownSymbol.NUnitTearDownAttribute), out var tearDown))
                    {
                        return(DisposableMember.IsDisposed(fieldOrProperty, tearDown, semanticModel, cancellationToken));
                    }
                }

                if (Attribute.TryFind(methodDeclaration, KnownSymbol.NUnitOneTimeSetUpAttribute, semanticModel, cancellationToken, out _))
                {
                    if (fieldOrProperty.ContainingType.TryFindFirstMethodRecursive(
                            x => x.GetAttributes().Any(a => a.AttributeClass == KnownSymbol.NUnitOneTimeTearDownAttribute),
                            out var tearDown))
                    {
                        return(DisposableMember.IsDisposed(fieldOrProperty, tearDown, semanticModel, cancellationToken));
                    }
                }
            }

            return(false);
        }
コード例 #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());
            }
        }
コード例 #4
0
 internal static bool IsAssignedInInitializeAndDisposedInCleanup(FieldOrProperty fieldOrProperty, TypeDeclarationSyntax scope, SemanticModel semanticModel, CancellationToken cancellationToken)
 {
     if (AssignmentExecutionWalker.SingleFor(fieldOrProperty.Symbol, scope, SearchScope.Member, semanticModel, cancellationToken, out var assignment) &&
         assignment.FirstAncestor <MethodDeclarationSyntax>() is { } methodDeclaration)
     {
         var cleanup = TearDown(KnownSymbol.NUnitSetUpAttribute, KnownSymbol.NUnitTearDownAttribute) ??
                       TearDown(KnownSymbol.NUnitOneTimeSetUpAttribute, KnownSymbol.NUnitOneTimeTearDownAttribute) ??
                       TearDown(KnownSymbol.TestInitializeAttribute, KnownSymbol.TestCleanupAttribute) ??
                       TearDown(KnownSymbol.ClassInitializeAttribute, KnownSymbol.ClassCleanupAttribute);
         return(cleanup is { } &&
コード例 #5
0
        internal static bool IsAssignedInSetUp(FieldOrProperty fieldOrProperty, TypeDeclarationSyntax scope, SemanticModel semanticModel, CancellationToken cancellationToken, out AttributeSyntax attribute)
        {
            if (AssignmentExecutionWalker.SingleFor(fieldOrProperty.Symbol, scope, Scope.Member, semanticModel, cancellationToken, out var assignment) &&
                assignment.FirstAncestor <MethodDeclarationSyntax>() is MethodDeclarationSyntax methodDeclaration)
            {
                return(Attribute.TryFind(methodDeclaration, KnownSymbol.NUnitSetUpAttribute, semanticModel, cancellationToken, out attribute) ||
                       Attribute.TryFind(methodDeclaration, KnownSymbol.NUnitOneTimeSetUpAttribute, semanticModel, cancellationToken, out attribute));
            }

            attribute = null;
            return(false);
        }
コード例 #6
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));
                }
            }
コード例 #7
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 _));
            }
        }
コード例 #8
0
        private static bool IsDefaultValueOfRegisteredType(ExpressionSyntax defaultValue, ITypeSymbol registeredType, SyntaxNodeAnalysisContext context, PooledSet <SyntaxNode> visited = null)
        {
            switch (defaultValue)
            {
            case ConditionalExpressionSyntax conditional:
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    return(visited.Add(defaultValue) &&
                           IsDefaultValueOfRegisteredType(conditional.WhenTrue, registeredType, context, visited) &&
                           IsDefaultValueOfRegisteredType(conditional.WhenFalse, registeredType, context, visited));
                }

            case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.CoalesceExpression):
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    return(visited.Add(defaultValue) &&
                           IsDefaultValueOfRegisteredType(binary.Left, registeredType, context, visited) &&
                           IsDefaultValueOfRegisteredType(binary.Right, registeredType, context, visited));
                }
            }

            if (context.SemanticModel.IsRepresentationPreservingConversion(defaultValue, registeredType, context.CancellationToken))
            {
                return(true);
            }

            if (context.SemanticModel.TryGetSymbol(defaultValue, context.CancellationToken, out ISymbol symbol))
            {
                if (symbol is IFieldSymbol field)
                {
                    if (field.TrySingleDeclaration(context.CancellationToken, out var fieldDeclaration))
                    {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                        using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                        {
                            if (fieldDeclaration.Declaration is VariableDeclarationSyntax variableDeclaration &&
                                variableDeclaration.Variables.TryLast(out var variable) &&
                                variable.Initializer is EqualsValueClauseSyntax initializer)
                            {
                                return(visited.Add(initializer.Value) &&
                                       IsDefaultValueOfRegisteredType(initializer.Value, registeredType, context, visited));
                            }

                            return(fieldDeclaration.TryFirstAncestor <TypeDeclarationSyntax>(out var typeDeclaration) &&
                                   AssignmentExecutionWalker.SingleFor(symbol, typeDeclaration, Scope.Instance, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                                   visited.Add(assignedValue) &&
                                   IsDefaultValueOfRegisteredType(assignedValue, registeredType, context, visited));
                        }
                    }

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

                if (symbol is IPropertySymbol property)
                {
                    if (property.TrySingleDeclaration(context.CancellationToken, out PropertyDeclarationSyntax propertyDeclaration))
                    {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                        using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                        {
                            if (propertyDeclaration.Initializer is EqualsValueClauseSyntax initializer)
                            {
                                return(visited.Add(initializer.Value) &&
                                       IsDefaultValueOfRegisteredType(initializer.Value, registeredType, context, visited));
                            }

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

                            return(propertyDeclaration.TryFirstAncestor <TypeDeclarationSyntax>(out var typeDeclaration) &&
                                   AssignmentExecutionWalker.SingleFor(symbol, typeDeclaration, Scope.Instance, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                                   visited.Add(assignedValue) &&
                                   IsDefaultValueOfRegisteredType(assignedValue, registeredType, context, visited));
                        }
                    }

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

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

            return(false);

            bool IsReturnValueOfRegisteredType(IMethodSymbol method, PooledSet <SyntaxNode> v)
            {
                if (method.TrySingleMethodDeclaration(context.CancellationToken, out var target))
                {
                    using (var walker = ReturnValueWalker.Borrow(target))
                    {
                        foreach (var returnValue in walker.ReturnValues)
                        {
                            if (!IsDefaultValueOfRegisteredType(returnValue, registeredType, context, v))
                            {
                                return(false);
                            }
                        }

                        return(true);
                    }
                }

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