public void IsObjectEquals(string check, bool expected)
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System;

    public class Foo
    {
        private int? bar1;
        private Nullable<int> bar2;
        private int bar3;
        private double? bar4;
        private string bar5;

        public Foo()
        {
            Equals(this.bar1, this.bar1);
        }

        public int? Bar1 => this.bar1;
    }
}";

            testCode = testCode.AssertReplace("Equals(this.bar1, this.bar1)", check);
            var syntaxTree    = CSharpSyntaxTree.ParseText(testCode);
            var compilation   = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
            var semanticModel = compilation.GetSemanticModel(syntaxTree);
            var invocation    = syntaxTree.FindInvocation(check);
            var arg0          = semanticModel.GetSymbolSafe(invocation.ArgumentList.Arguments[0].Expression, CancellationToken.None);
            var arg1          = semanticModel.GetSymbolSafe(invocation.ArgumentList.Arguments[1].Expression, CancellationToken.None);

            Assert.AreEqual(expected, Equality.IsObjectEquals(invocation, semanticModel, CancellationToken.None, arg0, arg1));
            Assert.AreEqual(expected, Equality.IsObjectEquals(invocation, semanticModel, CancellationToken.None, arg1, arg0));
        }
Esempio n. 2
0
        private static void HandleInvocation(SyntaxNodeAnalysisContext context)
        {
            if (context.IsExcludedFromAnalysis())
            {
                return;
            }

            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement?.Condition == null)
            {
                return;
            }

            var setter = ifStatement.FirstAncestorOrSelf <AccessorDeclarationSyntax>();

            if (setter?.IsKind(SyntaxKind.SetAccessorDeclaration) != true)
            {
                return;
            }

            if (!Notifies(setter, context.SemanticModel, context.CancellationToken))
            {
                return;
            }

            var propertyDeclaration = setter.FirstAncestorOrSelf <PropertyDeclarationSyntax>();
            var property            = context.SemanticModel.GetDeclaredSymbolSafe(propertyDeclaration, context.CancellationToken);

            if (property == null ||
                property.Type.IsValueType ||
                property.Type == KnownSymbol.String)
            {
                return;
            }

            if (!Property.TryGetBackingField(property, context.SemanticModel, context.CancellationToken, out IFieldSymbol backingField))
            {
                return;
            }

            if (Property.TryFindValue(setter, context.SemanticModel, context.CancellationToken, out IParameterSymbol value))
            {
                foreach (var member in new ISymbol[] { backingField, property })
                {
                    if (Equality.IsObjectEquals(ifStatement.Condition, context.SemanticModel, context.CancellationToken, value, member) ||
                        IsNegatedObjectEqualsCheck(ifStatement.Condition, context.SemanticModel, context.CancellationToken, value, member))
                    {
                        if (Equality.UsesObjectOrNone(ifStatement.Condition))
                        {
                            return;
                        }
                    }
                }
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, ifStatement.GetLocation()));
        }
Esempio n. 3
0
        private static bool IsNegatedObjectEqualsCheck(ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken, IParameterSymbol value, ISymbol member)
        {
            var unaryExpression = expression as PrefixUnaryExpressionSyntax;

            if (unaryExpression?.IsKind(SyntaxKind.LogicalNotExpression) == true)
            {
                return(Equality.IsObjectEquals(unaryExpression.Operand, semanticModel, cancellationToken, value, member));
            }

            return(false);
        }
        private static bool CanFix(IfStatementSyntax ifStatement, SemanticModel semanticModel, CancellationToken cancellationToken, IParameterSymbol value, IFieldSymbol backingField, IPropertySymbol property)
        {
            foreach (var member in new ISymbol[] { backingField, property })
            {
                if (Equality.IsOperatorEquals(ifStatement.Condition, semanticModel, cancellationToken, value, member) ||
                    Equality.IsObjectEquals(ifStatement.Condition, semanticModel, cancellationToken, value, member) ||
                    Equality.IsReferenceEquals(ifStatement.Condition, semanticModel, cancellationToken, value, member) ||
                    Equality.IsInstanceEquals(ifStatement.Condition, semanticModel, cancellationToken, value, member) ||
                    Equality.IsInstanceEquals(ifStatement.Condition, semanticModel, cancellationToken, member, value))
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 5
0
        private static bool IsEqualsCheck(ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken, IParameterSymbol value, ISymbol member)
        {
            var equals = expression as InvocationExpressionSyntax;

            if (equals == null)
            {
                return(false);
            }

            if (Equality.IsObjectEquals(equals, semanticModel, cancellationToken, value, member) ||
                Equality.IsInstanceEquals(equals, semanticModel, cancellationToken, value, member) ||
                Equality.IsInstanceEquals(equals, semanticModel, cancellationToken, member, value) ||
                Equality.IsReferenceEquals(equals, semanticModel, cancellationToken, value, member) ||
                Equality.IsEqualityComparerEquals(equals, semanticModel, cancellationToken, value, member) ||
                Equality.IsNullableEquals(equals, semanticModel, cancellationToken, value, member))
            {
                return(true);
            }

            return(false);
        }