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)); }
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)); }
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)); }
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))); }