| File: Language\TagHelperDiscoveryService.cs | Web Access |
| Project: src\roslyn\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.AspNetCore.Razor.Language.TagHelpers.Producers; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; namespace Microsoft.AspNetCore.Razor.Language; internal sealed class TagHelperDiscoveryService : RazorEngineFeatureBase, ITagHelperDiscoveryService { private ImmutableArray<ITagHelperProducerFactory> _producerFactories; protected override void OnInitialized() { _producerFactories = Engine.GetFeatures<ITagHelperProducerFactory>(); } public TagHelperCollection GetTagHelpers( Compilation compilation, TagHelperDiscoveryOptions options, CancellationToken cancellationToken = default) => GetTagHelpersForCompilation(compilation, options, cancellationToken); public TagHelperCollection GetTagHelpers( Compilation compilation, CancellationToken cancellationToken = default) => GetTagHelpersForCompilation(compilation, options: default, cancellationToken); private TagHelperCollection GetTagHelpersForCompilation( Compilation compilation, TagHelperDiscoveryOptions options, CancellationToken cancellationToken = default) { ArgHelper.ThrowIfNull(compilation); if (!TryGetDiscoverer(compilation, options, out var discoverer)) { return TagHelperCollection.Empty; } using var collections = new MemoryBuilder<TagHelperCollection>(initialCapacity: 512, clearArray: true); if (compilation.Assembly is { } compilationAssembly) { var collection = discoverer.GetTagHelpers(compilationAssembly, cancellationToken); if (!collection.IsEmpty) { collections.Append(collection); } } foreach (var reference in compilation.References) { cancellationToken.ThrowIfCancellationRequested(); if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol referenceAssembly) { var collection = discoverer.GetTagHelpers(referenceAssembly, cancellationToken); if (!collection.IsEmpty) { collections.Append(collection); } } } return TagHelperCollection.Merge(collections.AsMemory().Span); } public bool TryGetDiscoverer(Compilation compilation, TagHelperDiscoveryOptions options, [NotNullWhen(true)] out TagHelperDiscoverer? discoverer) { ArgHelper.ThrowIfNull(compilation); var excludeHidden = options.IsFlagSet(TagHelperDiscoveryOptions.ExcludeHidden); var includeDocumentation = options.IsFlagSet(TagHelperDiscoveryOptions.IncludeDocumentation); var producers = GetProducers(compilation, includeDocumentation, excludeHidden); if (producers.IsEmpty) { discoverer = default; return false; } discoverer = new TagHelperDiscoverer(producers, includeDocumentation, excludeHidden); return true; } public bool TryGetDiscoverer(Compilation compilation, [NotNullWhen(true)] out TagHelperDiscoverer? discoverer) => TryGetDiscoverer(compilation, options: default, out discoverer); private ImmutableArray<TagHelperProducer> GetProducers(Compilation compilation, bool includeDocumentation, bool excludeHidden) { if (_producerFactories.IsDefaultOrEmpty) { return []; } using var builder = new PooledArrayBuilder<TagHelperProducer>(_producerFactories.Length); foreach (var factory in _producerFactories) { if (factory.TryCreate(compilation, includeDocumentation, excludeHidden, out var producer)) { builder.Add(producer); } } return builder.ToImmutableAndClear(); } }