Merge pull request #7960 from DustinCampbell/object-pools

Add object pooling infrastructure
This commit is contained in:
Dustin Campbell 2022-12-01 15:43:42 -08:00 коммит произвёл GitHub
Родитель 19db03aa11 3c35928f66
Коммит 942d44e61e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
58 изменённых файлов: 935 добавлений и 64 удалений

Просмотреть файл

@ -180,6 +180,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorSyntaxGenerator", "src
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Compiler Tests", "Compiler Tests", "{A5E2E4FA-6087-4C16-BB7A-89E23AA0F4E3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Common.Test", "src\Razor\test\Microsoft.AspNetCore.Razor.Common.Test\Microsoft.AspNetCore.Razor.Common.Test.csproj", "{23E48E5E-91FC-421E-B122-C7D084FCE39A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -756,6 +758,14 @@ Global
{A9F9B5E5-C5C2-4860-BE56-038C70ADBAC9}.Release|Any CPU.Build.0 = Release|Any CPU
{A9F9B5E5-C5C2-4860-BE56-038C70ADBAC9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
{A9F9B5E5-C5C2-4860-BE56-038C70ADBAC9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.Release|Any CPU.Build.0 = Release|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
{23E48E5E-91FC-421E-B122-C7D084FCE39A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -839,6 +849,7 @@ Global
{1360ABF4-752C-4069-84A9-8D1831281AF1} = {FB7C870E-A173-4F75-BE63-4EF39C79A759}
{97DE8703-467C-49A7-BCE4-42FF1FEC8AC2} = {FB7C870E-A173-4F75-BE63-4EF39C79A759}
{A9F9B5E5-C5C2-4860-BE56-038C70ADBAC9} = {FB7C870E-A173-4F75-BE63-4EF39C79A759}
{23E48E5E-91FC-421E-B122-C7D084FCE39A} = {92463391-81BE-462B-AC3C-78C6C760741F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0035341D-175A-4D05-95E6-F1C2785A1E26}

Просмотреть файл

@ -10,6 +10,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Telemetry" Version="$(MicrosoftVisualStudioTelemetryVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="$(MicrosoftVisualStudioThreadingPackageVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutablePackageVersion)" />

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class ArrayBuilderPool<T>
{
private class Policy : IPooledObjectPolicy<ImmutableArray<T>.Builder>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public ImmutableArray<T>.Builder Create() => ImmutableArray.CreateBuilder<T>();
public bool Return(ImmutableArray<T>.Builder builder)
{
var count = builder.Count;
builder.Clear();
if (count > DefaultPool.MaximumObjectSize)
{
builder.Capacity = DefaultPool.MaximumObjectSize;
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="ImmutableArray{T}.Builder"/> instances.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class ArrayBuilderPool<T>
{
public static readonly ObjectPool<ImmutableArray<T>.Builder> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject(out ImmutableArray<T>.Builder builder)
=> Default.GetPooledObject(out builder);
}

Просмотреть файл

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static class DefaultPool
{
public const int MaximumObjectSize = 512;
public static ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy)
where T : class
=> new DefaultObjectPool<T>(policy, 20);
}

Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class DictionaryPool<TKey, TValue>
where TKey : notnull
{
private class Policy : IPooledObjectPolicy<Dictionary<TKey, TValue>>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public Dictionary<TKey, TValue> Create() => new();
public bool Return(Dictionary<TKey, TValue> map)
{
var count = map.Count;
map.Clear();
return count <= DefaultPool.MaximumObjectSize;
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="Dictionary{TKey, TValue}"/> instances.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class DictionaryPool<TKey, TValue>
where TKey : notnull
{
public static readonly ObjectPool<Dictionary<TKey, TValue>> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject(out Dictionary<TKey, TValue> map)
=> Default.GetPooledObject(out map);
}

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class HashSetPool<T>
{
private class Policy : IPooledObjectPolicy<HashSet<T>>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public HashSet<T> Create() => new();
public bool Return(HashSet<T> set)
{
var count = set.Count;
set.Clear();
if (count > DefaultPool.MaximumObjectSize)
{
set.TrimExcess();
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="HashSet{T}"/> instances that compares items using default equality.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class HashSetPool<T>
{
public static readonly ObjectPool<HashSet<T>> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<HashSet<T>> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<HashSet<T>> GetPooledObject(out HashSet<T> set)
=> Default.GetPooledObject(out set);
}

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class ListPool<T>
{
private class Policy : IPooledObjectPolicy<List<T>>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public List<T> Create() => new();
public bool Return(List<T> list)
{
var count = list.Count;
list.Clear();
if (count > DefaultPool.MaximumObjectSize)
{
list.TrimExcess();
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="List{T}"/> instances.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class ListPool<T>
{
public static readonly ObjectPool<List<T>> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<List<T>> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<List<T>> GetPooledObject(out List<T> list)
=> Default.GetPooledObject(out list);
}

Просмотреть файл

@ -0,0 +1,99 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class PooledObjectExtensions
{
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject<T>(this ObjectPool<ImmutableArray<T>.Builder> pool)
=> new(pool);
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject<T>(
this ObjectPool<ImmutableArray<T>.Builder> pool,
out ImmutableArray<T>.Builder builder)
{
var pooledObject = pool.GetPooledObject();
builder = pooledObject.Object;
return pooledObject;
}
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject<TKey, TValue>(this ObjectPool<Dictionary<TKey, TValue>> pool)
where TKey : notnull
=> new(pool);
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject<TKey, TValue>(
this ObjectPool<Dictionary<TKey, TValue>> pool,
out Dictionary<TKey, TValue> map)
where TKey : notnull
{
var pooledObject = pool.GetPooledObject();
map = pooledObject.Object;
return pooledObject;
}
public static PooledObject<HashSet<T>> GetPooledObject<T>(this ObjectPool<HashSet<T>> pool)
=> new(pool);
public static PooledObject<HashSet<T>> GetPooledObject<T>(
this ObjectPool<HashSet<T>> pool,
out HashSet<T> set)
{
var pooledObject = pool.GetPooledObject();
set = pooledObject.Object;
return pooledObject;
}
public static PooledObject<List<T>> GetPooledObject<T>(this ObjectPool<List<T>> pool)
=> new(pool);
public static PooledObject<List<T>> GetPooledObject<T>(
this ObjectPool<List<T>> pool,
out List<T> list)
{
var pooledObject = pool.GetPooledObject();
list = pooledObject.Object;
return pooledObject;
}
public static PooledObject<Stack<T>> GetPooledObject<T>(this ObjectPool<Stack<T>> pool)
=> new(pool);
public static PooledObject<Stack<T>> GetPooledObject<T>(
this ObjectPool<Stack<T>> pool,
out Stack<T> stack)
{
var pooledObject = pool.GetPooledObject();
stack = pooledObject.Object;
return pooledObject;
}
public static PooledObject<Stopwatch> GetPooledObject(this ObjectPool<Stopwatch> pool)
=> new(pool);
public static PooledObject<Stopwatch> GetPooledObject(
this ObjectPool<Stopwatch> pool,
out Stopwatch watch)
{
var pooledObject = pool.GetPooledObject();
watch = pooledObject.Object;
return pooledObject;
}
public static PooledObject<StringBuilder> GetPooledObject(this ObjectPool<StringBuilder> pool)
=> new(pool);
public static PooledObject<StringBuilder> GetPooledObject(
this ObjectPool<StringBuilder> pool,
out StringBuilder builder)
{
var pooledObject = pool.GetPooledObject();
builder = pooledObject.Object;
return pooledObject;
}
}

Просмотреть файл

@ -0,0 +1,37 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
// Copied from https://github/dotnet/roslyn
using System;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal struct PooledObject<T> : IDisposable
where T : class
{
private readonly ObjectPool<T> _pool;
private T? _object;
// Because of how this API is intended to be used, we don't want the consumption code to have
// to deal with Object being a nullable reference type. Intead, the guarantee is that this is
// non-null until this is disposed.
public T Object => _object!;
public PooledObject(ObjectPool<T> pool)
: this()
{
_pool = pool;
_object = pool.Get();
}
public void Dispose()
{
if (_object is { } obj)
{
_pool.Return(obj);
_object = null;
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Utilities;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class ReferenceEqualityHashSetPool<T>
{
private class Policy : IPooledObjectPolicy<HashSet<T>>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public HashSet<T> Create() => new(ReferenceEqualityComparer<T>.Instance);
public bool Return(HashSet<T> set)
{
var count = set.Count;
set.Clear();
if (count > DefaultPool.MaximumObjectSize)
{
set.TrimExcess();
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="HashSet{T}"/> instances that compares items using reference equality.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class ReferenceEqualityHashSetPool<T>
where T : class
{
public static readonly ObjectPool<HashSet<T>> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<HashSet<T>> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<HashSet<T>> GetPooledObject(out HashSet<T> set)
=> Default.GetPooledObject(out set);
}

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class StackPool<T>
{
private class Policy : IPooledObjectPolicy<Stack<T>>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public Stack<T> Create() => new();
public bool Return(Stack<T> stack)
{
var count = stack.Count;
stack.Clear();
if (count > DefaultPool.MaximumObjectSize)
{
stack.TrimExcess();
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="Stack{T}"/> instances.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class StackPool<T>
{
public static readonly ObjectPool<Stack<T>> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<Stack<T>> GetPooledObject() => Default.GetPooledObject();
public static PooledObject<Stack<T>> GetPooledObject(out Stack<T> stack)
=> Default.GetPooledObject(out stack);
}

Просмотреть файл

@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Diagnostics;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class StopwatchPool
{
private class Policy : IPooledObjectPolicy<Stopwatch>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public Stopwatch Create() => new();
public bool Return(Stopwatch watch)
{
watch.Reset();
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Diagnostics;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="Stopwatch"/> instances.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class StopwatchPool
{
public static readonly ObjectPool<Stopwatch> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<Stopwatch> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<Stopwatch> GetPooledObject(out Stopwatch watch)
=> Default.GetPooledObject(out watch);
}

Просмотреть файл

@ -0,0 +1,33 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Text;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class StringBuilderPool
{
private class Policy : IPooledObjectPolicy<StringBuilder>
{
public static readonly Policy Instance = new();
private Policy()
{
}
public StringBuilder Create() => new();
public bool Return(StringBuilder builder)
{
builder.Clear();
if (builder.Capacity > DefaultPool.MaximumObjectSize)
{
builder.Capacity = DefaultPool.MaximumObjectSize;
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Text;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// A pool of <see cref="StringBuilder"/> instances.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class StringBuilderPool
{
public static readonly ObjectPool<StringBuilder> Default = DefaultPool.Create(Policy.Instance);
public static PooledObject<StringBuilder> GetPooledObject()
=> Default.GetPooledObject();
public static PooledObject<StringBuilder> GetPooledObject(out StringBuilder builder)
=> Default.GetPooledObject(out builder);
}

Просмотреть файл

@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class StringDictionaryPool<TValue>
{
private class OrdinalIgnoreCasePolicy : IPooledObjectPolicy<Dictionary<string, TValue>>
{
public static readonly OrdinalIgnoreCasePolicy Instance = new();
private OrdinalIgnoreCasePolicy()
{
}
public Dictionary<string, TValue> Create() => new(StringComparer.OrdinalIgnoreCase);
public bool Return(Dictionary<string, TValue> map)
{
var count = map.Count;
map.Clear();
// If the map grew too large, don't return it to the pool.
return count <= DefaultPool.MaximumObjectSize;
}
}
}

Просмотреть файл

@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
internal static partial class StringDictionaryPool<TValue>
{
private class OrdinalPolicy : IPooledObjectPolicy<Dictionary<string, TValue>>
{
public static readonly OrdinalPolicy Instance = new();
private OrdinalPolicy()
{
}
public Dictionary<string, TValue> Create() => new(StringComparer.Ordinal);
public bool Return(Dictionary<string, TValue> map)
{
var count = map.Count;
map.Clear();
// If the map grew too large, don't return it to the pool.
return count <= DefaultPool.MaximumObjectSize;
}
}
}

Просмотреть файл

@ -0,0 +1,37 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Razor.PooledObjects;
/// <summary>
/// Pooled <see cref="Dictionary{TKey, TValue}"/> instances when the key is of type <see cref="string"/>.
/// </summary>
///
/// <remarks>
/// Instances originating from this pool are intended to be short-lived and are suitable
/// for temporary work. Do not return them as the results of methods or store them in fields.
/// </remarks>
internal static partial class StringDictionaryPool<TValue>
{
public static readonly ObjectPool<Dictionary<string, TValue>> Ordinal = ObjectPool.Create(OrdinalPolicy.Instance);
public static readonly ObjectPool<Dictionary<string, TValue>> OrdinalIgnoreCase = ObjectPool.Create(OrdinalIgnoreCasePolicy.Instance);
public static PooledObject<Dictionary<string, TValue>> GetPooledObject()
=> Ordinal.GetPooledObject();
public static PooledObject<Dictionary<string, TValue>> GetPooledObject(out Dictionary<string, TValue> map)
=> Ordinal.GetPooledObject(out map);
public static PooledObject<Dictionary<string, TValue>> GetPooledObject(bool ignoreCase)
=> ignoreCase
? OrdinalIgnoreCase.GetPooledObject()
: Ordinal.GetPooledObject();
public static PooledObject<Dictionary<string, TValue>> GetPooledObject(bool ignoreCase, out Dictionary<string, TValue> map)
=> ignoreCase
? OrdinalIgnoreCase.GetPooledObject(out map)
: Ordinal.GetPooledObject(out map);
}

Просмотреть файл

@ -3,6 +3,7 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Common.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.Common, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.Common.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

Просмотреть файл

@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Text;
namespace Microsoft.AspNetCore.Razor;
internal static class StringBuilderExtensions
{
public static void SetCapacityIfLarger(this StringBuilder builder, int newCapacity)
{
if (builder.Capacity < newCapacity)
{
builder.Capacity = newCapacity;
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Microsoft.AspNetCore.Razor.Utilities;
internal sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T>
where T : class
{
public static readonly ReferenceEqualityComparer<T> Instance = new();
private ReferenceEqualityComparer()
{
}
bool IEqualityComparer<T>.Equals(T? x, T? y)
=> ReferenceEquals(x, y);
int IEqualityComparer<T>.GetHashCode(T obj)
=> RuntimeHelpers.GetHashCode(obj);
}

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
@ -12,6 +11,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.AspNetCore.Razor.LanguageServer.Protocol;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.Extensions.Logging;
@ -165,7 +165,8 @@ internal class TextDocumentUriPresentationEndpoint : AbstractTextDocumentPresent
// TODO: Add @using statements if required, or fully qualify (GetTypeName())
var sb = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var sb);
sb.Append('<');
sb.Append(typeName);

Просмотреть файл

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
@ -14,6 +13,7 @@ using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions;
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
using Microsoft.AspNetCore.Razor.LanguageServer.Protocol;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions;
@ -401,7 +401,10 @@ internal class CSharpOnTypeFormattingPass : CSharpFormattingPassBase
private static string PrependLines(string text, string newLine, int count)
{
var builder = new StringBuilder((newLine.Length * count) + text.Length);
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.SetCapacityIfLarger((newLine.Length * count) + text.Length);
for (var i = 0; i < count; i++)
{
builder.Append(newLine);

Просмотреть файл

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.AspNetCore.Razor.LanguageServer;
@ -84,7 +84,9 @@ internal class SourceTextDiffer : TextDiffer
var start = 0;
var end = 0;
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
foreach (var edit in edits)
{
var startPosition = _lineDiffOnly ? OldText.Lines[edit.Position].Start : edit.Position;

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis.Razor.Tooltip;
using Microsoft.VisualStudio.LanguageServer.Protocol;
@ -36,7 +37,8 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
//
// Additional description infos result in a triple `---` to separate the markdown entries.
var descriptionBuilder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var descriptionBuilder);
for (var i = 0; i < associatedTagHelperInfos.Count; i++)
{
var descriptionInfo = associatedTagHelperInfos[i];
@ -70,6 +72,7 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
Kind = markupKind,
Value = descriptionBuilder.ToString(),
};
return true;
}
@ -97,7 +100,8 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
//
// Additional description infos result in a triple `---` to separate the markdown entries.
var descriptionBuilder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var descriptionBuilder);
for (var i = 0; i < associatedAttributeInfos.Count; i++)
{
var descriptionInfo = associatedAttributeInfos[i];
@ -117,11 +121,11 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
var reducedReturnTypeName = ReduceTypeName(returnTypeName);
descriptionBuilder.Append(reducedReturnTypeName);
StartOrEndBold(descriptionBuilder, markupKind);
descriptionBuilder.Append(" ");
descriptionBuilder.Append(' ');
var tagHelperTypeName = descriptionInfo.TypeName;
var reducedTagHelperTypeName = ReduceTypeName(tagHelperTypeName);
descriptionBuilder.Append(reducedTagHelperTypeName);
descriptionBuilder.Append(".");
descriptionBuilder.Append('.');
StartOrEndBold(descriptionBuilder, markupKind);
descriptionBuilder.Append(descriptionInfo.PropertyName);
StartOrEndBold(descriptionBuilder, markupKind);
@ -143,6 +147,7 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
Kind = markupKind,
Value = descriptionBuilder.ToString(),
};
return true;
}
@ -155,7 +160,10 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
// it'll be serialized as html (wont show).
summaryContent = summaryContent.Trim();
var crefMatches = ExtractCrefMatches(summaryContent);
var summaryBuilder = new StringBuilder(summaryContent);
using var _ = StringBuilderPool.GetPooledObject(out var summaryBuilder);
summaryBuilder.Append(summaryContent);
for (var i = crefMatches.Count - 1; i >= 0; i--)
{
@ -175,11 +183,11 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
return finalSummaryContent;
}
private void StartOrEndBold(StringBuilder stringBuilder, MarkupKind markupKind)
private static void StartOrEndBold(StringBuilder builder, MarkupKind markupKind)
{
if (markupKind == MarkupKind.Markdown)
{
stringBuilder.Append("**");
builder.Append("**");
}
}
}

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis.Razor.Tooltip;
using Microsoft.VisualStudio.Core.Imaging;
using Microsoft.VisualStudio.Text.Adornments;
@ -243,7 +244,8 @@ internal class DefaultVSLSPTagHelperTooltipFactory : VSLSPTagHelperTooltipFactor
private static void ClassifyReducedTypeName(List<ClassifiedTextRun> runs, string reducedTypeName)
{
var currentTextRun = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var currentTextRun);
for (var i = 0; i < reducedTypeName.Length; i++)
{
var ch = reducedTypeName[i];
@ -352,7 +354,8 @@ internal class DefaultVSLSPTagHelperTooltipFactory : VSLSPTagHelperTooltipFactor
return;
}
var currentTextRun = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var currentTextRun);
var currentCrefMatchIndex = 0;
var currentCodeMatchIndex = 0;
for (var i = 0; i < summaryContent.Length; i++)
@ -360,7 +363,7 @@ internal class DefaultVSLSPTagHelperTooltipFactory : VSLSPTagHelperTooltipFactor
// If we made it through all the crefs and code matches, add the rest of the text and break out of the loop.
if (currentCrefMatchIndex == crefMatches.Count && currentCodeMatchIndex == codeMatches.Count)
{
currentTextRun.Append(summaryContent.Substring(i));
currentTextRun.Append(summaryContent[i..]);
break;
}

Просмотреть файл

@ -29,6 +29,7 @@
<_PublishedFiles Include="$(PublishDir)**\Microsoft.CodeAnalysis.Remote.Razor.*" Exclude="@(_ExcludedFiles)"/>
<_PublishedFiles Include="$(PublishDir)**\Microsoft.AspNetCore.*" />
<_PublishedFiles Include="$(PublishDir)**\Microsoft.Extensions.Logging.Abstractions.dll" />
<_PublishedFiles Include="$(PublishDir)**\Microsoft.Extensions.ObjectPool.dll" />
<_PublishedFiles Remove="@(_PublishedFiles)" Condition="'%(Extension)' == '.pdb'" />
<_PublishedFiles Remove="@(_PublishedFiles)" Condition="'%(Extension)' == '.xml'" />

Просмотреть файл

@ -81,6 +81,7 @@
<MPackFile Include="$(ArtifactsBinDir)Microsoft.AspNetCore.Razor.LanguageServer.Common\$(Configuration)\net472\Microsoft.AspNetCore.Razor.LanguageServer.Common.dll" />
<MPackFile Include="$(ArtifactsBinDir)Microsoft.AspNetCore.Razor.LanguageServer.Protocol\$(Configuration)\net472\Microsoft.AspNetCore.Razor.LanguageServer.Protocol.dll" />
<MPackFile Include="$(ArtifactsBinDir)Microsoft.AspNetCore.Razor.LanguageServer\$(Configuration)\net472\Microsoft.AspNetCore.Razor.LanguageServer.dll" />
<MPackFile Include="$(ArtifactsBinDir)Microsoft.VisualStudio.Mac.RazorAddin\$(Configuration)\net472\Microsoft.Extensions.ObjectPool.dll" />
<MPackFile Include="$(ArtifactsBinDir)Microsoft.VisualStudio.Mac.RazorAddin\$(Configuration)\net472\Microsoft.Extensions.Options.dll" />
<MPackFile Include="$(ArtifactsBinDir)Microsoft.VisualStudio.Mac.RazorAddin\$(Configuration)\net472\Microsoft.Extensions.Primitives.dll" />
<MPackFile Include="$(ArtifactsBinDir)Microsoft.VisualStudio.Mac.RazorAddin\$(Configuration)\net472\Microsoft.Extensions.DependencyInjection.dll" />

Просмотреть файл

@ -17,6 +17,7 @@
<Import assembly="Microsoft.AspNetCore.Razor.LanguageServer.dll" />
<Import assembly="Microsoft.AspNetCore.Razor.LanguageServer.Common.dll" />
<Import assembly="Microsoft.AspNetCore.Razor.LanguageServer.Protocol.dll" />
<Import assembly="Microsoft.Extensions.ObjectPool.dll" />
<Import assembly="Microsoft.Extensions.Options.dll" />
<Import assembly="Microsoft.Extensions.Primitives.dll" />
<Import assembly="Microsoft.Extensions.DependencyInjection.dll" />

Просмотреть файл

@ -17,6 +17,7 @@
<Import assembly="Microsoft.AspNetCore.Razor.LanguageServer.dll" />
<Import assembly="Microsoft.AspNetCore.Razor.LanguageServer.Common.dll" />
<Import assembly="Microsoft.AspNetCore.Razor.LanguageServer.Protocol.dll" />
<Import assembly="Microsoft.Extensions.ObjectPool.dll" />
<Import assembly="Microsoft.Extensions.Options.dll" />
<Import assembly="Microsoft.Extensions.Primitives.dll" />
<Import assembly="Microsoft.Extensions.DependencyInjection.dll" />

Просмотреть файл

@ -7,55 +7,62 @@ using Microsoft.VisualStudio.Shell;
AssemblyName = "Microsoft.Extensions.Logging.Abstractions",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.Logging",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.DependencyInjection",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.DependencyInjection.Abstractions",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.ObjectPool",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.Options",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.Configuration.Abstractions",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.Configuration",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]
[assembly: ProvideBindingRedirection(
AssemblyName = "Microsoft.Extensions.Primitives",
GenerateCodeBase = true,
PublicKeyToken = "adb9793829ddae60",
OldVersionLowerBound = "2.0.0.0",
OldVersionUpperBound = "2.0.0.0",
OldVersionLowerBound = "0.0.0.0",
OldVersionUpperBound = "6.0.0.0",
NewVersion = "6.0.0.0")]

Просмотреть файл

@ -9,6 +9,7 @@ using Microsoft.VisualStudio.Shell;
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\OmniSharp.Extensions.LanguageServer.dll")]
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\OmniSharp.Extensions.LanguageServer.Shared.dll")]
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.CommonLanguageServerProtocol.Framework.dll")]
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.Extensions.ObjectPool.dll")]
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.Extensions.Options.dll")]
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.Extensions.Primitives.dll")]
[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.Extensions.DependencyInjection.dll")]

Просмотреть файл

@ -143,6 +143,7 @@
<RazorNgendVSIXSourceItem Include="$(OutputPath)OmniSharp.Extensions.LanguageProtocol.dll" />
<RazorNgendVSIXSourceItem Include="$(OutputPath)OmniSharp.Extensions.LanguageServer.dll" />
<RazorNgendVSIXSourceItem Include="$(OutputPath)OmniSharp.Extensions.LanguageServer.Shared.dll" />
<RazorNgendVSIXSourceItem Include="$(OutputPath)Microsoft.Extensions.ObjectPool.dll" />
<RazorNgendVSIXSourceItem Include="$(OutputPath)Microsoft.Extensions.Options.dll" />
<RazorNgendVSIXSourceItem Include="$(OutputPath)Microsoft.Extensions.Options.ConfigurationExtensions.dll" />
<RazorNgendVSIXSourceItem Include="$(OutputPath)Microsoft.Extensions.Primitives.dll" />

Просмотреть файл

@ -42,6 +42,7 @@
<Asset Type="Microsoft.VisualStudio.Assembly" Path="OmniSharp.Extensions.LanguageServer.Shared.dll" />
<Asset Type="Microsoft.VisualStudio.Assembly" Path="Microsoft.Extensions.Configuration.Binder.dll" />
<Asset Type="Microsoft.VisualStudio.Assembly" Path="Microsoft.CommonLanguageServerProtocol.Framework.dll" />
<Asset Type="Microsoft.VisualStudio.Assembly" Path="Microsoft.Extensions.ObjectPool.dll" />
<Asset Type="Microsoft.VisualStudio.Assembly" Path="Microsoft.Extensions.Options.dll" />
<Asset Type="Microsoft.VisualStudio.Assembly" Path="Microsoft.Extensions.Options.ConfigurationExtensions.dll" />
<Asset Type="Microsoft.VisualStudio.Assembly" Path="Microsoft.Extensions.Primitives.dll" />

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);$(DefaultNetFxTargetFramework)</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Common\Microsoft.AspNetCore.Razor.Common.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using Xunit;
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)]

Просмотреть файл

@ -0,0 +1,5 @@
{
"methodDisplay": "method",
"shadowCopy": false,
"parallelizeTestCollections": false
}

Просмотреть файл

@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Completion;
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
using Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models;
using Microsoft.AspNetCore.Razor.LanguageServer.Test.Common;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions;
using Microsoft.VisualStudio.LanguageServer.Protocol;
@ -159,7 +160,8 @@ public abstract class SemanticTokenTestBase : TagHelperServiceTestBase
private static void GenerateSemanticBaseline(IEnumerable<int>? actual, string baselineFileName)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
if (actual != null)
{
var actualArray = actual.ToArray();

Просмотреть файл

@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis;
using Xunit.Sdk;
@ -27,7 +28,8 @@ public class CompilationFailedException : XunitException
{
get
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine("Compilation failed: ");
var syntaxTreesWithErrors = new HashSet<SyntaxTree>();

Просмотреть файл

@ -7,8 +7,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Xunit;
using Xunit.Sdk;
@ -242,7 +242,8 @@ public static class IntermediateNodeVerifier
private static string Format(IntermediateNode[] ancestors, string expected, string actual, string userMessage)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -9,9 +9,9 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.Mef;
using Microsoft.CodeAnalysis;
@ -398,7 +398,8 @@ public class RazorIntegrationTestBase : TestBase
{
get
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine("Compilation failed: ");
var diagnostics = Compilation.GetDiagnostics();

Просмотреть файл

@ -4,6 +4,7 @@
#nullable disable
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests;
@ -11,7 +12,8 @@ public static class SourceMappingsSerializer
{
public static string Serialize(RazorCSharpDocument csharpDocument, RazorSourceDocument sourceDocument)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
var charBuffer = new char[sourceDocument.Length];
sourceDocument.CopyTo(0, charBuffer, 0, sourceDocument.Length);
var sourceContent = new string(charBuffer);

Просмотреть файл

@ -5,8 +5,8 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Xunit;
using Xunit.Sdk;
@ -99,7 +99,9 @@ public static class IntermediateNodeAssert
try
{
var html = Assert.IsType<HtmlContentIntermediateNode>(node);
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < html.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(html.Children[i]);
@ -120,7 +122,9 @@ public static class IntermediateNodeAssert
try
{
var statement = Assert.IsType<CSharpCodeIntermediateNode>(node);
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < statement.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(statement.Children[i]);
@ -207,7 +211,8 @@ public static class IntermediateNodeAssert
try
{
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < attributeValue.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(attributeValue.Children[i]);
@ -230,7 +235,8 @@ public static class IntermediateNodeAssert
try
{
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < attributeValue.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(attributeValue.Children[i]);
@ -253,7 +259,8 @@ public static class IntermediateNodeAssert
{
var cSharp = Assert.IsType<CSharpExpressionIntermediateNode>(node);
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < cSharp.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(cSharp.Children[i]);
@ -274,7 +281,9 @@ public static class IntermediateNodeAssert
try
{
var beginNode = Assert.IsType<CSharpCodeIntermediateNode>(node);
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < beginNode.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(beginNode.Children[i]);
@ -295,7 +304,9 @@ public static class IntermediateNodeAssert
try
{
var endNode = Assert.IsType<CSharpCodeIntermediateNode>(node);
var content = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < endNode.Children.Count; i++)
{
var token = Assert.IsType<IntermediateToken>(endNode.Children[i]);
@ -458,7 +469,8 @@ public static class IntermediateNodeAssert
private static string Format(IntermediateNode[] ancestors, IEnumerable<IntermediateNode> nodes, string userMessage)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -5,7 +5,7 @@
using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Xunit;
using Xunit.Sdk;
@ -90,7 +90,8 @@ internal class ClassifiedSpanVerifier
private static string Format(string expected, string actual, string userMessage)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -7,8 +7,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Xunit;
using Xunit.Sdk;
@ -263,7 +263,8 @@ public static class SyntaxNodeVerifier
private static string Format(SyntaxNode[] ancestors, string expected, string actual, string userMessage)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -8,6 +8,7 @@ using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Legacy;
using Microsoft.AspNetCore.Razor.PooledObjects;
namespace Microsoft.AspNetCore.Razor.Language.Syntax;
@ -113,7 +114,9 @@ internal class SyntaxNodeWriter : SyntaxRewriter
return;
}
var builder = new StringBuilder("Directive:{");
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.Append("Directive:{");
builder.Append(node.DirectiveDescriptor.Directive);
builder.Append(';');
builder.Append(node.DirectiveDescriptor.Kind);

Просмотреть файл

@ -5,7 +5,7 @@
using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Xunit;
using Xunit.Sdk;
@ -90,7 +90,8 @@ internal class TagHelperSpanVerifier
private static string Format(string expected, string actual, string userMessage)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.VisualStudio.Composition;
using Roslyn.Utilities;
@ -225,7 +225,8 @@ public HostServices GetHostServices()
{
var configuration = CompositionConfiguration.Create(GetCatalog());
var sb = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var sb);
foreach (var errorGroup in configuration.CompositionErrors)
{
foreach (var error in errorGroup)

Просмотреть файл

@ -3,8 +3,8 @@
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Outlining;
@ -93,7 +93,8 @@ public class CodeFoldingTests : AbstractRazorEditorTest
static string PrintLines(ImmutableArray<CollapsibleBlock> lines, ITextView textView)
{
var sb = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var sb);
foreach (var line in lines)
{
sb.AppendLine();

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Adornments;
@ -68,7 +69,8 @@ internal partial class EditorInProcess
{
var hoverContent = await HoverAsync(position, cancellationToken);
var sb = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var sb);
TraverseContent(hoverContent, sb);
return sb.ToString();

Просмотреть файл

@ -6,10 +6,10 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.VisualStudio.Razor.IntegrationTests.InProcess;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
@ -143,7 +143,8 @@ public class RazorSemanticTokensTests : AbstractRazorEditorTest
private static void GenerateSemanticBaseline(IEnumerable<ClassificationSpan> actual, string baselineFileName)
{
var builder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var builder);
foreach (var baseline in actual)
{
builder.Append(baseline.Span.Start.Position).Append(Separator);

Просмотреть файл

@ -6,9 +6,9 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.Internal.VisualStudio.Shell.Embeddable.Feedback;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
@ -98,7 +98,8 @@ internal static class VisualStudioLogging
private static void RazorExtensionExplorerLogger(string filePath)
{
var hiveDirectory = GetHiveDirectory();
var fileBuilder = new StringBuilder();
using var _ = StringBuilderPool.GetPooledObject(out var fileBuilder);
var extensionsDir = Path.Combine(hiveDirectory, "Extensions");
var compatListFile = Path.Combine(extensionsDir, "CompatibilityList.xml");