143 lines
6.8 KiB
C#
143 lines
6.8 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
|
|
|
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|
{
|
|
internal class PreallocatedAttributeTargetExtension : IPreallocatedAttributeTargetExtension
|
|
{
|
|
public string TagHelperAttributeTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute";
|
|
|
|
public string EncodedHtmlStringTypeName { get; set; } = "Microsoft.AspNetCore.Html.HtmlString";
|
|
|
|
public string ExecutionContextVariableName { get; set; } = "__tagHelperExecutionContext";
|
|
|
|
public string ExecutionContextAddHtmlAttributeMethodName { get; set; } = "AddHtmlAttribute";
|
|
|
|
public string ExecutionContextAddTagHelperAttributeMethodName { get; set; } = "AddTagHelperAttribute";
|
|
|
|
public string FormatInvalidIndexerAssignmentMethodName { get; set; } = "InvalidTagHelperIndexerAssignment";
|
|
|
|
public void WriteDeclarePreallocatedTagHelperHtmlAttribute(CSharpRenderingContext context, DeclarePreallocatedTagHelperHtmlAttributeIntermediateNode node)
|
|
{
|
|
context.Writer
|
|
.Write("private static readonly global::")
|
|
.Write(TagHelperAttributeTypeName)
|
|
.Write(" ")
|
|
.Write(node.VariableName)
|
|
.Write(" = ")
|
|
.WriteStartNewObject("global::" + TagHelperAttributeTypeName)
|
|
.WriteStringLiteral(node.Name);
|
|
|
|
if (node.AttributeStructure == AttributeStructure.Minimized)
|
|
{
|
|
context.Writer.WriteEndMethodInvocation();
|
|
}
|
|
else
|
|
{
|
|
context.Writer
|
|
.WriteParameterSeparator()
|
|
.WriteStartNewObject("global::" + EncodedHtmlStringTypeName)
|
|
.WriteStringLiteral(node.Value)
|
|
.WriteEndMethodInvocation(endLine: false)
|
|
.WriteParameterSeparator()
|
|
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.AttributeStructure}")
|
|
.WriteEndMethodInvocation();
|
|
}
|
|
}
|
|
|
|
public void WriteAddPreallocatedTagHelperHtmlAttribute(CSharpRenderingContext context, AddPreallocatedTagHelperHtmlAttributeIntermediateNode node)
|
|
{
|
|
context.Writer
|
|
.WriteStartInstanceMethodInvocation(ExecutionContextVariableName, ExecutionContextAddHtmlAttributeMethodName)
|
|
.Write(node.VariableName)
|
|
.WriteEndMethodInvocation();
|
|
}
|
|
|
|
public void WriteDeclarePreallocatedTagHelperAttribute(CSharpRenderingContext context, DeclarePreallocatedTagHelperAttributeIntermediateNode node)
|
|
{
|
|
context.Writer
|
|
.Write("private static readonly global::")
|
|
.Write(TagHelperAttributeTypeName)
|
|
.Write(" ")
|
|
.Write(node.VariableName)
|
|
.Write(" = ")
|
|
.WriteStartNewObject("global::" + TagHelperAttributeTypeName)
|
|
.WriteStringLiteral(node.Name)
|
|
.WriteParameterSeparator()
|
|
.WriteStringLiteral(node.Value)
|
|
.WriteParameterSeparator()
|
|
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.AttributeStructure}")
|
|
.WriteEndMethodInvocation();
|
|
}
|
|
|
|
public void WriteSetPreallocatedTagHelperProperty(CSharpRenderingContext context, SetPreallocatedTagHelperPropertyIntermediateNode node)
|
|
{
|
|
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
|
var propertyName = node.Descriptor.GetPropertyName();
|
|
var propertyValueAccessor = GetTagHelperPropertyAccessor(node.IsIndexerNameMatch, tagHelperVariableName, node.AttributeName, node.Descriptor);
|
|
var attributeValueAccessor = $"{node.VariableName}.Value" /* ORIGINAL: TagHelperAttributeValuePropertyName */;
|
|
|
|
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
|
if (node.IsIndexerNameMatch &&
|
|
context.TagHelperRenderingContext.VerifiedPropertyDictionaries.Add($"{node.TagHelperTypeName}.{propertyName}"))
|
|
{
|
|
// Throw a reasonable Exception at runtime if the dictionary property is null.
|
|
context.Writer
|
|
.Write("if (")
|
|
.Write(tagHelperVariableName)
|
|
.Write(".")
|
|
.Write(propertyName)
|
|
.WriteLine(" == null)");
|
|
using (context.Writer.BuildScope())
|
|
{
|
|
// System is in Host.NamespaceImports for all MVC scenarios. No need to generate FullName
|
|
// of InvalidOperationException type.
|
|
context.Writer
|
|
.Write("throw ")
|
|
.WriteStartNewObject(nameof(InvalidOperationException))
|
|
.WriteStartMethodInvocation(FormatInvalidIndexerAssignmentMethodName)
|
|
.WriteStringLiteral(node.AttributeName)
|
|
.WriteParameterSeparator()
|
|
.WriteStringLiteral(node.TagHelperTypeName)
|
|
.WriteParameterSeparator()
|
|
.WriteStringLiteral(propertyName)
|
|
.WriteEndMethodInvocation(endLine: false) // End of method call
|
|
.WriteEndMethodInvocation(); // End of new expression / throw statement
|
|
}
|
|
}
|
|
|
|
context.Writer
|
|
.WriteStartAssignment(propertyValueAccessor)
|
|
.Write("(string)")
|
|
.Write(attributeValueAccessor)
|
|
.WriteLine(";")
|
|
.WriteStartInstanceMethodInvocation(ExecutionContextVariableName, ExecutionContextAddTagHelperAttributeMethodName)
|
|
.Write(node.VariableName)
|
|
.WriteEndMethodInvocation();
|
|
}
|
|
|
|
private static string GetTagHelperVariableName(string tagHelperTypeName) => "__" + tagHelperTypeName.Replace('.', '_');
|
|
|
|
private static string GetTagHelperPropertyAccessor(
|
|
bool isIndexerNameMatch,
|
|
string tagHelperVariableName,
|
|
string attributeName,
|
|
BoundAttributeDescriptor descriptor)
|
|
{
|
|
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.GetPropertyName()}";
|
|
|
|
if (isIndexerNameMatch)
|
|
{
|
|
var dictionaryKey = attributeName.Substring(descriptor.IndexerNamePrefix.Length);
|
|
propertyAccessor += $"[\"{dictionaryKey}\"]";
|
|
}
|
|
|
|
return propertyAccessor;
|
|
}
|
|
}
|
|
}
|