diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs index cdaf2cb082..2915ee8015 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions public override void VisitCSharpExpression(CSharpExpressionIRNode node) { - if (node.Source != null && !(node.Parent is CSharpAttributeValueIRNode)) + if (node.Source != null) { Items.Add(new InstrumentationItem(node, isLiteral: false, source: node.Source.Value)); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/BasicWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/BasicWriter.cs index aa7ff41d8f..9f8af2de06 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/BasicWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/BasicWriter.cs @@ -21,6 +21,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration public abstract void WriteHtmlAttributeValue(CSharpRenderingContext context, HtmlAttributeValueIRNode node); - public abstract void WriteCSharpAttributeValue(CSharpRenderingContext context, CSharpAttributeValueIRNode node); + public abstract void WriteCSharpExpressionAttributeValue(CSharpRenderingContext context, CSharpExpressionAttributeValueIRNode node); + + public abstract void WriteCSharpStatementAttributeValue(CSharpRenderingContext context, CSharpStatementAttributeValueIRNode node); } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs index 8b119c0c34..da7d5e431b 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs @@ -209,9 +209,14 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration Context.BasicWriter.WriteHtmlAttributeValue(Context, node); } - public override void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node) + public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIRNode node) { - Context.BasicWriter.WriteCSharpAttributeValue(Context, node); + Context.BasicWriter.WriteCSharpExpressionAttributeValue(Context, node); + } + + public override void VisitCSharpStatementAttributeValue(CSharpStatementAttributeValueIRNode node) + { + Context.BasicWriter.WriteCSharpStatementAttributeValue(Context, node); } public override void VisitHtml(HtmlContentIRNode node) diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeBasicWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeBasicWriter.cs index 02e446479f..c891644bed 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeBasicWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeBasicWriter.cs @@ -2,6 +2,7 @@ // 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.Language.Intermediate; namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration @@ -153,9 +154,115 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration context.RenderChildren(node); } - public override void WriteCSharpAttributeValue(CSharpRenderingContext context, CSharpAttributeValueIRNode node) + public override void WriteCSharpExpressionAttributeValue(CSharpRenderingContext context, CSharpExpressionAttributeValueIRNode node) { - context.RenderChildren(node); + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + if (node.Children.Count == 0) + { + return; + } + + var firstChild = node.Children[0]; + if (firstChild.Source != null) + { + using (context.Writer.BuildLinePragma(firstChild.Source.Value)) + { + var offset = RazorDesignTimeIRPass.DesignTimeVariable.Length + " = ".Length; + context.Writer.WritePadding(offset, firstChild.Source, context); + context.Writer.WriteStartAssignment(RazorDesignTimeIRPass.DesignTimeVariable); + + for (var i = 0; i < node.Children.Count; i++) + { + if (node.Children[i] is RazorIRToken token && token.IsCSharp) + { + context.AddLineMappingFor(token); + context.Writer.Write(token.Content); + } + else + { + // There may be something else inside the expression like a Template or another extension node. + context.RenderNode(node.Children[i]); + } + } + + context.Writer.WriteLine(";"); + } + } + else + { + context.Writer.WriteStartAssignment(RazorDesignTimeIRPass.DesignTimeVariable); + for (var i = 0; i < node.Children.Count; i++) + { + if (node.Children[i] is RazorIRToken token && token.IsCSharp) + { + if (token.Source != null) + { + context.AddLineMappingFor(token); + } + + context.Writer.Write(token.Content); + } + else + { + // There may be something else inside the expression like a Template or another extension node. + context.RenderNode(node.Children[i]); + } + } + context.Writer.WriteLine(";"); + } + } + + public override void WriteCSharpStatementAttributeValue(CSharpRenderingContext context, CSharpStatementAttributeValueIRNode node) + { + for (var i = 0; i < node.Children.Count; i++) + { + if (node.Children[i] is RazorIRToken token && token.IsCSharp) + { + IDisposable linePragmaScope = null; + var isWhitespaceStatement = string.IsNullOrWhiteSpace(token.Content); + + if (token.Source != null) + { + if (!isWhitespaceStatement) + { + linePragmaScope = context.Writer.BuildLinePragma(token.Source.Value); + } + + context.Writer.WritePadding(0, token.Source.Value, context); + } + else if (isWhitespaceStatement) + { + // Don't write whitespace if there is no line mapping for it. + continue; + } + + context.AddLineMappingFor(token); + context.Writer.Write(token.Content); + + if (linePragmaScope != null) + { + linePragmaScope.Dispose(); + } + else + { + context.Writer.WriteLine(); + } + } + else + { + // There may be something else inside the statement like an extension node. + context.RenderNode(node.Children[i]); + } + } } public override void WriteHtmlContent(CSharpRenderingContext context, HtmlContentIRNode node) diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeBasicWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeBasicWriter.cs index 73c10af3a8..50236d7407 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeBasicWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeBasicWriter.cs @@ -147,7 +147,12 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration { var valuePieceCount = node .Children - .Count(child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode); + .Count(child => + child is HtmlAttributeValueIRNode || + child is CSharpExpressionAttributeValueIRNode || + child is CSharpStatementAttributeValueIRNode || + child is ExtensionIRNode); + var prefixLocation = node.Source.Value.AbsoluteIndex; var suffixLocation = node.Source.Value.AbsoluteIndex + node.Source.Value.Length - node.Suffix.Length; context.Writer @@ -182,8 +187,23 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration .WriteStringLiteral(node.Prefix) .WriteParameterSeparator() .Write(prefixLocation.ToString(CultureInfo.InvariantCulture)) - .WriteParameterSeparator() - .WriteStringLiteral(node.Content) + .WriteParameterSeparator(); + + // Write content + for (var i = 0; i < node.Children.Count; i++) + { + if (node.Children[i] is RazorIRToken token && token.IsHtml) + { + context.Writer.WriteStringLiteral(token.Content); + } + else + { + // There may be something else inside the attribute value like an extension node. + context.RenderNode(node.Children[i]); + } + } + + context.Writer .WriteParameterSeparator() .Write(valueLocation.ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator() @@ -193,12 +213,48 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration .WriteEndMethodInvocation(); } - public override void WriteCSharpAttributeValue(CSharpRenderingContext context, CSharpAttributeValueIRNode node) + public override void WriteCSharpExpressionAttributeValue(CSharpRenderingContext context, CSharpExpressionAttributeValueIRNode node) + { + using (context.Writer.BuildLinePragma(node.Source.Value)) + { + var prefixLocation = node.Source.Value.AbsoluteIndex; + context.Writer + .WriteStartMethodInvocation(WriteAttributeValueMethod) + .WriteStringLiteral(node.Prefix) + .WriteParameterSeparator() + .Write(prefixLocation.ToString(CultureInfo.InvariantCulture)) + .WriteParameterSeparator(); + + for (var i = 0; i < node.Children.Count; i++) + { + if (node.Children[i] is RazorIRToken token && token.IsCSharp) + { + context.Writer.Write(token.Content); + } + else + { + // There may be something else inside the expression like an extension node. + context.RenderNode(node.Children[i]); + } + } + + var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length; + var valueLength = node.Source.Value.Length - node.Prefix.Length; + context.Writer + .WriteParameterSeparator() + .Write(valueLocation.ToString(CultureInfo.InvariantCulture)) + .WriteParameterSeparator() + .Write(valueLength.ToString(CultureInfo.InvariantCulture)) + .WriteParameterSeparator() + .WriteBooleanLiteral(false) + .WriteEndMethodInvocation(); + } + } + + public override void WriteCSharpStatementAttributeValue(CSharpRenderingContext context, CSharpStatementAttributeValueIRNode node) { const string ValueWriterName = "__razor_attribute_value_writer"; - var expressionValue = node.Children.FirstOrDefault() as CSharpExpressionIRNode; - var linePragma = expressionValue != null ? context.Writer.BuildLinePragma(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; @@ -209,29 +265,56 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration .Write(prefixLocation.ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator(); - if (expressionValue != null) - { - Debug.Assert(node.Children.Count == 1); + context.Writer.WriteStartNewObject(TemplateTypeName); - RenderExpressionInline(context, expressionValue); - } - else + using (context.Writer.BuildAsyncLambda(endLine: false, parameterNames: ValueWriterName)) { - // Not an expression; need to buffer the result. - context.Writer.WriteStartNewObject(TemplateTypeName); + context.Writer.WriteMethodInvocation(PushWriterMethod, ValueWriterName); - using (context.Writer.BuildAsyncLambda(endLine: false, parameterNames: ValueWriterName)) + for (var i = 0; i < node.Children.Count; i++) { - context.Writer.WriteMethodInvocation(PushWriterMethod, ValueWriterName); + if (node.Children[i] is RazorIRToken token && token.IsCSharp) + { + var isWhitespaceStatement = string.IsNullOrWhiteSpace(token.Content); + IDisposable linePragmaScope = null; + if (token.Source != null) + { + if (!isWhitespaceStatement) + { + linePragmaScope = context.Writer.BuildLinePragma(token.Source.Value); + } - context.RenderChildren(node); + context.Writer.WritePadding(0, token.Source.Value, context); + } + else if (isWhitespaceStatement) + { + // Don't write whitespace if there is no line mapping for it. + continue; + } - context.Writer.WriteMethodInvocation(PopWriterMethod); + context.Writer.Write(token.Content); + + if (linePragmaScope != null) + { + linePragmaScope.Dispose(); + } + else + { + context.Writer.WriteLine(); + } + } + else + { + // There may be something else inside the statement like an extension node. + context.RenderNode(node.Children[i]); + } } - context.Writer.WriteEndMethodInvocation(false); + context.Writer.WriteMethodInvocation(PopWriterMethod); } + context.Writer.WriteEndMethodInvocation(false); + context.Writer .WriteParameterSeparator() .Write(valueLocation.ToString(CultureInfo.InvariantCulture)) @@ -240,8 +323,6 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration .WriteParameterSeparator() .WriteBooleanLiteral(false) .WriteEndMethodInvocation(); - - linePragma?.Dispose(); } public override void WriteHtmlContent(CSharpRenderingContext context, HtmlContentIRNode node) @@ -283,20 +364,5 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration charactersConsumed += textToRender.Length; } } - - protected static void RenderExpressionInline(CSharpRenderingContext context, RazorIRNode node) - { - if (node is RazorIRToken token && token.IsCSharp) - { - context.Writer.Write(token.Content); - } - else - { - for (var i = 0; i < node.Children.Count; i++) - { - RenderExpressionInline(context, node.Children[i]); - } - } - } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs index c90a2f0db1..5367ec5bb7 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs @@ -242,7 +242,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node) { var attributeValueStyleParameter = $"{HtmlAttributeValueStyleTypeName}.{node.ValueStyle}"; - var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode); + var isConditionalAttributeValue = node.Children.Any( + child => child is CSharpExpressionAttributeValueIRNode || child is CSharpStatementAttributeValueIRNode); // All simple text and minimized attributes will be pre-allocated. if (isConditionalAttributeValue) @@ -253,7 +254,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration // 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); + child => + child is HtmlAttributeValueIRNode || + child is CSharpExpressionAttributeValueIRNode || + child is CSharpStatementAttributeValueIRNode || + child is ExtensionIRNode); context.Writer .WriteStartMethodInvocation(BeginAddHtmlAttributeValuesMethodName) diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs index f6e97ebec8..ac6c15dca2 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs @@ -295,11 +295,23 @@ namespace Microsoft.AspNetCore.Razor.Language // Children will contain a token for @false. public override void VisitDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block) { - _builder.Push(new CSharpAttributeValueIRNode() + var firstChild = block.Children.FirstOrDefault(c => c.IsBlock) as Block; + if (firstChild == null || firstChild.Type == BlockKindInternal.Expression) { - Prefix = chunkGenerator.Prefix, - Source = BuildSourceSpanFromNode(block), - }); + _builder.Push(new CSharpExpressionAttributeValueIRNode() + { + Prefix = chunkGenerator.Prefix, + Source = BuildSourceSpanFromNode(block), + }); + } + else + { + _builder.Push(new CSharpStatementAttributeValueIRNode() + { + Prefix = chunkGenerator.Prefix, + Source = BuildSourceSpanFromNode(block), + }); + } VisitDefault(block); @@ -308,12 +320,32 @@ namespace Microsoft.AspNetCore.Razor.Language public override void VisitLiteralAttributeSpan(LiteralAttributeChunkGenerator chunkGenerator, Span span) { - _builder.Add(new HtmlAttributeValueIRNode() + _builder.Push(new HtmlAttributeValueIRNode() { Prefix = chunkGenerator.Prefix, - Content = chunkGenerator.Value, Source = BuildSourceSpanFromNode(span), }); + + var location = chunkGenerator.Value.Location; + SourceSpan? valueSpan = null; + if (location != SourceLocation.Undefined) + { + valueSpan = new SourceSpan( + location.FilePath ?? FileName, + location.AbsoluteIndex, + location.LineIndex, + location.CharacterIndex, + chunkGenerator.Value.Value.Length); + } + + _builder.Add(new RazorIRToken() + { + Content = chunkGenerator.Value, + Kind = RazorIRToken.TokenKind.Html, + Source = valueSpan + }); + + _builder.Pop(); } public override void VisitTemplateBlock(TemplateBlockChunkGenerator chunkGenerator, Block block) @@ -354,7 +386,14 @@ namespace Microsoft.AspNetCore.Razor.Language // We need to capture this in the IR so that we can give each piece the correct source mappings public override void VisitExpressionBlock(ExpressionChunkGenerator chunkGenerator, Block block) { + if (_builder.Current is CSharpExpressionAttributeValueIRNode) + { + VisitDefault(block); + return; + } + var expressionNode = new CSharpExpressionIRNode(); + _builder.Push(expressionNode); VisitDefault(block); @@ -394,11 +433,16 @@ namespace Microsoft.AspNetCore.Razor.Language public override void VisitStatementSpan(StatementChunkGenerator chunkGenerator, Span span) { - var statementNode = new CSharpStatementIRNode() + var isAttributeValue = _builder.Current is CSharpStatementAttributeValueIRNode; + + if (!isAttributeValue) { - Source = BuildSourceSpanFromNode(span) - }; - _builder.Push(statementNode); + var statementNode = new CSharpStatementIRNode() + { + Source = BuildSourceSpanFromNode(span) + }; + _builder.Push(statementNode); + } _builder.Add(new RazorIRToken() { @@ -407,7 +451,10 @@ namespace Microsoft.AspNetCore.Razor.Language Source = BuildSourceSpanFromNode(span), }); - _builder.Pop(); + if (!isAttributeValue) + { + _builder.Pop(); + } } public override void VisitMarkupSpan(MarkupChunkGenerator chunkGenerator, Span span) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs new file mode 100644 index 0000000000..8d79bdeb72 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs @@ -0,0 +1,31 @@ +// 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.Language.Intermediate +{ + public sealed class CSharpExpressionAttributeValueIRNode : RazorIRNode + { + public override ItemCollection Annotations => ReadOnlyItemCollection.Empty; + + public override IList Children { get; } = new List(); + + public override RazorIRNode Parent { get; set; } + + public override SourceSpan? Source { get; set; } + + public string Prefix { get; set; } + + public override void Accept(RazorIRNodeVisitor visitor) + { + if (visitor == null) + { + throw new ArgumentNullException(nameof(visitor)); + } + + visitor.VisitCSharpExpressionAttributeValue(this); + } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpStatementAttributeValueIRNode.cs similarity index 86% rename from src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpAttributeValueIRNode.cs rename to src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpStatementAttributeValueIRNode.cs index b9e36ec07a..5b64d9b63f 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpAttributeValueIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpStatementAttributeValueIRNode.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.Razor.Language.Intermediate { - public sealed class CSharpAttributeValueIRNode : RazorIRNode + public sealed class CSharpStatementAttributeValueIRNode : RazorIRNode { public override ItemCollection Annotations => ReadOnlyItemCollection.Empty; @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate throw new ArgumentNullException(nameof(visitor)); } - visitor.VisitCSharpAttributeValue(this); + visitor.VisitCSharpStatementAttributeValue(this); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs index 7173328f89..64d839b24c 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override ItemCollection Annotations => ReadOnlyItemCollection.Empty; - public override IList Children { get; } = EmptyArray; + public override IList Children { get; } = new List(); public override RazorIRNode Parent { get; set; } @@ -18,8 +18,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public string Prefix { get; set; } - public string Content { get; set; } - public override void Accept(RazorIRNodeVisitor visitor) { if (visitor == null) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs index 33cec8b2b1..373f061b9f 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs @@ -54,7 +54,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate VisitDefault(node); } - public virtual void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node) + public virtual void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIRNode node) + { + VisitDefault(node); + } + + public virtual void VisitCSharpStatementAttributeValue(CSharpStatementAttributeValueIRNode node) { VisitDefault(node); } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.ir.txt index 3e12c1547d..10d87d250b 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.ir.txt @@ -30,9 +30,8 @@ Document - HtmlContent - (0:0,0 [4] Basic.cshtml) RazorIRToken - (0:0,0 [4] Basic.cshtml) - Html -
RazorIRToken - (30:0,30 [23] Basic.cshtml) - Html - \n Hello world\n @@ -47,13 +46,11 @@ Document - HtmlContent - (123:7,0 [2] Basic.cshtml) RazorIRToken - (123:7,0 [2] Basic.cshtml) - Html -

RazorIRToken - (162:7,39 [2] Basic.cshtml) - Html - \n diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs index 17491f249f..986c30e628 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs @@ -54,11 +54,13 @@ Write(string.Format("{0}", "Hello")); #line default #line hidden + BeginContext(153, 3, false); #line 8 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic.cshtml" Write(cls); #line default #line hidden + EndContext(); #line 8 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic.cshtml" } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.ir.txt index 67f2f76a9f..0e1e665162 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.ir.txt @@ -17,9 +17,8 @@ Document - CSharpStatement - RazorIRToken - - CSharp - EndContext(); HtmlAttribute - (4:0,4 [25] Basic.cshtml) - class=" - " - CSharpAttributeValue - (12:0,12 [16] Basic.cshtml) - - CSharpExpression - (13:0,13 [15] Basic.cshtml) - RazorIRToken - (13:0,13 [15] Basic.cshtml) - CSharp - this.ToString() + CSharpExpressionAttributeValue - (12:0,12 [16] Basic.cshtml) - + RazorIRToken - (13:0,13 [15] Basic.cshtml) - CSharp - this.ToString() CSharpStatement - RazorIRToken - - CSharp - BeginContext(29, 24, true); HtmlContent - (29:0,29 [24] Basic.cshtml) @@ -51,13 +50,15 @@ Document - CSharpStatement - RazorIRToken - - CSharp - EndContext(); HtmlAttribute - (125:7,2 [34] Basic.cshtml) - class=" - " - CSharpAttributeValue - (133:7,10 [25] Basic.cshtml) - - CSharpStatement - (134:7,11 [18] Basic.cshtml) - RazorIRToken - (134:7,11 [18] Basic.cshtml) - CSharp - if(cls != null) { + CSharpStatementAttributeValue - (133:7,10 [25] Basic.cshtml) - + RazorIRToken - (134:7,11 [18] Basic.cshtml) - CSharp - if(cls != null) { + CSharpStatement - + RazorIRToken - - CSharp - BeginContext(153, 3, false); CSharpExpression - (153:7,30 [3] Basic.cshtml) RazorIRToken - (153:7,30 [3] Basic.cshtml) - CSharp - cls - CSharpStatement - (156:7,33 [2] Basic.cshtml) - RazorIRToken - (156:7,33 [2] Basic.cshtml) - CSharp - } + CSharpStatement - + RazorIRToken - - CSharp - EndContext(); + RazorIRToken - (156:7,33 [2] Basic.cshtml) - CSharp - } CSharpStatement - RazorIRToken - - CSharp - BeginContext(159, 5, true); HtmlContent - (159:7,36 [5] Basic.cshtml) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs index 3a694af26b..8d49153ac6 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Xunit; @@ -405,6 +406,147 @@ if (true) { } ignoreLineEndingDifferences: true); } + [Fact] + public void WriteCSharpExpressionAttributeValue_RendersCorrectly() + { + var writer = new DesignTimeBasicWriter(); + var context = GetCSharpRenderingContext(writer); + + var content = ""; + var sourceDocument = TestRazorSourceDocument.Create(content); + var codeDocument = RazorCodeDocument.Create(sourceDocument); + context.CodeDocument = codeDocument; + var irDocument = Lower(codeDocument); + var node = irDocument.Children.OfType().Single().Children[1] as CSharpExpressionAttributeValueIRNode; + + // Act + writer.WriteCSharpExpressionAttributeValue(context, node); + + // Assert + var csharp = context.Writer.Builder.ToString(); + Assert.Equal( +@"#line 1 ""test.cshtml"" + __o = false; + +#line default +#line hidden +", + csharp, + ignoreLineEndingDifferences: true); + } + + [Fact] + public void WriteCSharpStatementAttributeValue_RendersCorrectly() + { + var writer = new DesignTimeBasicWriter(); + var context = GetCSharpRenderingContext(writer); + + var content = ""; + var sourceDocument = TestRazorSourceDocument.Create(content); + var codeDocument = RazorCodeDocument.Create(sourceDocument); + context.CodeDocument = codeDocument; + var irDocument = Lower(codeDocument); + var node = irDocument.Children.OfType().Single().Children[1] as CSharpStatementAttributeValueIRNode; + + // Act + writer.WriteCSharpStatementAttributeValue(context, node); + + // Assert + var csharp = context.Writer.Builder.ToString(); + Assert.Equal( +@"#line 1 ""test.cshtml"" + if(@true){ } + +#line default +#line hidden +", + csharp, + ignoreLineEndingDifferences: true); + } + + [Fact] + public void WriteCSharpStatementAttributeValue_WithExpression_RendersCorrectly() + { + var writer = new DesignTimeBasicWriter(); + var context = GetCSharpRenderingContext(writer); + + var content = ""; + var sourceDocument = TestRazorSourceDocument.Create(content); + var codeDocument = RazorCodeDocument.Create(sourceDocument); + context.CodeDocument = codeDocument; + var irDocument = Lower(codeDocument); + var node = irDocument.Children.OfType().Single().Children[1] as CSharpStatementAttributeValueIRNode; + + // Act + writer.WriteCSharpStatementAttributeValue(context, node); + + // Assert + var csharp = context.Writer.Builder.ToString(); + Assert.Equal( +@"#line 1 ""test.cshtml"" + if(@true){ + +#line default +#line hidden +Render Node - CSharpExpressionIRNode +#line 1 ""test.cshtml"" + } + +#line default +#line hidden +", + csharp, + ignoreLineEndingDifferences: true); + } + + private static CSharpRenderingContext GetCSharpRenderingContext(BasicWriter writer) + { + var options = RazorCodeGenerationOptions.CreateDefault(); + var codeWriter = new Legacy.CSharpCodeWriter(); + var context = new CSharpRenderingContext() + { + Writer = codeWriter, + Options = options, + BasicWriter = writer, + RenderChildren = n => + { + codeWriter.WriteLine("Render Children"); + }, + RenderNode = n => + { + codeWriter.WriteLine($"Render Node - {n.GetType().Name}"); + } + }; + + return context; + } + + private static DocumentIRNode Lower(RazorCodeDocument codeDocument) + { + var engine = RazorEngine.Create(); + + return Lower(codeDocument, engine); + } + + private static DocumentIRNode Lower(RazorCodeDocument codeDocument, RazorEngine engine) + { + for (var i = 0; i < engine.Phases.Count; i++) + { + var phase = engine.Phases[i]; + phase.Execute(codeDocument); + + if (phase is IRazorIRLoweringPhase) + { + break; + } + } + + var irDocument = codeDocument.GetIRDocument(); + Assert.NotNull(irDocument); + + return irDocument; + } + private class MyExtensionIRNode : ExtensionIRNode { public override IList Children => throw new NotImplementedException(); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs index 74736f8196..e061f25e19 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs @@ -543,7 +543,7 @@ EndWriteAttribute(); } [Fact] - public void WriteCSharpAttributeValue_RendersCorrectly() + public void WriteCSharpExpressionAttributeValue_RendersCorrectly() { var writer = new RuntimeBasicWriter(); var context = GetCSharpRenderingContext(writer); @@ -552,10 +552,10 @@ EndWriteAttribute(); var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); var irDocument = Lower(codeDocument); - var node = irDocument.Children.OfType().Single().Children[1] as CSharpAttributeValueIRNode; + var node = irDocument.Children.OfType().Single().Children[1] as CSharpExpressionAttributeValueIRNode; // Act - writer.WriteCSharpAttributeValue(context, node); + writer.WriteCSharpExpressionAttributeValue(context, node); // Assert var csharp = context.Writer.Builder.ToString(); @@ -571,7 +571,7 @@ WriteAttributeValue("" "", 27, false, 28, 6, false); } [Fact] - public void WriteCSharpAttributeValue_NonExpression_BuffersResult() + public void WriteCSharpStatementAttributeValue_BuffersResult() { var writer = new RuntimeBasicWriter(); var context = GetCSharpRenderingContext(writer); @@ -579,18 +579,23 @@ WriteAttributeValue("" "", 27, false, 28, 6, false); var content = ""; var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); + context.CodeDocument = codeDocument; var irDocument = Lower(codeDocument); - var node = irDocument.Children.OfType().Single().Children[1] as CSharpAttributeValueIRNode; + var node = irDocument.Children.OfType().Single().Children[1] as CSharpStatementAttributeValueIRNode; // Act - writer.WriteCSharpAttributeValue(context, node); + writer.WriteCSharpStatementAttributeValue(context, node); // Assert var csharp = context.Writer.Builder.ToString(); Assert.Equal( @"WriteAttributeValue("" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => { PushWriter(__razor_attribute_value_writer); - Render Children +#line 1 ""test.cshtml"" + if(@true){ } + +#line default +#line hidden PopWriter(); } ), 28, 13, false); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeBasicWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeBasicWriterTest.cs index 09f86684a9..b1588f8e3c 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeBasicWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeBasicWriterTest.cs @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration } [Fact] - public void WriteCSharpAttributeValue_RendersCorrectly() + public void WriteCSharpExpressionAttributeValue_RendersCorrectly() { var writer = new TagHelperHtmlAttributeRuntimeBasicWriter(); var context = GetCSharpRenderingContext(writer); @@ -43,10 +43,10 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); var irDocument = Lower(codeDocument); - var node = irDocument.Children.OfType().Single().Children[1] as CSharpAttributeValueIRNode; + var node = irDocument.Children.OfType().Single().Children[1] as CSharpExpressionAttributeValueIRNode; // Act - writer.WriteCSharpAttributeValue(context, node); + writer.WriteCSharpExpressionAttributeValue(context, node); // Assert var csharp = context.Writer.Builder.ToString(); @@ -62,7 +62,7 @@ AddHtmlAttributeValue("" "", 27, false, 28, 6, false); } [Fact] - public void WriteCSharpAttributeValue_NonExpression_BuffersResult() + public void WriteCSharpStatementAttributeValue_BuffersResult() { var writer = new TagHelperHtmlAttributeRuntimeBasicWriter(); var context = GetCSharpRenderingContext(writer); @@ -70,18 +70,23 @@ AddHtmlAttributeValue("" "", 27, false, 28, 6, false); var content = ""; var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); + context.CodeDocument = codeDocument; var irDocument = Lower(codeDocument); - var node = irDocument.Children.OfType().Single().Children[1] as CSharpAttributeValueIRNode; + var node = irDocument.Children.OfType().Single().Children[1] as CSharpStatementAttributeValueIRNode; // Act - writer.WriteCSharpAttributeValue(context, node); + writer.WriteCSharpStatementAttributeValue(context, node); // Assert var csharp = context.Writer.Builder.ToString(); Assert.Equal( @"AddHtmlAttributeValue("" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => { PushWriter(__razor_attribute_value_writer); - Render Children +#line 1 ""test.cshtml"" + if(@true){ } + +#line default +#line hidden PopWriter(); } ), 28, 13, false); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIRLoweringPhaseIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIRLoweringPhaseIntegrationTest.cs index be3643d202..e2d5639a52 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIRLoweringPhaseIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorIRLoweringPhaseIntegrationTest.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Xunit; @@ -145,7 +144,7 @@ namespace Microsoft.AspNetCore.Razor.Language node: n, valueValidators: new Action[] { - value => CSharpAttributeValue(string.Empty, "Hello", value), + value => CSharpExpressionAttributeValue(string.Empty, "Hello", value), value => LiteralAttributeValue(" ", "World", value) }), n => Html(@" /> @@ -226,7 +225,7 @@ namespace Microsoft.AspNetCore.Razor.Language "val", HtmlAttributeValueStyle.DoubleQuotes, c, - v => CSharpAttributeValue(string.Empty, "Hello", v), + v => CSharpExpressionAttributeValue(string.Empty, "Hello", v), v => LiteralAttributeValue(" ", "World", v)))); } @@ -270,7 +269,7 @@ namespace Microsoft.AspNetCore.Razor.Language "val", HtmlAttributeValueStyle.DoubleQuotes, c, - v => CSharpAttributeValue(string.Empty, "Hello", v), + v => CSharpExpressionAttributeValue(string.Empty, "Hello", v), v => LiteralAttributeValue(" ", "World", v)))); } @@ -316,7 +315,7 @@ namespace Microsoft.AspNetCore.Razor.Language "val", HtmlAttributeValueStyle.DoubleQuotes, c2, - v => CSharpAttributeValue(string.Empty, "Hello", v), + v => CSharpExpressionAttributeValue(string.Empty, "Hello", v), v => LiteralAttributeValue(" ", "World", v))), c1 => Html(Environment.NewLine, c1)), n => TagHelperFieldDeclaration(n, "SpanTagHelper")); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_DesignTime.ir.txt index 8b13889380..b04bcf0e01 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_DesignTime.ir.txt @@ -131,11 +131,12 @@ Document - RazorIRToken - (705:19,13 [10] ComplexTagHelpers.cshtml) - Html - \n CreateTagHelper - - TestNamespace.PTagHelper AddTagHelperHtmlAttribute - - time - HtmlAttributeValueStyle.DoubleQuotes - HtmlAttributeValue - (197:8,17 [7] ComplexTagHelpers.cshtml) - - Current - HtmlAttributeValue - (204:8,24 [6] ComplexTagHelpers.cshtml) - - Time: - CSharpAttributeValue - (210:8,30 [14] ComplexTagHelpers.cshtml) - - CSharpExpression - (212:8,32 [12] ComplexTagHelpers.cshtml) - RazorIRToken - (212:8,32 [12] ComplexTagHelpers.cshtml) - CSharp - DateTime.Now + HtmlAttributeValue - (197:8,17 [7] ComplexTagHelpers.cshtml) - + RazorIRToken - (197:8,17 [7] ComplexTagHelpers.cshtml) - Html - Current + HtmlAttributeValue - (204:8,24 [6] ComplexTagHelpers.cshtml) - + RazorIRToken - (205:8,25 [5] ComplexTagHelpers.cshtml) - Html - Time: + CSharpExpressionAttributeValue - (210:8,30 [14] ComplexTagHelpers.cshtml) - + RazorIRToken - (212:8,32 [12] ComplexTagHelpers.cshtml) - CSharp - DateTime.Now HtmlContent - (719:20,12 [10] ComplexTagHelpers.cshtml) RazorIRToken - (719:20,12 [10] ComplexTagHelpers.cshtml) - Html - \n TagHelper - (729:21,8 [181] ComplexTagHelpers.cshtml) - p - TagMode.StartTagAndEndTag diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_Runtime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_Runtime.ir.txt index df5a971024..0f255239c3 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers_Runtime.ir.txt @@ -140,11 +140,12 @@ Document - RazorIRToken - (707:20,0 [8] ComplexTagHelpers.cshtml) - Html - CreateTagHelper - - TestNamespace.PTagHelper AddTagHelperHtmlAttribute - - time - HtmlAttributeValueStyle.DoubleQuotes - HtmlAttributeValue - (197:8,17 [7] ComplexTagHelpers.cshtml) - - Current - HtmlAttributeValue - (204:8,24 [6] ComplexTagHelpers.cshtml) - - Time: - CSharpAttributeValue - (210:8,30 [14] ComplexTagHelpers.cshtml) - - CSharpExpression - (212:8,32 [12] ComplexTagHelpers.cshtml) - RazorIRToken - (212:8,32 [12] ComplexTagHelpers.cshtml) - CSharp - DateTime.Now + HtmlAttributeValue - (197:8,17 [7] ComplexTagHelpers.cshtml) - + RazorIRToken - (197:8,17 [7] ComplexTagHelpers.cshtml) - Html - Current + HtmlAttributeValue - (204:8,24 [6] ComplexTagHelpers.cshtml) - + RazorIRToken - (205:8,25 [5] ComplexTagHelpers.cshtml) - Html - Time: + CSharpExpressionAttributeValue - (210:8,30 [14] ComplexTagHelpers.cshtml) - + RazorIRToken - (212:8,32 [12] ComplexTagHelpers.cshtml) - CSharp - DateTime.Now HtmlContent - (719:20,12 [10] ComplexTagHelpers.cshtml) RazorIRToken - (719:20,12 [10] ComplexTagHelpers.cshtml) - Html - \n TagHelper - (729:21,8 [181] ComplexTagHelpers.cshtml) - p - TagMode.StartTagAndEndTag diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt index 7278e26e4d..7296cb478f 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt @@ -17,9 +17,8 @@ Document - HtmlContent - (72:4,4 [2] ConditionalAttributes.cshtml) RazorIRToken - (72:4,4 [2] ConditionalAttributes.cshtml) - Html -

