File: ConvertLinq\ConvertForEachToLinqQuery\ToToListConverter.cs
Web Access
Project: src\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.ConvertLinq.ConvertForEachToLinqQuery;
using Microsoft.CodeAnalysis.CSharp.Syntax;
 
namespace Microsoft.CodeAnalysis.CSharp.ConvertLinq.ConvertForEachToLinqQuery;
 
/// <summary>
/// Provides a conversion to query.ToList().
/// </summary>
internal sealed class ToToListConverter(
    ForEachInfo<ForEachStatementSyntax, StatementSyntax> forEachInfo,
    ExpressionSyntax selectExpression,
    ExpressionSyntax modifyingExpression,
    SyntaxTrivia[] trivia) : AbstractToMethodConverter(forEachInfo, selectExpression, modifyingExpression, trivia)
{
    protected override string MethodName => nameof(Enumerable.ToList);
 
    /// Checks that the expression is "new List();"
    /// Exclude "new List(a);" and new List() { 1, 2, 3}
    protected override bool CanReplaceInitialization(
        ExpressionSyntax expression, CancellationToken cancellationToken)
        => expression is ObjectCreationExpressionSyntax objectCreationExpression &&
           ForEachInfo.SemanticModel.GetSymbolInfo(objectCreationExpression.Type, cancellationToken).Symbol is ITypeSymbol typeSymbol &&
           CSharpConvertForEachToLinqQueryProvider.TypeSymbolIsList(typeSymbol, ForEachInfo.SemanticModel) &&
           (objectCreationExpression.ArgumentList == null || !objectCreationExpression.ArgumentList.Arguments.Any()) &&
           (objectCreationExpression.Initializer == null || !objectCreationExpression.Initializer.Expressions.Any());
 
    /// Input:
    /// foreach(...)
    /// {
    ///     ...
    ///     ...
    ///     list.Add(item);
    ///  }
    ///  
    ///  Output:
    ///  list.AddRange(queryGenerated);
    protected override StatementSyntax CreateDefaultStatement(ExpressionSyntax queryOrLinqInvocationExpression, ExpressionSyntax expression)
        => SyntaxFactory.ExpressionStatement(
            SyntaxFactory.InvocationExpression(
                SyntaxFactory.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    expression,
                    SyntaxFactory.IdentifierName(nameof(List<object>.AddRange))),
                SyntaxFactory.ArgumentList([SyntaxFactory.Argument(queryOrLinqInvocationExpression)])));
}