Introduces RuntimeTarget and abstraction for APIs
This is a new abstraction that represents the api surface available for codegen to target. Every kind of document should have an associated RuntimeTarget or just use the default. To prevent breakage, our DocumentClassifierBase class will provide a default API set to implementors (like MVC). I haven't fundamentally changed how codegen is done yet, I've just hidden it behind a new abstraction. The RuntimeTarget now is also responsible for selecting between design time and runtime. The bulk of the noise here is from splitting a lot of the codegen stuff into its own files.
This commit is contained in:
parent
f861c23d1f
commit
0dbf62196c
|
|
@ -0,0 +1,16 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class CSharpLiteralCodeConventions : CSharpRenderingConventions
|
||||
{
|
||||
public CSharpLiteralCodeConventions(CSharpCodeWriter writer) : base(writer)
|
||||
{
|
||||
}
|
||||
|
||||
public override string StartWriteMethod => StartWriteLiteralMethod;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class CSharpRedirectRenderingConventions : CSharpRenderingConventions
|
||||
{
|
||||
private readonly string _redirectWriter;
|
||||
|
||||
public CSharpRedirectRenderingConventions(string redirectWriter, CSharpCodeWriter writer)
|
||||
: base(writer)
|
||||
{
|
||||
_redirectWriter = redirectWriter;
|
||||
}
|
||||
|
||||
public override string StartWriteMethod => "WriteTo(" + _redirectWriter + ", " /* ORIGINAL: WriteToMethodName */;
|
||||
|
||||
public override string StartWriteLiteralMethod => "WriteLiteralTo(" + _redirectWriter + ", " /* ORIGINAL: WriteLiteralToMethodName */;
|
||||
|
||||
public override string StartBeginWriteAttributeMethod => "BeginWriteAttributeTo(" + _redirectWriter + ", " /* ORIGINAL: BeginWriteAttributeToMethodName */;
|
||||
|
||||
public override string StartWriteAttributeValueMethod => "WriteAttributeValueTo(" + _redirectWriter + ", " /* ORIGINAL: WriteAttributeValueToMethodName */;
|
||||
|
||||
public override string StartEndWriteAttributeMethod => "EndWriteAttributeTo(" + _redirectWriter /* ORIGINAL: EndWriteAttributeToMethodName */;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class CSharpRenderingContext
|
||||
{
|
||||
private CSharpRenderingConventions _renderingConventions;
|
||||
|
||||
public ICollection<DirectiveDescriptor> Directives { get; set; }
|
||||
|
||||
public Func<string> IdGenerator { get; set; } = () => Guid.NewGuid().ToString("N");
|
||||
|
||||
public List<LineMapping> LineMappings { get; } = new List<LineMapping>();
|
||||
|
||||
public CSharpCodeWriter Writer { get; set; }
|
||||
|
||||
public CSharpRenderingConventions RenderingConventions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_renderingConventions == null)
|
||||
{
|
||||
_renderingConventions = new CSharpRenderingConventions(Writer);
|
||||
}
|
||||
|
||||
return _renderingConventions;
|
||||
}
|
||||
set
|
||||
{
|
||||
_renderingConventions = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ErrorSink ErrorSink { get; } = new ErrorSink();
|
||||
|
||||
public RazorSourceDocument SourceDocument { get; set; }
|
||||
|
||||
public RazorParserOptions Options { get; set; }
|
||||
|
||||
public TagHelperRenderingContext TagHelperRenderingContext { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class CSharpRenderingConventions
|
||||
{
|
||||
public CSharpRenderingConventions(CSharpCodeWriter writer)
|
||||
{
|
||||
Writer = writer;
|
||||
}
|
||||
|
||||
protected CSharpCodeWriter Writer { get; }
|
||||
|
||||
public virtual string StartWriteMethod => "Write(" /* ORIGINAL: WriteMethodName */;
|
||||
|
||||
public virtual string StartWriteLiteralMethod => "WriteLiteral(" /* ORIGINAL: WriteLiteralMethodName */;
|
||||
|
||||
public virtual string StartBeginWriteAttributeMethod => "BeginWriteAttribute(" /* ORIGINAL: BeginWriteAttributeMethodName */;
|
||||
|
||||
public virtual string StartWriteAttributeValueMethod => "WriteAttributeValue(" /* ORIGINAL: WriteAttributeValueMethodName */;
|
||||
|
||||
public virtual string StartEndWriteAttributeMethod => "EndWriteAttribute(" /* ORIGINAL: EndWriteAttributeMethodName */;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class DefaultRuntimeTarget : RuntimeTarget
|
||||
{
|
||||
private readonly RazorParserOptions _options;
|
||||
|
||||
public DefaultRuntimeTarget(RazorParserOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
internal override PageStructureCSharpRenderer CreateRenderer(CSharpRenderingContext context)
|
||||
{
|
||||
if (_options.DesignTimeMode)
|
||||
{
|
||||
return new DesignTimeCSharpRenderer(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new RuntimeCSharpRenderer(context);
|
||||
}
|
||||
}
|
||||
|
||||
public override TExtension GetExtension<TExtension>()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool HasExtension<TExtension>()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class DefaultRuntimeTargetBuilder : IRuntimeTargetBuilder
|
||||
{
|
||||
public DefaultRuntimeTargetBuilder(RazorCodeDocument codeDocument, RazorParserOptions options)
|
||||
{
|
||||
CodeDocument = codeDocument;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public RazorCodeDocument CodeDocument { get; }
|
||||
|
||||
public RazorParserOptions Options { get; }
|
||||
|
||||
public RuntimeTarget Build()
|
||||
{
|
||||
return new DefaultRuntimeTarget(Options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
// 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 System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class DesignTimeCSharpRenderer : PageStructureCSharpRenderer
|
||||
{
|
||||
public DesignTimeCSharpRenderer(CSharpRenderingContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void VisitCSharpToken(CSharpTokenIRNode node)
|
||||
{
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitCSharpExpression(CSharpExpressionIRNode node)
|
||||
{
|
||||
if (node.Children.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var padding = BuildOffsetPadding(RazorDesignTimeIRPass.DesignTimeVariable.Length, node.Source.Value, Context);
|
||||
|
||||
Context.Writer
|
||||
.Write(padding)
|
||||
.WriteStartAssignment(RazorDesignTimeIRPass.DesignTimeVariable);
|
||||
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var childNode = node.Children[i];
|
||||
|
||||
if (childNode is CSharpTokenIRNode)
|
||||
{
|
||||
AddLineMappingFor(childNode);
|
||||
}
|
||||
|
||||
childNode.Accept(this);
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.WriteStartAssignment(RazorDesignTimeIRPass.DesignTimeVariable);
|
||||
VisitDefault(node);
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitUsingStatement(UsingStatementIRNode node)
|
||||
{
|
||||
Context.Writer.WriteUsing(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitCSharpStatement(CSharpStatementIRNode node)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var padding = BuildOffsetPadding(0, node.Source.Value, Context);
|
||||
Context.Writer.Write(padding);
|
||||
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.WriteLine(node.Content);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitDirectiveToken(DirectiveTokenIRNode node)
|
||||
{
|
||||
const string TypeHelper = "__typeHelper";
|
||||
|
||||
var tokenKind = node.Descriptor.Kind;
|
||||
if (node.Source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wrap the directive token in a lambda to isolate variable names.
|
||||
Context.Writer
|
||||
.Write("((")
|
||||
.Write(typeof(Action).FullName)
|
||||
.Write(")(");
|
||||
using (Context.Writer.BuildLambda(endLine: false))
|
||||
{
|
||||
var originalIndent = Context.Writer.CurrentIndent;
|
||||
Context.Writer.ResetIndent();
|
||||
switch (tokenKind)
|
||||
{
|
||||
case DirectiveTokenKind.Type:
|
||||
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer
|
||||
.Write(node.Content)
|
||||
.Write(" ")
|
||||
.WriteStartAssignment(TypeHelper)
|
||||
.WriteLine("null;");
|
||||
break;
|
||||
case DirectiveTokenKind.Member:
|
||||
Context.Writer
|
||||
.Write(typeof(object).FullName)
|
||||
.Write(" ");
|
||||
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer
|
||||
.Write(node.Content)
|
||||
.WriteLine(" = null;");
|
||||
break;
|
||||
case DirectiveTokenKind.String:
|
||||
Context.Writer
|
||||
.Write(typeof(object).FullName)
|
||||
.Write(" ")
|
||||
.WriteStartAssignment(TypeHelper);
|
||||
|
||||
if (node.Content.StartsWith("\"", StringComparison.Ordinal))
|
||||
{
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.Write("\"");
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer
|
||||
.Write(node.Content)
|
||||
.Write("\"");
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
break;
|
||||
}
|
||||
Context.Writer.SetIndent(originalIndent);
|
||||
}
|
||||
Context.Writer.WriteLine("))();");
|
||||
|
||||
}
|
||||
|
||||
public override void VisitTemplate(TemplateIRNode node)
|
||||
{
|
||||
const string ItemParameterName = "item";
|
||||
const string TemplateWriterName = "__razor_template_writer";
|
||||
|
||||
Context.Writer
|
||||
.Write(ItemParameterName).Write(" => ")
|
||||
.WriteStartNewObject("Microsoft.AspNetCore.Mvc.Razor.HelperResult" /* ORIGINAL: TemplateTypeName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
var redirectConventions = new CSharpRedirectRenderingConventions(TemplateWriterName, Context.Writer);
|
||||
Context.RenderingConventions = redirectConventions;
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false, parameterNames: TemplateWriterName))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation(endLine: false);
|
||||
}
|
||||
|
||||
public override void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
var initialTagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
Context.TagHelperRenderingContext = new TagHelperRenderingContext();
|
||||
VisitDefault(node);
|
||||
Context.TagHelperRenderingContext = initialTagHelperRenderingContext;
|
||||
}
|
||||
|
||||
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment(tagHelperVariableName)
|
||||
.WriteStartMethodInvocation(
|
||||
"CreateTagHelper" /* ORIGINAL: CreateTagHelperMethodName */,
|
||||
"global::" + node.TagHelperTypeName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||
|
||||
string previousValueAccessor;
|
||||
if (tagHelperRenderingContext.RenderedBoundAttributes.TryGetValue(node.AttributeName, out previousValueAccessor))
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write(previousValueAccessor)
|
||||
.WriteLine(";");
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagHelperRenderingContext.RenderedBoundAttributes[node.AttributeName] = propertyValueAccessor;
|
||||
}
|
||||
|
||||
if (node.Descriptor.IsStringProperty)
|
||||
{
|
||||
VisitDefault(node);
|
||||
|
||||
Context.Writer.WriteStartAssignment(propertyValueAccessor);
|
||||
if (node.Children.Count == 1 && node.Children.First() is HtmlContentIRNode)
|
||||
{
|
||||
var htmlNode = node.Children.First() as HtmlContentIRNode;
|
||||
if (htmlNode != null)
|
||||
{
|
||||
Context.Writer.WriteStringLiteral(htmlNode.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.Write("string.Empty");
|
||||
}
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstMappedChild = node.Children.FirstOrDefault(child => child.Source != null) as RazorIRNode;
|
||||
var valueStart = firstMappedChild?.Source;
|
||||
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var assignmentPrefixLength = propertyValueAccessor.Length + " = ".Length;
|
||||
if (node.Descriptor.IsEnum &&
|
||||
node.Children.Count == 1 &&
|
||||
node.Children.First() is HtmlContentIRNode)
|
||||
{
|
||||
assignmentPrefixLength += $"global::{node.Descriptor.TypeName}.".Length;
|
||||
|
||||
if (valueStart != null)
|
||||
{
|
||||
var padding = BuildOffsetPadding(assignmentPrefixLength, node.Source.Value, Context);
|
||||
|
||||
Context.Writer.Write(padding);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write("global::")
|
||||
.Write(node.Descriptor.TypeName)
|
||||
.Write(".");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (valueStart != null)
|
||||
{
|
||||
var padding = BuildOffsetPadding(assignmentPrefixLength, node.Source.Value, Context);
|
||||
|
||||
Context.Writer.Write(padding);
|
||||
}
|
||||
|
||||
Context.Writer.WriteStartAssignment(propertyValueAccessor);
|
||||
}
|
||||
|
||||
RenderTagHelperAttributeInline(node, node.Source.Value);
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
foreach (var tagHelperTypeName in node.UsedTagHelperTypeNames)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(tagHelperTypeName);
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
tagHelperTypeName,
|
||||
tagHelperVariableName,
|
||||
value: null);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLineMappingFor(RazorIRNode node)
|
||||
{
|
||||
var sourceLocation = node.Source.Value;
|
||||
var generatedLocation = new SourceSpan(Context.Writer.GetCurrentSourceLocation(), sourceLocation.Length);
|
||||
var lineMapping = new LineMapping(sourceLocation, generatedLocation);
|
||||
|
||||
Context.LineMappings.Add(lineMapping);
|
||||
}
|
||||
|
||||
private void RenderTagHelperAttributeInline(
|
||||
RazorIRNode node,
|
||||
SourceSpan documentLocation)
|
||||
{
|
||||
if (node is SetTagHelperPropertyIRNode || node is CSharpExpressionIRNode)
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
RenderTagHelperAttributeInline(node.Children[i], documentLocation);
|
||||
}
|
||||
}
|
||||
else if (node is HtmlContentIRNode)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
AddLineMappingFor(node);
|
||||
}
|
||||
|
||||
Context.Writer.Write(((HtmlContentIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpTokenIRNode)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
AddLineMappingFor(node);
|
||||
}
|
||||
|
||||
Context.Writer.Write(((CSharpTokenIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpStatementIRNode)
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.TagHelpers_CodeBlocks_NotSupported_InAttributes,
|
||||
documentLocation.Length);
|
||||
}
|
||||
else if (node is TemplateIRNode)
|
||||
{
|
||||
var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent;
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(attributeValueNode.Descriptor.TypeName),
|
||||
documentLocation.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
public interface IRuntimeTargetBuilder
|
||||
{
|
||||
RazorCodeDocument CodeDocument { get; }
|
||||
|
||||
RazorParserOptions Options { get; }
|
||||
|
||||
RuntimeTarget Build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
public interface IRuntimeTargetExtension
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// 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.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class LinePragmaWriter : IDisposable
|
||||
{
|
||||
private readonly CSharpCodeWriter _writer;
|
||||
private readonly int _startIndent;
|
||||
|
||||
public LinePragmaWriter(CSharpCodeWriter writer, SourceSpan documentLocation)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(writer));
|
||||
}
|
||||
|
||||
_writer = writer;
|
||||
_startIndent = _writer.CurrentIndent;
|
||||
_writer.ResetIndent();
|
||||
_writer.WriteLineNumberDirective(documentLocation, documentLocation.FilePath);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Need to add an additional line at the end IF there wasn't one already written.
|
||||
// This is needed to work with the C# editor's handling of #line ...
|
||||
var builder = _writer.Builder;
|
||||
var endsWithNewline = builder.Length > 0 && builder[builder.Length - 1] == '\n';
|
||||
|
||||
// Always write at least 1 empty line to potentially separate code from pragmas.
|
||||
_writer.WriteLine();
|
||||
|
||||
// Check if the previous empty line wasn't enough to separate code from pragmas.
|
||||
if (!endsWithNewline)
|
||||
{
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
_writer
|
||||
.WriteLineDefaultDirective()
|
||||
.WriteLineHiddenDirective()
|
||||
.SetIndent(_startIndent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
// 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.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class PageStructureCSharpRenderer : RazorIRNodeWalker
|
||||
{
|
||||
protected readonly CSharpRenderingContext Context;
|
||||
|
||||
public PageStructureCSharpRenderer(CSharpRenderingContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public override void VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("namespace ")
|
||||
.WriteLine(node.Content);
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer.WriteLineHiddenDirective();
|
||||
VisitDefault(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitRazorMethodDeclaration(RazorMethodDeclarationIRNode node)
|
||||
{
|
||||
Context.Writer.WriteLine("#pragma warning disable 1998");
|
||||
|
||||
Context.Writer
|
||||
.Write(node.AccessModifier)
|
||||
.Write(" ");
|
||||
|
||||
if (node.Modifiers != null)
|
||||
{
|
||||
for (var i = 0; i < node.Modifiers.Count; i++)
|
||||
{
|
||||
Context.Writer.Write(node.Modifiers[i]);
|
||||
|
||||
if (i + 1 < node.Modifiers.Count)
|
||||
{
|
||||
Context.Writer.Write(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.Write(" ")
|
||||
.Write(node.ReturnType)
|
||||
.Write(" ")
|
||||
.Write(node.Name)
|
||||
.WriteLine("()");
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine("#pragma warning restore 1998");
|
||||
}
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write(node.AccessModifier)
|
||||
.Write(" class ")
|
||||
.Write(node.Name);
|
||||
|
||||
if (node.BaseType != null || node.Interfaces != null)
|
||||
{
|
||||
Context.Writer.Write(" : ");
|
||||
}
|
||||
|
||||
if (node.BaseType != null)
|
||||
{
|
||||
Context.Writer.Write(node.BaseType);
|
||||
|
||||
if (node.Interfaces != null)
|
||||
{
|
||||
Context.Writer.WriteParameterSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
if (node.Interfaces != null)
|
||||
{
|
||||
for (var i = 0; i < node.Interfaces.Count; i++)
|
||||
{
|
||||
Context.Writer.Write(node.Interfaces[i]);
|
||||
|
||||
if (i + 1 < node.Interfaces.Count)
|
||||
{
|
||||
Context.Writer.WriteParameterSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine();
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void RenderExpressionInline(RazorIRNode node, CSharpRenderingContext context)
|
||||
{
|
||||
if (node is CSharpTokenIRNode)
|
||||
{
|
||||
context.Writer.Write(((CSharpTokenIRNode)node).Content);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
RenderExpressionInline(node.Children[i], context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static int CalculateExpressionPadding(SourceSpan sourceRange, CSharpRenderingContext context)
|
||||
{
|
||||
var spaceCount = 0;
|
||||
for (var i = sourceRange.AbsoluteIndex - 1; i >= 0; i--)
|
||||
{
|
||||
var @char = context.SourceDocument[i];
|
||||
if (@char == '\n' || @char == '\r')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (@char == '\t')
|
||||
{
|
||||
spaceCount += context.Options.TabSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
spaceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return spaceCount;
|
||||
}
|
||||
|
||||
protected static string BuildOffsetPadding(int generatedOffset, SourceSpan sourceRange, CSharpRenderingContext context)
|
||||
{
|
||||
var basePadding = CalculateExpressionPadding(sourceRange, context);
|
||||
var resolvedPadding = Math.Max(basePadding - generatedOffset, 0);
|
||||
|
||||
if (context.Options.IsIndentingWithTabs)
|
||||
{
|
||||
var spaces = resolvedPadding % context.Options.TabSize;
|
||||
var tabs = resolvedPadding / context.Options.TabSize;
|
||||
|
||||
return new string('\t', tabs) + new string(' ', spaces);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new string(' ', resolvedPadding);
|
||||
}
|
||||
}
|
||||
|
||||
protected static string GetTagHelperVariableName(string tagHelperTypeName) => "__" + tagHelperTypeName.Replace('.', '_');
|
||||
|
||||
protected static string GetTagHelperPropertyAccessor(
|
||||
string tagHelperVariableName,
|
||||
string attributeName,
|
||||
TagHelperAttributeDescriptor descriptor)
|
||||
{
|
||||
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.PropertyName}";
|
||||
|
||||
if (descriptor.IsIndexer)
|
||||
{
|
||||
var dictionaryKey = attributeName.Substring(descriptor.Name.Length);
|
||||
propertyAccessor += $"[\"{dictionaryKey}\"]";
|
||||
}
|
||||
|
||||
return propertyAccessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,695 @@
|
|||
// 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 System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class RuntimeCSharpRenderer : PageStructureCSharpRenderer
|
||||
{
|
||||
public RuntimeCSharpRenderer(CSharpRenderingContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void VisitChecksum(ChecksumIRNode node)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(node.Bytes))
|
||||
{
|
||||
Context.Writer
|
||||
.Write("#pragma checksum \"")
|
||||
.Write(node.Filename)
|
||||
.Write("\" \"")
|
||||
.Write(node.Guid)
|
||||
.Write("\" \"")
|
||||
.Write(node.Bytes)
|
||||
.WriteLine("\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitCSharpToken(CSharpTokenIRNode node)
|
||||
{
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitHtml(HtmlContentIRNode node)
|
||||
{
|
||||
const int MaxStringLiteralLength = 1024;
|
||||
|
||||
var charactersConsumed = 0;
|
||||
|
||||
// Render the string in pieces to avoid Roslyn OOM exceptions at compile time: https://github.com/aspnet/External/issues/54
|
||||
while (charactersConsumed < node.Content.Length)
|
||||
{
|
||||
string textToRender;
|
||||
if (node.Content.Length <= MaxStringLiteralLength)
|
||||
{
|
||||
textToRender = node.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
var charactersToSubstring = Math.Min(MaxStringLiteralLength, node.Content.Length - charactersConsumed);
|
||||
textToRender = node.Content.Substring(charactersConsumed, charactersToSubstring);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteLiteralMethod)
|
||||
.WriteStringLiteral(textToRender)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
charactersConsumed += textToRender.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitCSharpExpression(CSharpExpressionIRNode node)
|
||||
{
|
||||
IDisposable linePragmaScope = null;
|
||||
if (node.Source != null)
|
||||
{
|
||||
linePragmaScope = new LinePragmaWriter(Context.Writer, node.Source.Value);
|
||||
var padding = BuildOffsetPadding(Context.RenderingConventions.StartWriteMethod.Length, node.Source.Value, Context);
|
||||
Context.Writer.Write(padding);
|
||||
}
|
||||
|
||||
Context.Writer.Write(Context.RenderingConventions.StartWriteMethod);
|
||||
|
||||
VisitDefault(node);
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation();
|
||||
|
||||
linePragmaScope?.Dispose();
|
||||
}
|
||||
|
||||
public override void VisitUsingStatement(UsingStatementIRNode node)
|
||||
{
|
||||
Context.Writer.WriteUsing(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitHtmlAttribute(HtmlAttributeIRNode node)
|
||||
{
|
||||
var valuePieceCount = node
|
||||
.Children
|
||||
.Count(child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
var suffixLocation = node.Source.Value.AbsoluteIndex + node.Source.Value.Length - node.Suffix.Length;
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartBeginWriteAttributeMethod)
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Prefix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Suffix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(suffixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
VisitDefault(node);
|
||||
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartEndWriteAttributeMethod)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitHtmlAttributeValue(HtmlAttributeValueIRNode node)
|
||||
{
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length;
|
||||
var valueLength = node.Source.Value.Length;
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteAttributeValueMethod)
|
||||
.WriteStringLiteral(node.Prefix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Content)
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLength.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteBooleanLiteral(true)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node)
|
||||
{
|
||||
const string ValueWriterName = "__razor_attribute_value_writer";
|
||||
|
||||
var expressionValue = node.Children.FirstOrDefault() as CSharpExpressionIRNode;
|
||||
var linePragma = expressionValue != null ? new LinePragmaWriter(Context.Writer, node.Source.Value) : null;
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length;
|
||||
var valueLength = node.Source.Value.Length - node.Prefix.Length;
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteAttributeValueMethod)
|
||||
.WriteStringLiteral(node.Prefix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator();
|
||||
|
||||
if (expressionValue != null)
|
||||
{
|
||||
Debug.Assert(node.Children.Count == 1);
|
||||
|
||||
RenderExpressionInline(expressionValue, Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not an expression; need to buffer the result.
|
||||
Context.Writer.WriteStartNewObject("Microsoft.AspNetCore.Mvc.Razor.HelperResult" /* ORIGINAL: TemplateTypeName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRedirectRenderingConventions(ValueWriterName, Context.Writer);
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false, parameterNames: ValueWriterName))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation(false);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLength.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteBooleanLiteral(false)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
linePragma?.Dispose();
|
||||
}
|
||||
|
||||
public override void VisitCSharpStatement(CSharpStatementIRNode node)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(node.Content))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var padding = BuildOffsetPadding(0, node.Source.Value, Context);
|
||||
Context.Writer
|
||||
.Write(padding)
|
||||
.WriteLine(node.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.WriteLine(node.Content);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitTemplate(TemplateIRNode node)
|
||||
{
|
||||
const string ItemParameterName = "item";
|
||||
const string TemplateWriterName = "__razor_template_writer";
|
||||
|
||||
Context.Writer
|
||||
.Write(ItemParameterName).Write(" => ")
|
||||
.WriteStartNewObject("Microsoft.AspNetCore.Mvc.Razor.HelperResult" /* ORIGINAL: TemplateTypeName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRedirectRenderingConventions(TemplateWriterName, Context.Writer);
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false, parameterNames: TemplateWriterName))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation(endLine: false);
|
||||
}
|
||||
|
||||
public override void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
var initialTagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
Context.TagHelperRenderingContext = new TagHelperRenderingContext();
|
||||
VisitDefault(node);
|
||||
Context.TagHelperRenderingContext = initialTagHelperRenderingContext;
|
||||
}
|
||||
|
||||
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
// Call into the tag helper scope manager to start a new tag helper scope.
|
||||
// Also capture the value as the current execution context.
|
||||
Context.Writer
|
||||
.WriteStartAssignment("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */,
|
||||
"Begin" /* ORIGINAL: ScopeManagerBeginMethodName */);
|
||||
|
||||
// Assign a unique ID for this instance of the source HTML tag. This must be unique
|
||||
// per call site, e.g. if the tag is on the view twice, there should be two IDs.
|
||||
Context.Writer.WriteStringLiteral(node.TagName)
|
||||
.WriteParameterSeparator()
|
||||
.Write("global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.TagMode")
|
||||
.Write(".")
|
||||
.Write(node.TagMode.ToString())
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(Context.IdGenerator())
|
||||
.WriteParameterSeparator();
|
||||
|
||||
// We remove and redirect writers so TagHelper authors can retrieve content.
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRenderingConventions(Context.Writer);
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment(tagHelperVariableName)
|
||||
.WriteStartMethodInvocation(
|
||||
"CreateTagHelper" /* ORIGINAL: CreateTagHelperMethodName */,
|
||||
"global::" + node.TagHelperTypeName)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
Context.Writer.WriteInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"Add" /* ORIGINAL: ExecutionContextAddMethodName */,
|
||||
tagHelperVariableName);
|
||||
}
|
||||
|
||||
public override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddHtmlAttribute" /* ORIGINAL: ExecutionContextAddHtmlAttributeMethodName */)
|
||||
.Write(node.VariableName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
var attributeValueStyleParameter = $"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}";
|
||||
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);
|
||||
|
||||
// All simple text and minimized attributes will be pre-allocated.
|
||||
if (isConditionalAttributeValue)
|
||||
{
|
||||
// Dynamic attribute value should be run through the conditional attribute removal system. It's
|
||||
// unbound and contains C#.
|
||||
|
||||
// TagHelper attribute rendering is buffered by default. We do not want to write to the current
|
||||
// writer.
|
||||
var valuePieceCount = node.Children.Count(
|
||||
child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
|
||||
|
||||
Context.Writer
|
||||
.WriteStartMethodInvocation("BeginAddHtmlAttributeValues" /* ORIGINAL: BeginAddHtmlAttributeValuesMethodName */)
|
||||
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(attributeValueStyleParameter)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new TagHelperHtmlAttributeRenderingConventions(Context.Writer);
|
||||
VisitDefault(node);
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer
|
||||
.WriteMethodInvocation(
|
||||
"EndAddHtmlAttributeValues" /* ORIGINAL: EndAddHtmlAttributeValuesMethodName */,
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or
|
||||
// other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to
|
||||
// determine its final value.
|
||||
|
||||
// Attribute value is not plain text, must be buffered to determine its final value.
|
||||
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);
|
||||
|
||||
// We're building a writing scope around the provided chunks which captures everything written from the
|
||||
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
|
||||
// ensure we capture all content that's written, directly or indirectly.
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRenderingConventions(Context.Writer);
|
||||
VisitDefault(node);
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteMethodInvocation("EndWriteTagHelperAttribute" /* ORIGINAL: EndWriteTagHelperAttributeMethodName */)
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddHtmlAttribute" /* ORIGINAL: ExecutionContextAddHtmlAttributeMethodName */)
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStartMethodInvocation("Html.Raw" /* ORIGINAL: MarkAsHtmlEncodedMethodName */)
|
||||
.Write("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteEndMethodInvocation(endLine: false)
|
||||
.WriteParameterSeparator()
|
||||
.Write(attributeValueStyleParameter)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||
var attributeValueAccessor = $"{node.VariableName}.Value" /* ORIGINAL: TagHelperAttributeValuePropertyName */;
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write("(string)")
|
||||
.Write(attributeValueAccessor)
|
||||
.WriteLine(";")
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddTagHelperAttribute" /* ORIGINAL: ExecutionContextAddTagHelperAttributeMethodName */)
|
||||
.Write(node.VariableName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
|
||||
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
||||
if (node.Descriptor.IsIndexer &&
|
||||
tagHelperRenderingContext.VerifiedPropertyDictionaries.Add(node.Descriptor.PropertyName))
|
||||
{
|
||||
// Throw a reasonable Exception at runtime if the dictionary property is null.
|
||||
Context.Writer
|
||||
.Write("if (")
|
||||
.Write(tagHelperVariableName)
|
||||
.Write(".")
|
||||
.Write(node.Descriptor.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("InvalidTagHelperIndexerAssignment" /* ORIGINAL: FormatInvalidIndexerAssignmentMethodName */)
|
||||
.WriteStringLiteral(node.AttributeName)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.TagHelperTypeName)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Descriptor.PropertyName)
|
||||
.WriteEndMethodInvocation(endLine: false) // End of method call
|
||||
.WriteEndMethodInvocation(); // End of new expression / throw statement
|
||||
}
|
||||
}
|
||||
|
||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||
|
||||
string previousValueAccessor;
|
||||
if (tagHelperRenderingContext.RenderedBoundAttributes.TryGetValue(node.AttributeName, out previousValueAccessor))
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write(previousValueAccessor)
|
||||
.WriteLine(";");
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagHelperRenderingContext.RenderedBoundAttributes[node.AttributeName] = propertyValueAccessor;
|
||||
}
|
||||
|
||||
if (node.Descriptor.IsStringProperty)
|
||||
{
|
||||
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpLiteralCodeConventions(Context.Writer);
|
||||
VisitDefault(node);
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteMethodInvocation("EndWriteTagHelperAttribute" /* ORIGINAL: EndWriteTagHelperAttributeMethodName */)
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteLine(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
Context.Writer.WriteStartAssignment(propertyValueAccessor);
|
||||
|
||||
if (node.Descriptor.IsEnum &&
|
||||
node.Children.Count == 1 &&
|
||||
node.Children.First() is HtmlContentIRNode)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("global::")
|
||||
.Write(node.Descriptor.TypeName)
|
||||
.Write(".");
|
||||
}
|
||||
|
||||
RenderTagHelperAttributeInline(node, node.Source.Value);
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
|
||||
// We need to inform the context of the attribute value.
|
||||
Context.Writer
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddTagHelperAttribute" /* ORIGINAL: ExecutionContextAddTagHelperAttributeMethodName */)
|
||||
.WriteStringLiteral(node.AttributeName)
|
||||
.WriteParameterSeparator()
|
||||
.Write(propertyValueAccessor)
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("await ")
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperRunner" /* ORIGINAL: RunnerVariableName */,
|
||||
"RunAsync" /* ORIGINAL: RunnerRunAsyncMethodName */)
|
||||
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
var executionContextVariableName = "__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */;
|
||||
var executionContextOutputPropertyName = "Output" /* ORIGINAL: ExecutionContextOutputPropertyName */;
|
||||
var tagHelperOutputAccessor = $"{executionContextVariableName}.{executionContextOutputPropertyName}";
|
||||
|
||||
Context.Writer
|
||||
.Write("if (!")
|
||||
.Write(tagHelperOutputAccessor)
|
||||
.Write(".")
|
||||
.Write("IsContentModified" /* ORIGINAL: TagHelperOutputIsContentModifiedPropertyName */)
|
||||
.WriteLine(")");
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer
|
||||
.Write("await ")
|
||||
.WriteInstanceMethodInvocation(
|
||||
executionContextVariableName,
|
||||
"SetOutputContentAsync" /* ORIGINAL: ExecutionContextSetOutputContentAsyncMethodName */);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteMethod)
|
||||
.Write(tagHelperOutputAccessor)
|
||||
.WriteEndMethodInvocation()
|
||||
.WriteStartAssignment(executionContextVariableName)
|
||||
.WriteInstanceMethodInvocation(
|
||||
"__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */,
|
||||
"End" /* ORIGINAL: ScopeManagerEndMethodName */);
|
||||
}
|
||||
|
||||
public override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("private static readonly global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.Write(" ")
|
||||
.Write(node.VariableName)
|
||||
.Write(" = ")
|
||||
.WriteStartNewObject("global::" + "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.WriteStringLiteral(node.Name);
|
||||
|
||||
if (node.ValueStyle == HtmlAttributeValueStyle.Minimized)
|
||||
{
|
||||
Context.Writer.WriteEndMethodInvocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer
|
||||
.WriteParameterSeparator()
|
||||
.WriteStartNewObject("global::" + "Microsoft.AspNetCore.Html.HtmlString" /* ORIGINAL: EncodedHtmlStringTypeName */)
|
||||
.WriteStringLiteral(node.Value)
|
||||
.WriteEndMethodInvocation(endLine: false)
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("private static readonly global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.Write(" ")
|
||||
.Write(node.VariableName)
|
||||
.Write(" = ")
|
||||
.WriteStartNewObject("global::" + "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Value)
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
Context.Writer.WriteLineHiddenDirective();
|
||||
|
||||
// Need to disable the warning "X is assigned to but never used." for the value buffer since
|
||||
// whether it's used depends on how a TagHelper is used.
|
||||
Context.Writer
|
||||
.WritePragma("warning disable 0414")
|
||||
.Write("private ")
|
||||
.WriteVariableDeclaration("string", "__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */, value: null)
|
||||
.WritePragma("warning restore 0414");
|
||||
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
"Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext" /* ORIGINAL: ExecutionContextTypeName */,
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
value: null);
|
||||
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner" /* ORIGINAL: RunnerTypeName */)
|
||||
.Write(" ")
|
||||
.Write("__tagHelperRunner" /* ORIGINAL: RunnerVariableName */)
|
||||
.Write(" = new global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner" /* ORIGINAL: RunnerTypeName */)
|
||||
.WriteLine("();");
|
||||
|
||||
const string backedScopeManageVariableName = "__backed" + "__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */;
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
"Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager",
|
||||
backedScopeManageVariableName,
|
||||
value: null);
|
||||
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager" /* ORIGINAL: ScopeManagerTypeName */)
|
||||
.Write(" ")
|
||||
.WriteLine("__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */);
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer.WriteLine("get");
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer
|
||||
.Write("if (")
|
||||
.Write(backedScopeManageVariableName)
|
||||
.WriteLine(" == null)");
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartAssignment(backedScopeManageVariableName)
|
||||
.WriteStartNewObject("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager" /* ORIGINAL: ScopeManagerTypeName */)
|
||||
.Write("StartTagHelperWritingScope" /* ORIGINAL: StartTagHelperWritingScopeMethodName */)
|
||||
.WriteParameterSeparator()
|
||||
.Write("EndTagHelperWritingScope" /* ORIGINAL: EndTagHelperWritingScopeMethodName */)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
Context.Writer.WriteReturn(backedScopeManageVariableName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var tagHelperTypeName in node.UsedTagHelperTypeNames)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(tagHelperTypeName);
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
tagHelperTypeName,
|
||||
tagHelperVariableName,
|
||||
value: null);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTagHelperAttributeInline(
|
||||
RazorIRNode node,
|
||||
SourceSpan documentLocation)
|
||||
{
|
||||
if (node is SetTagHelperPropertyIRNode || node is CSharpExpressionIRNode)
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
RenderTagHelperAttributeInline(node.Children[i], documentLocation);
|
||||
}
|
||||
}
|
||||
else if (node is HtmlContentIRNode)
|
||||
{
|
||||
Context.Writer.Write(((HtmlContentIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpTokenIRNode)
|
||||
{
|
||||
Context.Writer.Write(((CSharpTokenIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpStatementIRNode)
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.TagHelpers_CodeBlocks_NotSupported_InAttributes,
|
||||
documentLocation.Length);
|
||||
}
|
||||
else if (node is TemplateIRNode)
|
||||
{
|
||||
var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent;
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(attributeValueNode.Descriptor.TypeName),
|
||||
documentLocation.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
public abstract class RuntimeTarget
|
||||
{
|
||||
public static RuntimeTarget CreateDefault(RazorCodeDocument codeDocument, RazorParserOptions options)
|
||||
{
|
||||
if (codeDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocument));
|
||||
}
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
return CreateDefault(codeDocument, options, configure: null);
|
||||
}
|
||||
|
||||
public static RuntimeTarget CreateDefault(
|
||||
RazorCodeDocument codeDocument,
|
||||
RazorParserOptions options,
|
||||
Action<IRuntimeTargetBuilder> configure)
|
||||
{
|
||||
if (codeDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocument));
|
||||
}
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
var builder = new DefaultRuntimeTargetBuilder(codeDocument, options);
|
||||
|
||||
if (builder.Options.DesignTimeMode)
|
||||
{
|
||||
AddDesignTimeDefaults(builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRuntimeDefaults(builder);
|
||||
}
|
||||
|
||||
if (configure != null)
|
||||
{
|
||||
configure.Invoke(builder);
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
public static RuntimeTarget CreateEmpty(
|
||||
RazorCodeDocument codeDocument,
|
||||
RazorParserOptions options,
|
||||
Action<IRuntimeTargetBuilder> configure)
|
||||
{
|
||||
if (codeDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocument));
|
||||
}
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
var builder = new DefaultRuntimeTargetBuilder(codeDocument, options);
|
||||
configure?.Invoke(builder);
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
internal static void AddDesignTimeDefaults(IRuntimeTargetBuilder builder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal static void AddRuntimeDefaults(IRuntimeTargetBuilder builder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal abstract PageStructureCSharpRenderer CreateRenderer(CSharpRenderingContext context);
|
||||
|
||||
public abstract TExtension GetExtension<TExtension>() where TExtension : class, IRuntimeTargetExtension;
|
||||
|
||||
public abstract bool HasExtension<TExtension>() where TExtension : class, IRuntimeTargetExtension;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class TagHelperHtmlAttributeRenderingConventions : CSharpRenderingConventions
|
||||
{
|
||||
public TagHelperHtmlAttributeRenderingConventions(CSharpCodeWriter writer) : base(writer)
|
||||
{
|
||||
}
|
||||
|
||||
public override string StartWriteAttributeValueMethod => "AddHtmlAttributeValue(" /* ORIGINAL: AddHtmlAttributeValueMethodName */;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// 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 System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
internal class TagHelperRenderingContext
|
||||
{
|
||||
private Dictionary<string, string> _renderedBoundAttributes;
|
||||
private HashSet<string> _verifiedPropertyDictionaries;
|
||||
|
||||
public Dictionary<string, string> RenderedBoundAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_renderedBoundAttributes == null)
|
||||
{
|
||||
_renderedBoundAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return _renderedBoundAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<string> VerifiedPropertyDictionaries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_verifiedPropertyDictionaries == null)
|
||||
{
|
||||
_verifiedPropertyDictionaries = new HashSet<string>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
return _verifiedPropertyDictionaries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,10 +14,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
|
||||
public override DocumentIRNode ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDocumentDependency(syntaxTree);
|
||||
|
||||
var parserOptions = syntaxTree.Options;
|
||||
var parserOptions = irDocument.Options;
|
||||
|
||||
var designTime = parserOptions.DesignTimeMode;
|
||||
var walker = new DirectiveWalker(designTime);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
// 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 System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
internal class DefaultRazorCSharpLoweringPhase : RazorEnginePhaseBase, IRazorCSharpLoweringPhase
|
||||
{
|
||||
internal static readonly object NewLineString = "NewLineString";
|
||||
|
||||
internal static readonly object SuppressUniqueIds = "SuppressUniqueIds";
|
||||
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var irDocument = codeDocument.GetIRDocument();
|
||||
ThrowForMissingDependency(irDocument);
|
||||
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDependency(syntaxTree);
|
||||
|
||||
var target = irDocument.Target;
|
||||
if (target == null)
|
||||
{
|
||||
var message = Resources.FormatDocumentMissingTarget(
|
||||
irDocument.DocumentKind,
|
||||
nameof(RuntimeTarget),
|
||||
nameof(DocumentIRNode.Target));
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var codeWriter = new CSharpCodeWriter();
|
||||
var newLineString = codeDocument.Items[NewLineString];
|
||||
if (newLineString != null)
|
||||
{
|
||||
// Set new line character to a specific string regardless of platform, for testing purposes.
|
||||
codeWriter.NewLine = (string)newLineString;
|
||||
}
|
||||
|
||||
var renderingContext = new CSharpRenderingContext()
|
||||
{
|
||||
Writer = codeWriter,
|
||||
SourceDocument = codeDocument.Source,
|
||||
Options = irDocument.Options,
|
||||
};
|
||||
|
||||
var idValue = codeDocument.Items[SuppressUniqueIds];
|
||||
if (idValue != null)
|
||||
{
|
||||
// Generate a static value for unique ids instead of a guid, for testing purposes.
|
||||
renderingContext.IdGenerator = () => idValue.ToString();
|
||||
}
|
||||
|
||||
var renderer = target.CreateRenderer(renderingContext);
|
||||
renderer.VisitDocument(irDocument);
|
||||
|
||||
var combinedErrors = syntaxTree.Diagnostics.Concat(renderingContext.ErrorSink.Errors).ToList();
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = renderingContext.Writer.GenerateCode(),
|
||||
LineMappings = renderingContext.LineMappings,
|
||||
Diagnostics = combinedErrors
|
||||
};
|
||||
|
||||
codeDocument.SetCSharpDocument(csharpDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,397 +0,0 @@
|
|||
// 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 System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
internal class DefaultRazorDesignTimeCSharpLoweringPhase : RazorCSharpLoweringPhaseBase
|
||||
{
|
||||
internal static readonly object NewLineString = "NewLineString";
|
||||
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var irDocument = codeDocument.GetIRDocument();
|
||||
ThrowForMissingDependency(irDocument);
|
||||
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDependency(syntaxTree);
|
||||
|
||||
var codeWriter = new CSharpCodeWriter();
|
||||
var newLineString = codeDocument.Items[NewLineString];
|
||||
if (newLineString != null)
|
||||
{
|
||||
// Set new line character to a specific string regardless of platform, for testing purposes.
|
||||
codeWriter.NewLine = (string)newLineString;
|
||||
}
|
||||
|
||||
var renderingContext = new CSharpRenderingContext()
|
||||
{
|
||||
Writer = codeWriter,
|
||||
SourceDocument = codeDocument.Source,
|
||||
Options = syntaxTree.Options,
|
||||
};
|
||||
var visitor = new CSharpRenderer(renderingContext);
|
||||
visitor.VisitDocument(irDocument);
|
||||
|
||||
var combinedErrors = syntaxTree.Diagnostics.Concat(renderingContext.ErrorSink.Errors).ToList();
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = renderingContext.Writer.GenerateCode(),
|
||||
LineMappings = renderingContext.LineMappings,
|
||||
Diagnostics = combinedErrors
|
||||
};
|
||||
|
||||
codeDocument.SetCSharpDocument(csharpDocument);
|
||||
}
|
||||
|
||||
private class CSharpRenderer : PageStructureCSharpRenderer
|
||||
{
|
||||
public CSharpRenderer(CSharpRenderingContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void VisitCSharpToken(CSharpTokenIRNode node)
|
||||
{
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitCSharpExpression(CSharpExpressionIRNode node)
|
||||
{
|
||||
if (node.Children.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var padding = BuildOffsetPadding(RazorDesignTimeIRPass.DesignTimeVariable.Length, node.Source.Value, Context);
|
||||
|
||||
Context.Writer
|
||||
.Write(padding)
|
||||
.WriteStartAssignment(RazorDesignTimeIRPass.DesignTimeVariable);
|
||||
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var childNode = node.Children[i];
|
||||
|
||||
if (childNode is CSharpTokenIRNode)
|
||||
{
|
||||
AddLineMappingFor(childNode);
|
||||
}
|
||||
|
||||
childNode.Accept(this);
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.WriteStartAssignment(RazorDesignTimeIRPass.DesignTimeVariable);
|
||||
VisitDefault(node);
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitUsingStatement(UsingStatementIRNode node)
|
||||
{
|
||||
Context.Writer.WriteUsing(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitCSharpStatement(CSharpStatementIRNode node)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var padding = BuildOffsetPadding(0, node.Source.Value, Context);
|
||||
Context.Writer.Write(padding);
|
||||
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.WriteLine(node.Content);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitDirectiveToken(DirectiveTokenIRNode node)
|
||||
{
|
||||
const string TypeHelper = "__typeHelper";
|
||||
|
||||
var tokenKind = node.Descriptor.Kind;
|
||||
if (node.Source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wrap the directive token in a lambda to isolate variable names.
|
||||
Context.Writer
|
||||
.Write("((")
|
||||
.Write(typeof(Action).FullName)
|
||||
.Write(")(");
|
||||
using (Context.Writer.BuildLambda(endLine: false))
|
||||
{
|
||||
var originalIndent = Context.Writer.CurrentIndent;
|
||||
Context.Writer.ResetIndent();
|
||||
switch (tokenKind)
|
||||
{
|
||||
case DirectiveTokenKind.Type:
|
||||
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer
|
||||
.Write(node.Content)
|
||||
.Write(" ")
|
||||
.WriteStartAssignment(TypeHelper)
|
||||
.WriteLine("null;");
|
||||
break;
|
||||
case DirectiveTokenKind.Member:
|
||||
Context.Writer
|
||||
.Write(typeof(object).FullName)
|
||||
.Write(" ");
|
||||
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer
|
||||
.Write(node.Content)
|
||||
.WriteLine(" = null;");
|
||||
break;
|
||||
case DirectiveTokenKind.String:
|
||||
Context.Writer
|
||||
.Write(typeof(object).FullName)
|
||||
.Write(" ")
|
||||
.WriteStartAssignment(TypeHelper);
|
||||
|
||||
if (node.Content.StartsWith("\"", StringComparison.Ordinal))
|
||||
{
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.Write("\"");
|
||||
AddLineMappingFor(node);
|
||||
Context.Writer
|
||||
.Write(node.Content)
|
||||
.Write("\"");
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
break;
|
||||
}
|
||||
Context.Writer.SetIndent(originalIndent);
|
||||
}
|
||||
Context.Writer.WriteLine("))();");
|
||||
|
||||
}
|
||||
|
||||
public override void VisitTemplate(TemplateIRNode node)
|
||||
{
|
||||
const string ItemParameterName = "item";
|
||||
const string TemplateWriterName = "__razor_template_writer";
|
||||
|
||||
Context.Writer
|
||||
.Write(ItemParameterName).Write(" => ")
|
||||
.WriteStartNewObject("Microsoft.AspNetCore.Mvc.Razor.HelperResult" /* ORIGINAL: TemplateTypeName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
var redirectConventions = new CSharpRedirectRenderingConventions(TemplateWriterName, Context.Writer);
|
||||
Context.RenderingConventions = redirectConventions;
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false, parameterNames: TemplateWriterName))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation(endLine: false);
|
||||
}
|
||||
|
||||
public override void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
var initialTagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
Context.TagHelperRenderingContext = new TagHelperRenderingContext();
|
||||
VisitDefault(node);
|
||||
Context.TagHelperRenderingContext = initialTagHelperRenderingContext;
|
||||
}
|
||||
|
||||
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment(tagHelperVariableName)
|
||||
.WriteStartMethodInvocation(
|
||||
"CreateTagHelper" /* ORIGINAL: CreateTagHelperMethodName */,
|
||||
"global::" + node.TagHelperTypeName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||
|
||||
string previousValueAccessor;
|
||||
if (tagHelperRenderingContext.RenderedBoundAttributes.TryGetValue(node.AttributeName, out previousValueAccessor))
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write(previousValueAccessor)
|
||||
.WriteLine(";");
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagHelperRenderingContext.RenderedBoundAttributes[node.AttributeName] = propertyValueAccessor;
|
||||
}
|
||||
|
||||
if (node.Descriptor.IsStringProperty)
|
||||
{
|
||||
VisitDefault(node);
|
||||
|
||||
Context.Writer.WriteStartAssignment(propertyValueAccessor);
|
||||
if (node.Children.Count == 1 && node.Children.First() is HtmlContentIRNode)
|
||||
{
|
||||
var htmlNode = node.Children.First() as HtmlContentIRNode;
|
||||
if (htmlNode != null)
|
||||
{
|
||||
Context.Writer.WriteStringLiteral(htmlNode.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.Write("string.Empty");
|
||||
}
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstMappedChild = node.Children.FirstOrDefault(child => child.Source != null) as RazorIRNode;
|
||||
var valueStart = firstMappedChild?.Source;
|
||||
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var assignmentPrefixLength = propertyValueAccessor.Length + " = ".Length;
|
||||
if (node.Descriptor.IsEnum &&
|
||||
node.Children.Count == 1 &&
|
||||
node.Children.First() is HtmlContentIRNode)
|
||||
{
|
||||
assignmentPrefixLength += $"global::{node.Descriptor.TypeName}.".Length;
|
||||
|
||||
if (valueStart != null)
|
||||
{
|
||||
var padding = BuildOffsetPadding(assignmentPrefixLength, node.Source.Value, Context);
|
||||
|
||||
Context.Writer.Write(padding);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write("global::")
|
||||
.Write(node.Descriptor.TypeName)
|
||||
.Write(".");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (valueStart != null)
|
||||
{
|
||||
var padding = BuildOffsetPadding(assignmentPrefixLength, node.Source.Value, Context);
|
||||
|
||||
Context.Writer.Write(padding);
|
||||
}
|
||||
|
||||
Context.Writer.WriteStartAssignment(propertyValueAccessor);
|
||||
}
|
||||
|
||||
RenderTagHelperAttributeInline(node, node.Source.Value);
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
foreach (var tagHelperTypeName in node.UsedTagHelperTypeNames)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(tagHelperTypeName);
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
tagHelperTypeName,
|
||||
tagHelperVariableName,
|
||||
value: null);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLineMappingFor(RazorIRNode node)
|
||||
{
|
||||
var sourceLocation = node.Source.Value;
|
||||
var generatedLocation = new SourceSpan(Context.Writer.GetCurrentSourceLocation(), sourceLocation.Length);
|
||||
var lineMapping = new LineMapping(sourceLocation, generatedLocation);
|
||||
|
||||
Context.LineMappings.Add(lineMapping);
|
||||
}
|
||||
|
||||
private void RenderTagHelperAttributeInline(
|
||||
RazorIRNode node,
|
||||
SourceSpan documentLocation)
|
||||
{
|
||||
if (node is SetTagHelperPropertyIRNode || node is CSharpExpressionIRNode)
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
RenderTagHelperAttributeInline(node.Children[i], documentLocation);
|
||||
}
|
||||
}
|
||||
else if (node is HtmlContentIRNode)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
AddLineMappingFor(node);
|
||||
}
|
||||
|
||||
Context.Writer.Write(((HtmlContentIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpTokenIRNode)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
AddLineMappingFor(node);
|
||||
}
|
||||
|
||||
Context.Writer.Write(((CSharpTokenIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpStatementIRNode)
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.TagHelpers_CodeBlocks_NotSupported_InAttributes,
|
||||
documentLocation.Length);
|
||||
}
|
||||
else if (node is TemplateIRNode)
|
||||
{
|
||||
var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent;
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(attributeValueNode.Descriptor.TypeName),
|
||||
documentLocation.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
ThrowForMissingDependency(syntaxTree);
|
||||
|
||||
var builder = RazorIRBuilder.Document();
|
||||
|
||||
var document = (DocumentIRNode)builder.Current;
|
||||
document.Options = syntaxTree.Options;
|
||||
|
||||
var namespaces = new HashSet<string>();
|
||||
|
||||
var i = 0;
|
||||
|
|
|
|||
|
|
@ -1,734 +0,0 @@
|
|||
// 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 System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
internal class DefaultRazorRuntimeCSharpLoweringPhase : RazorCSharpLoweringPhaseBase
|
||||
{
|
||||
internal static readonly object SuppressUniqueIds = "SuppressUniqueIds";
|
||||
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var irDocument = codeDocument.GetIRDocument();
|
||||
ThrowForMissingDependency(irDocument);
|
||||
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDependency(syntaxTree);
|
||||
|
||||
var renderingContext = new CSharpRenderingContext()
|
||||
{
|
||||
Writer = new CSharpCodeWriter(),
|
||||
SourceDocument = codeDocument.Source,
|
||||
Options = syntaxTree.Options,
|
||||
};
|
||||
|
||||
var idValue = codeDocument.Items[SuppressUniqueIds];
|
||||
if (idValue != null)
|
||||
{
|
||||
renderingContext.IdGenerator = () => idValue.ToString();
|
||||
}
|
||||
|
||||
var visitor = new CSharpRenderer(renderingContext);
|
||||
visitor.VisitDocument(irDocument);
|
||||
|
||||
var combinedErrors = syntaxTree.Diagnostics.Concat(renderingContext.ErrorSink.Errors).ToList();
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = renderingContext.Writer.GenerateCode(),
|
||||
LineMappings = renderingContext.LineMappings,
|
||||
Diagnostics = combinedErrors
|
||||
};
|
||||
|
||||
codeDocument.SetCSharpDocument(csharpDocument);
|
||||
}
|
||||
|
||||
private class CSharpRenderer : PageStructureCSharpRenderer
|
||||
{
|
||||
public CSharpRenderer(CSharpRenderingContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void VisitChecksum(ChecksumIRNode node)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(node.Bytes))
|
||||
{
|
||||
Context.Writer
|
||||
.Write("#pragma checksum \"")
|
||||
.Write(node.Filename)
|
||||
.Write("\" \"")
|
||||
.Write(node.Guid)
|
||||
.Write("\" \"")
|
||||
.Write(node.Bytes)
|
||||
.WriteLine("\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitCSharpToken(CSharpTokenIRNode node)
|
||||
{
|
||||
Context.Writer.Write(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitHtml(HtmlContentIRNode node)
|
||||
{
|
||||
const int MaxStringLiteralLength = 1024;
|
||||
|
||||
var charactersConsumed = 0;
|
||||
|
||||
// Render the string in pieces to avoid Roslyn OOM exceptions at compile time: https://github.com/aspnet/External/issues/54
|
||||
while (charactersConsumed < node.Content.Length)
|
||||
{
|
||||
string textToRender;
|
||||
if (node.Content.Length <= MaxStringLiteralLength)
|
||||
{
|
||||
textToRender = node.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
var charactersToSubstring = Math.Min(MaxStringLiteralLength, node.Content.Length - charactersConsumed);
|
||||
textToRender = node.Content.Substring(charactersConsumed, charactersToSubstring);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteLiteralMethod)
|
||||
.WriteStringLiteral(textToRender)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
charactersConsumed += textToRender.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitCSharpExpression(CSharpExpressionIRNode node)
|
||||
{
|
||||
IDisposable linePragmaScope = null;
|
||||
if (node.Source != null)
|
||||
{
|
||||
linePragmaScope = new LinePragmaWriter(Context.Writer, node.Source.Value);
|
||||
var padding = BuildOffsetPadding(Context.RenderingConventions.StartWriteMethod.Length, node.Source.Value, Context);
|
||||
Context.Writer.Write(padding);
|
||||
}
|
||||
|
||||
Context.Writer.Write(Context.RenderingConventions.StartWriteMethod);
|
||||
|
||||
VisitDefault(node);
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation();
|
||||
|
||||
linePragmaScope?.Dispose();
|
||||
}
|
||||
|
||||
public override void VisitUsingStatement(UsingStatementIRNode node)
|
||||
{
|
||||
Context.Writer.WriteUsing(node.Content);
|
||||
}
|
||||
|
||||
public override void VisitHtmlAttribute(HtmlAttributeIRNode node)
|
||||
{
|
||||
var valuePieceCount = node
|
||||
.Children
|
||||
.Count(child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
var suffixLocation = node.Source.Value.AbsoluteIndex + node.Source.Value.Length - node.Suffix.Length;
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartBeginWriteAttributeMethod)
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Prefix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Suffix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(suffixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
VisitDefault(node);
|
||||
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartEndWriteAttributeMethod)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitHtmlAttributeValue(HtmlAttributeValueIRNode node)
|
||||
{
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length;
|
||||
var valueLength = node.Source.Value.Length;
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteAttributeValueMethod)
|
||||
.WriteStringLiteral(node.Prefix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Content)
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLength.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteBooleanLiteral(true)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node)
|
||||
{
|
||||
const string ValueWriterName = "__razor_attribute_value_writer";
|
||||
|
||||
var expressionValue = node.Children.FirstOrDefault() as CSharpExpressionIRNode;
|
||||
var linePragma = expressionValue != null ? new LinePragmaWriter(Context.Writer, node.Source.Value) : null;
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length;
|
||||
var valueLength = node.Source.Value.Length - node.Prefix.Length;
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteAttributeValueMethod)
|
||||
.WriteStringLiteral(node.Prefix)
|
||||
.WriteParameterSeparator()
|
||||
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator();
|
||||
|
||||
if (expressionValue != null)
|
||||
{
|
||||
Debug.Assert(node.Children.Count == 1);
|
||||
|
||||
RenderExpressionInline(expressionValue, Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not an expression; need to buffer the result.
|
||||
Context.Writer.WriteStartNewObject("Microsoft.AspNetCore.Mvc.Razor.HelperResult" /* ORIGINAL: TemplateTypeName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRedirectRenderingConventions(ValueWriterName, Context.Writer);
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false, parameterNames: ValueWriterName))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation(false);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLocation.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueLength.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.WriteBooleanLiteral(false)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
linePragma?.Dispose();
|
||||
}
|
||||
|
||||
public override void VisitCSharpStatement(CSharpStatementIRNode node)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(node.Content))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
var padding = BuildOffsetPadding(0, node.Source.Value, Context);
|
||||
Context.Writer
|
||||
.Write(padding)
|
||||
.WriteLine(node.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer.WriteLine(node.Content);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitTemplate(TemplateIRNode node)
|
||||
{
|
||||
const string ItemParameterName = "item";
|
||||
const string TemplateWriterName = "__razor_template_writer";
|
||||
|
||||
Context.Writer
|
||||
.Write(ItemParameterName).Write(" => ")
|
||||
.WriteStartNewObject("Microsoft.AspNetCore.Mvc.Razor.HelperResult" /* ORIGINAL: TemplateTypeName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRedirectRenderingConventions(TemplateWriterName, Context.Writer);
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false, parameterNames: TemplateWriterName))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation(endLine: false);
|
||||
}
|
||||
|
||||
public override void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
var initialTagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
Context.TagHelperRenderingContext = new TagHelperRenderingContext();
|
||||
VisitDefault(node);
|
||||
Context.TagHelperRenderingContext = initialTagHelperRenderingContext;
|
||||
}
|
||||
|
||||
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
// Call into the tag helper scope manager to start a new tag helper scope.
|
||||
// Also capture the value as the current execution context.
|
||||
Context.Writer
|
||||
.WriteStartAssignment("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */,
|
||||
"Begin" /* ORIGINAL: ScopeManagerBeginMethodName */);
|
||||
|
||||
// Assign a unique ID for this instance of the source HTML tag. This must be unique
|
||||
// per call site, e.g. if the tag is on the view twice, there should be two IDs.
|
||||
Context.Writer.WriteStringLiteral(node.TagName)
|
||||
.WriteParameterSeparator()
|
||||
.Write("global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.TagMode")
|
||||
.Write(".")
|
||||
.Write(node.TagMode.ToString())
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(Context.IdGenerator())
|
||||
.WriteParameterSeparator();
|
||||
|
||||
// We remove and redirect writers so TagHelper authors can retrieve content.
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRenderingConventions(Context.Writer);
|
||||
using (Context.Writer.BuildAsyncLambda(endLine: false))
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment(tagHelperVariableName)
|
||||
.WriteStartMethodInvocation(
|
||||
"CreateTagHelper" /* ORIGINAL: CreateTagHelperMethodName */,
|
||||
"global::" + node.TagHelperTypeName)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
Context.Writer.WriteInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"Add" /* ORIGINAL: ExecutionContextAddMethodName */,
|
||||
tagHelperVariableName);
|
||||
}
|
||||
|
||||
public override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddHtmlAttribute" /* ORIGINAL: ExecutionContextAddHtmlAttributeMethodName */)
|
||||
.Write(node.VariableName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
var attributeValueStyleParameter = $"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}";
|
||||
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);
|
||||
|
||||
// All simple text and minimized attributes will be pre-allocated.
|
||||
if (isConditionalAttributeValue)
|
||||
{
|
||||
// Dynamic attribute value should be run through the conditional attribute removal system. It's
|
||||
// unbound and contains C#.
|
||||
|
||||
// TagHelper attribute rendering is buffered by default. We do not want to write to the current
|
||||
// writer.
|
||||
var valuePieceCount = node.Children.Count(
|
||||
child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
|
||||
|
||||
Context.Writer
|
||||
.WriteStartMethodInvocation("BeginAddHtmlAttributeValues" /* ORIGINAL: BeginAddHtmlAttributeValuesMethodName */)
|
||||
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
|
||||
.WriteParameterSeparator()
|
||||
.Write(attributeValueStyleParameter)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new TagHelperHtmlAttributeRenderingConventions(Context.Writer);
|
||||
VisitDefault(node);
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer
|
||||
.WriteMethodInvocation(
|
||||
"EndAddHtmlAttributeValues" /* ORIGINAL: EndAddHtmlAttributeValuesMethodName */,
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or
|
||||
// other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to
|
||||
// determine its final value.
|
||||
|
||||
// Attribute value is not plain text, must be buffered to determine its final value.
|
||||
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);
|
||||
|
||||
// We're building a writing scope around the provided chunks which captures everything written from the
|
||||
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
|
||||
// ensure we capture all content that's written, directly or indirectly.
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpRenderingConventions(Context.Writer);
|
||||
VisitDefault(node);
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteMethodInvocation("EndWriteTagHelperAttribute" /* ORIGINAL: EndWriteTagHelperAttributeMethodName */)
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddHtmlAttribute" /* ORIGINAL: ExecutionContextAddHtmlAttributeMethodName */)
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStartMethodInvocation("Html.Raw" /* ORIGINAL: MarkAsHtmlEncodedMethodName */)
|
||||
.Write("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteEndMethodInvocation(endLine: false)
|
||||
.WriteParameterSeparator()
|
||||
.Write(attributeValueStyleParameter)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||
var attributeValueAccessor = $"{node.VariableName}.Value" /* ORIGINAL: TagHelperAttributeValuePropertyName */;
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write("(string)")
|
||||
.Write(attributeValueAccessor)
|
||||
.WriteLine(";")
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddTagHelperAttribute" /* ORIGINAL: ExecutionContextAddTagHelperAttributeMethodName */)
|
||||
.Write(node.VariableName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
|
||||
|
||||
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
||||
if (node.Descriptor.IsIndexer &&
|
||||
tagHelperRenderingContext.VerifiedPropertyDictionaries.Add(node.Descriptor.PropertyName))
|
||||
{
|
||||
// Throw a reasonable Exception at runtime if the dictionary property is null.
|
||||
Context.Writer
|
||||
.Write("if (")
|
||||
.Write(tagHelperVariableName)
|
||||
.Write(".")
|
||||
.Write(node.Descriptor.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("InvalidTagHelperIndexerAssignment" /* ORIGINAL: FormatInvalidIndexerAssignmentMethodName */)
|
||||
.WriteStringLiteral(node.AttributeName)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.TagHelperTypeName)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Descriptor.PropertyName)
|
||||
.WriteEndMethodInvocation(endLine: false) // End of method call
|
||||
.WriteEndMethodInvocation(); // End of new expression / throw statement
|
||||
}
|
||||
}
|
||||
|
||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||
|
||||
string previousValueAccessor;
|
||||
if (tagHelperRenderingContext.RenderedBoundAttributes.TryGetValue(node.AttributeName, out previousValueAccessor))
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write(previousValueAccessor)
|
||||
.WriteLine(";");
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagHelperRenderingContext.RenderedBoundAttributes[node.AttributeName] = propertyValueAccessor;
|
||||
}
|
||||
|
||||
if (node.Descriptor.IsStringProperty)
|
||||
{
|
||||
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);
|
||||
|
||||
var initialRenderingConventions = Context.RenderingConventions;
|
||||
Context.RenderingConventions = new CSharpLiteralCodeConventions(Context.Writer);
|
||||
VisitDefault(node);
|
||||
Context.RenderingConventions = initialRenderingConventions;
|
||||
|
||||
Context.Writer
|
||||
.WriteStartAssignment("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteMethodInvocation("EndWriteTagHelperAttribute" /* ORIGINAL: EndWriteTagHelperAttributeMethodName */)
|
||||
.WriteStartAssignment(propertyValueAccessor)
|
||||
.Write("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
|
||||
.WriteLine(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new LinePragmaWriter(Context.Writer, node.Source.Value))
|
||||
{
|
||||
Context.Writer.WriteStartAssignment(propertyValueAccessor);
|
||||
|
||||
if (node.Descriptor.IsEnum &&
|
||||
node.Children.Count == 1 &&
|
||||
node.Children.First() is HtmlContentIRNode)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("global::")
|
||||
.Write(node.Descriptor.TypeName)
|
||||
.Write(".");
|
||||
}
|
||||
|
||||
RenderTagHelperAttributeInline(node, node.Source.Value);
|
||||
|
||||
Context.Writer.WriteLine(";");
|
||||
}
|
||||
}
|
||||
|
||||
// We need to inform the context of the attribute value.
|
||||
Context.Writer
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
"AddTagHelperAttribute" /* ORIGINAL: ExecutionContextAddTagHelperAttributeMethodName */)
|
||||
.WriteStringLiteral(node.AttributeName)
|
||||
.WriteParameterSeparator()
|
||||
.Write(propertyValueAccessor)
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("await ")
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
"__tagHelperRunner" /* ORIGINAL: RunnerVariableName */,
|
||||
"RunAsync" /* ORIGINAL: RunnerRunAsyncMethodName */)
|
||||
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
|
||||
.WriteEndMethodInvocation();
|
||||
|
||||
var executionContextVariableName = "__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */;
|
||||
var executionContextOutputPropertyName = "Output" /* ORIGINAL: ExecutionContextOutputPropertyName */;
|
||||
var tagHelperOutputAccessor = $"{executionContextVariableName}.{executionContextOutputPropertyName}";
|
||||
|
||||
Context.Writer
|
||||
.Write("if (!")
|
||||
.Write(tagHelperOutputAccessor)
|
||||
.Write(".")
|
||||
.Write("IsContentModified" /* ORIGINAL: TagHelperOutputIsContentModifiedPropertyName */)
|
||||
.WriteLine(")");
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer
|
||||
.Write("await ")
|
||||
.WriteInstanceMethodInvocation(
|
||||
executionContextVariableName,
|
||||
"SetOutputContentAsync" /* ORIGINAL: ExecutionContextSetOutputContentAsyncMethodName */);
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.Write(Context.RenderingConventions.StartWriteMethod)
|
||||
.Write(tagHelperOutputAccessor)
|
||||
.WriteEndMethodInvocation()
|
||||
.WriteStartAssignment(executionContextVariableName)
|
||||
.WriteInstanceMethodInvocation(
|
||||
"__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */,
|
||||
"End" /* ORIGINAL: ScopeManagerEndMethodName */);
|
||||
}
|
||||
|
||||
public override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("private static readonly global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.Write(" ")
|
||||
.Write(node.VariableName)
|
||||
.Write(" = ")
|
||||
.WriteStartNewObject("global::" + "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.WriteStringLiteral(node.Name);
|
||||
|
||||
if (node.ValueStyle == HtmlAttributeValueStyle.Minimized)
|
||||
{
|
||||
Context.Writer.WriteEndMethodInvocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.Writer
|
||||
.WriteParameterSeparator()
|
||||
.WriteStartNewObject("global::" + "Microsoft.AspNetCore.Html.HtmlString" /* ORIGINAL: EncodedHtmlStringTypeName */)
|
||||
.WriteStringLiteral(node.Value)
|
||||
.WriteEndMethodInvocation(endLine: false)
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("private static readonly global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.Write(" ")
|
||||
.Write(node.VariableName)
|
||||
.Write(" = ")
|
||||
.WriteStartNewObject("global::" + "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute" /* ORIGINAL: TagHelperAttributeTypeName */)
|
||||
.WriteStringLiteral(node.Name)
|
||||
.WriteParameterSeparator()
|
||||
.WriteStringLiteral(node.Value)
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}")
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
Context.Writer.WriteLineHiddenDirective();
|
||||
|
||||
// Need to disable the warning "X is assigned to but never used." for the value buffer since
|
||||
// whether it's used depends on how a TagHelper is used.
|
||||
Context.Writer
|
||||
.WritePragma("warning disable 0414")
|
||||
.Write("private ")
|
||||
.WriteVariableDeclaration("string", "__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */, value: null)
|
||||
.WritePragma("warning restore 0414");
|
||||
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
"Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext" /* ORIGINAL: ExecutionContextTypeName */,
|
||||
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
|
||||
value: null);
|
||||
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner" /* ORIGINAL: RunnerTypeName */)
|
||||
.Write(" ")
|
||||
.Write("__tagHelperRunner" /* ORIGINAL: RunnerVariableName */)
|
||||
.Write(" = new global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner" /* ORIGINAL: RunnerTypeName */)
|
||||
.WriteLine("();");
|
||||
|
||||
const string backedScopeManageVariableName = "__backed" + "__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */;
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
"Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager",
|
||||
backedScopeManageVariableName,
|
||||
value: null);
|
||||
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.Write("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager" /* ORIGINAL: ScopeManagerTypeName */)
|
||||
.Write(" ")
|
||||
.WriteLine("__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */);
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer.WriteLine("get");
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer
|
||||
.Write("if (")
|
||||
.Write(backedScopeManageVariableName)
|
||||
.WriteLine(" == null)");
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer
|
||||
.WriteStartAssignment(backedScopeManageVariableName)
|
||||
.WriteStartNewObject("Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager" /* ORIGINAL: ScopeManagerTypeName */)
|
||||
.Write("StartTagHelperWritingScope" /* ORIGINAL: StartTagHelperWritingScopeMethodName */)
|
||||
.WriteParameterSeparator()
|
||||
.Write("EndTagHelperWritingScope" /* ORIGINAL: EndTagHelperWritingScopeMethodName */)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
|
||||
Context.Writer.WriteReturn(backedScopeManageVariableName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var tagHelperTypeName in node.UsedTagHelperTypeNames)
|
||||
{
|
||||
var tagHelperVariableName = GetTagHelperVariableName(tagHelperTypeName);
|
||||
Context.Writer
|
||||
.Write("private global::")
|
||||
.WriteVariableDeclaration(
|
||||
tagHelperTypeName,
|
||||
tagHelperVariableName,
|
||||
value: null);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTagHelperAttributeInline(
|
||||
RazorIRNode node,
|
||||
SourceSpan documentLocation)
|
||||
{
|
||||
if (node is SetTagHelperPropertyIRNode || node is CSharpExpressionIRNode)
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
RenderTagHelperAttributeInline(node.Children[i], documentLocation);
|
||||
}
|
||||
}
|
||||
else if (node is HtmlContentIRNode)
|
||||
{
|
||||
Context.Writer.Write(((HtmlContentIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpTokenIRNode)
|
||||
{
|
||||
Context.Writer.Write(((CSharpTokenIRNode)node).Content);
|
||||
}
|
||||
else if (node is CSharpStatementIRNode)
|
||||
{
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.TagHelpers_CodeBlocks_NotSupported_InAttributes,
|
||||
documentLocation.Length);
|
||||
}
|
||||
else if (node is TemplateIRNode)
|
||||
{
|
||||
var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent;
|
||||
Context.ErrorSink.OnError(
|
||||
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
|
||||
LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(attributeValueNode.Descriptor.TypeName),
|
||||
documentLocation.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
|
|
@ -25,6 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
}
|
||||
|
||||
irDocument.DocumentKind = DocumentKind;
|
||||
irDocument.Target = CreateTarget(codeDocument, irDocument.Options);
|
||||
|
||||
Rewrite(codeDocument, irDocument);
|
||||
|
||||
|
|
@ -82,6 +84,16 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
|
||||
protected abstract bool IsMatch(RazorCodeDocument codeDocument, DocumentIRNode irDocument);
|
||||
|
||||
private RuntimeTarget CreateTarget(RazorCodeDocument codeDocument, RazorParserOptions options)
|
||||
{
|
||||
return RuntimeTarget.CreateDefault(codeDocument, options, (builder) => ConfigureTarget(codeDocument, builder));
|
||||
}
|
||||
|
||||
protected virtual void ConfigureTarget(RazorCodeDocument codeDocument, IRuntimeTargetBuilder builder)
|
||||
{
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
protected virtual void OnDocumentStructureCreated(
|
||||
RazorCodeDocument codeDocument,
|
||||
NamespaceDeclarationIRNode @namespace,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
|
|
@ -13,10 +13,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
|
||||
public string DocumentKind { get; set; }
|
||||
|
||||
public RazorParserOptions Options { get; set; }
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public RuntimeTarget Target { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -202,6 +202,22 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("DirectiveDescriptor_BeginOptionalsAlreadyInvoked"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'.
|
||||
/// </summary>
|
||||
internal static string DocumentMissingTarget
|
||||
{
|
||||
get { return GetString("DocumentMissingTarget"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'.
|
||||
/// </summary>
|
||||
internal static string FormatDocumentMissingTarget(object p0, object p1, object p2)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DocumentMissingTarget"), p0, p1, p2);
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -1,358 +0,0 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
internal abstract class RazorCSharpLoweringPhaseBase : RazorEnginePhaseBase, IRazorCSharpLoweringPhase
|
||||
{
|
||||
protected static void RenderExpressionInline(RazorIRNode node, CSharpRenderingContext context)
|
||||
{
|
||||
if (node is CSharpTokenIRNode)
|
||||
{
|
||||
context.Writer.Write(((CSharpTokenIRNode)node).Content);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
RenderExpressionInline(node.Children[i], context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static int CalculateExpressionPadding(SourceSpan sourceRange, CSharpRenderingContext context)
|
||||
{
|
||||
var spaceCount = 0;
|
||||
for (var i = sourceRange.AbsoluteIndex - 1; i >= 0; i--)
|
||||
{
|
||||
var @char = context.SourceDocument[i];
|
||||
if (@char == '\n' || @char == '\r')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (@char == '\t')
|
||||
{
|
||||
spaceCount += context.Options.TabSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
spaceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return spaceCount;
|
||||
}
|
||||
|
||||
protected static string BuildOffsetPadding(int generatedOffset, SourceSpan sourceRange, CSharpRenderingContext context)
|
||||
{
|
||||
var basePadding = CalculateExpressionPadding(sourceRange, context);
|
||||
var resolvedPadding = Math.Max(basePadding - generatedOffset, 0);
|
||||
|
||||
if (context.Options.IsIndentingWithTabs)
|
||||
{
|
||||
var spaces = resolvedPadding % context.Options.TabSize;
|
||||
var tabs = resolvedPadding / context.Options.TabSize;
|
||||
|
||||
return new string('\t', tabs) + new string(' ', spaces);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new string(' ', resolvedPadding);
|
||||
}
|
||||
}
|
||||
|
||||
protected static string GetTagHelperVariableName(string tagHelperTypeName) => "__" + tagHelperTypeName.Replace('.', '_');
|
||||
|
||||
protected static string GetTagHelperPropertyAccessor(
|
||||
string tagHelperVariableName,
|
||||
string attributeName,
|
||||
TagHelperAttributeDescriptor descriptor)
|
||||
{
|
||||
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.PropertyName}";
|
||||
|
||||
if (descriptor.IsIndexer)
|
||||
{
|
||||
var dictionaryKey = attributeName.Substring(descriptor.Name.Length);
|
||||
propertyAccessor += $"[\"{dictionaryKey}\"]";
|
||||
}
|
||||
|
||||
return propertyAccessor;
|
||||
}
|
||||
|
||||
protected class LinePragmaWriter : IDisposable
|
||||
{
|
||||
private readonly CSharpCodeWriter _writer;
|
||||
private readonly int _startIndent;
|
||||
|
||||
public LinePragmaWriter(CSharpCodeWriter writer, SourceSpan documentLocation)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(writer));
|
||||
}
|
||||
|
||||
_writer = writer;
|
||||
_startIndent = _writer.CurrentIndent;
|
||||
_writer.ResetIndent();
|
||||
_writer.WriteLineNumberDirective(documentLocation, documentLocation.FilePath);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Need to add an additional line at the end IF there wasn't one already written.
|
||||
// This is needed to work with the C# editor's handling of #line ...
|
||||
var builder = _writer.Builder;
|
||||
var endsWithNewline = builder.Length > 0 && builder[builder.Length - 1] == '\n';
|
||||
|
||||
// Always write at least 1 empty line to potentially separate code from pragmas.
|
||||
_writer.WriteLine();
|
||||
|
||||
// Check if the previous empty line wasn't enough to separate code from pragmas.
|
||||
if (!endsWithNewline)
|
||||
{
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
_writer
|
||||
.WriteLineDefaultDirective()
|
||||
.WriteLineHiddenDirective()
|
||||
.SetIndent(_startIndent);
|
||||
}
|
||||
}
|
||||
|
||||
protected class CSharpRedirectRenderingConventions : CSharpRenderingConventions
|
||||
{
|
||||
private readonly string _redirectWriter;
|
||||
|
||||
public CSharpRedirectRenderingConventions(string redirectWriter, CSharpCodeWriter writer) : base(writer)
|
||||
{
|
||||
_redirectWriter = redirectWriter;
|
||||
}
|
||||
|
||||
public override string StartWriteMethod => "WriteTo(" + _redirectWriter + ", " /* ORIGINAL: WriteToMethodName */;
|
||||
|
||||
public override string StartWriteLiteralMethod => "WriteLiteralTo(" + _redirectWriter + ", " /* ORIGINAL: WriteLiteralToMethodName */;
|
||||
|
||||
public override string StartBeginWriteAttributeMethod => "BeginWriteAttributeTo(" + _redirectWriter + ", " /* ORIGINAL: BeginWriteAttributeToMethodName */;
|
||||
|
||||
public override string StartWriteAttributeValueMethod => "WriteAttributeValueTo(" + _redirectWriter + ", " /* ORIGINAL: WriteAttributeValueToMethodName */;
|
||||
|
||||
public override string StartEndWriteAttributeMethod => "EndWriteAttributeTo(" + _redirectWriter /* ORIGINAL: EndWriteAttributeToMethodName */;
|
||||
}
|
||||
|
||||
protected class CSharpRenderingConventions
|
||||
{
|
||||
public CSharpRenderingConventions(CSharpCodeWriter writer)
|
||||
{
|
||||
Writer = writer;
|
||||
}
|
||||
|
||||
protected CSharpCodeWriter Writer { get; }
|
||||
|
||||
public virtual string StartWriteMethod => "Write(" /* ORIGINAL: WriteMethodName */;
|
||||
|
||||
public virtual string StartWriteLiteralMethod => "WriteLiteral(" /* ORIGINAL: WriteLiteralMethodName */;
|
||||
|
||||
public virtual string StartBeginWriteAttributeMethod => "BeginWriteAttribute(" /* ORIGINAL: BeginWriteAttributeMethodName */;
|
||||
|
||||
public virtual string StartWriteAttributeValueMethod => "WriteAttributeValue(" /* ORIGINAL: WriteAttributeValueMethodName */;
|
||||
|
||||
public virtual string StartEndWriteAttributeMethod => "EndWriteAttribute(" /* ORIGINAL: EndWriteAttributeMethodName */;
|
||||
}
|
||||
|
||||
protected class TagHelperHtmlAttributeRenderingConventions : CSharpRenderingConventions
|
||||
{
|
||||
public TagHelperHtmlAttributeRenderingConventions(CSharpCodeWriter writer) : base(writer)
|
||||
{
|
||||
}
|
||||
|
||||
public override string StartWriteAttributeValueMethod => "AddHtmlAttributeValue(" /* ORIGINAL: AddHtmlAttributeValueMethodName */;
|
||||
}
|
||||
|
||||
protected class CSharpLiteralCodeConventions : CSharpRenderingConventions
|
||||
{
|
||||
public CSharpLiteralCodeConventions(CSharpCodeWriter writer) : base(writer)
|
||||
{
|
||||
}
|
||||
|
||||
public override string StartWriteMethod => StartWriteLiteralMethod;
|
||||
}
|
||||
|
||||
protected class CSharpRenderingContext
|
||||
{
|
||||
private CSharpRenderingConventions _renderingConventions;
|
||||
|
||||
public ICollection<DirectiveDescriptor> Directives { get; set; }
|
||||
|
||||
public Func<string> IdGenerator { get; set; } = () => Guid.NewGuid().ToString("N");
|
||||
|
||||
public List<LineMapping> LineMappings { get; } = new List<LineMapping>();
|
||||
|
||||
public CSharpCodeWriter Writer { get; set; }
|
||||
|
||||
public CSharpRenderingConventions RenderingConventions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_renderingConventions == null)
|
||||
{
|
||||
_renderingConventions = new CSharpRenderingConventions(Writer);
|
||||
}
|
||||
|
||||
return _renderingConventions;
|
||||
}
|
||||
set
|
||||
{
|
||||
_renderingConventions = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ErrorSink ErrorSink { get; } = new ErrorSink();
|
||||
|
||||
public RazorSourceDocument SourceDocument { get; set; }
|
||||
|
||||
public RazorParserOptions Options { get; set; }
|
||||
|
||||
public TagHelperRenderingContext TagHelperRenderingContext { get; set; }
|
||||
}
|
||||
|
||||
protected class TagHelperRenderingContext
|
||||
{
|
||||
private Dictionary<string, string> _renderedBoundAttributes;
|
||||
private HashSet<string> _verifiedPropertyDictionaries;
|
||||
|
||||
public Dictionary<string, string> RenderedBoundAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_renderedBoundAttributes == null)
|
||||
{
|
||||
_renderedBoundAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return _renderedBoundAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<string> VerifiedPropertyDictionaries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_verifiedPropertyDictionaries == null)
|
||||
{
|
||||
_verifiedPropertyDictionaries = new HashSet<string>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
return _verifiedPropertyDictionaries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class PageStructureCSharpRenderer : RazorIRNodeWalker
|
||||
{
|
||||
protected readonly CSharpRenderingContext Context;
|
||||
|
||||
public PageStructureCSharpRenderer(CSharpRenderingContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public override void VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write("namespace ")
|
||||
.WriteLine(node.Content);
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
Context.Writer.WriteLineHiddenDirective();
|
||||
VisitDefault(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitRazorMethodDeclaration(RazorMethodDeclarationIRNode node)
|
||||
{
|
||||
Context.Writer.WriteLine("#pragma warning disable 1998");
|
||||
|
||||
Context.Writer
|
||||
.Write(node.AccessModifier)
|
||||
.Write(" ");
|
||||
|
||||
if (node.Modifiers != null)
|
||||
{
|
||||
for (var i = 0; i < node.Modifiers.Count; i++)
|
||||
{
|
||||
Context.Writer.Write(node.Modifiers[i]);
|
||||
|
||||
if (i + 1 < node.Modifiers.Count)
|
||||
{
|
||||
Context.Writer.Write(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context.Writer
|
||||
.Write(" ")
|
||||
.Write(node.ReturnType)
|
||||
.Write(" ")
|
||||
.Write(node.Name)
|
||||
.WriteLine("()");
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine("#pragma warning restore 1998");
|
||||
}
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Context.Writer
|
||||
.Write(node.AccessModifier)
|
||||
.Write(" class ")
|
||||
.Write(node.Name);
|
||||
|
||||
if (node.BaseType != null || node.Interfaces != null)
|
||||
{
|
||||
Context.Writer.Write(" : ");
|
||||
}
|
||||
|
||||
if (node.BaseType != null)
|
||||
{
|
||||
Context.Writer.Write(node.BaseType);
|
||||
|
||||
if (node.Interfaces != null)
|
||||
{
|
||||
Context.Writer.WriteParameterSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
if (node.Interfaces != null)
|
||||
{
|
||||
for (var i = 0; i < node.Interfaces.Count; i++)
|
||||
{
|
||||
Context.Writer.Write(node.Interfaces[i]);
|
||||
|
||||
if (i + 1 < node.Interfaces.Count)
|
||||
{
|
||||
Context.Writer.WriteParameterSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context.Writer.WriteLine();
|
||||
|
||||
using (Context.Writer.BuildScope())
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
builder.Phases.Add(new DefaultRazorSyntaxTreePhase());
|
||||
builder.Phases.Add(new DefaultRazorIRLoweringPhase());
|
||||
builder.Phases.Add(new DefaultRazorIRPhase());
|
||||
builder.Phases.Add(new DefaultRazorCSharpLoweringPhase());
|
||||
|
||||
// Syntax Tree passes
|
||||
builder.Features.Add(new DefaultDirectiveSyntaxTreePass());
|
||||
|
|
@ -65,15 +66,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
|
||||
internal static void AddRuntimeDefaults(IRazorEngineBuilder builder)
|
||||
{
|
||||
builder.Phases.Add(new DefaultRazorRuntimeCSharpLoweringPhase());
|
||||
|
||||
builder.Features.Add(new RazorPreallocatedTagHelperAttributeOptimizationPass());
|
||||
}
|
||||
|
||||
internal static void AddDesignTimeDefaults(IRazorEngineBuilder builder)
|
||||
{
|
||||
builder.Phases.Add(new DefaultRazorDesignTimeCSharpLoweringPhase());
|
||||
|
||||
builder.Features.Add(new ConfigureDesignTimeOptions());
|
||||
builder.Features.Add(new RazorDesignTimeIRPass());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,4 +153,7 @@
|
|||
<data name="DirectiveDescriptor_BeginOptionalsAlreadyInvoked" xml:space="preserve">
|
||||
<value>The method '{0}' has already been invoked.</value>
|
||||
</data>
|
||||
<data name="DocumentMissingTarget" xml:space="preserve">
|
||||
<value>The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
public class DefaultRuntimeTargetBuilderTest
|
||||
{
|
||||
[Fact]
|
||||
public void Build_CreatesDefaultRuntimeTarget()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
|
||||
var builder = new DefaultRuntimeTargetBuilder(codeDocument, options);
|
||||
|
||||
// Act
|
||||
var target = builder.Build();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<DefaultRuntimeTarget>(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
public class DefaultRuntimeTargetTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreateRenderer_DesignTime_CreatesDesignTimeRenderer()
|
||||
{
|
||||
// Arrange
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
options.DesignTimeMode = true;
|
||||
|
||||
var target = new DefaultRuntimeTarget(options);
|
||||
|
||||
// Act
|
||||
var renderer = target.CreateRenderer(new CSharpRenderingContext());
|
||||
|
||||
// Assert
|
||||
Assert.IsType<DesignTimeCSharpRenderer>(renderer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateRenderer_Runtime_CreatesRuntimeRenderer()
|
||||
{
|
||||
// Arrange
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
options.DesignTimeMode = false;
|
||||
|
||||
var target = new DefaultRuntimeTarget(options);
|
||||
|
||||
// Act
|
||||
var renderer = target.CreateRenderer(new CSharpRenderingContext());
|
||||
|
||||
// Assert
|
||||
Assert.IsType<RuntimeCSharpRenderer>(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
|
||||
{
|
||||
public class RuntimeTargetTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreateDefault_CreatesDefaultRuntimeTarget()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
|
||||
// Act
|
||||
var target = RuntimeTarget.CreateDefault(codeDocument, options);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<DefaultRuntimeTarget>(target);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDefault_CallsDelegate()
|
||||
{
|
||||
// Arrange
|
||||
var wasCalled = false;
|
||||
Action<IRuntimeTargetBuilder> @delegate = (b) => { wasCalled = true; };
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
|
||||
// Act
|
||||
RuntimeTarget.CreateDefault(codeDocument, options, @delegate);
|
||||
|
||||
// Assert
|
||||
Assert.True(wasCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDefault_AllowsNullDelegate()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
|
||||
// Act
|
||||
RuntimeTarget.CreateDefault(codeDocument, options, configure: null);
|
||||
|
||||
// Assert (does not throw)
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateEmpty_AllowsNullDelegate()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
var options = RazorParserOptions.CreateDefaultOptions();
|
||||
|
||||
// Act
|
||||
RuntimeTarget.CreateDefault(codeDocument, options, configure: null);
|
||||
|
||||
// Assert (does not throw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
DocumentKind = "ignore",
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var pass = new DefaultDocumentClassifierPass();
|
||||
|
|
@ -36,7 +37,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_CreatesClassStructure()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var pass = new DefaultDocumentClassifierPass();
|
||||
pass.Engine = RazorEngine.CreateEmpty(b =>{ });
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// 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.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
public class DefaultRazorCSharpLoweringPhaseTest
|
||||
{
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency_IRDocument()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorCSharpLoweringPhase();
|
||||
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source));
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(
|
||||
() => phase.Execute(codeDocument),
|
||||
$"The '{nameof(DefaultRazorCSharpLoweringPhase)}' phase requires a '{nameof(DocumentIRNode)}' " +
|
||||
$"provided by the '{nameof(RazorCodeDocument)}'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency_SyntaxTree()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorCSharpLoweringPhase();
|
||||
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
var irDocument = new DocumentIRNode();
|
||||
codeDocument.SetIRDocument(irDocument);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(
|
||||
() => phase.Execute(codeDocument),
|
||||
$"The '{nameof(DefaultRazorCSharpLoweringPhase)}' phase requires a '{nameof(RazorSyntaxTree)}' " +
|
||||
$"provided by the '{nameof(RazorCodeDocument)}'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency_RuntimeTarget()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorCSharpLoweringPhase();
|
||||
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source));
|
||||
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
DocumentKind = "test",
|
||||
};
|
||||
codeDocument.SetIRDocument(irDocument);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(
|
||||
() => phase.Execute(codeDocument),
|
||||
$"The document of kind 'test' does not have a '{nameof(RuntimeTarget)}'. " +
|
||||
$"The document classifier must set a value for '{nameof(DocumentIRNode.Target)}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Xunit;
|
||||
using static Microsoft.AspNetCore.Razor.Evolution.Intermediate.RazorIRAssert;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
public class DefaultRazorIRLoweringPhaseIntegrationTest
|
||||
{
|
||||
|
|
@ -29,6 +29,20 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
n => Using("System.Threading.Tasks", n));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_SetsOptions()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
// Act
|
||||
var irDocument = Lower(codeDocument);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(irDocument.Options);
|
||||
Assert.Same(codeDocument.GetSyntaxTree().Options, irDocument.Options);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_HelloWorld()
|
||||
{
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// 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.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
public class DefaultRazorRuntimeCSharpLoweringPhaseTest
|
||||
{
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorRuntimeCSharpLoweringPhase();
|
||||
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(
|
||||
() => phase.Execute(codeDocument),
|
||||
$"The '{nameof(DefaultRazorRuntimeCSharpLoweringPhase)}' phase requires a '{nameof(DocumentIRNode)}' " +
|
||||
$"provided by the '{nameof(RazorCodeDocument)}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
DocumentKind = "ignore",
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var pass = new TestDocumentClassifierPass();
|
||||
|
|
@ -35,7 +36,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_NoMatch_IgnoresDocument()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var pass = new TestDocumentClassifierPass()
|
||||
{
|
||||
|
|
@ -55,7 +59,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_Match_SetsDocumentType_AndCreatesStructure()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var pass = new TestDocumentClassifierPass();
|
||||
pass.Engine = RazorEngine.CreateEmpty(b => { });
|
||||
|
|
@ -65,6 +72,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
|
||||
// Assert
|
||||
Assert.Equal("test", irDocument.DocumentKind);
|
||||
Assert.NotNull(irDocument.Target);
|
||||
|
||||
var @namespace = SingleChild<NamespaceDeclarationIRNode>(irDocument);
|
||||
var @class = SingleChild<ClassDeclarationIRNode>(@namespace);
|
||||
|
|
@ -76,7 +84,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_AddsCheckumFirstToDocument()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var builder = RazorIRBuilder.Create(irDocument);
|
||||
builder.Add(new ChecksumIRNode());
|
||||
|
|
@ -98,7 +109,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_AddsUsingsToNamespace()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var builder = RazorIRBuilder.Create(irDocument);
|
||||
builder.Add(new UsingStatementIRNode());
|
||||
|
|
@ -121,7 +135,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_AddsTagHelperFieldsToClass()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var builder = RazorIRBuilder.Create(irDocument);
|
||||
builder.Add(new DeclareTagHelperFieldsIRNode());
|
||||
|
|
@ -145,7 +162,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_AddsTheRestToMethod()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var builder = RazorIRBuilder.Create(irDocument);
|
||||
builder.Add(new HtmlContentIRNode());
|
||||
|
|
@ -171,7 +191,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
public void Execute_CanInitializeDefaults()
|
||||
{
|
||||
// Arrange
|
||||
var irDocument = new DocumentIRNode();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
Options = RazorParserOptions.CreateDefaultOptions(),
|
||||
};
|
||||
|
||||
var builder = RazorIRBuilder.Create(irDocument);
|
||||
builder.Add(new HtmlContentIRNode());
|
||||
|
|
|
|||
|
|
@ -1486,10 +1486,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
|||
TestRazorSourceDocument.CreateResource(sourceFilename, encoding: null, normalizeNewLines: true));
|
||||
|
||||
// This will ensure that we're not putting any randomly generated data in a baseline.
|
||||
codeDocument.Items[DefaultRazorRuntimeCSharpLoweringPhase.SuppressUniqueIds] = "test";
|
||||
codeDocument.Items[DefaultRazorCSharpLoweringPhase.SuppressUniqueIds] = "test";
|
||||
|
||||
// This is to make tests work cross platform.
|
||||
codeDocument.Items[DefaultRazorDesignTimeCSharpLoweringPhase.NewLineString] = "\r\n";
|
||||
codeDocument.Items[DefaultRazorCSharpLoweringPhase.NewLineString] = "\r\n";
|
||||
|
||||
return codeDocument;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
|||
TestRazorSourceDocument.CreateResource(sourceFilename, encoding: null, normalizeNewLines: true), imports);
|
||||
|
||||
// This will ensure that we're not putting any randomly generated data in a baseline.
|
||||
codeDocument.Items[DefaultRazorRuntimeCSharpLoweringPhase.SuppressUniqueIds] = "test";
|
||||
codeDocument.Items[DefaultRazorCSharpLoweringPhase.SuppressUniqueIds] = "test";
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
phase => Assert.IsType<DefaultRazorSyntaxTreePhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorIRLoweringPhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorIRPhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorRuntimeCSharpLoweringPhase>(phase));
|
||||
phase => Assert.IsType<DefaultRazorCSharpLoweringPhase>(phase));
|
||||
}
|
||||
|
||||
private static void AssertDefaultDesignTimeFeatures(IEnumerable<IRazorEngineFeature> features)
|
||||
|
|
@ -176,7 +176,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
phase => Assert.IsType<DefaultRazorSyntaxTreePhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorIRLoweringPhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorIRPhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorDesignTimeCSharpLoweringPhase>(phase));
|
||||
phase => Assert.IsType<DefaultRazorCSharpLoweringPhase>(phase));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue