private static SyntaxNode GetNegationOfConstantPattern(
            SyntaxNode pattern,
            SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal
            )
        {
            var syntaxFacts = generatorInternal.SyntaxFacts;

            // If we have `is true/false` just swap that to be `is false/true`.

            var expression = syntaxFacts.GetExpressionOfConstantPattern(pattern);

            if (syntaxFacts.IsTrueLiteralExpression(expression))
            {
                return(generatorInternal.ConstantPattern(generator.FalseLiteralExpression()));
            }

            if (syntaxFacts.IsFalseLiteralExpression(expression))
            {
                return(generatorInternal.ConstantPattern(generator.TrueLiteralExpression()));
            }

            // Otherwise, just negate the entire pattern, we don't have anything else special we can do here.
            return(generatorInternal.NotPattern(pattern));
        }
Exemple #2
0
        private static SyntaxNode GetNegationOfUnaryPattern(
            SyntaxNode pattern,
            SyntaxGeneratorInternal generatorInternal,
            ISyntaxFacts syntaxFacts)
        {
            syntaxFacts.GetPartsOfUnaryPattern(pattern, out var opToken, out var subPattern);

            // not not p    ->   p
            if (syntaxFacts.IsNotPattern(pattern))
            {
                return(subPattern.WithPrependedLeadingTrivia(opToken.LeadingTrivia)
                       .WithAdditionalAnnotations(Simplifier.Annotation));
            }

            // If there are other interesting unary patterns in the future, we can support specialized logic for
            // negating them here.
            return(generatorInternal.NotPattern(pattern));
        }
Exemple #3
0
        public static SyntaxNode Negate(
            this SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal,
            SyntaxNode expressionOrPattern,
            SemanticModel semanticModel,
            bool negateBinary,
            CancellationToken cancellationToken)
        {
            var syntaxFacts = generatorInternal.SyntaxFacts;

            if (syntaxFacts.IsParenthesizedExpression(expressionOrPattern))
            {
                return(generatorInternal.AddParentheses(
                           generator.Negate(
                               generatorInternal,
                               syntaxFacts.GetExpressionOfParenthesizedExpression(expressionOrPattern),
                               semanticModel,
                               negateBinary,
                               cancellationToken))
                       .WithTriviaFrom(expressionOrPattern));
            }

            if (negateBinary && syntaxFacts.IsBinaryExpression(expressionOrPattern))
            {
                return(GetNegationOfBinaryExpression(expressionOrPattern, generator, generatorInternal, semanticModel, cancellationToken));
            }

            if (syntaxFacts.IsLiteralExpression(expressionOrPattern))
            {
                return(GetNegationOfLiteralExpression(expressionOrPattern, generator, semanticModel));
            }

            if (syntaxFacts.IsLogicalNotExpression(expressionOrPattern))
            {
                return(GetNegationOfLogicalNotExpression(expressionOrPattern, syntaxFacts));
            }

            if (negateBinary && syntaxFacts.IsIsPatternExpression(expressionOrPattern))
            {
                return(GetNegationOfIsPatternExpression(expressionOrPattern, generator, generatorInternal, semanticModel, cancellationToken));
            }

            if (syntaxFacts.IsParenthesizedPattern(expressionOrPattern))
            {
                // Push the negation inside the parenthesized pattern.
                return(generatorInternal.AddParentheses(
                           generator.Negate(
                               generatorInternal,
                               syntaxFacts.GetPatternOfParenthesizedPattern(expressionOrPattern),
                               semanticModel,
                               negateBinary,
                               cancellationToken))
                       .WithTriviaFrom(expressionOrPattern));
            }

            if (negateBinary && syntaxFacts.IsBinaryPattern(expressionOrPattern))
            {
                return(GetNegationOfBinaryPattern(expressionOrPattern, generator, generatorInternal, semanticModel, cancellationToken));
            }

            if (syntaxFacts.IsConstantPattern(expressionOrPattern))
            {
                return(GetNegationOfConstantPattern(expressionOrPattern, generator, generatorInternal));
            }

            if (syntaxFacts.IsUnaryPattern(expressionOrPattern))
            {
                return(GetNegationOfUnaryPattern(expressionOrPattern, generatorInternal, syntaxFacts));
            }

            // TODO(cyrusn): We could support negating relational patterns in the future.  i.e.
            //
            //      not >= 0   ->    < 0

            return(syntaxFacts.IsAnyPattern(expressionOrPattern)
                ? generatorInternal.NotPattern(expressionOrPattern)
                : generator.LogicalNotExpression(expressionOrPattern));
        }
