| File: Language\Components\ComponentReferenceCaptureLoweringPass.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; using System.Threading; using Microsoft.AspNetCore.Razor.Language.Intermediate; namespace Microsoft.AspNetCore.Razor.Language.Components; internal sealed class ComponentReferenceCaptureLoweringPass : ComponentIntermediateNodePassBase, IRazorOptimizationPass { // Run after component lowering pass public override int Order => 50; protected override void ExecuteCore( RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode, CancellationToken cancellationToken) { if (!IsComponentDocument(documentNode)) { return; } var namespaceNode = documentNode.FindPrimaryNamespace(); var classNode = documentNode.FindPrimaryClass(); if (namespaceNode == null || classNode == null) { // Nothing to do, bail. We can't function without the standard structure. return; } var references = documentNode.FindDescendantReferences<TagHelperDirectiveAttributeIntermediateNode>(); foreach (var reference in references) { if (reference.Node.TagHelper.Kind == TagHelperKind.Ref) { RewriteUsage(reference); } } } private static void RewriteUsage(IntermediateNodeReference<TagHelperDirectiveAttributeIntermediateNode> reference) { var (node, parent) = reference; // If we can't get a non-empty attribute name, do nothing because there will // already be a diagnostic for empty values var identifierToken = DetermineIdentifierToken(node); if (identifierToken is null) { return; } // Determine whether this is an element capture or a component capture, and // if applicable the type name that will appear in the resulting capture code var referenceCapture = parent as ComponentIntermediateNode is { Component: { } componentTagHelper } ? new ReferenceCaptureIntermediateNode(identifierToken, componentTagHelper.TypeName) : new ReferenceCaptureIntermediateNode(identifierToken); reference.Replace(referenceCapture); } private static IntermediateToken? DetermineIdentifierToken(TagHelperDirectiveAttributeIntermediateNode attributeNode) { var foundToken = attributeNode.Children switch { [IntermediateToken token] => token, [CSharpExpressionIntermediateNode { Children: [IntermediateToken token] }] => token, _ => null, }; if (foundToken is null) { return null; } return !foundToken.Content.IsNullOrWhiteSpace() ? foundToken : null; } }