Skip to content

Commit 4524dbf

Browse files
Use Linq helpers. (#79775)
2 parents 498e8d3 + 042a013 commit 4524dbf

File tree

99 files changed

+375
-487
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+375
-487
lines changed

src/Analyzers/CSharp/CodeFixes/AssignOutParameters/AbstractAssignOutParametersCodeFixProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ private static bool IsValidLocation(SyntaxNode location)
111111

112112
var outParameters = parameterList.Parameters
113113
.Select(p => semanticModel.GetRequiredDeclaredSymbol(p, cancellationToken))
114-
.Where(p => p.RefKind == RefKind.Out)
115-
.ToImmutableArray();
114+
.WhereAsArray(p => p.RefKind == RefKind.Out);
116115

117116
var distinctExprsOrStatements = group.Select(t => t.exprOrStatement).Distinct();
118117
foreach (var exprOrStatement in distinctExprsOrStatements)

src/Analyzers/Core/CodeFixes/GenerateConstructor/AbstractGenerateConstructorService.State.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ private async Task<bool> TryInitializeAsync(
123123
private async Task InitializeNonDelegatedConstructorAsync(CancellationToken cancellationToken)
124124
{
125125
Contract.ThrowIfNull(TypeToGenerateIn);
126-
var typeParametersNames = TypeToGenerateIn.GetAllTypeParameters().Select(t => t.Name).ToImmutableArray();
126+
var typeParametersNames = TypeToGenerateIn.GetAllTypeParameters().SelectAsArray(t => t.Name);
127127
var parameterNames = GetParameterNames(_arguments, typeParametersNames, cancellationToken);
128128

129129
(_parameters, _parameterToExistingMemberMap, ParameterToNewFieldMap, ParameterToNewPropertyMap) =

src/Analyzers/Core/CodeFixes/ImplementInterface/ImplementHelpers.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.CodeAnalysis.LanguageService;
1111
using Microsoft.CodeAnalysis.PooledObjects;
1212
using Microsoft.CodeAnalysis.Shared.Extensions;
13+
using Roslyn.Utilities;
1314

1415
namespace Microsoft.CodeAnalysis.ImplementInterface;
1516

@@ -25,15 +26,11 @@ public static ImmutableArray<ISymbol> GetDelegatableMembers(
2526

2627
var fields = namedType.GetMembers()
2728
.OfType<IFieldSymbol>()
28-
.Where(f => !f.IsImplicitlyDeclared)
29-
.Where(f => includeMemberType(f.Type))
30-
.ToImmutableArray();
29+
.WhereAsArray(f => !f.IsImplicitlyDeclared && includeMemberType(f.Type));
3130

3231
var properties = namedType.GetMembers()
3332
.OfType<IPropertySymbol>()
34-
.Where(p => !p.IsImplicitlyDeclared && p.Parameters.Length == 0 && p.GetMethod != null)
35-
.Where(p => includeMemberType(p.Type))
36-
.ToImmutableArray();
33+
.WhereAsArray(p => !p.IsImplicitlyDeclared && p.Parameters.Length == 0 && p.GetMethod != null && includeMemberType(p.Type));
3734

3835
var parameters = GetNonCapturedPrimaryConstructorParameters(fields, properties);
3936

src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.CustomFixAllProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ private static async Task<Solution> FixAllByDocumentAsync(
7676
// the tree won't be the same.
7777
var documentIdToDiagnosticsMap = diagnostics
7878
.GroupBy(diagnostic => diagnostic.Location.SourceTree)
79-
.Where(group => group.Key is not null)
80-
.SelectAsArray(group => (id: solution.GetRequiredDocument(group.Key!).Id, diagnostics: group.ToImmutableArray()));
79+
.SelectAsArray(
80+
predicate: group => group.Key is not null,
81+
selector: group => (id: solution.GetRequiredDocument(group.Key!).Id, diagnostics: group.ToImmutableArray()));
8182

8283
var newSolution = solution;
8384

src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,9 +829,8 @@ private async Task<SyntaxNode> AdjustLocalDeclarationsAsync(
829829
var originalDocument = document;
830830
var originalDeclStatementsToMoveOrRemove =
831831
memberDeclaration.DescendantNodes()
832-
.Where(n => n.HasAnnotation(s_newLocalDeclarationStatementAnnotation) ||
833-
n.HasAnnotation(s_existingLocalDeclarationWithoutInitializerAnnotation))
834-
.ToImmutableArray();
832+
.WhereAsArray(n => n.HasAnnotation(s_newLocalDeclarationStatementAnnotation) ||
833+
n.HasAnnotation(s_existingLocalDeclarationWithoutInitializerAnnotation));
835834
if (originalDeclStatementsToMoveOrRemove.IsEmpty)
836835
{
837836
return memberDeclaration;

src/Dependencies/Collections/Extensions/IEnumerableExtensions.cs

Lines changed: 106 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
using System.Collections.Immutable;
1111
using System.Collections.ObjectModel;
1212
using System.Diagnostics;
13+
using System.Diagnostics.CodeAnalysis;
1314
using System.Linq;
14-
using System.Runtime.InteropServices;
1515
using System.Threading;
1616
using System.Threading.Tasks;
1717
using Microsoft.CodeAnalysis;
@@ -331,9 +331,66 @@ public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> source)
331331
return source.Where((Func<T?, bool>)s_notNullTest)!;
332332
}
333333

334+
/// <summary>
335+
/// Uses a builder to store results computed from <paramref name="source"/>. If <paramref name="source"/> is
336+
/// null, or definitely empty, this returns false, allowing the caller to immediately return <c>[]</c> without
337+
/// further allocations. If this returns true, then <paramref name="builder"/> will be set to an appropriate
338+
/// builder to receive temporary values.
339+
/// </summary>
340+
/// <param name="useCountForBuilder">If the count of <paramref name="source"/> can be determined (and is non-zero),
341+
/// if <paramref name="builder"/> should be initialized to that same count. This should be passed true
342+
/// for 'SelectAsArray' methods, and false for 'WhereAsArray' or 'SelectManyAsArray' methods (as the latter two
343+
/// do not know how many items will be added to the builder).</param>
344+
private static bool TryGetBuilder<TSource, TResult>(
345+
[NotNullWhen(true)] IEnumerable<TSource>? source,
346+
bool useCountForBuilder,
347+
[NotNullWhen(true)] out ArrayBuilder<TResult>? builder)
348+
{
349+
if (source is null)
350+
{
351+
builder = null;
352+
return false;
353+
}
354+
355+
#if NET
356+
if (source.TryGetNonEnumeratedCount(out var count))
357+
{
358+
if (count == 0)
359+
{
360+
builder = null;
361+
return false;
362+
}
363+
364+
if (useCountForBuilder)
365+
{
366+
builder = ArrayBuilder<TResult>.GetInstance(count);
367+
return true;
368+
}
369+
}
370+
#endif
371+
372+
builder = ArrayBuilder<TResult>.GetInstance();
373+
return true;
374+
}
375+
376+
public static ImmutableArray<T> WhereAsArray<T>(this IEnumerable<T> values, Func<T, bool> predicate)
377+
{
378+
if (!TryGetBuilder<T, T>(values, useCountForBuilder: false, out var builder))
379+
return [];
380+
381+
foreach (var value in values)
382+
{
383+
if (predicate(value))
384+
builder.Add(value);
385+
}
386+
387+
return builder.ToImmutableAndFree();
388+
}
389+
334390
public static ImmutableArray<T> WhereAsArray<T, TArg>(this IEnumerable<T> values, Func<T, TArg, bool> predicate, TArg arg)
335391
{
336-
var result = ArrayBuilder<T>.GetInstance();
392+
if (!TryGetBuilder<T, T>(values, useCountForBuilder: false, out var result))
393+
return [];
337394

338395
foreach (var value in values)
339396
{
@@ -349,25 +406,34 @@ public static T[] AsArray<T>(this IEnumerable<T> source)
349406

350407
public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IEnumerable<TSource>? source, Func<TSource, TResult> selector)
351408
{
352-
if (source == null)
353-
{
354-
return ImmutableArray<TResult>.Empty;
355-
}
409+
if (!TryGetBuilder<TSource, TResult>(source, useCountForBuilder: true, out var builder))
410+
return [];
356411

357-
var builder = ArrayBuilder<TResult>.GetInstance();
358412
builder.AddRange(source.Select(selector));
413+
return builder.ToImmutableAndFree();
414+
415+
}
416+
417+
public static ImmutableArray<TResult> SelectAsArray<TItem, TResult>(this IEnumerable<TItem>? source, Func<TItem, bool> predicate, Func<TItem, TResult> selector)
418+
{
419+
if (!TryGetBuilder<TItem, TResult>(source, useCountForBuilder: false, out var builder))
420+
return [];
421+
422+
foreach (var item in source)
423+
{
424+
if (predicate(item))
425+
builder.Add(selector(item));
426+
}
359427

360428
return builder.ToImmutableAndFree();
361429
}
362430

363431
public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IEnumerable<TSource>? source, Func<TSource, int, TResult> selector)
364432
{
365-
if (source == null)
366-
return ImmutableArray<TResult>.Empty;
433+
if (!TryGetBuilder<TSource, TResult>(source, useCountForBuilder: true, out var builder))
434+
return [];
367435

368-
var builder = ArrayBuilder<TResult>.GetInstance();
369-
370-
int index = 0;
436+
var index = 0;
371437
foreach (var element in source)
372438
{
373439
builder.Add(selector(element, index));
@@ -379,42 +445,33 @@ public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IEnum
379445

380446
public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IReadOnlyCollection<TSource>? source, Func<TSource, TResult> selector)
381447
{
382-
if (source == null)
383-
return ImmutableArray<TResult>.Empty;
448+
if (source is null or { Count: 0 })
449+
return [];
384450

385-
var builder = new TResult[source.Count];
386-
var index = 0;
451+
var builder = new FixedSizeArrayBuilder<TResult>(source.Count);
387452
foreach (var item in source)
388-
{
389-
builder[index] = selector(item);
390-
index++;
391-
}
453+
builder.Add(selector(item));
392454

393-
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
455+
return builder.MoveToImmutable();
394456
}
395457

396458
public static ImmutableArray<TResult> SelectAsArray<TSource, TResult, TArg>(this IReadOnlyCollection<TSource>? source, Func<TSource, TArg, TResult> selector, TArg arg)
397459
{
398-
if (source == null)
399-
return ImmutableArray<TResult>.Empty;
460+
if (source is null or { Count: 0 })
461+
return [];
400462

401-
var builder = new TResult[source.Count];
402-
var index = 0;
463+
var builder = new FixedSizeArrayBuilder<TResult>(source.Count);
403464
foreach (var item in source)
404-
{
405-
builder[index] = selector(item, arg);
406-
index++;
407-
}
465+
builder.Add(selector(item, arg));
408466

409-
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
467+
return builder.MoveToImmutable();
410468
}
411469

412470
public static ImmutableArray<TResult> SelectManyAsArray<TSource, TResult>(this IEnumerable<TSource>? source, Func<TSource, IEnumerable<TResult>> selector)
413471
{
414-
if (source == null)
415-
return ImmutableArray<TResult>.Empty;
472+
if (!TryGetBuilder<TSource, TResult>(source, useCountForBuilder: false, out var builder))
473+
return [];
416474

417-
var builder = ArrayBuilder<TResult>.GetInstance();
418475
foreach (var item in source)
419476
builder.AddRange(selector(item));
420477

@@ -423,10 +480,9 @@ public static ImmutableArray<TResult> SelectManyAsArray<TSource, TResult>(this I
423480

424481
public static ImmutableArray<TResult> SelectManyAsArray<TItem, TArg, TResult>(this IEnumerable<TItem>? source, Func<TItem, TArg, IEnumerable<TResult>> selector, TArg arg)
425482
{
426-
if (source == null)
427-
return ImmutableArray<TResult>.Empty;
483+
if (!TryGetBuilder<TItem, TResult>(source, useCountForBuilder: false, out var builder))
484+
return [];
428485

429-
var builder = ArrayBuilder<TResult>.GetInstance();
430486
foreach (var item in source)
431487
builder.AddRange(selector(item, arg));
432488

@@ -435,8 +491,8 @@ public static ImmutableArray<TResult> SelectManyAsArray<TItem, TArg, TResult>(th
435491

436492
public static ImmutableArray<TResult> SelectManyAsArray<TItem, TResult>(this IReadOnlyCollection<TItem>? source, Func<TItem, IEnumerable<TResult>> selector)
437493
{
438-
if (source == null)
439-
return ImmutableArray<TResult>.Empty;
494+
if (source is null or { Count: 0 })
495+
return [];
440496

441497
// Basic heuristic. Assume each element in the source adds one item to the result.
442498
var builder = ArrayBuilder<TResult>.GetInstance(source.Count);
@@ -448,8 +504,8 @@ public static ImmutableArray<TResult> SelectManyAsArray<TItem, TResult>(this IRe
448504

449505
public static ImmutableArray<TResult> SelectManyAsArray<TItem, TArg, TResult>(this IReadOnlyCollection<TItem>? source, Func<TItem, TArg, IEnumerable<TResult>> selector, TArg arg)
450506
{
451-
if (source == null)
452-
return ImmutableArray<TResult>.Empty;
507+
if (source is null or { Count: 0 })
508+
return [];
453509

454510
// Basic heuristic. Assume each element in the source adds one item to the result.
455511
var builder = ArrayBuilder<TResult>.GetInstance(source.Count);
@@ -461,10 +517,9 @@ public static ImmutableArray<TResult> SelectManyAsArray<TItem, TArg, TResult>(th
461517

462518
public static ImmutableArray<TResult> SelectManyAsArray<TSource, TResult>(this IEnumerable<TSource>? source, Func<TSource, OneOrMany<TResult>> selector)
463519
{
464-
if (source == null)
465-
return ImmutableArray<TResult>.Empty;
520+
if (!TryGetBuilder<TSource, TResult>(source, useCountForBuilder: false, out var builder))
521+
return [];
466522

467-
var builder = ArrayBuilder<TResult>.GetInstance();
468523
foreach (var item in source)
469524
selector(item).AddRangeTo(builder);
470525

@@ -476,12 +531,11 @@ public static ImmutableArray<TResult> SelectManyAsArray<TSource, TResult>(this I
476531
/// </summary>
477532
public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem, TResult>(this IEnumerable<TItem> source, Func<TItem, ValueTask<TResult>> selector)
478533
{
479-
var builder = ArrayBuilder<TResult>.GetInstance();
534+
if (!TryGetBuilder<TItem, TResult>(source, useCountForBuilder: true, out var builder))
535+
return [];
480536

481537
foreach (var item in source)
482-
{
483538
builder.Add(await selector(item).ConfigureAwait(false));
484-
}
485539

486540
return builder.ToImmutableAndFree();
487541
}
@@ -491,12 +545,11 @@ public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem,
491545
/// </summary>
492546
public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem, TResult>(this IEnumerable<TItem> source, Func<TItem, CancellationToken, ValueTask<TResult>> selector, CancellationToken cancellationToken)
493547
{
494-
var builder = ArrayBuilder<TResult>.GetInstance();
548+
if (!TryGetBuilder<TItem, TResult>(source, useCountForBuilder: true, out var builder))
549+
return [];
495550

496551
foreach (var item in source)
497-
{
498552
builder.Add(await selector(item, cancellationToken).ConfigureAwait(false));
499-
}
500553

501554
return builder.ToImmutableAndFree();
502555
}
@@ -506,24 +559,22 @@ public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem,
506559
/// </summary>
507560
public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem, TArg, TResult>(this IEnumerable<TItem> source, Func<TItem, TArg, CancellationToken, ValueTask<TResult>> selector, TArg arg, CancellationToken cancellationToken)
508561
{
509-
var builder = ArrayBuilder<TResult>.GetInstance();
562+
if (!TryGetBuilder<TItem, TResult>(source, useCountForBuilder: true, out var builder))
563+
return [];
510564

511565
foreach (var item in source)
512-
{
513566
builder.Add(await selector(item, arg, cancellationToken).ConfigureAwait(false));
514-
}
515567

516568
return builder.ToImmutableAndFree();
517569
}
518570

519571
public static async ValueTask<ImmutableArray<TResult>> SelectManyAsArrayAsync<TItem, TArg, TResult>(this IEnumerable<TItem> source, Func<TItem, TArg, CancellationToken, ValueTask<IEnumerable<TResult>>> selector, TArg arg, CancellationToken cancellationToken)
520572
{
521-
var builder = ArrayBuilder<TResult>.GetInstance();
573+
if (!TryGetBuilder<TItem, TResult>(source, useCountForBuilder: false, out var builder))
574+
return [];
522575

523576
foreach (var item in source)
524-
{
525577
builder.AddRange(await selector(item, arg, cancellationToken).ConfigureAwait(false));
526-
}
527578

528579
return builder.ToImmutableAndFree();
529580
}

0 commit comments

Comments
 (0)