public static bool CanRefactor(
            ForEachStatementSyntax forEachStatement,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (forEachStatement == null)
            {
                throw new ArgumentNullException(nameof(forEachStatement));
            }

            if (semanticModel == null)
            {
                throw new ArgumentNullException(nameof(semanticModel));
            }

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(forEachStatement.Expression, cancellationToken);

            if (typeSymbol?.IsErrorType() == false)
            {
                return(typeSymbol.IsString() ||
                       typeSymbol.IsArrayType() ||
                       SymbolUtility.FindGetItemMethodWithInt32Parameter(typeSymbol)?.IsAccessible(forEachStatement.SpanStart, semanticModel) == true);
            }

            return(false);
        }
        internal static void Analyze(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax invocation, MemberAccessExpressionSyntax memberAccess)
        {
            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            if (semanticModel
                .GetExtensionMethodInfo(invocation, ExtensionMethodKind.Reduced, cancellationToken)
                .IsLinqExtensionOfIEnumerableOfTWithoutParameters("First", allowImmutableArrayExtension: true))
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(memberAccess.Expression, cancellationToken);

                if (typeSymbol != null &&
                    (typeSymbol.IsArrayType() || SymbolUtility.FindGetItemMethodWithInt32Parameter(typeSymbol)?.IsAccessible(invocation.SpanStart, semanticModel) == true))
                {
                    context.ReportDiagnostic(
                        DiagnosticDescriptors.UseElementAccessInsteadOfFirst,
                        memberAccess.Name);
                }
            }
        }
        private static async Task ProcessElementAtAsync(RefactoringContext context, InvocationExpressionSyntax invocation)
        {
            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            if (invocation.ArgumentList?.Arguments.Count == 1 &&
                semanticModel
                .GetExtensionMethodInfo(invocation, ExtensionMethodKind.Reduced, context.CancellationToken)
                .IsLinqElementAt(allowImmutableArrayExtension: true))
            {
                var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression;

                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(memberAccess.Expression, context.CancellationToken);

                if (typeSymbol != null &&
                    (typeSymbol.IsArrayType() || SymbolUtility.FindGetItemMethodWithInt32Parameter(typeSymbol)?.IsAccessible(invocation.SpanStart, semanticModel) == true))
                {
                    context.RegisterRefactoring(
                        "Use [] instead of calling 'ElementAt'",
                        cancellationToken => RefactorAsync(context.Document, invocation, null, cancellationToken));
                }
            }
        }
        private static async Task ProcessFirstOrLastAsync(RefactoringContext context, InvocationExpressionSyntax invocation, string methodName)
        {
            if (invocation.ArgumentList.Arguments.Count == 0)
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                if (semanticModel
                    .GetExtensionMethodInfo(invocation, ExtensionMethodKind.Reduced, context.CancellationToken)
                    .IsLinqExtensionOfIEnumerableOfTWithoutParameters(methodName, allowImmutableArrayExtension: true))
                {
                    var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression;

                    ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(memberAccess.Expression, context.CancellationToken);

                    if (typeSymbol != null &&
                        (typeSymbol.IsArrayType() || SymbolUtility.FindGetItemMethodWithInt32Parameter(typeSymbol)?.IsAccessible(invocation.SpanStart, semanticModel) == true))
                    {
                        string propertyName = GetCountOrLengthPropertyName(memberAccess.Expression, semanticModel, context.CancellationToken);

                        if (propertyName != null)
                        {
                            context.RegisterRefactoring(
                                $"Use [] instead of calling '{methodName}'",
                                cancellationToken =>
                            {
                                return(RefactorAsync(
                                           context.Document,
                                           invocation,
                                           propertyName,
                                           cancellationToken));
                            });
                        }
                    }
                }
            }
        }