| File: Completion\SharedSyntaxContextsWithSpeculativeModel.cs | Web Access |
| Project: src\roslyn\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Concurrent; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Completion; internal sealed class SharedSyntaxContextsWithSpeculativeModel { private readonly Document _document; private readonly int _position; private readonly ConcurrentDictionary<Document, AsyncLazy<SyntaxContext>> _cache; private readonly Lazy<ImmutableArray<DocumentId>> _lazyRelatedDocumentIds; public SharedSyntaxContextsWithSpeculativeModel(Document document, int position) { _document = document; _position = position; _cache = []; _lazyRelatedDocumentIds = new(_document.GetLinkedDocumentIds, isThreadSafe: true); } public Task<SyntaxContext> GetSyntaxContextAsync(Document document, CancellationToken cancellationToken) { if (!_cache.TryGetValue(document, out var lazyContext)) { if (_document.Id != document.Id && !_lazyRelatedDocumentIds.Value.Contains(document.Id)) throw new ArgumentException("Don't support getting SyntaxContext for document unrelated to the original document"); lazyContext = GetLazySyntaxContextWithSpeculativeModel(document, this); } return lazyContext.GetValueAsync(cancellationToken); // Extract a local function to avoid creating a closure for code path of cache hit. static AsyncLazy<SyntaxContext> GetLazySyntaxContextWithSpeculativeModel(Document document, SharedSyntaxContextsWithSpeculativeModel self) { return self._cache.GetOrAdd(document, d => AsyncLazy.Create(static (arg, cancellationToken) => Utilities.CreateSyntaxContextWithExistingSpeculativeModelAsync(arg.d, arg._position, cancellationToken), (d, self._position))); } } }