| File: Snippets\AbstractSnippetService.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.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Snippets.SnippetProviders; namespace Microsoft.CodeAnalysis.Snippets; internal abstract class AbstractSnippetService(IEnumerable<Lazy<ISnippetProvider, LanguageMetadata>> lazySnippetProviders) : ISnippetService { private readonly ImmutableArray<Lazy<ISnippetProvider, LanguageMetadata>> _lazySnippetProviders = [.. lazySnippetProviders]; private readonly Dictionary<string, ISnippetProvider> _identifierToProviderMap = []; private readonly object _snippetProvidersLock = new(); private ImmutableArray<ISnippetProvider> _snippetProviders; /// <summary> /// This should never be called prior to GetSnippetsAsync because it gets populated /// at that point in time. /// </summary> public ISnippetProvider GetSnippetProvider(string snippetIdentifier) { Contract.ThrowIfFalse(_identifierToProviderMap.ContainsKey(snippetIdentifier)); return _identifierToProviderMap[snippetIdentifier]; } /// <summary> /// Iterates through all providers and determines if the snippet /// can be added to the Completion list at the corresponding position. /// </summary> public ImmutableArray<SnippetData> GetSnippets(SnippetContext context, CancellationToken cancellationToken) { using var _ = ArrayBuilder<SnippetData>.GetInstance(out var arrayBuilder); EnsureSnippetsLoaded(context.Document.Project.Language); foreach (var provider in _snippetProviders) { if (provider.IsValidSnippetLocation(context, cancellationToken)) arrayBuilder.Add(new(provider.Identifier, provider.Description, provider.AdditionalFilterTexts)); } return arrayBuilder.ToImmutableAndClear(); } internal void EnsureSnippetsLoaded(string language) { lock (_snippetProvidersLock) { if (_snippetProviders.IsDefault) { using var _ = ArrayBuilder<ISnippetProvider>.GetInstance(out var arrayBuilder); foreach (var provider in _lazySnippetProviders.Where(p => p.Metadata.Language == language)) { var providerData = provider.Value; Debug.Assert(!_identifierToProviderMap.TryGetValue(providerData.Identifier, out var _)); _identifierToProviderMap.Add(providerData.Identifier, providerData); arrayBuilder.Add(providerData); } _snippetProviders = arrayBuilder.ToImmutable(); } } } }