Exemple #4
0
        private static SyntaxNode GetNegationOfBinaryExpression(
            SyntaxNode expressionNode,
            SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var syntaxFacts = generatorInternal.SyntaxFacts;

            syntaxFacts.GetPartsOfBinaryExpression(expressionNode, out var leftOperand, out var operatorToken, out var rightOperand);

            var binaryOperation = semanticModel.GetOperation(expressionNode, cancellationToken) as IBinaryOperation;

            if (binaryOperation == null)
            {
                // x is y   ->    x is not y
                if (syntaxFacts.IsIsExpression(expressionNode) && syntaxFacts.SupportsNotPattern(semanticModel.SyntaxTree.Options))
                {
                    return(generatorInternal.IsPatternExpression(leftOperand, operatorToken, generatorInternal.NotPattern(generatorInternal.TypePattern(rightOperand))));
                }

                // Apply the logical not operator if it is not a binary operation.
                return(generator.LogicalNotExpression(expressionNode));
            }

            if (!s_negatedBinaryMap.TryGetValue(binaryOperation.OperatorKind, out var negatedKind))
            {
                return(generator.LogicalNotExpression(expressionNode));
            }
            else
            {
                var negateOperands = false;
                switch (binaryOperation.OperatorKind)
                {
                case BinaryOperatorKind.Or:
                case BinaryOperatorKind.And:
                case BinaryOperatorKind.ConditionalAnd:
                case BinaryOperatorKind.ConditionalOr:
                    negateOperands = true;
                    break;
                }

                //Workaround for https://github.com/dotnet/roslyn/issues/23956
                //Issue to remove this when above is merged
                if (binaryOperation.OperatorKind == BinaryOperatorKind.Or && syntaxFacts.IsLogicalOrExpression(expressionNode))
                {
                    negatedKind = BinaryOperatorKind.ConditionalAnd;
                }
                else if (binaryOperation.OperatorKind == BinaryOperatorKind.And && syntaxFacts.IsLogicalAndExpression(expressionNode))
                {
                    negatedKind = BinaryOperatorKind.ConditionalOr;
                }

                var newLeftOperand  = leftOperand;
                var newRightOperand = rightOperand;
                if (negateOperands)
                {
                    newLeftOperand  = generator.Negate(generatorInternal, leftOperand, semanticModel, cancellationToken);
                    newRightOperand = generator.Negate(generatorInternal, rightOperand, semanticModel, cancellationToken);
                }

                var newBinaryExpressionSyntax = NewBinaryOperation(binaryOperation, newLeftOperand, negatedKind, newRightOperand, generator)
                                                .WithTriviaFrom(expressionNode);

                var newToken           = syntaxFacts.GetOperatorTokenOfBinaryExpression(newBinaryExpressionSyntax);
                var newTokenWithTrivia = newToken.WithTriviaFrom(operatorToken);
                return(newBinaryExpressionSyntax.ReplaceToken(newToken, newTokenWithTrivia));
            }
        }
        private static SyntaxNode GetNegationOfBinaryExpression(
            SyntaxNode expressionNode,
            SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var syntaxFacts = generatorInternal.SyntaxFacts;

            syntaxFacts.GetPartsOfBinaryExpression(expressionNode, out var leftOperand, out var operatorToken, out var rightOperand);

            var operation = semanticModel.GetOperation(expressionNode, cancellationToken);

            if (operation is not IBinaryOperation binaryOperation)
            {
                if (syntaxFacts.IsIsTypeExpression(expressionNode))
                {
                    // `is object`  ->   `is null`
                    if (syntaxFacts.IsPredefinedType(rightOperand, PredefinedType.Object) &&
                        generatorInternal.SupportsPatterns(semanticModel.SyntaxTree.Options))
                    {
                        return(generatorInternal.IsPatternExpression(leftOperand, operatorToken, generatorInternal.ConstantPattern(generator.NullLiteralExpression())));
                    }

                    // `is y`   ->    `is not y`
                    if (syntaxFacts.SupportsNotPattern(semanticModel.SyntaxTree.Options))
                    {
                        return(generatorInternal.IsPatternExpression(leftOperand, operatorToken, generatorInternal.NotPattern(generatorInternal.TypePattern(rightOperand))));
                    }
                }

                // Apply the logical not operator if it is not a binary operation.
                return(generator.LogicalNotExpression(expressionNode));
            }

            if (!s_negatedBinaryMap.TryGetValue(binaryOperation.OperatorKind, out var negatedKind))
            {
                return(generator.LogicalNotExpression(expressionNode));
            }

            if (binaryOperation.OperatorKind is BinaryOperatorKind.Or or
                BinaryOperatorKind.And or
                BinaryOperatorKind.ConditionalAnd or
                BinaryOperatorKind.ConditionalOr)
            {
                leftOperand  = generator.Negate(generatorInternal, leftOperand, semanticModel, cancellationToken);
                rightOperand = generator.Negate(generatorInternal, rightOperand, semanticModel, cancellationToken);
            }

            var newBinaryExpressionSyntax = negatedKind is BinaryOperatorKind.Equals or BinaryOperatorKind.NotEquals
                ? generatorInternal.NegateEquality(generator, expressionNode, leftOperand, negatedKind, rightOperand)
                : NegateRelational(generator, binaryOperation, leftOperand, negatedKind, rightOperand);

            newBinaryExpressionSyntax = newBinaryExpressionSyntax.WithTriviaFrom(expressionNode);

            var newToken = syntaxFacts.GetOperatorTokenOfBinaryExpression(newBinaryExpressionSyntax);

            return(newBinaryExpressionSyntax.ReplaceToken(
                       newToken,
                       newToken.WithTriviaFrom(operatorToken)));
        }