Skip to content

PooledObjects cleanup #78382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Roslyn.sln
Original file line number Diff line number Diff line change
Expand Up @@ -2185,6 +2185,7 @@ Global
src\RoslynAnalyzers\Utilities\Workspaces\Workspaces.Utilities.projitems*{3f65d29d-ed95-2d6f-b927-47c5cf070aa5}*SharedItemsImports = 5
src\Dependencies\Contracts\Microsoft.CodeAnalysis.Contracts.projitems*{41ed1bfa-fdad-4fe4-8118-db23fb49b0b0}*SharedItemsImports = 5
src\Workspaces\SharedUtilitiesAndExtensions\Workspace\CSharp\CSharpWorkspaceExtensions.projitems*{438db8af-f3f0-4ed9-80b5-13fddd5b8787}*SharedItemsImports = 13
src\Dependencies\Contracts\Microsoft.CodeAnalysis.Contracts.projitems*{49e7c367-181b-499c-ac2e-8e17c81418d6}*SharedItemsImports = 5
src\Compilers\CSharp\csc\CscCommandLine.projitems*{4b45ca0c-03a0-400f-b454-3d4bcb16af38}*SharedItemsImports = 5
src\RoslynAnalyzers\Utilities\Refactoring.VisualBasic\Refactoring.VisualBasic.Utilities.projitems*{4c362c30-c4b1-4c4b-a545-dbf67c7e9153}*SharedItemsImports = 13
src\Analyzers\CSharp\Tests\CSharpAnalyzers.UnitTests.projitems*{5018d049-5870-465a-889b-c742ce1e31cb}*SharedItemsImports = 5
Expand Down Expand Up @@ -2221,6 +2222,7 @@ Global
src\RoslynAnalyzers\Utilities\Compiler\Analyzer.Utilities.projitems*{8ce66034-25e2-8ff2-93a1-0bd3672ad86d}*SharedItemsImports = 5
src\Dependencies\Collections\Microsoft.CodeAnalysis.Collections.projitems*{8e2a252e-a140-45a6-a81a-2652996ea589}*SharedItemsImports = 5
src\Dependencies\Contracts\Microsoft.CodeAnalysis.Contracts.projitems*{8e2a252e-a140-45a6-a81a-2652996ea589}*SharedItemsImports = 5
src\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems*{8e2a252e-a140-45a6-a81a-2652996ea589}*SharedItemsImports = 5
src\Dependencies\Threading\Microsoft.CodeAnalysis.Threading.projitems*{8e2a252e-a140-45a6-a81a-2652996ea589}*SharedItemsImports = 5
src\RoslynAnalyzers\Utilities\Compiler\Analyzer.Utilities.projitems*{923e34ba-ca8a-971e-7ff7-51dd346394a1}*SharedItemsImports = 5
src\RoslynAnalyzers\Utilities\Workspaces\Workspaces.Utilities.projitems*{923e34ba-ca8a-971e-7ff7-51dd346394a1}*SharedItemsImports = 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)

var additionalLocations = ArrayBuilder<Location>.GetInstance();
additionalLocations.Add(switchStatement.GetLocation());
additionalLocations.AddOptional(declaratorToRemoveOpt?.GetLocation());
additionalLocations.AddIfNotNull(declaratorToRemoveOpt?.GetLocation());

context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor,
// Report the diagnostic on the "switch" keyword.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1687,7 +1687,7 @@ private ImmutableArray<ISymbol> LookupSymbolsInternal(
}

if (name == null)
results.RemoveWhere(static (symbol, _, _) => !symbol.CanBeReferencedByName, arg: 0);
results.RemoveAll(static (symbol, _) => !symbol.CanBeReferencedByName, arg: 0);

