| File: Mvc\ModelExpressionPass.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.Collections.Generic; using System.Threading; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Intermediate; namespace Microsoft.AspNetCore.Mvc.Razor.Extensions; public sealed class ModelExpressionPass : IntermediateNodePassBase, IRazorOptimizationPass { private const string ModelExpressionTypeName = "Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression"; protected override void ExecuteCore( RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode, CancellationToken cancellationToken) { if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind && documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind) { // Not a MVC file. Skip. return; } var visitor = new Visitor(); visitor.Visit(documentNode); } private class Visitor : IntermediateNodeWalker { public List<TagHelperIntermediateNode> TagHelpers { get; } = new List<TagHelperIntermediateNode>(); public override void VisitTagHelperProperty(TagHelperPropertyIntermediateNode node) { if (string.Equals(node.BoundAttribute.TypeName, ModelExpressionTypeName, StringComparison.Ordinal) || (node.IsIndexerNameMatch && string.Equals(node.BoundAttribute.IndexerTypeName, ModelExpressionTypeName, StringComparison.Ordinal))) { var expression = new CSharpExpressionIntermediateNode(); expression.Children.Add(IntermediateNodeFactory.CSharpToken("ModelExpressionProvider.CreateModelExpression(ViewData, __model => ")); if (node.Children.Count == 1 && node.Children[0] is CSharpIntermediateToken token) { // A 'simple' expression will look like __model => __model.Foo expression.Children.Add(IntermediateNodeFactory.CSharpToken("__model.")); expression.Children.Add(token); } else { for (var i = 0; i < node.Children.Count; i++) { if (node.Children[i] is CSharpExpressionIntermediateNode nestedExpression) { for (var j = 0; j < nestedExpression.Children.Count; j++) { if (nestedExpression.Children[j] is CSharpIntermediateToken csharpToken) { expression.Children.Add(csharpToken); } } continue; } } } expression.Children.Add(IntermediateNodeFactory.CSharpToken(")")); node.Children.Clear(); node.Children.Add(expression); } } } }