| File: Language\Components\ComponentKeyLoweringPass.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 ComponentKeyLoweringPass : 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 @namespace = documentNode.FindPrimaryNamespace(); var @class = documentNode.FindPrimaryClass(); if (@namespace == null || @class == 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.Key) { RewriteUsage(reference); } } } private static void RewriteUsage(IntermediateNodeReference<TagHelperDirectiveAttributeIntermediateNode> reference) { var (node, _) = reference; // If we can't get a nonempty attribute value, do nothing because there will // already be a diagnostic for empty values var keyValueToken = DetermineKeyValueToken(node); if (keyValueToken is null) { return; } var newNode = new SetKeyIntermediateNode(keyValueToken); reference.Replace(newNode); } private static IntermediateToken? DetermineKeyValueToken(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; } }