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));
        }
Esempio n. 2
0
        private TInterpolationSyntax Update(
            SyntaxGeneratorInternal generator,
            TInterpolatedStringExpressionSyntax interpolatedString,
            TInterpolationSyntax interpolation,
            TExpressionSyntax unwrapped,
            TExpressionSyntax?alignment,
            string?formatString
            )
        {
            var result = WithExpression(interpolation, unwrapped);

            if (alignment != null)
            {
                result = WithAlignmentClause(
                    result,
                    (TInterpolationAlignmentClause)generator.InterpolationAlignmentClause(alignment)
                    );
            }

            if (!string.IsNullOrEmpty(formatString))
            {
                result = WithFormatClause(
                    result,
                    (TInterpolationFormatClause?)generator.InterpolationFormatClause(
                        Escape(interpolatedString, formatString !)
                        )
                    );
            }

            return(result);
        }
Esempio n. 3
0
        public static ImmutableArray <SyntaxNode> CreateGetHashCodeStatementsUsingSystemHashCode(
            this SyntaxGenerator factory, SyntaxGeneratorInternal generatorInternal,
            INamedTypeSymbol hashCodeType, ImmutableArray <SyntaxNode> memberReferences)
        {
            if (memberReferences.Length <= 8)
            {
                var statement = factory.ReturnStatement(
                    factory.InvocationExpression(
                        factory.MemberAccessExpression(factory.TypeExpression(hashCodeType), "Combine"),
                        memberReferences));
                return(ImmutableArray.Create(statement));
            }

            const string hashName   = "hash";
            var          statements = ArrayBuilder <SyntaxNode> .GetInstance();

            statements.Add(factory.SimpleLocalDeclarationStatement(generatorInternal,
                                                                   hashCodeType, hashName, factory.ObjectCreationExpression(hashCodeType)));

            var localReference = factory.IdentifierName(hashName);

            foreach (var member in memberReferences)
            {
                statements.Add(factory.ExpressionStatement(
                                   factory.InvocationExpression(
                                       factory.MemberAccessExpression(localReference, "Add"),
                                       member)));
            }

            statements.Add(factory.ReturnStatement(
                               factory.InvocationExpression(
                                   factory.MemberAccessExpression(localReference, "ToHashCode"))));

            return(statements.ToImmutableAndFree());
        }
Esempio n. 4
0
        private static SyntaxNode GetNegationOfBinaryPattern(
            SyntaxNode pattern,
            SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            // Apply demorgans's law here.
            //
            //  not (a and b)   ->   not a or not b
            //  not (a or b)    ->   not a and not b

            var syntaxFacts = generatorInternal.SyntaxFacts;

            syntaxFacts.GetPartsOfBinaryPattern(pattern, out var left, out var operatorToken, out var right);

            var newLeft  = generator.Negate(generatorInternal, left, semanticModel, cancellationToken);
            var newRight = generator.Negate(generatorInternal, right, semanticModel, cancellationToken);

            var newPattern =
                syntaxFacts.IsAndPattern(pattern) ? generatorInternal.OrPattern(newLeft, newRight) :
                syntaxFacts.IsOrPattern(pattern) ? generatorInternal.AndPattern(newLeft, newRight) :
                throw ExceptionUtilities.UnexpectedValue(pattern.RawKind);

            newPattern = newPattern.WithTriviaFrom(pattern);

            syntaxFacts.GetPartsOfBinaryPattern(newPattern, out _, out var newToken, out _);
            var newTokenWithTrivia = newToken.WithTriviaFrom(operatorToken);

            return(newPattern.ReplaceToken(newToken, newTokenWithTrivia));
        }
        public async Task <Document> FormatNewDocumentAsync(Document document, Document?hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken)
        {
            var rootToFormat = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // Apply file header preferences
            var fileHeaderTemplate = options.DocumentFormattingOptions.FileHeaderTemplate;

            if (!string.IsNullOrEmpty(fileHeaderTemplate))
            {
                var newLineTrivia      = SyntaxGeneratorInternal.EndOfLine(options.FormattingOptions.NewLine);
                var rootWithFileHeader = await AbstractFileHeaderCodeFixProvider.GetTransformedSyntaxRootAsync(
                    SyntaxGenerator.SyntaxFacts,
                    FileHeaderHelper,
                    newLineTrivia,
                    document,
                    fileHeaderTemplate,
                    cancellationToken).ConfigureAwait(false);

                return(document.WithSyntaxRoot(rootWithFileHeader));
            }
            else if (hintDocument is not null)
            {
                // If there is no file header preference, see if we can use the one in the hint document
                var bannerService  = hintDocument.GetRequiredLanguageService <IFileBannerFactsService>();
                var hintSyntaxRoot = await hintDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var fileBanner = bannerService.GetFileBanner(hintSyntaxRoot);

                var rootWithBanner = rootToFormat.WithPrependedLeadingTrivia(fileBanner);
                return(document.WithSyntaxRoot(rootWithBanner));
            }

            return(document);
        }
Esempio n. 6
0
 private static SyntaxNode SimpleLocalDeclarationStatement(
     this SyntaxGenerator generator, SyntaxGeneratorInternal generatorInternal, INamedTypeSymbol namedTypeSymbol,
     string name, SyntaxNode initializer)
 {
     return(generatorInternal.RequiresLocalDeclarationType()
         ? generator.LocalDeclarationStatement(namedTypeSymbol, name, initializer)
         : generator.LocalDeclarationStatement(name, initializer));
 }
Esempio n. 7
0
 public static SyntaxNode Negate(
     this SyntaxGenerator generator,
     SyntaxGeneratorInternal generatorInternal,
     SyntaxNode expression,
     SemanticModel semanticModel,
     CancellationToken cancellationToken)
 {
     return(Negate(generator, generatorInternal, expression, semanticModel, negateBinary: true, cancellationToken));
 }
Esempio n. 8
0
        public static SyntaxNode GetDefaultEqualityComparer(
            this SyntaxGenerator factory,
            SyntaxGeneratorInternal generatorInternal,
            Compilation compilation,
            ITypeSymbol type)
        {
            var equalityComparerType = compilation.EqualityComparerOfTType();
            var typeExpression       = equalityComparerType == null
                ? factory.GenericName(nameof(EqualityComparer <int>), type)
                : generatorInternal.Type(equalityComparerType.Construct(type), typeContext: false);

            return(factory.MemberAccessExpression(typeExpression, factory.IdentifierName(DefaultName)));
        }
Esempio n. 9
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 operation = semanticModel.GetOperation(expressionNode, cancellationToken);

            if (operation is not IBinaryOperation binaryOperation)
            {
                // 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));
            }

            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)));
        }
        private static SyntaxNode GetNegationOfIsPatternExpression(
            SyntaxNode isExpression,
            SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal,
            SemanticModel semanticModel,
            CancellationToken cancellationToken
            )
        {
            // Don't recurse into patterns if the language doesn't support negated patterns.
            // Just wrap with a normal '!' expression.
            var syntaxFacts = generatorInternal.SyntaxFacts;

            if (syntaxFacts.SupportsNotPattern(semanticModel.SyntaxTree.Options))
            {
                syntaxFacts.GetPartsOfIsPatternExpression(
                    isExpression,
                    out var left,
                    out var isToken,
                    out var pattern
                    );
                var negated = generator.Negate(
                    generatorInternal,
                    pattern,
                    semanticModel,
                    cancellationToken
                    );

                // Negating the pattern may have formed something illegal.  If so, just do a normal `!` negation.
                if (IsLegalPattern(syntaxFacts, negated, designatorsLegal: true))
                {
                    if (syntaxFacts.IsTypePattern(negated))
                    {
                        // We started with `x is not t`.  Unwrap the type pattern for 't' and create a simple `is` binary expr `x is t`.
                        var type = syntaxFacts.GetTypeOfTypePattern(negated);
                        return(generator.IsTypeExpression(left, type));
                    }
                    else
                    {
                        // Keep this as a normal `is-pattern`, just with the pattern portion negated.
                        return(generatorInternal.IsPatternExpression(left, isToken, negated));
                    }
                }
            }

            return(generator.LogicalNotExpression(isExpression));
        }
Esempio n. 11
0
        public static IMethodSymbol CreateEqualsMethod(
            this SyntaxGenerator factory,
            SyntaxGeneratorInternal generatorInternal,
            Compilation compilation,
            ParseOptions parseOptions,
            INamedTypeSymbol containingType,
            ImmutableArray <ISymbol> symbols,
            string localNameOpt,
            SyntaxAnnotation statementAnnotation)
        {
            var statements = CreateEqualsMethodStatements(
                factory, generatorInternal, compilation, parseOptions, containingType, symbols, localNameOpt);

            statements = statements.SelectAsArray(s => s.WithAdditionalAnnotations(statementAnnotation));

            return(CreateEqualsMethod(compilation, statements));
        }
