File: ConvertLinq\ConvertForEachToLinqQuery\ToToListConverter.cs
Web Access
Project: ..\..\..\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 : AbstractToMethodConverter
    {
        public ToToListConverter(
            ForEachInfo<ForEachStatementSyntax, StatementSyntax> forEachInfo,
            ExpressionSyntax selectExpression,
            ExpressionSyntax modifyingExpression,
            SyntaxTrivia[] trivia)
            : base(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.SingletonSeparatedList(SyntaxFactory.Argument(queryOrLinqInvocationExpression)))));
    }
}