diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.Cache.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.Cache.cs index 36871bcf0cf..9d05bb3a128 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.Cache.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.Cache.cs @@ -1,15 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Threading; +using Microsoft.CodeAnalysis; namespace Microsoft.AspNetCore.Razor.Language; public abstract partial class TagHelperCollector where T : TagHelperCollector { - private class Cache + private sealed class Cache(IAssemblySymbol assembly) { private const int IncludeDocumentation = 1 << 0; private const int ExcludeHidden = 1 << 1; @@ -19,6 +23,8 @@ private class Cache private readonly TagHelperDescriptor[]?[] _tagHelpers = new TagHelperDescriptor[CacheSize][]; + public bool MightContainTagHelpers { get; } = CalculateMightContainTagHelpers(assembly); + public bool TryGet(bool includeDocumentation, bool excludeHidden, [NotNullWhen(true)] out TagHelperDescriptor[]? tagHelpers) { var index = CalculateIndex(includeDocumentation, excludeHidden); @@ -50,5 +56,15 @@ private static int CalculateIndex(bool includeDocumentation, bool excludeHidden) return index; } + + private static bool CalculateMightContainTagHelpers(IAssemblySymbol assembly) + { + // In order to contain tag helpers, components, or anything else we might want to find, + // the assembly must start with "Microsoft.AspNetCore." or reference an assembly that + // starts with "Microsoft.AspNetCore." + return assembly.Name.StartsWith("Microsoft.AspNetCore.", StringComparison.Ordinal) || + assembly.Modules.First().ReferencedAssemblies.Any( + a => a.Name.StartsWith("Microsoft.AspNetCore.", StringComparison.Ordinal)); + } } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.cs index b893bb8de7c..5ea79866ddf 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/TagHelperCollector.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; @@ -25,17 +23,6 @@ protected TagHelperCollector(Compilation compilation, ISymbol? targetSymbol) _targetSymbol = targetSymbol; } - private static bool MightContainTagHelpers(IAssemblySymbol assembly) - { - // In order to contain tag helpers, components, or anything else we might want to find, - // the assembly must start with "Microsoft.AspNetCore." or reference an assembly that - // starts with "Microsoft.AspNetCore." - - return assembly.Name.StartsWith("Microsoft.AspNetCore.", StringComparison.Ordinal) || - assembly.Modules.First().ReferencedAssemblies.Any( - a => a.Name.StartsWith("Microsoft.AspNetCore.", StringComparison.Ordinal)); - } - protected abstract void Collect(ISymbol symbol, ICollection results); public void Collect(TagHelperDescriptorProviderContext context) @@ -52,17 +39,17 @@ public void Collect(TagHelperDescriptorProviderContext context) { if (_compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly) { - if (!MightContainTagHelpers(assembly)) - { - continue; - } - // Check to see if we already have tag helpers cached for this assembly // and use the cached versions if we do. Roslyn shares PE assembly symbols // across compilations, so this ensures that we don't produce new tag helpers // for the same assemblies over and over again. - var cache = s_perAssemblyCaches.GetOrCreateValue(assembly); + var cache = s_perAssemblyCaches.GetValue(assembly, static assembly => new Cache(assembly)); + + if (!cache.MightContainTagHelpers) + { + continue; + } var includeDocumentation = context.IncludeDocumentation; var excludeHidden = context.ExcludeHidden;