Esempio n. 12
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));
        }
            private IMethodSymbol CreateEqualityOperator(
                Compilation compilation,
                SyntaxGenerator generator,
                SyntaxGeneratorInternal generatorInternal,
                ImmutableArray <IParameterSymbol> parameters)
            {
                var expression = _containingType.IsValueType
                    ? generator.InvocationExpression(
                    generator.MemberAccessExpression(
                        generator.IdentifierName(LeftName),
                        generator.IdentifierName(EqualsName)),
                    generator.IdentifierName(RightName))
                    : generator.InvocationExpression(
                    generator.MemberAccessExpression(
                        generator.GetDefaultEqualityComparer(generatorInternal, compilation, _containingType),
                        generator.IdentifierName(EqualsName)),
                    generator.IdentifierName(LeftName),
                    generator.IdentifierName(RightName));

                return(CodeGenerationSymbolFactory.CreateOperatorSymbol(
Esempio n. 14
0
        public static ImmutableArray <SyntaxNode> GetGetHashCodeComponents(
            this SyntaxGenerator factory,
            SyntaxGeneratorInternal generatorInternal,
            Compilation compilation,
            INamedTypeSymbol?containingType,
            ImmutableArray <ISymbol> members,
            bool justMemberReference)
        {
            var result = ArrayBuilder <SyntaxNode> .GetInstance();

            if (containingType != null && GetBaseGetHashCodeMethod(containingType) != null)
            {
                result.Add(factory.InvocationExpression(
                               factory.MemberAccessExpression(factory.BaseExpression(), GetHashCodeName)));
            }

            foreach (var member in members)
            {
                result.Add(GetMemberForGetHashCode(factory, generatorInternal, compilation, member, justMemberReference));
            }

            return(result.ToImmutableAndFree());
        }
Esempio n. 15
0
        private static SyntaxNode GetMemberForGetHashCode(
            SyntaxGenerator factory,
            SyntaxGeneratorInternal generatorInternal,
            Compilation compilation,
            ISymbol member,
            bool justMemberReference)
        {
            var getHashCodeNameExpression = factory.IdentifierName(GetHashCodeName);
            var thisSymbol = factory.MemberAccessExpression(factory.ThisExpression(),
                                                            factory.IdentifierName(member.Name)).WithAdditionalAnnotations(Simplification.Simplifier.Annotation);

            // Caller only wanted the reference to the member, nothing else added.
            if (justMemberReference)
            {
                return(thisSymbol);
            }

            if (member.GetSymbolType()?.IsValueType ?? false)
            {
                // There is no reason to generate the bulkier syntax of EqualityComparer<>.Default.GetHashCode for value
                // types. No null check is necessary, and there's no performance advantage on .NET Core for using
                // EqualityComparer.GetHashCode instead of calling GetHashCode directly. On .NET Framework, using
                // EqualityComparer.GetHashCode on value types actually performs more poorly.

                return(factory.InvocationExpression(
                           factory.MemberAccessExpression(thisSymbol, nameof(object.GetHashCode))));
            }
            else
            {
                return(factory.InvocationExpression(
                           factory.MemberAccessExpression(
                               GetDefaultEqualityComparer(factory, generatorInternal, compilation, GetType(compilation, member)),
                               getHashCodeNameExpression),
                           thisSymbol));
            }
        }
        public static SyntaxNode Negate(
            this SyntaxGenerator generator,
            SyntaxGeneratorInternal generatorInternal,
            SyntaxNode expression,
            SemanticModel semanticModel,
            bool negateBinary,
            CancellationToken cancellationToken)
        {
            var syntaxFacts = generatorInternal.SyntaxFacts;

            if (syntaxFacts.IsParenthesizedExpression(expression))
            {
                return(generatorInternal.AddParentheses(
                           generator.Negate(
                               generatorInternal,
                               syntaxFacts.GetExpressionOfParenthesizedExpression(expression),
                               semanticModel,
                               negateBinary,
                               cancellationToken))
                       .WithTriviaFrom(expression));
            }
            if (negateBinary && syntaxFacts.IsBinaryExpression(expression))
            {
                return(GetNegationOfBinaryExpression(expression, generator, generatorInternal, semanticModel, cancellationToken));
            }
            else if (syntaxFacts.IsLiteralExpression(expression))
            {
                return(GetNegationOfLiteralExpression(expression, generator, semanticModel));
            }
            else if (syntaxFacts.IsLogicalNotExpression(expression))
            {
                return(GetNegationOfLogicalNotExpression(expression, syntaxFacts));
            }

            return(generator.LogicalNotExpression(expression));
        }
Esempio n. 17
0
 private static TExpressionSyntax MakeRef(SyntaxGeneratorInternal generator, bool isRef, TExpressionSyntax syntaxNode)
 => isRef ? (TExpressionSyntax)generator.RefExpression(syntaxNode) : syntaxNode;
Esempio n. 18
0
        public static ImmutableArray <SyntaxNode> CreateGetHashCodeMethodStatements(
            this SyntaxGenerator factory,
            SyntaxGeneratorInternal generatorInternal,
            Compilation compilation,
            INamedTypeSymbol containingType,
            ImmutableArray <ISymbol> members,
            bool useInt64)
        {
            var components = GetGetHashCodeComponents(
                factory, compilation, containingType, members, justMemberReference: false);

            if (components.Length == 0)
            {
                return(ImmutableArray.Create(factory.ReturnStatement(factory.LiteralExpression(0))));
            }

            const int hashFactor = -1521134295;

            var initHash     = 0;
            var baseHashCode = GetBaseGetHashCodeMethod(containingType);

            if (baseHashCode != null)
            {
                initHash = initHash * hashFactor + Hash.GetFNVHashCode(baseHashCode.Name);
            }

            foreach (var symbol in members)
            {
                initHash = initHash * hashFactor + Hash.GetFNVHashCode(symbol.Name);
            }

            if (components.Length == 1 && !useInt64)
            {
                // If there's just one value to hash, then we can compute and directly
                // return it.  i.e.  The full computation is:
                //
                //      return initHash * hashfactor + ...
                //
                // But as we know the values of initHash and hashFactor we can just compute
                // is here and directly inject the result value, producing:
                //
                //      return someHash + this.S1.GetHashCode();    // or

                var multiplyResult = initHash * hashFactor;
                return(ImmutableArray.Create(factory.ReturnStatement(
                                                 factory.AddExpression(
                                                     CreateLiteralExpression(factory, multiplyResult),
                                                     components[0]))));
            }

            var statements = ArrayBuilder <SyntaxNode> .GetInstance();

            // initialize the initial hashCode:
            //
            //      var hashCode = initialHashCode;

            const string HashCodeName = "hashCode";

            statements.Add(!useInt64
                ? factory.SimpleLocalDeclarationStatement(generatorInternal, compilation.GetSpecialType(SpecialType.System_Int32), HashCodeName, CreateLiteralExpression(factory, initHash))
                : factory.LocalDeclarationStatement(compilation.GetSpecialType(SpecialType.System_Int64), HashCodeName, CreateLiteralExpression(factory, initHash)));

            var hashCodeNameExpression = factory.IdentifierName(HashCodeName);

            // -1521134295
            var permuteValue = CreateLiteralExpression(factory, hashFactor);

            foreach (var component in components)
            {
                // hashCode = hashCode * -1521134295 + this.S.GetHashCode();
                var rightSide =
                    factory.AddExpression(
                        factory.MultiplyExpression(hashCodeNameExpression, permuteValue),
                        component);

                if (useInt64)
                {
                    rightSide = factory.InvocationExpression(
                        factory.MemberAccessExpression(rightSide, GetHashCodeName));
                }

                statements.Add(factory.ExpressionStatement(
                                   factory.AssignmentStatement(hashCodeNameExpression, rightSide)));
            }

            // And finally, the "return hashCode;" statement.
            statements.Add(!useInt64
                ? factory.ReturnStatement(hashCodeNameExpression)
                : factory.ReturnStatement(
                               factory.ConvertExpression(
                                   compilation.GetSpecialType(SpecialType.System_Int32),
                                   hashCodeNameExpression)));

            return(statements.ToImmutableAndFree());
        }
Esempio n. 19
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));
        }