return results.ToImmutableAndFree();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public static LoweredDynamicOperation Bad(
TypeSymbol resultType)
{
var children = ArrayBuilder<BoundExpression>.GetInstance();
children.AddOptional(loweredReceiver);
children.AddIfNotNull(loweredReceiver);
children.AddRange(loweredArguments);
children.AddOptional(loweredRight);
children.AddIfNotNull(loweredRight);

return LoweredDynamicOperation.Bad(resultType, children.ToImmutableAndFree());
}
Expand Down
263 changes: 2 additions & 261 deletions src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,257 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
{
internal static class ArrayBuilderExtensions
{
public static bool Any<T>(this ArrayBuilder<T> builder, Func<T, bool> predicate)
{
foreach (var item in builder)
{
if (predicate(item))
{
return true;
}
}
return false;
}

public static bool Any<T, A>(this ArrayBuilder<T> builder, Func<T, A, bool> predicate, A arg)
{
foreach (var item in builder)
{
if (predicate(item, arg))
{
return true;
}
}
return false;
}

public static bool All<T>(this ArrayBuilder<T> builder, Func<T, bool> predicate)
{
foreach (var item in builder)
{
if (!predicate(item))
{
return false;
}
}
return true;
}

public static bool All<T, A>(this ArrayBuilder<T> builder, Func<T, A, bool> predicate, A arg)
{
foreach (var item in builder)
{
if (!predicate(item, arg))
{
return false;
}
}
return true;
}

/// <summary>
/// Maps an array builder to immutable array.
/// </summary>
/// <typeparam name="TItem"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="items">The array to map</param>
/// <param name="map">The mapping delegate</param>
/// <returns>If the items's length is 0, this will return an empty immutable array</returns>
public static ImmutableArray<TResult> SelectAsArray<TItem, TResult>(this ArrayBuilder<TItem> items, Func<TItem, TResult> map)
{
switch (items.Count)
{
case 0:
return ImmutableArray<TResult>.Empty;

case 1:
return ImmutableArray.Create(map(items[0]));

case 2:
return ImmutableArray.Create(map(items[0]), map(items[1]));

case 3:
return ImmutableArray.Create(map(items[0]), map(items[1]), map(items[2]));

case 4:
return ImmutableArray.Create(map(items[0]), map(items[1]), map(items[2]), map(items[3]));

default:
var builder = ArrayBuilder<TResult>.GetInstance(items.Count);
foreach (var item in items)
{
builder.Add(map(item));
}

return builder.ToImmutableAndFree();
}
}

/// <summary>
/// Maps an array builder to immutable array.
/// </summary>
/// <typeparam name="TItem"></typeparam>
/// <typeparam name="TArg"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="items">The sequence to map</param>
/// <param name="map">The mapping delegate</param>
/// <param name="arg">The extra input used by mapping delegate</param>
/// <returns>If the items's length is 0, this will return an empty immutable array.</returns>
public static ImmutableArray<TResult> SelectAsArray<TItem, TArg, TResult>(this ArrayBuilder<TItem> items, Func<TItem, TArg, TResult> map, TArg arg)
{
switch (items.Count)
{
case 0:
return ImmutableArray<TResult>.Empty;

case 1:
return ImmutableArray.Create(map(items[0], arg));

case 2:
return ImmutableArray.Create(map(items[0], arg), map(items[1], arg));

case 3:
return ImmutableArray.Create(map(items[0], arg), map(items[1], arg), map(items[2], arg));

case 4:
return ImmutableArray.Create(map(items[0], arg), map(items[1], arg), map(items[2], arg), map(items[3], arg));

default:
var builder = ArrayBuilder<TResult>.GetInstance(items.Count);
foreach (var item in items)
{
builder.Add(map(item, arg));
}

return builder.ToImmutableAndFree();
}
}

/// <summary>
/// Maps an array builder to immutable array.
/// </summary>
/// <typeparam name="TItem"></typeparam>
/// <typeparam name="TArg"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="items">The sequence to map</param>
/// <param name="map">The mapping delegate</param>
/// <param name="arg">The extra input used by mapping delegate</param>
/// <returns>If the items's length is 0, this will return an empty immutable array.</returns>
public static ImmutableArray<TResult> SelectAsArrayWithIndex<TItem, TArg, TResult>(this ArrayBuilder<TItem> items, Func<TItem, int, TArg, TResult> map, TArg arg)
{
switch (items.Count)
{
case 0:
return ImmutableArray<TResult>.Empty;

case 1:
return ImmutableArray.Create(map(items[0], 0, arg));

case 2:
return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg));

case 3:
return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg), map(items[2], 2, arg));

case 4:
return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg), map(items[2], 2, arg), map(items[3], 3, arg));

default:
var builder = ArrayBuilder<TResult>.GetInstance(items.Count);
foreach (var item in items)
{
builder.Add(map(item, builder.Count, arg));
}

return builder.ToImmutableAndFree();
}
}

public static void AddOptional<T>(this ArrayBuilder<T> builder, T? item)
where T : class
{
if (item != null)
{
builder.Add(item);
}
}

