Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -225,17 +225,21 @@ protected override bool IsCandidateType(INamedTypeSymbol types)
=> types.DeclaredAccessibility == Accessibility.Public &&
types.Name == "BindAttributes";

protected override void Collect(IAssemblySymbol assembly, ICollection<TagHelperDescriptor> results, CancellationToken cancellationToken)
public override void Collect(TagHelperDescriptorProviderContext context, CancellationToken cancellationToken)
{
// Overrides the outermost version of Collect as TagHelperCollector.Collect(context, token)
// caches results per assembly. This provider needs to operate on the full set of calculated
// descriptors to handle case #4.

// First, collect the initial set of tag helpers from this assembly. This calls
// the Collect(INamedTypeSymbol, ...) overload below for cases #2 & #3.
base.Collect(assembly, results, cancellationToken);
base.Collect(context, cancellationToken);

// Then, for case #4 we look at the tag helpers that were already created corresponding to components
// and pattern match on properties.
using var componentBindTagHelpers = new PooledArrayBuilder<TagHelperDescriptor>(capacity: results.Count);
using var componentBindTagHelpers = new PooledArrayBuilder<TagHelperDescriptor>(capacity: context.Results.Count);

foreach (var tagHelper in results)
foreach (var tagHelper in context.Results)
{
cancellationToken.ThrowIfCancellationRequested();

Expand All @@ -244,7 +248,7 @@ protected override void Collect(IAssemblySymbol assembly, ICollection<TagHelperD

foreach (var tagHelper in componentBindTagHelpers)
{
results.Add(tagHelper);
context.Results.Add(tagHelper);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,50 +29,57 @@ protected abstract void Collect(
ICollection<TagHelperDescriptor> results,
CancellationToken cancellationToken);

public void Collect(TagHelperDescriptorProviderContext context, CancellationToken cancellationToken)
public virtual void Collect(TagHelperDescriptorProviderContext context, CancellationToken cancellationToken)
{
if (_targetAssembly is not null)
{
Collect(_targetAssembly, context.Results, cancellationToken);
CollectTagHelpersForAssembly(_targetAssembly, context, cancellationToken);
}
else
{
Collect(_compilation.Assembly, context.Results, cancellationToken);
CollectTagHelpersForAssembly(_compilation.Assembly, context, cancellationToken);

foreach (var reference in _compilation.References)
{
cancellationToken.ThrowIfCancellationRequested();

if (_compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly)
{
// 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.
CollectTagHelpersForAssembly(assembly, context, cancellationToken);
}
}
}

var assemblySymbolData = SymbolCache.GetAssemblySymbolData(assembly);
if (!assemblySymbolData.MightContainTagHelpers)
{
continue;
}
return;

var includeDocumentation = context.IncludeDocumentation;
var excludeHidden = context.ExcludeHidden;
void CollectTagHelpersForAssembly(IAssemblySymbol assembly, TagHelperDescriptorProviderContext context, CancellationToken cancellationToken)
{
// 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.GetValue(assembly, static assembly => new Cache());
if (!cache.TryGet(includeDocumentation, excludeHidden, out var tagHelpers))
{
using var _ = ListPool<TagHelperDescriptor>.GetPooledObject(out var referenceTagHelpers);
Collect(assembly, referenceTagHelpers, cancellationToken);
var assemblySymbolData = SymbolCache.GetAssemblySymbolData(assembly);
if (!assemblySymbolData.MightContainTagHelpers)
{
return;
}

tagHelpers = cache.Add(referenceTagHelpers.ToArrayOrEmpty(), includeDocumentation, excludeHidden);
}
var includeDocumentation = context.IncludeDocumentation;
var excludeHidden = context.ExcludeHidden;

foreach (var tagHelper in tagHelpers)
{
context.Results.Add(tagHelper);
}
}
var cache = s_perAssemblyCaches.GetValue(assembly, static assembly => new Cache());
if (!cache.TryGet(includeDocumentation, excludeHidden, out var tagHelpers))
{
using var _ = ListPool<TagHelperDescriptor>.GetPooledObject(out var referenceTagHelpers);
Collect(assembly, referenceTagHelpers, cancellationToken);

tagHelpers = cache.Add(referenceTagHelpers.ToArrayOrEmpty(), includeDocumentation, excludeHidden);
}

foreach (var tagHelper in tagHelpers)
{
context.Results.Add(tagHelper);
}
}
}
Expand Down