CSharpStatement - (90:4,22 [6] ConditionalAttributes.cshtml) @@ -27,10 +26,10 @@ Document - HtmlContent - (96:5,4 [2] ConditionalAttributes.cshtml) RazorIRToken - (96:5,4 [2] ConditionalAttributes.cshtml) - Html -

CSharpStatement - (118:5,26 [6] ConditionalAttributes.cshtml) @@ -38,10 +37,10 @@ Document - HtmlContent - (124:6,4 [2] ConditionalAttributes.cshtml) RazorIRToken - (124:6,4 [2] ConditionalAttributes.cshtml) - Html -

CSharpStatement - (146:6,26 [6] ConditionalAttributes.cshtml) @@ -50,9 +49,8 @@ Document - RazorIRToken - (152:7,4 [6] ConditionalAttributes.cshtml) - Html - CSharpStatement - (191:7,43 [6] ConditionalAttributes.cshtml) @@ -61,10 +59,10 @@ Document - RazorIRToken - (197:8,4 [6] ConditionalAttributes.cshtml) - Html - CSharpStatement - (240:8,47 [6] ConditionalAttributes.cshtml) @@ -72,13 +70,11 @@ Document - HtmlContent - (246:9,4 [2] ConditionalAttributes.cshtml) RazorIRToken - (246:9,4 [2] ConditionalAttributes.cshtml) - Html -

CSharpStatement - (285:9,43 [6] ConditionalAttributes.cshtml) @@ -92,9 +88,8 @@ Document - HtmlContent - (315:11,4 [7] ConditionalAttributes.cshtml) RazorIRToken - (315:11,4 [7] ConditionalAttributes.cshtml) - Html -