// The following extension methods allow an ArrayBuilder to be used as a stack.
// Note that the order of an IEnumerable from a List is from bottom to top of stack. An IEnumerable
// from the framework Stack is from top to bottom.
public static void Push<T>(this ArrayBuilder<T> builder, T e)
{
builder.Add(e);
}

public static T Pop<T>(this ArrayBuilder<T> builder)
{
var e = builder.Peek();
builder.RemoveAt(builder.Count - 1);
return e;
}

public static bool TryPop<T>(this ArrayBuilder<T> builder, [MaybeNullWhen(false)] out T result)
{
if (builder.Count > 0)
{
result = builder.Pop();
return true;
}

result = default;
return false;
}

public static T Peek<T>(this ArrayBuilder<T> builder)
{
return builder[builder.Count - 1];
}

public static ImmutableArray<T> ToImmutableOrEmptyAndFree<T>(this ArrayBuilder<T>? builder)
{
return builder?.ToImmutableAndFree() ?? ImmutableArray<T>.Empty;
}

public static void AddIfNotNull<T>(this ArrayBuilder<T> builder, T? value)
where T : struct
{
if (value != null)
{
builder.Add(value.Value);
}
}

public static void AddIfNotNull<T>(this ArrayBuilder<T> builder, T? value)
where T : class
{
if (value != null)
{
builder.Add(value);
}
}

public static void FreeAll<T>(this ArrayBuilder<T> builder, Func<T, ArrayBuilder<T>?> getNested)
{
foreach (var item in builder)
{
getNested(item)?.FreeAll(getNested);
}
builder.Free();
}

#if COMPILERCORE

/// <summary>
/// Realizes the OneOrMany and disposes the builder in one operation.
/// </summary>
Expand All @@ -270,24 +26,9 @@ public static OneOrMany<T> ToOneOrManyAndFree<T>(this ArrayBuilder<T> builder)
}
}

#endif

public static void RemoveWhere<TItem, TArg>(this ArrayBuilder<TItem> builder, Func<TItem, int, TArg, bool> filter, TArg arg)
public static void AddRange<T>(this ArrayBuilder<T> builder, OneOrMany<T> items)
{
var writeIndex = 0;
for (var i = 0; i < builder.Count; i++)
{
var item = builder[i];
if (!filter(item, i, arg))
{
if (writeIndex != i)
builder[writeIndex] = item;

writeIndex++;
}
}

builder.Count = writeIndex;
items.AddRangeTo(builder);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ private ImmutableArray<TAttributeData> GetAttributes(TPEModuleBuilder moduleBuil
{
if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out var constructorArguments, out var namedArguments, syntaxNodeOpt, diagnostics))
{
builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_DispIdAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
builder.AddIfNotNull(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_DispIdAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
}
}
else
{
builder.AddOptional(PortAttributeIfNeedTo(attrData, syntaxNodeOpt, diagnostics));
builder.AddIfNotNull(PortAttributeIfNeedTo(attrData, syntaxNodeOpt, diagnostics));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,21 @@ private ImmutableArray<TAttributeData> GetAttributes(TPEModuleBuilder moduleBuil
{
if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
{
builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_ParamArrayAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
builder.AddIfNotNull(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_ParamArrayAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
}
}
else if (IsTargetAttribute(attrData, AttributeDescription.DateTimeConstantAttribute, out signatureIndex))
{
if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
{
builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_DateTimeConstantAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
builder.AddIfNotNull(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_DateTimeConstantAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
}
}
else if (IsTargetAttribute(attrData, AttributeDescription.DecimalConstantAttribute, out signatureIndex))
{
if ((signatureIndex == 0 || signatureIndex == 1) && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
{
builder.AddOptional(TypeManager.CreateSynthesizedAttribute(
builder.AddIfNotNull(TypeManager.CreateSynthesizedAttribute(
signatureIndex == 0 ? WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctor :
WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctorByteByteInt32Int32Int32,
constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
Expand All @@ -121,7 +121,7 @@ private ImmutableArray<TAttributeData> GetAttributes(TPEModuleBuilder moduleBuil
{
if (signatureIndex == 0 && TypeManager.TryGetAttributeArguments(attrData, out constructorArguments, out namedArguments, syntaxNodeOpt, diagnostics))
{
builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_DefaultParameterValueAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
builder.AddIfNotNull(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_DefaultParameterValueAttribute__ctor, constructorArguments, namedArguments, syntaxNodeOpt, diagnostics));
}
}
}
Expand Down
Loading