From 026f9ffb69fc5f34fc8ca823a14bd4fa84a1e757 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Tue, 6 Dec 2016 10:51:43 -0800 Subject: [PATCH] Nodes that have children should use .Children This removes special casing for nodes that contain children that were hiding them in a .Content or .Value property. --- .../DefaultRazorIRLoweringPhase.cs | 77 ++++--------------- .../CSharpAttributeValueIRNode.cs | 4 +- .../Intermediate/CSharpExpressionIRNode.cs | 4 +- .../Intermediate/HtmlAttributeIRNode.cs | 4 +- .../HtmlAttributeIntegrationTest.cs | 40 ++++++++++ .../IntegrationTests/RazorIRNodeWriter.cs | 9 +-- ...aultRazorIRLoweringPhaseIntegrationTest.cs | 4 +- .../Intermediate/RazorIRAssert.cs | 12 +-- .../HtmlWithConditionalAttribute.cshtml | 5 ++ .../HtmlWithConditionalAttribute.ir.txt | 10 +++ .../HtmlWithDataDashAttribute.cshtml | 5 ++ .../HtmlWithDataDashAttribute.ir.txt | 8 ++ 12 files changed, 96 insertions(+), 86 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/HtmlAttributeIntegrationTest.cs create mode 100644 test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.cshtml create mode 100644 test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.ir.txt create mode 100644 test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.cshtml create mode 100644 test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.ir.txt diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorIRLoweringPhase.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorIRLoweringPhase.cs index 98f4c5bf9e..dfc5dbeb3e 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorIRLoweringPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorIRLoweringPhase.cs @@ -50,45 +50,44 @@ namespace Microsoft.AspNetCore.Razor.Evolution public RazorMethodDeclarationIRNode Method { get; } + // Example + // + // Name=checked + // Prefix= checked=" + // Suffix=" public override void VisitStartAttributeBlock(AttributeBlockChunkGenerator chunkGenerator, Block block) { - var value = new ContainerRazorIRNode(); - Builder.Add(new HtmlAttributeIRNode() + Builder.Push(new HtmlAttributeIRNode() { Name = chunkGenerator.Name, Prefix = chunkGenerator.Prefix, - Value = value, Suffix = chunkGenerator.Suffix, SourceLocation = block.Start, }); - - var valueBuilder = RazorIRBuilder.Create(value); - _builders.Push(valueBuilder); } public override void VisitEndAttributeBlock(AttributeBlockChunkGenerator chunkGenerator, Block block) { - _builders.Pop(); + Builder.Pop(); } + // Example + // + // Prefix= (space) + // Children will contain a token for @false. public override void VisitStartDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block) { - var content = new ContainerRazorIRNode(); - Builder.Add(new CSharpAttributeValueIRNode() + Builder.Push(new CSharpAttributeValueIRNode() { Prefix = chunkGenerator.Prefix, - Content = content, SourceLocation = block.Start, }); - - var valueBuilder = RazorIRBuilder.Create(content); - _builders.Push(valueBuilder); } public override void VisitEndDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block) { - _builders.Pop(); + Builder.Pop(); } public override void VisitLiteralAttributeSpan(LiteralAttributeChunkGenerator chunkGenerator, Span span) @@ -119,20 +118,15 @@ namespace Microsoft.AspNetCore.Razor.Evolution // We need to capture this in the IR so that we can give each piece the correct source mappings public override void VisitStartExpressionBlock(ExpressionChunkGenerator chunkGenerator, Block block) { - var value = new ContainerRazorIRNode(); - Builder.Add(new CSharpExpressionIRNode() + Builder.Push(new CSharpExpressionIRNode() { - Content = value, SourceLocation = block.Start, }); - - var valueBuilder = RazorIRBuilder.Create(value); - _builders.Push(valueBuilder); } public override void VisitEndExpressionBlock(ExpressionChunkGenerator chunkGenerator, Block block) { - _builders.Pop(); + Builder.Pop(); } public override void VisitExpressionSpan(ExpressionChunkGenerator chunkGenerator, Span span) @@ -228,47 +222,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution { Builder.Pop(); } - - private class ContainerRazorIRNode : RazorIRNode - { - private SourceLocation? _location; - - public override IList Children { get; } = new List(); - - public override RazorIRNode Parent { get; set; } - - internal override SourceLocation SourceLocation - { - get - { - if (_location == null) - { - if (Children.Count > 0) - { - return Children[0].SourceLocation; - } - - return SourceLocation.Undefined; - } - - return _location.Value; - } - set - { - _location = value; - } - } - - public override void Accept(RazorIRNodeVisitor visitor) - { - visitor.VisitDefault(this); - } - - public override TResult Accept(RazorIRNodeVisitor visitor) - { - return visitor.VisitDefault(this); - } - } } } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpAttributeValueIRNode.cs index a588c54ad0..c453db4ede 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpAttributeValueIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpAttributeValueIRNode.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate { public class CSharpAttributeValueIRNode : RazorIRNode { - public override IList Children { get; } = EmptyArray; + public override IList Children { get; } = new List(); public override RazorIRNode Parent { get; set; } @@ -17,8 +17,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate public string Prefix { get; set; } - public RazorIRNode Content { get; set; } - public override void Accept(RazorIRNodeVisitor visitor) { if (visitor == null) diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpExpressionIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpExpressionIRNode.cs index a90d45b73a..ef63ea9276 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpExpressionIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CSharpExpressionIRNode.cs @@ -9,14 +9,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate { public class CSharpExpressionIRNode : RazorIRNode { - public override IList Children { get; } = EmptyArray; + public override IList Children { get; } = new List(); public override RazorIRNode Parent { get; set; } internal override SourceLocation SourceLocation { get; set; } - public RazorIRNode Content { get; set; } - public override void Accept(RazorIRNodeVisitor visitor) { if (visitor == null) diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/HtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/HtmlAttributeIRNode.cs index 0b0ce8e22a..d0bb940d27 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/HtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/HtmlAttributeIRNode.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate { public class HtmlAttributeIRNode : RazorIRNode { - public override IList Children { get; } = EmptyArray; + public override IList Children { get; } = new List(); public override RazorIRNode Parent { get; set; } @@ -19,8 +19,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate public string Prefix { get; set; } - public RazorIRNode Value { get; set; } - public string Suffix { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/HtmlAttributeIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/HtmlAttributeIntegrationTest.cs new file mode 100644 index 0000000000..0cb18c72d0 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/HtmlAttributeIntegrationTest.cs @@ -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 Xunit; + +namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests +{ + public class HtmlAttributeIntegrationTest : IntegrationTestBase + { + [Fact] + public void HtmlWithDataDashAttribute() + { + // Arrange + var engine = RazorEngine.Create(); + + var document = CreateCodeDocument(); + + // Act + engine.Process(document); + + // Assert + AssertIRMatchesBaseline(document.GetIRDocument()); + } + + [Fact] + public void HtmlWithConditionalAttribute() + { + // Arrange + var engine = RazorEngine.Create(); + + var document = CreateCodeDocument(); + + // Act + engine.Process(document); + + // Assert + AssertIRMatchesBaseline(document.GetIRDocument()); + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs index afd7e2881a..94ff92634a 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs @@ -31,12 +31,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests public override void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node) { - WriteContentNode(node, node.Prefix, node.Content.ToString()); // This is broken. - } - - public override void VisitCSharpExpression(CSharpExpressionIRNode node) - { - WriteContentNode(node, node.Content.ToString()); // This is broken + WriteContentNode(node, node.Prefix); } public override void VisitCSharpStatement(CSharpStatementIRNode node) @@ -66,7 +61,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests public override void VisitHtmlAttribute(HtmlAttributeIRNode node) { - WriteContentNode(node, node.Prefix, node.Value.ToString(), node.Suffix); + WriteContentNode(node, node.Prefix, node.Suffix); } public override void VisitHtmlAttributeValue(HtmlAttributeValueIRNode node) diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs index 9928f8b993..b1281fa359 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs @@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate } [Fact] - public void Lower_WithUsing() + public void Lower_WithFunctions() { // Arrange var codeDocument = TestRazorCodeDocument.Create(@"@functions { public int Foo { get; set; }}"); @@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate } [Fact] - public void Lower_WithFunctions() + public void Lower_WithUsing() { // Arrange var codeDocument = TestRazorCodeDocument.Create(@"@using System"); diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/RazorIRAssert.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/RazorIRAssert.cs index 3c3574177e..62306fafaf 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/RazorIRAssert.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/RazorIRAssert.cs @@ -101,11 +101,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate Assert.Equal(name, attribute.Name); Assert.Equal(suffix, attribute.Suffix); - Children(attribute.Value, valueValidators); + Children(attribute, valueValidators); } catch (XunitException e) { - throw new IRAssertException(attribute, attribute.Value.Children, e.Message, e); + throw new IRAssertException(attribute, attribute.Children, e.Message, e); } } @@ -117,11 +117,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate { Assert.Equal(prefix, attributeValue.Prefix); - Children(attributeValue.Content, n => CSharpExpression(expected, n)); + Children(attributeValue, n => CSharpExpression(expected, n)); } catch (XunitException e) { - throw new IRAssertException(attributeValue, attributeValue.Content.Children, e.Message, e); + throw new IRAssertException(attributeValue, attributeValue.Children, e.Message, e); } } @@ -147,9 +147,9 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate var cSharp = Assert.IsType(node); var content = new StringBuilder(); - for (var i = 0; i < cSharp.Content.Children.Count; i++) + for (var i = 0; i < cSharp.Children.Count; i++) { - content.Append(((CSharpTokenIRNode)cSharp.Content.Children[i]).Content); + content.Append(((CSharpTokenIRNode)cSharp.Children[i]).Content); } Assert.Equal(expected, content.ToString()); diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.cshtml new file mode 100644 index 0000000000..3a6c940b48 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.cshtml @@ -0,0 +1,5 @@ + + + + +" \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.ir.txt b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.ir.txt new file mode 100644 index 0000000000..5e1c335d6c --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithConditionalAttribute.ir.txt @@ -0,0 +1,10 @@ +Document - (0:0,0) + NamespaceDeclaration - (0:0,0) - + ClassDeclaration - (0:0,0) - - - - + RazorMethodDeclaration - (0:0,0) - - - - + HtmlContent - (0:0,0) - \r\n\r\n \r\n\r\n" diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.cshtml new file mode 100644 index 0000000000..ac18b96408 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.cshtml @@ -0,0 +1,5 @@ + + + + +" \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.ir.txt b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.ir.txt new file mode 100644 index 0000000000..3364c9391a --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/HtmlAttributeIntegrationTest/HtmlWithDataDashAttribute.ir.txt @@ -0,0 +1,8 @@ +Document - (0:0,0) + NamespaceDeclaration - (0:0,0) - + ClassDeclaration - (0:0,0) - - - - + RazorMethodDeclaration - (0:0,0) - - - - + HtmlContent - (0:0,0) - \r\n\r\n \r\n\r\n"