Esempio n. 20
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 GetNegationOfIsPatternExpression(SyntaxNode isExpression, SyntaxGenerator generator, SyntaxGeneratorInternal generatorInternal, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            // Don't recurse into patterns if the language doesn't support negated patterns.
            // Just wrap with a normal '!' expression.
            var syntaxFacts = generatorInternal.SyntaxFacts;

            syntaxFacts.GetPartsOfIsPatternExpression(isExpression, out var left, out var isToken, out var pattern);

            SyntaxNode?negatedPattern = null;

            if (syntaxFacts.SupportsNotPattern(semanticModel.SyntaxTree.Options))
            {
                // We do support 'not' patterns.  So attempt to push a 'not' pattern into the current is-pattern RHS.
                negatedPattern = generator.Negate(generatorInternal, pattern, semanticModel, cancellationToken);
            }
            else if (syntaxFacts.IsNotPattern(pattern))
            {
                // we don't support 'not' patterns, but we have a 'not' pattern in code.  Do a simple unwrapping of it.
                negatedPattern = GetNegationOfNotPattern(pattern, generator, generatorInternal, syntaxFacts);
            }

            // Negating the pattern may have formed something illegal.  If so, just do a normal `!` negation.
            if (negatedPattern != null && IsLegalPattern(syntaxFacts, negatedPattern, designatorsLegal: true))
            {
                if (syntaxFacts.IsTypePattern(negatedPattern))
                {
                    // We started with `x is not t`.  Unwrap the type pattern for 't' and create a simple `is` binary expr `x is t`.
                    var type = syntaxFacts.GetTypeOfTypePattern(negatedPattern);
                    return(generator.IsTypeExpression(left, type));
                }
                else
                {
                    // Keep this as a normal `is-pattern`, just with the pattern portion negated.
                    return(generatorInternal.IsPatternExpression(left, isToken, negatedPattern));
                }
            }

            return(generator.LogicalNotExpression(isExpression));
        }