提交 e68c4dba 编写于 作者: C Cyrus Najmabadi

Use pooling pattern for ArrayBuilders.

上级 6705741e
......@@ -196,7 +196,7 @@ private async Task TrackActiveSpansAsync()
var baseActiveStatements = await _editSession.BaseActiveStatements.GetValueAsync(cancellationToken).ConfigureAwait(false);
var lastCommittedSolution = _editSession.DebuggingSession.LastCommittedSolution;
var currentSolution = _editSession.DebuggingSession.Workspace.CurrentSolution;
var activeSpansToTrack = ArrayBuilder<(Document, Document, ITextSnapshot, ImmutableArray<ActiveStatement>)>.GetInstance();
using var _ = ArrayBuilder<(Document, Document, ITextSnapshot, ImmutableArray<ActiveStatement>)>.GetInstance(out var activeSpansToTrack);
foreach (var (documentId, documentActiveStatements) in baseActiveStatements.DocumentMap)
{
......@@ -231,8 +231,6 @@ private async Task TrackActiveSpansAsync()
}
}
activeSpansToTrack.Free();
_service.OnTrackingSpansChanged(leafChanged: true);
}
catch (OperationCanceledException)
......
......@@ -356,34 +356,28 @@ private string GetUsingDirectiveString(INamespaceOrTypeSymbol namespaceOrTypeSym
var (usingDirective, hasExistingUsing) = GetUsingDirective(
document, namespaceOrTypeSymbol, semanticModel, root, contextNode);
var newImports = ArrayBuilder<SyntaxNode>.GetInstance();
try
{
if (!hasExistingExtern && externAliasDirective != null)
{
newImports.Add(externAliasDirective);
}
if (!hasExistingUsing && usingDirective != null)
{
newImports.Add(usingDirective);
}
using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var newImports);
if (newImports.Count == 0)
{
return root;
}
if (!hasExistingExtern && externAliasDirective != null)
{
newImports.Add(externAliasDirective);
}
var addImportService = document.GetLanguageService<IAddImportsService>();
var generator = SyntaxGenerator.GetGenerator(document);
var newRoot = addImportService.AddImports(
semanticModel.Compilation, root, contextNode, newImports, generator, placeSystemNamespaceFirst, cancellationToken);
return (CompilationUnitSyntax)newRoot;
if (!hasExistingUsing && usingDirective != null)
{
newImports.Add(usingDirective);
}
finally
if (newImports.Count == 0)
{
newImports.Free();
return root;
}
var addImportService = document.GetLanguageService<IAddImportsService>();
var generator = SyntaxGenerator.GetGenerator(document);
var newRoot = addImportService.AddImports(
semanticModel.Compilation, root, contextNode, newImports, generator, placeSystemNamespaceFirst, cancellationToken);
return (CompilationUnitSyntax)newRoot;
}
protected override async Task<Document> AddImportAsync(
......
......@@ -208,32 +208,26 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
var variableName = identifier.ValueText;
var references = ArrayBuilder<MemberAccessExpressionSyntax>.GetInstance();
try
{
// If the user actually uses the tuple local for anything other than accessing
// fields off of it, then we can't deconstruct this tuple into locals.
if (!OnlyUsedToAccessTupleFields(
semanticModel, searchScope, local, references, cancellationToken))
{
return false;
}
// Can only deconstruct the tuple if the names we introduce won't collide
// with anything else in scope (either outside, or inside the method).
if (AnyTupleFieldNamesCollideWithExistingNames(
semanticModel, tupleType, searchScope, cancellationToken))
{
return false;
}
using var _ = ArrayBuilder<MemberAccessExpressionSyntax>.GetInstance(out var references);
memberAccessExpressions = references.ToImmutable();
return true;
// If the user actually uses the tuple local for anything other than accessing
// fields off of it, then we can't deconstruct this tuple into locals.
if (!OnlyUsedToAccessTupleFields(
semanticModel, searchScope, local, references, cancellationToken))
{
return false;
}
finally
// Can only deconstruct the tuple if the names we introduce won't collide
// with anything else in scope (either outside, or inside the method).
if (AnyTupleFieldNamesCollideWithExistingNames(
semanticModel, tupleType, searchScope, cancellationToken))
{
references.Free();
return false;
}
memberAccessExpressions = references.ToImmutable();
return true;
}
private static bool AnyTupleFieldNamesCollideWithExistingNames(
......
......@@ -306,33 +306,26 @@ private AnalyzerConfigDocument FindOrGenerateEditorConfig()
if (IDEDiagnosticIdToOptionMappingHelper.TryGetMappedOptions(diagnostic.Id, project.Language, out var options))
{
var optionSet = project.Solution.Workspace.Options;
var builder = ArrayBuilder<(OptionKey, ICodeStyleOption, IEditorConfigStorageLocation2, bool)>.GetInstance();
using var _ = ArrayBuilder<(OptionKey, ICodeStyleOption, IEditorConfigStorageLocation2, bool)>.GetInstance(out var builder);
try
foreach (var option in options.OrderBy(option => option.Name))
{
foreach (var option in options.OrderBy(option => option.Name))
var editorConfigLocation = option.StorageLocations.OfType<IEditorConfigStorageLocation2>().FirstOrDefault();
if (editorConfigLocation != null)
{
var editorConfigLocation = option.StorageLocations.OfType<IEditorConfigStorageLocation2>().FirstOrDefault();
if (editorConfigLocation != null)
var optionKey = new OptionKey(option, option.IsPerLanguage ? project.Language : null);
if (optionSet.GetOption(optionKey) is ICodeStyleOption codeStyleOption)
{
var optionKey = new OptionKey(option, option.IsPerLanguage ? project.Language : null);
if (optionSet.GetOption(optionKey) is ICodeStyleOption codeStyleOption)
{
builder.Add((optionKey, codeStyleOption, editorConfigLocation, option.IsPerLanguage));
continue;
}
builder.Add((optionKey, codeStyleOption, editorConfigLocation, option.IsPerLanguage));
continue;
}
// Did not find a match.
return ImmutableArray<(OptionKey, ICodeStyleOption, IEditorConfigStorageLocation2, bool)>.Empty;
}
return builder.ToImmutable();
}
finally
{
builder.Free();
// Did not find a match.
return ImmutableArray<(OptionKey, ICodeStyleOption, IEditorConfigStorageLocation2, bool)>.Empty;
}
return builder.ToImmutable();
}
return ImmutableArray<(OptionKey, ICodeStyleOption, IEditorConfigStorageLocation2, bool)>.Empty;
......
......@@ -76,7 +76,7 @@ private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnume
// For each code style option, create a top level code action with nested code actions for every valid option value.
// For example, if the option value is CodeStyleOption<bool>, we will have two nested actions, one for 'true' setting and one
// for 'false' setting. If the option value is CodeStyleOption<SomeEnum>, we will have a nested action for each enum field.
var nestedActions = ArrayBuilder<CodeAction>.GetInstance();
using var _ = ArrayBuilder<CodeAction>.GetInstance(out var nestedActions);
var optionSet = project.Solution.Workspace.Options;
var hasMultipleOptions = codeStyleOptions.Length > 1;
foreach (var (optionKey, codeStyleOption, editorConfigLocation, perLanguageOption) in codeStyleOptions.OrderBy(t => t.optionKey.Option.Name))
......@@ -97,8 +97,6 @@ private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnume
result.Add(new CodeFix(project, resultCodeAction, diagnostic));
}
nestedActions.Free();
}
return result.ToImmutableAndFree();
......@@ -111,12 +109,12 @@ private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnume
Diagnostic diagnostic,
bool isPerLanguage,
OptionSet optionSet,
bool hasMultiplOptions)
bool hasMultipleOptions)
{
// Add a code action for every valid value of the given code style option.
// We only support light-bulb configuration of code style options with boolean or enum values.
var nestedActions = ArrayBuilder<CodeAction>.GetInstance();
using var _ = ArrayBuilder<CodeAction>.GetInstance(out var nestedActions);
var severity = codeStyleOption.Notification.ToEditorConfigString();
string optionName = null;
......@@ -140,12 +138,11 @@ private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnume
// If this is not a unique code style option for the diagnostic, use the optionName as the code action title.
// In that case, we will already have a containing top level action for the diagnostic.
// Otherwise, use the diagnostic information in the title.
return hasMultiplOptions
? new TopLevelConfigureCodeStyleOptionCodeAction(optionName, nestedActions.ToImmutableAndFree())
: new TopLevelConfigureCodeStyleOptionCodeAction(diagnostic, nestedActions.ToImmutableAndFree());
return hasMultipleOptions
? new TopLevelConfigureCodeStyleOptionCodeAction(optionName, nestedActions.ToImmutable())
: new TopLevelConfigureCodeStyleOptionCodeAction(diagnostic, nestedActions.ToImmutable());
}
nestedActions.Free();
return null;
// Local functions
......
......@@ -164,7 +164,7 @@ private ConcatImmutableArray<CodeRefactoringProvider> GetProviders(Document docu
try
{
var actions = ArrayBuilder<(CodeAction action, TextSpan? applicableToSpan)>.GetInstance();
using var _ = ArrayBuilder<(CodeAction action, TextSpan? applicableToSpan)>.GetInstance(out var actions);
var context = new CodeRefactoringContext(document, state,
// TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
......@@ -186,8 +186,6 @@ private ConcatImmutableArray<CodeRefactoringProvider> GetProviders(Document docu
? new CodeRefactoring(provider, actions.ToImmutable())
: null;
actions.Free();
return result;
}
catch (OperationCanceledException)
......
......@@ -445,41 +445,35 @@ public LocationForAffectedSymbol(ReferenceLocation location, bool isReferenceToE
private static async Task<ImmutableArray<LocationForAffectedSymbol>> FindReferenceLocationsForSymbol(
Document document, ISymbol symbol, CancellationToken cancellationToken)
{
var builder = ArrayBuilder<LocationForAffectedSymbol>.GetInstance();
try
using var _ = ArrayBuilder<LocationForAffectedSymbol>.GetInstance(out var builder);
var referencedSymbols = await FindReferencesAsync(symbol, document, cancellationToken).ConfigureAwait(false);
builder.AddRange(referencedSymbols
.Where(refSymbol => refSymbol.Definition.Equals(symbol))
.SelectMany(refSymbol => refSymbol.Locations)
.Select(location => new LocationForAffectedSymbol(location, isReferenceToExtensionMethod: false)));
// So far we only have references to types declared in affected namespace. We also need to
// handle invocation of extension methods (in reduced form) that are declared in those types.
// Therefore additional calls to find references are needed for those extension methods.
// This will returns all the references, not just in the reduced form. But we will
// not further distinguish the usage. In the worst case, those references are redundant because
// they are already covered by the type references found above.
if (symbol is INamedTypeSymbol typeSymbol && typeSymbol.MightContainExtensionMethods)
{
var referencedSymbols = await FindReferencesAsync(symbol, document, cancellationToken).ConfigureAwait(false);
builder.AddRange(referencedSymbols
.Where(refSymbol => refSymbol.Definition.Equals(symbol))
.SelectMany(refSymbol => refSymbol.Locations)
.Select(location => new LocationForAffectedSymbol(location, isReferenceToExtensionMethod: false)));
// So far we only have references to types declared in affected namespace. We also need to
// handle invocation of extension methods (in reduced form) that are declared in those types.
// Therefore additional calls to find references are needed for those extension methods.
// This will returns all the references, not just in the reduced form. But we will
// not further distinguish the usage. In the worst case, those references are redundant because
// they are already covered by the type references found above.
if (symbol is INamedTypeSymbol typeSymbol && typeSymbol.MightContainExtensionMethods)
foreach (var methodSymbol in typeSymbol.GetMembers().OfType<IMethodSymbol>())
{
foreach (var methodSymbol in typeSymbol.GetMembers().OfType<IMethodSymbol>())
if (methodSymbol.IsExtensionMethod)
{
if (methodSymbol.IsExtensionMethod)
{
var referencedMethodSymbols = await FindReferencesAsync(methodSymbol, document, cancellationToken).ConfigureAwait(false);
builder.AddRange(referencedMethodSymbols
.SelectMany(refSymbol => refSymbol.Locations)
.Select(location => new LocationForAffectedSymbol(location, isReferenceToExtensionMethod: true)));
}
var referencedMethodSymbols = await FindReferencesAsync(methodSymbol, document, cancellationToken).ConfigureAwait(false);
builder.AddRange(referencedMethodSymbols
.SelectMany(refSymbol => refSymbol.Locations)
.Select(location => new LocationForAffectedSymbol(location, isReferenceToExtensionMethod: true)));
}
}
return builder.ToImmutable();
}
finally
{
builder.Free();
}
return builder.ToImmutable();
}
private static async Task<ImmutableArray<ReferencedSymbol>> FindReferencesAsync(ISymbol symbol, Document document, CancellationToken cancellationToken)
......
......@@ -73,10 +73,9 @@ public bool Supports(Feature feature)
public (ImmutableArray<AnalyzedSwitchSection>, SyntaxNode TargetExpression) AnalyzeIfStatementSequence(ReadOnlySpan<IOperation> operations)
{
var sections = ArrayBuilder<AnalyzedSwitchSection>.GetInstance();
using var _ = ArrayBuilder<AnalyzedSwitchSection>.GetInstance(out var sections);
if (!ParseIfStatementSequence(operations, sections, out var defaultBodyOpt))
{
sections.Free();
return default;
}
......@@ -86,7 +85,7 @@ public bool Supports(Feature feature)
}
RoslynDebug.Assert(_switchTargetExpression is object);
return (sections.ToImmutableAndFree(), _switchTargetExpression);
return (sections.ToImmutable(), _switchTargetExpression);
}
// Tree to parse:
......@@ -175,14 +174,13 @@ private bool ParseIfStatementOrBlock(IOperation op, ArrayBuilder<AnalyzedSwitchS
private AnalyzedSwitchSection? ParseSwitchSection(IConditionalOperation operation)
{
var labels = ArrayBuilder<AnalyzedSwitchLabel>.GetInstance();
using var _ = ArrayBuilder<AnalyzedSwitchLabel>.GetInstance(out var labels);
if (!ParseSwitchLabels(operation.Condition, labels))
{
labels.Free();
return null;
}
return new AnalyzedSwitchSection(labels.ToImmutableAndFree(), operation.WhenTrue, operation.Syntax);
return new AnalyzedSwitchSection(labels.ToImmutable(), operation.WhenTrue, operation.Syntax);
}
// Tree to parse:
......@@ -215,15 +213,14 @@ private bool ParseSwitchLabels(IOperation operation, ArrayBuilder<AnalyzedSwitch
private AnalyzedSwitchLabel? ParseSwitchLabel(IOperation operation)
{
var guards = ArrayBuilder<TExpressionSyntax>.GetInstance();
using var _ = ArrayBuilder<TExpressionSyntax>.GetInstance(out var guards);
var pattern = ParsePattern(operation, guards);
if (pattern is null)
{
guards.Free();
return null;
}
return new AnalyzedSwitchLabel(pattern, guards.ToImmutableAndFree());
return new AnalyzedSwitchLabel(pattern, guards.ToImmutable());
}
private enum ConstantResult
......
......@@ -117,37 +117,30 @@ protected override void InitializeWorker(AnalysisContext context)
out var disposeAnalysisResult, out var pointsToAnalysisResult,
interproceduralAnalysisPredicateOpt))
{
var notDisposedDiagnostics = ArrayBuilder<Diagnostic>.GetInstance();
var mayBeNotDisposedDiagnostics = ArrayBuilder<Diagnostic>.GetInstance();
try
{
// Compute diagnostics for undisposed objects at exit block.
var exitBlock = disposeAnalysisResult.ControlFlowGraph.ExitBlock();
var disposeDataAtExit = disposeAnalysisResult.ExitBlockOutput.Data;
ComputeDiagnostics(disposeDataAtExit, notDisposedDiagnostics, mayBeNotDisposedDiagnostics,
disposeAnalysisResult, pointsToAnalysisResult);
using var _1 = ArrayBuilder<Diagnostic>.GetInstance(out var notDisposedDiagnostics);
using var _2 = ArrayBuilder<Diagnostic>.GetInstance(out var mayBeNotDisposedDiagnostics);
if (disposeAnalysisResult.ControlFlowGraph.OriginalOperation.HasAnyOperationDescendant(o => o.Kind == OperationKind.None))
{
// Workaround for https://github.com/dotnet/roslyn/issues/32100
// Bail out in presence of OperationKind.None - not implemented IOperation.
return;
}
// Compute diagnostics for undisposed objects at exit block.
var exitBlock = disposeAnalysisResult.ControlFlowGraph.ExitBlock();
var disposeDataAtExit = disposeAnalysisResult.ExitBlockOutput.Data;
ComputeDiagnostics(disposeDataAtExit, notDisposedDiagnostics, mayBeNotDisposedDiagnostics,
disposeAnalysisResult, pointsToAnalysisResult);
// Report diagnostics preferring *not* disposed diagnostics over may be not disposed diagnostics
// and avoiding duplicates.
foreach (var diagnostic in notDisposedDiagnostics.Concat(mayBeNotDisposedDiagnostics))
{
if (reportedLocations.TryAdd(diagnostic.Location, true))
{
operationBlockContext.ReportDiagnostic(diagnostic);
}
}
if (disposeAnalysisResult.ControlFlowGraph.OriginalOperation.HasAnyOperationDescendant(o => o.Kind == OperationKind.None))
{
// Workaround for https://github.com/dotnet/roslyn/issues/32100
// Bail out in presence of OperationKind.None - not implemented IOperation.
return;
}
finally
// Report diagnostics preferring *not* disposed diagnostics over may be not disposed diagnostics
// and avoiding duplicates.
foreach (var diagnostic in notDisposedDiagnostics.Concat(mayBeNotDisposedDiagnostics))
{
notDisposedDiagnostics.Free();
mayBeNotDisposedDiagnostics.Free();
if (reportedLocations.TryAdd(diagnostic.Location, true))
{
operationBlockContext.ReportDiagnostic(diagnostic);
}
}
}
......
......@@ -647,7 +647,7 @@ private static bool ReportFatalErrorAnalyzeDocumentAsync(ImmutableArray<ActiveSt
Debug.Assert(oldActiveStatements.Length == newExceptionRegions.Length);
Debug.Assert(updatedMethods.Count == 0);
var updatedTrackingSpans = ArrayBuilder<(ActiveStatementId, ActiveStatementTextSpan)>.GetInstance();
using var _ = ArrayBuilder<(ActiveStatementId, ActiveStatementTextSpan)>.GetInstance(out var updatedTrackingSpans);
for (var i = 0; i < script.Edits.Length; i++)
{
......@@ -665,8 +665,6 @@ private static bool ReportFatalErrorAnalyzeDocumentAsync(ImmutableArray<ActiveSt
{
trackingService!.UpdateActiveStatementSpans(newText, updatedTrackingSpans);
}
updatedTrackingSpans.Free();
}
private void UpdateUneditedSpans(
......@@ -796,7 +794,7 @@ private static bool ReportFatalErrorAnalyzeDocumentAsync(ImmutableArray<ActiveSt
Debug.Assert(oldActiveStatements.Length == newActiveStatements.Length);
Debug.Assert(newExceptionRegions == null || oldActiveStatements.Length == newExceptionRegions.Length);
var updatedTrackingSpans = ArrayBuilder<(ActiveStatementId, ActiveStatementTextSpan)>.GetInstance();
using var _ = ArrayBuilder<(ActiveStatementId, ActiveStatementTextSpan)>.GetInstance(out var updatedTrackingSpans);
// Active statements in methods that were not updated
// are not changed but their spans might have been.
......@@ -842,8 +840,6 @@ private static bool ReportFatalErrorAnalyzeDocumentAsync(ImmutableArray<ActiveSt
{
trackingService!.UpdateActiveStatementSpans(newText, updatedTrackingSpans);
}
updatedTrackingSpans.Free();
}
internal readonly struct ActiveNode
......
......@@ -65,8 +65,8 @@ public void ReportDiagnostics(Solution solution, ProjectId? projectId, IEnumerab
return;
}
var documentDiagnosticData = ArrayBuilder<DiagnosticData>.GetInstance();
var nonDocumentDiagnosticData = ArrayBuilder<DiagnosticData>.GetInstance();
using var _1 = ArrayBuilder<DiagnosticData>.GetInstance(out var documentDiagnosticData);
using var _2 = ArrayBuilder<DiagnosticData>.GetInstance(out var nonDocumentDiagnosticData);
var workspace = solution.Workspace;
var options = solution.Options;
var project = (projectId != null) ? solution.GetProject(projectId) : null;
......@@ -117,9 +117,6 @@ public void ReportDiagnostics(Solution solution, ProjectId? projectId, IEnumerab
documentId: null,
diagnostics: nonDocumentDiagnosticData.ToImmutable()));
}
documentDiagnosticData.Free();
nonDocumentDiagnosticData.Free();
}
}
}
......@@ -345,8 +345,8 @@ private static async Task PopulateChangedAndAddedDocumentsAsync(CommittedSolutio
private async Task<(ImmutableArray<(Document Document, AsyncLazy<DocumentAnalysisResults> Results)>, ImmutableArray<Diagnostic> DocumentDiagnostics)> AnalyzeDocumentsAsync(
ArrayBuilder<Document> changedDocuments, ArrayBuilder<Document> addedDocuments, CancellationToken cancellationToken)
{
var documentDiagnostics = ArrayBuilder<Diagnostic>.GetInstance();
var builder = ArrayBuilder<(Document? Old, Document New)>.GetInstance();
using var _1 = ArrayBuilder<Diagnostic>.GetInstance(out var documentDiagnostics);
using var _2 = ArrayBuilder<(Document? Old, Document New)>.GetInstance(out var builder);
foreach (var document in changedDocuments)
{
......@@ -389,8 +389,7 @@ private static async Task PopulateChangedAndAddedDocumentsAsync(CommittedSolutio
}
}
builder.Free();
return (result, documentDiagnostics.ToImmutableAndFree());
return (result, documentDiagnostics.ToImmutable());
}
public AsyncLazy<DocumentAnalysisResults> GetDocumentAnalysis(Document? baseDocument, Document document)
......@@ -593,7 +592,7 @@ private static async Task<ProjectChanges> GetProjectChangesAsync(ImmutableArray<
var allEdits = ArrayBuilder<SemanticEdit>.GetInstance();
var allLineEdits = ArrayBuilder<(DocumentId, ImmutableArray<LineChange>)>.GetInstance();
var activeStatementsInChangedDocuments = ArrayBuilder<(DocumentId, ImmutableArray<ActiveStatement>, ImmutableArray<ImmutableArray<LinePositionSpan>>)>.GetInstance();
var allAddedSymbols = ArrayBuilder<ISymbol>.GetInstance();
using var _ = ArrayBuilder<ISymbol>.GetInstance(out var allAddedSymbols);
foreach (var (document, asyncResult) in changedDocumentAnalyses)
{
......@@ -632,7 +631,6 @@ private static async Task<ProjectChanges> GetProjectChangesAsync(ImmutableArray<
}
var allAddedSymbolResult = allAddedSymbols.ToImmutableHashSet();
allAddedSymbols.Free();
return new ProjectChanges(
allEdits.ToImmutableAndFree(),
......
......@@ -63,7 +63,7 @@ public async Task<Document> FormatDocumentAsync(Document document, CancellationT
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var generator = document.GetLanguageService<SyntaxGenerator>();
var expressions = ArrayBuilder<SyntaxNode>.GetInstance();
using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var expressions);
var objName = generator.IdentifierName("obj");
if (containingType.IsValueType)
{
......@@ -108,7 +108,6 @@ public async Task<Document> FormatDocumentAsync(Document document, CancellationT
var statement = generator.ReturnStatement(
expressions.Aggregate(generator.LogicalAndExpression));
expressions.Free();
return compilation.CreateEqualsMethod(
ImmutableArray.Create(statement));
}
......
......@@ -209,7 +209,7 @@ private void AddProperties(ArrayBuilder<ISymbol> members)
var availableTypeParameters = _service.GetAvailableTypeParameters(_state, _semanticDocument.SemanticModel, _intoNamespace, _cancellationToken);
var parameterTypes = GetArgumentTypes(argumentList);
var parameterNames = _service.GenerateParameterNames(_semanticDocument.SemanticModel, argumentList, _cancellationToken);
var parameters = ArrayBuilder<IParameterSymbol>.GetInstance();
using var _ = ArrayBuilder<IParameterSymbol>.GetInstance(out var parameters);
var parameterToExistingFieldMap = new Dictionary<string, ISymbol>();
var parameterToNewFieldMap = new Dictionary<string, string>();
......@@ -251,8 +251,6 @@ private void AddProperties(ArrayBuilder<ISymbol> members)
members.AddRange(fields);
members.Add(constructor);
}
parameters.Free();
}
private void AddExceptionConstructors(ArrayBuilder<ISymbol> members)
......
......@@ -223,7 +223,7 @@ private static (SyntaxTriviaList sameLine, SyntaxTriviaList endOfLine) SplitTrai
.ToImmutableArray();
// List of local variables that will be in the order they are declared.
var localVariables = ArrayBuilder<ISymbol>.GetInstance();
using var _0 = ArrayBuilder<ISymbol>.GetInstance(out var localVariables);
// Map a symbol to an index into the statementsFromDeclarationToEnd array.
using var _1 = PooledDictionary<ISymbol, int>.GetInstance(out var variableDeclarationIndex);
......@@ -282,8 +282,6 @@ private static (SyntaxTriviaList sameLine, SyntaxTriviaList endOfLine) SplitTrai
endOfUsingStatementIndex = Math.Max(endOfUsingStatementIndex, lastVariableUsageIndex[localSymbol]);
}
localVariables.Free();
return statementsFromDeclarationToEnd[endOfUsingStatementIndex];
}
......
......@@ -55,36 +55,28 @@ internal abstract partial class AbstractNavigateToSearchService
using (nameMatcher)
using (containerMatcherOpt)
{
var nameMatches = ArrayBuilder<PatternMatch>.GetInstance();
var containerMatches = ArrayBuilder<PatternMatch>.GetInstance();
try
{
var declaredSymbolInfoKindsSet = new DeclaredSymbolInfoKindSet(kinds);
// If we're searching a single document, then just do a full search of
// that document (we're fast enough to not need to optimize that case).
//
// If, however, we are searching a project, then see if we could potentially
// use the last computed results we have for that project. If so, it can
// be much faster to reuse and filter that result than to compute it from
// scratch.
using var _1 = ArrayBuilder<PatternMatch>.GetInstance(out var nameMatches);
using var _2 = ArrayBuilder<PatternMatch>.GetInstance(out var containerMatches);
var declaredSymbolInfoKindsSet = new DeclaredSymbolInfoKindSet(kinds);
// If we're searching a single document, then just do a full search of
// that document (we're fast enough to not need to optimize that case).
//
// If, however, we are searching a project, then see if we could potentially
// use the last computed results we have for that project. If so, it can
// be much faster to reuse and filter that result than to compute it from
// scratch.
#if true
var task = searchDocument != null
? ComputeSearchResultsAsync(project, priorityDocuments, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken)
: TryFilterPreviousSearchResultsAsync(project, priorityDocuments, searchDocument, pattern, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken);
var task = searchDocument != null
? ComputeSearchResultsAsync(project, priorityDocuments, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken)
: TryFilterPreviousSearchResultsAsync(project, priorityDocuments, searchDocument, pattern, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken);
#else
var task = ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken);
var task = ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken);
#endif
var searchResults = await task.ConfigureAwait(false);
return ImmutableArray<INavigateToSearchResult>.CastUp(searchResults);
}
finally
{
nameMatches.Free();
containerMatches.Free();
}
var searchResults = await task.ConfigureAwait(false);
return ImmutableArray<INavigateToSearchResult>.CastUp(searchResults);
}
}
......
......@@ -70,26 +70,20 @@ private class SearchResult : INavigateToSearchResult
private string ConstructSecondarySortString()
{
var parts = ArrayBuilder<string>.GetInstance();
try
{
parts.Add(DeclaredSymbolInfo.ParameterCount.ToString("X4"));
parts.Add(DeclaredSymbolInfo.TypeParameterCount.ToString("X4"));
parts.Add(DeclaredSymbolInfo.Name);
// For partial types, we break up the file name into pieces. i.e. If we have
// Outer.cs and Outer.Inner.cs then we add "Outer" and "Outer Inner" to
// the secondary sort string. That way "Outer.cs" will be weighted above
// "Outer.Inner.cs"
var fileName = Path.GetFileNameWithoutExtension(Document.FilePath ?? "");
parts.AddRange(fileName.Split(s_dotArray));
return string.Join(" ", parts);
}
finally
{
parts.Free();
}
using var _ = ArrayBuilder<string>.GetInstance(out var parts);
parts.Add(DeclaredSymbolInfo.ParameterCount.ToString("X4"));
parts.Add(DeclaredSymbolInfo.TypeParameterCount.ToString("X4"));
parts.Add(DeclaredSymbolInfo.Name);
// For partial types, we break up the file name into pieces. i.e. If we have
// Outer.cs and Outer.Inner.cs then we add "Outer" and "Outer Inner" to
// the secondary sort string. That way "Outer.cs" will be weighted above
// "Outer.Inner.cs"
var fileName = Path.GetFileNameWithoutExtension(Document.FilePath ?? "");
parts.AddRange(fileName.Split(s_dotArray));
return string.Join(" ", parts);
}
public string SecondarySort
......
......@@ -65,7 +65,7 @@ public override async Task ProvideBlockStructureAsync(BlockStructureContext cont
private void ProvideBlockStructureWorker(
BlockStructureContext context, SyntaxNode syntaxRoot)
{
var spans = ArrayBuilder<BlockSpan>.GetInstance();
using var _ = ArrayBuilder<BlockSpan>.GetInstance(out var spans);
BlockSpanCollector.CollectBlockSpans(
context.Document, syntaxRoot, _nodeProviderMap, _triviaProviderMap, spans, context.CancellationToken);
......@@ -73,8 +73,6 @@ public override async Task ProvideBlockStructureAsync(BlockStructureContext cont
{
context.AddBlockSpan(span);
}
spans.Free();
}
}
}
......@@ -123,7 +123,7 @@ private ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> GetChainChunks(SyntaxN
// nodes and tokens we want to treat as individual elements. i.e. an
// element that would be kept together. For example, the arg-list of an
// invocation is an element we do not want to ever break-up/wrap.
var pieces = ArrayBuilder<SyntaxNodeOrToken>.GetInstance();
using var _ = ArrayBuilder<SyntaxNodeOrToken>.GetInstance(out var pieces);
Decompose(node, pieces);
// Now that we have the pieces, find 'chunks' similar to the form:
......@@ -136,8 +136,6 @@ private ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> GetChainChunks(SyntaxN
var chunks = ArrayBuilder<ImmutableArray<SyntaxNodeOrToken>>.GetInstance();
BreakPiecesIntoChunks(pieces, chunks);
pieces.Free();
return chunks.ToImmutableAndFree();
}
......
......@@ -65,7 +65,7 @@ private async Task AddDeclarationEntriesAsync(DefinitionItem definition)
// lock, and I'd like to avoid that. That does mean that we might do extra
// work if multiple threads end up down this path. But only one of them will
// win when we access the lock below.
var declarations = ArrayBuilder<Entry>.GetInstance();
using var _ = ArrayBuilder<Entry>.GetInstance(out var declarations);
foreach (var declarationLocation in definition.SourceSpans)
{
var definitionEntry = await TryCreateDocumentSpanEntryAsync(
......@@ -92,8 +92,6 @@ private async Task AddDeclarationEntriesAsync(DefinitionItem definition)
// Let all our subscriptions know that we've updated.
NotifyChange();
}
declarations.Free();
}
private bool HasDeclarationEntries(DefinitionItem definition)
......
......@@ -45,7 +45,7 @@ protected override async Task OnDefinitionFoundWorkerAsync(DefinitionItem defini
{
var definitionBucket = GetOrCreateDefinitionBucket(definition);
var entries = ArrayBuilder<Entry>.GetInstance();
using var _ = ArrayBuilder<Entry>.GetInstance(out var entries);
if (definition.SourceSpans.Length == 1)
{
......@@ -91,8 +91,6 @@ protected override async Task OnDefinitionFoundWorkerAsync(DefinitionItem defini
NotifyChange();
}
entries.Free();
}
private async Task<Entry> TryCreateEntryAsync(
......
......@@ -225,7 +225,7 @@ private void SetDefinitionGroupingPriority(IFindAllReferencesWindow window, int
{
this.AssertIsForeground();
var newColumns = ArrayBuilder<ColumnState>.GetInstance();
using var _ = ArrayBuilder<ColumnState>.GetInstance(out var newColumns);
var tableControl = (IWpfTableControl2)window.TableControl;
foreach (var columnState in window.TableControl.ColumnStates)
......@@ -248,7 +248,6 @@ private void SetDefinitionGroupingPriority(IFindAllReferencesWindow window, int
}
tableControl.SetColumnStates(newColumns);
newColumns.Free();
}
}
}
......@@ -108,9 +108,9 @@ public void Shutdown()
public ImmutableArray<TItem> AggregateItems<TData>(IEnumerable<IGrouping<TData, TItem>> groupedItems)
{
var aggregateItems = ArrayBuilder<TItem>.GetInstance();
var projectNames = ArrayBuilder<string>.GetInstance();
var projectGuids = ArrayBuilder<Guid>.GetInstance();
using var _0 = ArrayBuilder<TItem>.GetInstance(out var aggregateItems);
using var _1 = ArrayBuilder<string>.GetInstance(out var projectNames);
using var _2 = ArrayBuilder<Guid>.GetInstance(out var projectGuids);
string[] stringArrayCache = null;
Guid[] guidArrayCache = null;
......@@ -161,12 +161,7 @@ static T[] GetOrCreateArray<T>(ref T[] cache, ArrayBuilder<T> value)
projectGuids.Clear();
}
projectNames.Free();
projectGuids.Free();
var result = Order(aggregateItems).ToImmutableArray();
aggregateItems.Free();
return result;
return Order(aggregateItems).ToImmutableArray();
}
public abstract IEqualityComparer<TItem> GroupingComparer { get; }
......
......@@ -24,10 +24,9 @@ public CSharpEditorClassificationService()
public override void AddLexicalClassifications(SourceText text, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
{
var temp = ArrayBuilder<ClassifiedSpan>.GetInstance();
using var _ = ArrayBuilder<ClassifiedSpan>.GetInstance(out var temp);
ClassificationHelpers.AddLexicalClassifications(text, textSpan, temp, cancellationToken);
AddRange(temp, result);
temp.Free();
}
public override ClassifiedSpan AdjustStaleClassification(SourceText text, ClassifiedSpan classifiedSpan)
......
......@@ -654,7 +654,7 @@ public override TDeclarationNode UpdateDeclarationAccessibility<TDeclarationNode
private static SyntaxTokenList UpdateDeclarationAccessibility(SyntaxTokenList modifiersList, Accessibility newAccessibility, CodeGenerationOptions options)
{
var newModifierTokens = ArrayBuilder<SyntaxToken>.GetInstance();
using var _ = ArrayBuilder<SyntaxToken>.GetInstance(out var newModifierTokens);
CSharpCodeGenerationHelpers.AddAccessibilityModifiers(newAccessibility, newModifierTokens, options, Accessibility.NotApplicable);
if (newModifierTokens.Count == 0)
{
......@@ -664,7 +664,6 @@ private static SyntaxTokenList UpdateDeclarationAccessibility(SyntaxTokenList mo
// TODO: Move more APIs to use pooled ArrayBuilder
// https://github.com/dotnet/roslyn/issues/34960
var list = newModifierTokens.ToList();
newModifierTokens.Free();
return GetUpdatedDeclarationAccessibilityModifiers(list, modifiersList, (SyntaxToken modifier) => SyntaxFacts.IsAccessibilityModifier(modifier.Kind()))
.ToSyntaxTokenList();
}
......
......@@ -108,45 +108,39 @@ private VirtualCharSequence TryConvertVerbatimStringToVirtualChars(SyntaxToken t
var startIndexInclusive = startDelimiter.Length;
var endIndexExclusive = tokenText.Length - endDelimiter.Length;
var result = ArrayBuilder<VirtualChar>.GetInstance();
try
using var _ = ArrayBuilder<VirtualChar>.GetInstance(out var result);
var offset = token.SpanStart;
for (var index = startIndexInclusive; index < endIndexExclusive;)
{
var offset = token.SpanStart;
for (var index = startIndexInclusive; index < endIndexExclusive;)
if (tokenText[index] == '\\')
{
if (tokenText[index] == '\\')
if (!TryAddEscape(result, tokenText, offset, index))
{
if (!TryAddEscape(result, tokenText, offset, index))
{
return default;
}
index += result.Last().Span.Length;
return default;
}
else if (escapeBraces &&
(tokenText[index] == '{' || tokenText[index] == '}'))
{
if (!TryAddBraceEscape(result, tokenText, offset, index))
{
return default;
}
index += result.Last().Span.Length;
}
else
index += result.Last().Span.Length;
}
else if (escapeBraces &&
(tokenText[index] == '{' || tokenText[index] == '}'))
{
if (!TryAddBraceEscape(result, tokenText, offset, index))
{
result.Add(new VirtualChar(tokenText[index], new TextSpan(offset + index, 1)));
index++;
return default;
}
}
return CreateVirtualCharSequence(
tokenText, offset, startIndexInclusive, endIndexExclusive, result);
}
finally
{
result.Free();
index += result.Last().Span.Length;
}
else
{
result.Add(new VirtualChar(tokenText[index], new TextSpan(offset + index, 1)));
index++;
}
}
return CreateVirtualCharSequence(
tokenText, offset, startIndexInclusive, endIndexExclusive, result);
}
private bool TryAddEscape(
......
......@@ -50,10 +50,9 @@ public async Task AddSemanticClassificationsAsync(Document document, TextSpan te
var getNodeClassifiers = extensionManager.CreateNodeExtensionGetter(classifiers, c => c.SyntaxNodeTypes);
var getTokenClassifiers = extensionManager.CreateTokenExtensionGetter(classifiers, c => c.SyntaxTokenKinds);
var temp = ArrayBuilder<ClassifiedSpan>.GetInstance();
using var _ = ArrayBuilder<ClassifiedSpan>.GetInstance(out var temp);
await classificationService.AddSemanticClassificationsAsync(document, textSpan, getNodeClassifiers, getTokenClassifiers, temp, cancellationToken).ConfigureAwait(false);
AddRange(temp, result);
temp.Free();
}
public async Task AddSyntacticClassificationsAsync(Document document, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
......@@ -82,10 +81,9 @@ public async Task AddSyntacticClassificationsAsync(Document document, TextSpan t
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
Contract.ThrowIfNull(syntaxTree);
var temp = ArrayBuilder<ClassifiedSpan>.GetInstance();
using var _ = ArrayBuilder<ClassifiedSpan>.GetInstance(out var temp);
classificationService.AddSyntacticClassifications(syntaxTree, textSpan, temp, cancellationToken);
AddRange(temp, result);
temp.Free();
}
protected void AddRange(ArrayBuilder<ClassifiedSpan> temp, List<ClassifiedSpan> result)
......
......@@ -42,27 +42,20 @@ public static class Classifier
var getNodeClassifiers = extensionManager.CreateNodeExtensionGetter(syntaxClassifiers, c => c.SyntaxNodeTypes);
var getTokenClassifiers = extensionManager.CreateTokenExtensionGetter(syntaxClassifiers, c => c.SyntaxTokenKinds);
var syntacticClassifications = ArrayBuilder<ClassifiedSpan>.GetInstance();
var semanticClassifications = ArrayBuilder<ClassifiedSpan>.GetInstance();
try
{
service.AddSyntacticClassifications(semanticModel.SyntaxTree, textSpan, syntacticClassifications, cancellationToken);
service.AddSemanticClassifications(semanticModel, textSpan, workspace, getNodeClassifiers, getTokenClassifiers, semanticClassifications, cancellationToken);
using var _1 = ArrayBuilder<ClassifiedSpan>.GetInstance(out var syntacticClassifications);
using var _2 = ArrayBuilder<ClassifiedSpan>.GetInstance(out var semanticClassifications);
var allClassifications = new List<ClassifiedSpan>(semanticClassifications.Where(s => s.TextSpan.OverlapsWith(textSpan)));
var semanticSet = semanticClassifications.Select(s => s.TextSpan).ToSet();
service.AddSyntacticClassifications(semanticModel.SyntaxTree, textSpan, syntacticClassifications, cancellationToken);
service.AddSemanticClassifications(semanticModel, textSpan, workspace, getNodeClassifiers, getTokenClassifiers, semanticClassifications, cancellationToken);
allClassifications.AddRange(syntacticClassifications.Where(
s => s.TextSpan.OverlapsWith(textSpan) && !semanticSet.Contains(s.TextSpan)));
allClassifications.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
var allClassifications = new List<ClassifiedSpan>(semanticClassifications.Where(s => s.TextSpan.OverlapsWith(textSpan)));
var semanticSet = semanticClassifications.Select(s => s.TextSpan).ToSet();
return allClassifications;
}
finally
{
syntacticClassifications.Free();
semanticClassifications.Free();
}
allClassifications.AddRange(syntacticClassifications.Where(
s => s.TextSpan.OverlapsWith(textSpan) && !semanticSet.Contains(s.TextSpan)));
allClassifications.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
return allClassifications;
}
internal static async Task<ImmutableArray<SymbolDisplayPart>> GetClassifiedSymbolDisplayPartsAsync(
......
......@@ -104,23 +104,15 @@ private static void RemoveAdditiveSpans(List<ClassifiedSpan> spans)
// things it knows about. i.e. there will be gaps in what it produces.
// Fill in those gaps so we have *all* parts of the span
// classified properly.
var filledInSyntaxSpans = ArrayBuilder<ClassifiedSpan>.GetInstance();
var filledInSemanticSpans = ArrayBuilder<ClassifiedSpan>.GetInstance();
using var _1 = ArrayBuilder<ClassifiedSpan>.GetInstance(out var filledInSyntaxSpans);
using var _2 = ArrayBuilder<ClassifiedSpan>.GetInstance(out var filledInSemanticSpans);
try
{
FillInClassifiedSpanGaps(widenedSpan.Start, syntaxSpans, filledInSyntaxSpans);
FillInClassifiedSpanGaps(widenedSpan.Start, semanticSpans, filledInSemanticSpans);
FillInClassifiedSpanGaps(widenedSpan.Start, syntaxSpans, filledInSyntaxSpans);
FillInClassifiedSpanGaps(widenedSpan.Start, semanticSpans, filledInSemanticSpans);
// Now merge the lists together, taking all the results from syntaxParts
// unless they were overridden by results in semanticParts.
return MergeParts(filledInSyntaxSpans, filledInSemanticSpans);
}
finally
{
filledInSyntaxSpans.Free();
filledInSemanticSpans.Free();
}
// Now merge the lists together, taking all the results from syntaxParts
// unless they were overridden by results in semanticParts.
return MergeParts(filledInSyntaxSpans, filledInSemanticSpans);
}
private static void Order(List<ClassifiedSpan> syntaxSpans)
......
......@@ -124,14 +124,15 @@ private void ClassifyNodeOrToken(SyntaxNodeOrToken nodeOrToken)
private void ClassifyNode(SyntaxNode syntax)
{
using var _ = ArrayBuilder<ClassifiedSpan>.GetInstance(out var result);
foreach (var classifier in _getNodeClassifiers(syntax))
{
_cancellationToken.ThrowIfCancellationRequested();
var result = ArrayBuilder<ClassifiedSpan>.GetInstance();
result.Clear();
classifier.AddClassifications(_workspace, syntax, _semanticModel, result, _cancellationToken);
AddClassifications(result);
result.Free();
}
}
......@@ -158,14 +159,15 @@ private void ClassifyToken(SyntaxToken syntax)
{
ClassifyStructuredTrivia(syntax.LeadingTrivia);
using var _ = ArrayBuilder<ClassifiedSpan>.GetInstance(out var result);
foreach (var classifier in _getTokenClassifiers(syntax))
{
_cancellationToken.ThrowIfCancellationRequested();
var result = ArrayBuilder<ClassifiedSpan>.GetInstance();
result.Clear();
classifier.AddClassifications(_workspace, syntax, _semanticModel, result, _cancellationToken);
AddClassifications(result);
result.Free();
}
ClassifyStructuredTrivia(syntax.TrailingTrivia);
......
......@@ -419,18 +419,13 @@ public virtual string GetFixAllTitle(FixAllState fixAllState)
SimpleIntervalTree<TextChange, TextChangeIntervalIntrospector> cumulativeChanges,
ImmutableArray<TextChange> currentChanges)
{
var overlappingSpans = ArrayBuilder<TextChange>.GetInstance();
var intersectingSpans = ArrayBuilder<TextChange>.GetInstance();
using var _1 = ArrayBuilder<TextChange>.GetInstance(out var overlappingSpans);
using var _2 = ArrayBuilder<TextChange>.GetInstance(out var intersectingSpans);
var result = AllChangesCanBeApplied(
return AllChangesCanBeApplied(
cumulativeChanges, currentChanges,
overlappingSpans: overlappingSpans,
intersectingSpans: intersectingSpans);
overlappingSpans.Free();
intersectingSpans.Free();
return result;
}
private static bool AllChangesCanBeApplied(
......
......@@ -156,7 +156,7 @@ CancellationToken cancellationToken
.Select(n => (syntaxnode: n, namespaceSymbol: GetExplicitNamespaceSymbol(n, model)))
.Where(x => x.namespaceSymbol != null);
var nodesToSimplify = ArrayBuilder<SyntaxNode>.GetInstance();
using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var nodesToSimplify);
var addedSymbols = new HashSet<INamespaceSymbol>();
......@@ -189,7 +189,6 @@ CancellationToken cancellationToken
if (nodesToSimplify.Count == 0)
{
nodesToSimplify.Free();
return (importsToAdd.ToImmutableAndFree(), addedSymbols, null);
}
......@@ -202,7 +201,6 @@ CancellationToken cancellationToken
var first = root.DescendantNodesAndSelf().First(x => x.HasAnnotation(annotation));
var last = root.DescendantNodesAndSelf().Last(x => x.HasAnnotation(annotation));
nodesToSimplify.Free();
return (importsToAdd.ToImmutableAndFree(), addedSymbols, first.GetCommonRoot(last));
}
......
......@@ -259,7 +259,7 @@ private RegexExpressionNode ParseAlternatingSequencesWorker(bool consumeClosePar
private RegexSequenceNode ParseSequence(bool consumeCloseParen)
{
var builder = ArrayBuilder<RegexExpressionNode>.GetInstance();
using var _ = ArrayBuilder<RegexExpressionNode>.GetInstance(out var builder);
while (ShouldConsumeSequenceElement(consumeCloseParen))
{
var last = builder.Count == 0 ? null : builder.Last();
......@@ -271,7 +271,6 @@ private RegexSequenceNode ParseSequence(bool consumeCloseParen)
// try to merge that into one single text node.
var sequence = ArrayBuilder<RegexExpressionNode>.GetInstance();
MergeTextNodes(builder, sequence);
builder.Free();
return new RegexSequenceNode(sequence.ToImmutableAndFree());
}
......@@ -1238,7 +1237,7 @@ private RegexBaseCharacterClassNode ParseCharacterClass()
// trivia is not allowed anywhere in a character class
ConsumeCurrentToken(allowTrivia: false);
var builder = ArrayBuilder<RegexExpressionNode>.GetInstance();
using var _ = ArrayBuilder<RegexExpressionNode>.GetInstance(out var builder);
while (_currentToken.Kind != RegexKind.EndOfFile)
{
Debug.Assert(_currentToken.VirtualChars.Length == 1);
......@@ -1258,7 +1257,6 @@ private RegexBaseCharacterClassNode ParseCharacterClass()
// try to merge that into one single text node.
var contents = ArrayBuilder<RegexExpressionNode>.GetInstance();
MergeTextNodes(builder, contents);
builder.Free();
if (closeBracketToken.IsMissing)
{
......
......@@ -133,42 +133,36 @@ private void CheckInvariants(SyntaxToken token, VirtualCharSequence result)
var startIndexInclusive = startDelimiter.Length;
var endIndexExclusive = tokenText.Length - endDelimiter.Length;
var result = ArrayBuilder<VirtualChar>.GetInstance();
using var _ = ArrayBuilder<VirtualChar>.GetInstance(out var result);
var offset = token.SpanStart;
try
for (var index = startIndexInclusive; index < endIndexExclusive;)
{
for (var index = startIndexInclusive; index < endIndexExclusive;)
if (tokenText[index] == '"' &&
tokenText[index + 1] == '"')
{
result.Add(new VirtualChar('"', new TextSpan(offset + index, 2)));
index += 2;
}
else if (escapeBraces &&
(tokenText[index] == '{' || tokenText[index] == '}'))
{
if (tokenText[index] == '"' &&
tokenText[index + 1] == '"')
if (!TryAddBraceEscape(result, tokenText, offset, index))
{
result.Add(new VirtualChar('"', new TextSpan(offset + index, 2)));
index += 2;
return default;
}
else if (escapeBraces &&
(tokenText[index] == '{' || tokenText[index] == '}'))
{
if (!TryAddBraceEscape(result, tokenText, offset, index))
{
return default;
}
index += result.Last().Span.Length;
}
else
{
result.Add(new VirtualChar(tokenText[index], new TextSpan(offset + index, 1)));
index++;
}
index += result.Last().Span.Length;
}
else
{
result.Add(new VirtualChar(tokenText[index], new TextSpan(offset + index, 1)));
index++;
}
return CreateVirtualCharSequence(
tokenText, offset, startIndexInclusive, endIndexExclusive, result);
}
finally
{
result.Free();
}
return CreateVirtualCharSequence(
tokenText, offset, startIndexInclusive, endIndexExclusive, result);
}
protected static VirtualCharSequence CreateVirtualCharSequence(
......
......@@ -127,7 +127,7 @@ public static partial class SymbolFinder
containingType, solution, projects, cancellationToken).ConfigureAwait(false);
var allTypes = derivedClasses.Concat(containingType);
var builder = ArrayBuilder<SymbolAndProjectId>.GetInstance();
using var _ = ArrayBuilder<SymbolAndProjectId>.GetInstance(out var builder);
foreach (var type in allTypes.Convert<INamedTypeSymbol, ITypeSymbol>())
{
......@@ -161,10 +161,8 @@ public static partial class SymbolFinder
}
}
var result = builder.Distinct(SymbolAndProjectIdComparer.SymbolEquivalenceInstance)
.ToImmutableArray();
builder.Free();
return result;
return builder.Distinct(SymbolAndProjectIdComparer.SymbolEquivalenceInstance)
.ToImmutableArray();
}
}
......
......@@ -506,25 +506,19 @@ private static int BinarySearch(string concatenatedNames, ImmutableArray<Node> n
}
else
{
var containerSymbols = ArrayBuilder<ISymbol>.GetInstance();
try
using var _ = ArrayBuilder<ISymbol>.GetInstance(out var containerSymbols);
Bind(node.ParentIndex, rootContainer, containerSymbols, cancellationToken);
foreach (var containerSymbol in containerSymbols)
{
Bind(node.ParentIndex, rootContainer, containerSymbols, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
foreach (var containerSymbol in containerSymbols)
if (containerSymbol is INamespaceOrTypeSymbol nsOrType)
{
cancellationToken.ThrowIfCancellationRequested();
if (containerSymbol is INamespaceOrTypeSymbol nsOrType)
{
results.AddRange(nsOrType.GetMembers(GetName(node)));
}
results.AddRange(nsOrType.GetMembers(GetName(node)));
}
}
finally
{
containerSymbols.Free();
}
}
}
......@@ -621,25 +615,20 @@ internal void AssertEquivalentTo(SymbolTreeInfo other)
var derivedTypeIndices = _inheritanceMap[baseTypeNameIndex];
var builder = ArrayBuilder<INamedTypeSymbol>.GetInstance();
using var _ = ArrayBuilder<ISymbol>.GetInstance(out var tempBuilder);
foreach (var derivedTypeIndex in derivedTypeIndices)
{
var tempBuilder = ArrayBuilder<ISymbol>.GetInstance();
try
tempBuilder.Clear();
Bind(derivedTypeIndex, compilation.GlobalNamespace, tempBuilder, cancellationToken);
foreach (var symbol in tempBuilder)
{
Bind(derivedTypeIndex, compilation.GlobalNamespace, tempBuilder, cancellationToken);
foreach (var symbol in tempBuilder)
if (symbol is INamedTypeSymbol namedType)
{
if (symbol is INamedTypeSymbol namedType)
{
builder.Add(namedType);
}
builder.Add(namedType);
}
}
finally
{
tempBuilder.Free();
}
}
return builder.ToImmutableAndFree();
......
......@@ -82,25 +82,18 @@ private static async Task<Checksum> ComputeSourceSymbolsChecksumAsync(ProjectSta
var parseOptionsChecksum = projectStateChecksums.ParseOptions;
var textChecksums = await Task.WhenAll(textChecksumsTasks).ConfigureAwait(false);
var allChecksums = ArrayBuilder<Checksum>.GetInstance();
try
{
allChecksums.AddRange(textChecksums);
allChecksums.Add(compilationOptionsChecksum);
allChecksums.Add(parseOptionsChecksum);
using var _ = ArrayBuilder<Checksum>.GetInstance(out var allChecksums);
// Include serialization format version in our checksum. That way if the
// version ever changes, all persisted data won't match the current checksum
// we expect, and we'll recompute things.
allChecksums.Add(SerializationFormatChecksum);
allChecksums.AddRange(textChecksums);
allChecksums.Add(compilationOptionsChecksum);
allChecksums.Add(parseOptionsChecksum);
var checksum = Checksum.Create(WellKnownSynchronizationKind.SymbolTreeInfo, allChecksums);
return checksum;
}
finally
{
allChecksums.Free();
}
// Include serialization format version in our checksum. That way if the
// version ever changes, all persisted data won't match the current checksum
// we expect, and we'll recompute things.
allChecksums.Add(SerializationFormatChecksum);
return Checksum.Create(WellKnownSynchronizationKind.SymbolTreeInfo, allChecksums);
}
internal static async Task<SymbolTreeInfo> CreateSourceSymbolTreeInfoAsync(
......
......@@ -216,7 +216,7 @@ private static string Substring(string name, TextSpan wordSpan)
string resourceId, out string reason)
{
reason = null;
var violations = ArrayBuilder<string>.GetInstance();
using var _ = ArrayBuilder<string>.GetInstance(out var violations);
foreach (var wordSpan in GetWordSpans(name, nameSpan))
{
......@@ -231,8 +231,6 @@ private static string Substring(string name, TextSpan wordSpan)
reason = string.Format(resourceId, string.Join(", ", violations));
}
violations.Free();
return reason == null;
}
......@@ -260,7 +258,7 @@ private bool CheckAllLower(string name, TextSpan nameSpan, out string reason)
out string reason)
{
reason = null;
var violations = ArrayBuilder<string>.GetInstance();
using var _ = ArrayBuilder<string>.GetInstance(out var violations);
var first = true;
......@@ -292,7 +290,6 @@ private bool CheckAllLower(string name, TextSpan nameSpan, out string reason)
: reason + Environment.NewLine + restString;
}
violations.Free();
return reason == null;
}
......
......@@ -59,45 +59,38 @@ private bool AddMatches(string container, ArrayBuilder<PatternMatch> matches, bo
return false;
}
var tempContainerMatches = ArrayBuilder<PatternMatch>.GetInstance();
using var _ = ArrayBuilder<PatternMatch>.GetInstance(out var tempContainerMatches);
try
{
var containerParts = container.Split(_containerSplitCharacters, StringSplitOptions.RemoveEmptyEntries);
var containerParts = container.Split(_containerSplitCharacters, StringSplitOptions.RemoveEmptyEntries);
var relevantDotSeparatedSegmentLength = _patternSegments.Length;
if (_patternSegments.Length > containerParts.Length)
{
// There weren't enough container parts to match against the pattern parts.
// So this definitely doesn't match.
return false;
}
var relevantDotSeparatedSegmentLength = _patternSegments.Length;
if (_patternSegments.Length > containerParts.Length)
{
// There weren't enough container parts to match against the pattern parts.
// So this definitely doesn't match.
return false;
}
// So far so good. Now break up the container for the candidate and check if all
// the dotted parts match up correctly.
// So far so good. Now break up the container for the candidate and check if all
// the dotted parts match up correctly.
for (int i = _patternSegments.Length - 1, j = containerParts.Length - 1;
i >= 0;
i--, j--)
for (int i = _patternSegments.Length - 1, j = containerParts.Length - 1;
i >= 0;
i--, j--)
{
var segment = _patternSegments[i];
var containerName = containerParts[j];
if (!MatchPatternSegment(containerName, segment, tempContainerMatches, fuzzyMatch))
{
var segment = _patternSegments[i];
var containerName = containerParts[j];
if (!MatchPatternSegment(containerName, segment, tempContainerMatches, fuzzyMatch))
{
// This container didn't match the pattern piece. So there's no match at all.
return false;
}
// This container didn't match the pattern piece. So there's no match at all.
return false;
}
// Success, this symbol's full name matched against the dotted name the user was asking
// about.
matches.AddRange(tempContainerMatches);
return true;
}
finally
{
tempContainerMatches.Free();
}
// Success, this symbol's full name matched against the dotted name the user was asking
// about.
matches.AddRange(tempContainerMatches);
return true;
}
}
}
......
......@@ -337,30 +337,23 @@ private static bool ContainsSpaceOrAsterisk(string text)
}
else
{
var tempMatches = ArrayBuilder<PatternMatch>.GetInstance();
using var _ = ArrayBuilder<PatternMatch>.GetInstance(out var tempMatches);
try
foreach (var subWordTextChunk in subWordTextChunks)
{
foreach (var subWordTextChunk in subWordTextChunks)
// Try to match the candidate with this word
var result = MatchPatternChunk(
candidate, subWordTextChunk, punctuationStripped: true, fuzzyMatch: fuzzyMatch);
if (result == null)
{
// Try to match the candidate with this word
var result = MatchPatternChunk(
candidate, subWordTextChunk, punctuationStripped: true, fuzzyMatch: fuzzyMatch);
if (result == null)
{
return false;
}
tempMatches.Add(result.Value);
return false;
}
matches.AddRange(tempMatches);
return tempMatches.Count > 0;
}
finally
{
tempMatches.Free();
tempMatches.Add(result.Value);
}
matches.AddRange(tempMatches);
return tempMatches.Count > 0;
}
}
......@@ -479,7 +472,7 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat
var patternHumpCount = patternHumps.Count;
var candidateHumpCount = candidateHumps.Count;
var matchSpans = ArrayBuilder<TextSpan>.GetInstance();
using var _ = ArrayBuilder<TextSpan>.GetInstance(out var matchSpans);
while (true)
{
// Let's consider our termination cases
......@@ -492,7 +485,6 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat
matchedSpans = _includeMatchedSpans
? new NormalizedTextSpanCollection(matchSpans).ToImmutableArray()
: ImmutableArray<TextSpan>.Empty;
matchSpans.Free();
var camelCaseResult = new CamelCaseResult(firstMatch == 0, contiguous.Value, matchCount, null);
return GetCamelCaseKind(camelCaseResult, candidateHumps);
......@@ -501,7 +493,6 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat
{
// No match, since we still have more of the pattern to hit
matchedSpans = ImmutableArray<TextSpan>.Empty;
matchSpans.Free();
return null;
}
......
......@@ -11,13 +11,9 @@ internal static class PatternMatcherExtensions
{
public static PatternMatch? GetFirstMatch(this PatternMatcher matcher, string candidate)
{
var matches = ArrayBuilder<PatternMatch>.GetInstance();
using var _ = ArrayBuilder<PatternMatch>.GetInstance(out var matches);
matcher.AddMatches(candidate, matches);
var result = matches.Any() ? (PatternMatch?)matches.First() : null;
matches.Free();
return result;
return matches.Any() ? (PatternMatch?)matches.First() : null;
}
public static bool Matches(this PatternMatcher matcher, string candidate)
......
......@@ -119,7 +119,7 @@ public static IMethodSymbol CreateEqualsMethod(this Compilation compilation, Imm
// These will be all the expressions that we'll '&&' together inside the final
// return statement of 'Equals'.
var expressions = ArrayBuilder<SyntaxNode>.GetInstance();
using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var expressions);
if (factory.SupportsPatterns(parseOptions))
{
......@@ -195,7 +195,6 @@ public static IMethodSymbol CreateEqualsMethod(this Compilation compilation, Imm
statements.Add(factory.ReturnStatement(
expressions.Aggregate(factory.LogicalAndExpression)));
expressions.Free();
return statements.ToImmutableAndFree();
}
......@@ -264,7 +263,7 @@ public static IMethodSymbol CreateEqualsMethod(this Compilation compilation, Imm
// These will be all the expressions that we'll '&&' together inside the final
// return statement of 'Equals'.
var expressions = ArrayBuilder<SyntaxNode>.GetInstance();
using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var expressions);
if (!containingType.IsValueType)
{
......@@ -296,7 +295,6 @@ public static IMethodSymbol CreateEqualsMethod(this Compilation compilation, Imm
statements.Add(factory.ReturnStatement(
expressions.Aggregate(factory.LogicalAndExpression)));
expressions.Free();
return statements.ToImmutableAndFree();
}
......
......@@ -58,15 +58,8 @@ internal partial class SQLitePersistentStorage
TKey key,
CancellationToken cancellationToken)
{
var writesToProcess = ArrayBuilder<Action<SqlConnection>>.GetInstance();
try
{
await FlushSpecificWritesAsync(keyToWriteActions, keyToWriteTask, key, writesToProcess, cancellationToken).ConfigureAwait(false);
}
finally
{
writesToProcess.Free();
}
using var _ = ArrayBuilder<Action<SqlConnection>>.GetInstance(out var writesToProcess);
await FlushSpecificWritesAsync(keyToWriteActions, keyToWriteTask, key, writesToProcess, cancellationToken).ConfigureAwait(false);
}
[PerformanceSensitive("https://github.com/dotnet/roslyn/issues/36114", AllowCaptures = false)]
......@@ -174,36 +167,29 @@ internal partial class SQLitePersistentStorage
private async Task FlushAllPendingWritesAsync(CancellationToken cancellationToken)
{
// Copy the work from _writeQueue to a local list that we can process.
var writesToProcess = ArrayBuilder<Action<SqlConnection>>.GetInstance();
try
using var _ = ArrayBuilder<Action<SqlConnection>>.GetInstance(out var writesToProcess);
using (await _writeQueueGate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
using (await _writeQueueGate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
// Copy the pending work the accessors have to the local copy.
_solutionAccessor.AddAndClearAllPendingWrites(writesToProcess);
_projectAccessor.AddAndClearAllPendingWrites(writesToProcess);
_documentAccessor.AddAndClearAllPendingWrites(writesToProcess);
// Indicate that there is no outstanding write task. The next request to
// write will cause one to be kicked off.
_flushAllTask = null;
// Note: we keep the lock while we're writing all. That way if any reads come
// in and want to wait for the respective keys to be written, they will see the
// results of our writes after the lock is released. Note: this is slightly
// heavyweight. But as we're only doing these writes in bulk a couple of times
// a second max, this should not be an area of contention.
if (writesToProcess.Count > 0)
{
// Copy the pending work the accessors have to the local copy.
_solutionAccessor.AddAndClearAllPendingWrites(writesToProcess);
_projectAccessor.AddAndClearAllPendingWrites(writesToProcess);
_documentAccessor.AddAndClearAllPendingWrites(writesToProcess);
// Indicate that there is no outstanding write task. The next request to
// write will cause one to be kicked off.
_flushAllTask = null;
// Note: we keep the lock while we're writing all. That way if any reads come
// in and want to wait for the respective keys to be written, they will see the
// results of our writes after the lock is released. Note: this is slightly
// heavyweight. But as we're only doing these writes in bulk a couple of times
// a second max, this should not be an area of contention.
if (writesToProcess.Count > 0)
{
using var pooledConnection = GetPooledConnection();
ProcessWriteQueue(pooledConnection.Connection, writesToProcess);
}
using var pooledConnection = GetPooledConnection();
ProcessWriteQueue(pooledConnection.Connection, writesToProcess);
}
}
finally
{
writesToProcess.Free();
}
}
private void ProcessWriteQueue(
......
......@@ -137,12 +137,9 @@ public bool HasIntervalThatContains<TIntrospector>(int start, int length, in TIn
private bool Any<TIntrospector>(int start, int length, TestInterval<TIntrospector> testInterval, in TIntrospector introspector)
where TIntrospector : struct, IIntervalIntrospector<T>
{
var builder = ArrayBuilder<T>.GetInstance();
using var _ = ArrayBuilder<T>.GetInstance(out var builder);
FillWithIntervalsThatMatch(start, length, testInterval, builder, in introspector, stopAfterFirst: true);
var result = builder.Count > 0;
builder.Free();
return result;
return builder.Count > 0;
}
private ImmutableArray<T> GetIntervalsThatMatch<TIntrospector>(
......
......@@ -718,34 +718,27 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol
return matchingNameParameters;
}
var allParameters = ArrayBuilder<TypeInferenceInfo>.GetInstance();
var matchingRefParameters = ArrayBuilder<TypeInferenceInfo>.GetInstance();
try
using var _1 = ArrayBuilder<TypeInferenceInfo>.GetInstance(out var allParameters);
using var _2 = ArrayBuilder<TypeInferenceInfo>.GetInstance(out var matchingRefParameters);
foreach (var parameterSet in parameterizedSymbols)
{
foreach (var parameterSet in parameterizedSymbols)
if (index < parameterSet.Length)
{
if (index < parameterSet.Length)
{
var parameter = parameterSet[index];
var info = new TypeInferenceInfo(parameter.Type, parameter.IsParams);
allParameters.Add(info);
var parameter = parameterSet[index];
var info = new TypeInferenceInfo(parameter.Type, parameter.IsParams);
allParameters.Add(info);
if (parameter.RefKind == refKind)
{
matchingRefParameters.Add(info);
}
if (parameter.RefKind == refKind)
{
matchingRefParameters.Add(info);
}
}
return matchingRefParameters.Count > 0
? matchingRefParameters.ToImmutable()
: allParameters.ToImmutable();
}
finally
{
allParameters.Free();
matchingRefParameters.Free();
}
return matchingRefParameters.Count > 0
? matchingRefParameters.ToImmutable()
: allParameters.ToImmutable();
}
private IEnumerable<TypeInferenceInfo> InferTypeInArrayCreationExpression(
......@@ -2162,47 +2155,40 @@ private IEnumerable<TypeInferenceInfo> InferTypeInVariableComponentAssignment(Ex
elementTypes = default;
elementNames = default;
var elementTypesBuilder = ArrayBuilder<ITypeSymbol>.GetInstance();
var elementNamesBuilder = ArrayBuilder<string>.GetInstance();
try
using var _1 = ArrayBuilder<ITypeSymbol>.GetInstance(out var elementTypesBuilder);
using var _2 = ArrayBuilder<string>.GetInstance(out var elementNamesBuilder);
foreach (var arg in arguments)
{
foreach (var arg in arguments)
var expr = arg.Expression;
if (expr.IsKind(SyntaxKind.DeclarationExpression))
{
var expr = arg.Expression;
if (expr.IsKind(SyntaxKind.DeclarationExpression))
{
AddTypeAndName((DeclarationExpressionSyntax)expr, elementTypesBuilder, elementNamesBuilder);
}
else if (expr.IsKind(SyntaxKind.TupleExpression))
{
AddTypeAndName((TupleExpressionSyntax)expr, elementTypesBuilder, elementNamesBuilder);
}
else if (expr is IdentifierNameSyntax name)
{
elementNamesBuilder.Add(name.Identifier.ValueText == "" ? null :
name.Identifier.ValueText);
elementTypesBuilder.Add(GetTypes(expr).FirstOrDefault().InferredType ?? this.Compilation.ObjectType);
}
else
{
return false;
}
AddTypeAndName((DeclarationExpressionSyntax)expr, elementTypesBuilder, elementNamesBuilder);
}
if (elementTypesBuilder.Contains(null) || elementTypesBuilder.Count != arguments.Count)
else if (expr.IsKind(SyntaxKind.TupleExpression))
{
AddTypeAndName((TupleExpressionSyntax)expr, elementTypesBuilder, elementNamesBuilder);
}
else if (expr is IdentifierNameSyntax name)
{
elementNamesBuilder.Add(name.Identifier.ValueText == "" ? null :
name.Identifier.ValueText);
elementTypesBuilder.Add(GetTypes(expr).FirstOrDefault().InferredType ?? this.Compilation.ObjectType);
}
else
{
return false;
}
elementTypes = elementTypesBuilder.ToImmutable();
elementNames = elementNamesBuilder.ToImmutable();
return true;
}
finally
if (elementTypesBuilder.Contains(null) || elementTypesBuilder.Count != arguments.Count)
{
elementTypesBuilder.Free();
elementNamesBuilder.Free();
return false;
}
elementTypes = elementTypesBuilder.ToImmutable();
elementNames = elementNamesBuilder.ToImmutable();
return true;
}
private void AddTypeAndName(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册