private static async Task <Document> UsePatternMatchingAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            IsKindExpressionInfo isKindExpression = IsKindExpressionInfo.Create(ifStatement.Condition, semanticModel, cancellationToken: cancellationToken);

            switch (isKindExpression.Style)
            {
            case IsKindExpressionStyle.IsKind:
            case IsKindExpressionStyle.IsKindConditional:
            case IsKindExpressionStyle.Kind:
            case IsKindExpressionStyle.KindConditional:
            {
                var block = (BlockSyntax)ifStatement.Statement;

                IsPatternExpressionSyntax isPatternExpression = CreateIsPatternExpression(block.Statements[0]);

                BlockSyntax newBlock = block.WithStatements(block.Statements.RemoveAt(0));

                IfStatementSyntax newIfStatement = ifStatement.Update(
                    ifStatement.IfKeyword,
                    ifStatement.OpenParenToken,
                    isPatternExpression,
                    ifStatement.CloseParenToken,
                    newBlock,
                    ifStatement.Else);

                newIfStatement = newIfStatement.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false));
            }

            case IsKindExpressionStyle.NotIsKind:
            case IsKindExpressionStyle.NotIsKindConditional:
            case IsKindExpressionStyle.NotKind:
            case IsKindExpressionStyle.NotKindConditional:
            {
                StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

                SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

                int index = statements.IndexOf(ifStatement);

                IsPatternExpressionSyntax isPatternExpression = CreateIsPatternExpression(statements[index + 1]);

                IfStatementSyntax newIfStatement = ifStatement.WithCondition(LogicalNotExpression(isPatternExpression.Parenthesize()).WithTriviaFrom(ifStatement.Condition));

                SyntaxList <StatementSyntax> newStatements = statements
                                                             .ReplaceAt(index, newIfStatement)
                                                             .RemoveAt(index + 1);

                return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));
            }

            default:
            {
                throw new InvalidOperationException();
            }
            }

            IsPatternExpressionSyntax CreateIsPatternExpression(StatementSyntax statement)
            {
                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement);

                var castExpression = (CastExpressionSyntax)localInfo.Value;

                return(IsPatternExpression(
                           isKindExpression.Expression,
                           DeclarationPattern(castExpression.Type, SingleVariableDesignation(localInfo.Identifier))));
            }
        }
        private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            IsKindExpressionInfo isKindExpression = IsKindExpressionInfo.Create(ifStatement.Condition, semanticModel, cancellationToken: cancellationToken);

            if (!isKindExpression.Success)
            {
                return;
            }

            Optional <object> optionalConstantValue = semanticModel.GetConstantValue(isKindExpression.KindExpression, cancellationToken);

            if (!optionalConstantValue.HasValue)
            {
                return;
            }

            if (!(optionalConstantValue.Value is ushort value))
            {
                return;
            }

            if (!_syntaxKindValuesToNames.TryGetValue(value, out string name))
            {
                return;
            }

            if (!_syntaxKindNames.Contains(name))
            {
                return;
            }

            switch (isKindExpression.Style)
            {
            case IsKindExpressionStyle.IsKind:
            case IsKindExpressionStyle.IsKindConditional:
            case IsKindExpressionStyle.Kind:
            case IsKindExpressionStyle.KindConditional:
            {
                if (!(ifStatement.Statement is BlockSyntax block))
                {
                    return;
                }

                Analyze(block.Statements.FirstOrDefault());
                break;
            }

            case IsKindExpressionStyle.NotIsKind:
            case IsKindExpressionStyle.NotIsKindConditional:
            case IsKindExpressionStyle.NotKind:
            case IsKindExpressionStyle.NotKindConditional:
            {
                if (ifStatement.Else != null)
                {
                    return;
                }

                StatementSyntax statement = ifStatement.Statement.SingleNonBlockStatementOrDefault();

                if (statement == null)
                {
                    return;
                }

                if (!CSharpFacts.IsJumpStatement(statement.Kind()))
                {
                    return;
                }

                Analyze(ifStatement.NextStatement());
                break;
            }
            }

            void Analyze(StatementSyntax statement)
            {
                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(statement);

                if (!localInfo.Success)
                {
                    return;
                }

                if (!(localInfo.Value is CastExpressionSyntax castExpression))
                {
                    return;
                }

                if (!IsFixableSyntaxSymbol(castExpression.Type, name, semanticModel, cancellationToken))
                {
                    return;
                }

                if (!CSharpFactory.AreEquivalent(isKindExpression.Expression, castExpression.Expression))
                {
                    return;
                }

                context.ReportDiagnostic(DiagnosticDescriptors.UsePatternMatching, ifStatement.IfKeyword);
            }
        }