| File: Language\TagHelperDescriptor.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.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.AspNetCore.Razor.Utilities; using Microsoft.CodeAnalysis; namespace Microsoft.AspNetCore.Razor.Language; [DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")] public sealed class TagHelperDescriptor : TagHelperObject<TagHelperDescriptor> { private readonly TagHelperFlags _flags; private ImmutableArray<BoundAttributeDescriptor> _editorRequiredAttributes; public TagHelperFlags Flags => _flags; public TagHelperKind Kind { get; } public RuntimeKind RuntimeKind { get; } public string Name { get; } public string AssemblyName { get; } public string TypeName => TypeNameObject.FullName.AssumeNotNull(); public string? TypeNamespace => TypeNameObject.Namespace; public string? TypeNameIdentifier => TypeNameObject.Name; public string? Documentation => DocumentationObject.GetText(); internal TypeNameObject TypeNameObject { get; } internal DocumentationObject DocumentationObject { get; } public string DisplayName { get; } public string? TagOutputHint { get; } public bool CaseSensitive => _flags.IsFlagSet(TagHelperFlags.CaseSensitive); public ImmutableArray<AllowedChildTagDescriptor> AllowedChildTags { get; } public ImmutableArray<BoundAttributeDescriptor> BoundAttributes { get; } public ImmutableArray<TagMatchingRuleDescriptor> TagMatchingRules { get; } public MetadataObject Metadata { get; } /// <summary> /// Gets whether the component matches a tag with a fully qualified name. /// </summary> internal bool IsFullyQualifiedNameMatch => _flags.IsFlagSet(TagHelperFlags.IsFullyQualifiedNameMatch); public bool ClassifyAttributesOnly => _flags.IsFlagSet(TagHelperFlags.ClassifyAttributesOnly); internal TagHelperDescriptor( TagHelperFlags flags, TagHelperKind kind, RuntimeKind runtimeKind, string name, string assemblyName, string displayName, TypeNameObject typeNameObject, DocumentationObject documentationObject, string? tagOutputHint, ImmutableArray<TagMatchingRuleDescriptor> tagMatchingRules, ImmutableArray<BoundAttributeDescriptor> attributeDescriptors, ImmutableArray<AllowedChildTagDescriptor> allowedChildTags, MetadataObject metadata, ImmutableArray<RazorDiagnostic> diagnostics) : base(diagnostics) { _flags = flags; RuntimeKind = runtimeKind; Kind = kind; Name = name; AssemblyName = assemblyName; DisplayName = displayName; TypeNameObject = typeNameObject; DocumentationObject = documentationObject; TagOutputHint = tagOutputHint; TagMatchingRules = tagMatchingRules.NullToEmpty(); BoundAttributes = attributeDescriptors.NullToEmpty(); AllowedChildTags = allowedChildTags.NullToEmpty(); Metadata = metadata; foreach (var tagMatchingRule in TagMatchingRules) { tagMatchingRule.SetParent(this); } foreach (var boundAttribute in BoundAttributes) { boundAttribute.SetParent(this); } foreach (var allowedChildTag in AllowedChildTags) { allowedChildTag.SetParent(this); } } private protected override void BuildChecksum(in Checksum.Builder builder) { builder.Append((byte)Flags); builder.Append((byte)Kind); builder.Append((byte)RuntimeKind); builder.Append(Name); builder.Append(AssemblyName); builder.Append(DisplayName); builder.Append(TagOutputHint); TypeNameObject.AppendToChecksum(in builder); DocumentationObject.AppendToChecksum(in builder); foreach (var descriptor in AllowedChildTags) { builder.Append(descriptor.Checksum); } foreach (var descriptor in BoundAttributes) { builder.Append(descriptor.Checksum); } foreach (var descriptor in TagMatchingRules) { builder.Append(descriptor.Checksum); } Metadata.AppendToChecksum(in builder); } internal ImmutableArray<BoundAttributeDescriptor> EditorRequiredAttributes { get { if (_editorRequiredAttributes.IsDefault) { ImmutableInterlocked.InterlockedInitialize(ref _editorRequiredAttributes, GetEditorRequiredAttributes(BoundAttributes)); } return _editorRequiredAttributes; static ImmutableArray<BoundAttributeDescriptor> GetEditorRequiredAttributes(ImmutableArray<BoundAttributeDescriptor> attributes) { if (attributes.Length == 0) { return ImmutableArray<BoundAttributeDescriptor>.Empty; } using var results = new PooledArrayBuilder<BoundAttributeDescriptor>(capacity: attributes.Length); foreach (var attribute in attributes) { if (attribute is { IsEditorRequired: true } editorRequiredAttribute) { results.Add(editorRequiredAttribute); } } return results.ToImmutableAndClear(); } } } public IEnumerable<RazorDiagnostic> GetAllDiagnostics() { using var diagnostics = new PooledArrayBuilder<RazorDiagnostic>(); AppendAllDiagnostics(ref diagnostics.AsRef()); foreach (var diagnostic in diagnostics) { yield return diagnostic; } } internal void AppendAllDiagnostics(ref PooledArrayBuilder<RazorDiagnostic> diagnostics) { foreach (var allowedChildTag in AllowedChildTags) { diagnostics.AddRange(allowedChildTag.Diagnostics); } foreach (var boundAttribute in BoundAttributes) { diagnostics.AddRange(boundAttribute.Diagnostics); } foreach (var tagMatchingRule in TagMatchingRules) { diagnostics.AddRange(tagMatchingRule.Diagnostics); } diagnostics.AddRange(Diagnostics); } public override string ToString() { return DisplayName ?? base.ToString()!; } private string GetDebuggerDisplay() { return $"{DisplayName} - {string.Join(" | ", TagMatchingRules.Select(r => r.GetDebuggerDisplay()))}"; } internal TagHelperDescriptor WithName(string name) { return new( Flags, Kind, RuntimeKind, name, AssemblyName, DisplayName, TypeNameObject, DocumentationObject, TagOutputHint, TagMatchingRules, BoundAttributes, AllowedChildTags, Metadata, Diagnostics); } }