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.
This commit is contained in:
Ryan Nowak 2016-12-06 10:51:43 -08:00
parent 18bb31cee4
commit 026f9ffb69
12 changed files with 96 additions and 86 deletions

View File

@ -50,45 +50,44 @@ namespace Microsoft.AspNetCore.Razor.Evolution
public RazorMethodDeclarationIRNode Method { get; } public RazorMethodDeclarationIRNode Method { get; }
// Example
// <input` checked="foo-bar @false"`/>
// Name=checked
// Prefix= checked="
// Suffix="
public override void VisitStartAttributeBlock(AttributeBlockChunkGenerator chunkGenerator, Block block) public override void VisitStartAttributeBlock(AttributeBlockChunkGenerator chunkGenerator, Block block)
{ {
var value = new ContainerRazorIRNode(); Builder.Push(new HtmlAttributeIRNode()
Builder.Add(new HtmlAttributeIRNode()
{ {
Name = chunkGenerator.Name, Name = chunkGenerator.Name,
Prefix = chunkGenerator.Prefix, Prefix = chunkGenerator.Prefix,
Value = value,
Suffix = chunkGenerator.Suffix, Suffix = chunkGenerator.Suffix,
SourceLocation = block.Start, SourceLocation = block.Start,
}); });
var valueBuilder = RazorIRBuilder.Create(value);
_builders.Push(valueBuilder);
} }
public override void VisitEndAttributeBlock(AttributeBlockChunkGenerator chunkGenerator, Block block) public override void VisitEndAttributeBlock(AttributeBlockChunkGenerator chunkGenerator, Block block)
{ {
_builders.Pop(); Builder.Pop();
} }
// Example
// <input checked="foo-bar `@false`"/>
// Prefix= (space)
// Children will contain a token for @false.
public override void VisitStartDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block) public override void VisitStartDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block)
{ {
var content = new ContainerRazorIRNode(); Builder.Push(new CSharpAttributeValueIRNode()
Builder.Add(new CSharpAttributeValueIRNode()
{ {
Prefix = chunkGenerator.Prefix, Prefix = chunkGenerator.Prefix,
Content = content,
SourceLocation = block.Start, SourceLocation = block.Start,
}); });
var valueBuilder = RazorIRBuilder.Create(content);
_builders.Push(valueBuilder);
} }
public override void VisitEndDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block) public override void VisitEndDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunkGenerator, Block block)
{ {
_builders.Pop(); Builder.Pop();
} }
public override void VisitLiteralAttributeSpan(LiteralAttributeChunkGenerator chunkGenerator, Span span) 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 // 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) public override void VisitStartExpressionBlock(ExpressionChunkGenerator chunkGenerator, Block block)
{ {
var value = new ContainerRazorIRNode(); Builder.Push(new CSharpExpressionIRNode()
Builder.Add(new CSharpExpressionIRNode()
{ {
Content = value,
SourceLocation = block.Start, SourceLocation = block.Start,
}); });
var valueBuilder = RazorIRBuilder.Create(value);
_builders.Push(valueBuilder);
} }
public override void VisitEndExpressionBlock(ExpressionChunkGenerator chunkGenerator, Block block) public override void VisitEndExpressionBlock(ExpressionChunkGenerator chunkGenerator, Block block)
{ {
_builders.Pop(); Builder.Pop();
} }
public override void VisitExpressionSpan(ExpressionChunkGenerator chunkGenerator, Span span) public override void VisitExpressionSpan(ExpressionChunkGenerator chunkGenerator, Span span)
@ -228,47 +222,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution
{ {
Builder.Pop(); Builder.Pop();
} }
private class ContainerRazorIRNode : RazorIRNode
{
private SourceLocation? _location;
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
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<TResult>(RazorIRNodeVisitor<TResult> visitor)
{
return visitor.VisitDefault(this);
}
}
} }
} }
} }

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{ {
public class CSharpAttributeValueIRNode : RazorIRNode public class CSharpAttributeValueIRNode : RazorIRNode
{ {
public override IList<RazorIRNode> Children { get; } = EmptyArray; public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
public override RazorIRNode Parent { get; set; } public override RazorIRNode Parent { get; set; }
@ -17,8 +17,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
public string Prefix { get; set; } public string Prefix { get; set; }
public RazorIRNode Content { get; set; }
public override void Accept(RazorIRNodeVisitor visitor) public override void Accept(RazorIRNodeVisitor visitor)
{ {
if (visitor == null) if (visitor == null)

View File

@ -9,14 +9,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{ {
public class CSharpExpressionIRNode : RazorIRNode public class CSharpExpressionIRNode : RazorIRNode
{ {
public override IList<RazorIRNode> Children { get; } = EmptyArray; public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
public override RazorIRNode Parent { get; set; } public override RazorIRNode Parent { get; set; }
internal override SourceLocation SourceLocation { get; set; } internal override SourceLocation SourceLocation { get; set; }
public RazorIRNode Content { get; set; }
public override void Accept(RazorIRNodeVisitor visitor) public override void Accept(RazorIRNodeVisitor visitor)
{ {
if (visitor == null) if (visitor == null)

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{ {
public class HtmlAttributeIRNode : RazorIRNode public class HtmlAttributeIRNode : RazorIRNode
{ {
public override IList<RazorIRNode> Children { get; } = EmptyArray; public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
public override RazorIRNode Parent { get; set; } public override RazorIRNode Parent { get; set; }
@ -19,8 +19,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
public string Prefix { get; set; } public string Prefix { get; set; }
public RazorIRNode Value { get; set; }
public string Suffix { get; set; } public string Suffix { get; set; }
public override void Accept(RazorIRNodeVisitor visitor) public override void Accept(RazorIRNodeVisitor visitor)

View File

@ -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());
}
}
}

View File

@ -31,12 +31,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
public override void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node) public override void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node)
{ {
WriteContentNode(node, node.Prefix, node.Content.ToString()); // This is broken. WriteContentNode(node, node.Prefix);
}
public override void VisitCSharpExpression(CSharpExpressionIRNode node)
{
WriteContentNode(node, node.Content.ToString()); // This is broken
} }
public override void VisitCSharpStatement(CSharpStatementIRNode node) public override void VisitCSharpStatement(CSharpStatementIRNode node)
@ -66,7 +61,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
public override void VisitHtmlAttribute(HtmlAttributeIRNode node) 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) public override void VisitHtmlAttributeValue(HtmlAttributeValueIRNode node)

View File

@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
} }
[Fact] [Fact]
public void Lower_WithUsing() public void Lower_WithFunctions()
{ {
// Arrange // Arrange
var codeDocument = TestRazorCodeDocument.Create(@"@functions { public int Foo { get; set; }}"); var codeDocument = TestRazorCodeDocument.Create(@"@functions { public int Foo { get; set; }}");
@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
} }
[Fact] [Fact]
public void Lower_WithFunctions() public void Lower_WithUsing()
{ {
// Arrange // Arrange
var codeDocument = TestRazorCodeDocument.Create(@"@using System"); var codeDocument = TestRazorCodeDocument.Create(@"@using System");

View File

@ -101,11 +101,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
Assert.Equal(name, attribute.Name); Assert.Equal(name, attribute.Name);
Assert.Equal(suffix, attribute.Suffix); Assert.Equal(suffix, attribute.Suffix);
Children(attribute.Value, valueValidators); Children(attribute, valueValidators);
} }
catch (XunitException e) 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); Assert.Equal(prefix, attributeValue.Prefix);
Children(attributeValue.Content, n => CSharpExpression(expected, n)); Children(attributeValue, n => CSharpExpression(expected, n));
} }
catch (XunitException e) 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<CSharpExpressionIRNode>(node); var cSharp = Assert.IsType<CSharpExpressionIRNode>(node);
var content = new StringBuilder(); 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()); Assert.Equal(expected, content.ToString());

View File

@ -0,0 +1,5 @@
<html>
<body>
<span val="@Hello" />
</body>
</html>"

View File

@ -0,0 +1,10 @@
Document - (0:0,0)
NamespaceDeclaration - (0:0,0) -
ClassDeclaration - (0:0,0) - - - -
RazorMethodDeclaration - (0:0,0) - - - -
HtmlContent - (0:0,0) - <html>\r\n<body>\r\n <span
HtmlAttribute - (25:2,9) - val=" - "
CSharpAttributeValue - (31:2,15) -
CSharpExpression - (31:2,15)
CSharpToken - (32:2,16) - Hello
HtmlContent - (38:2,22) - />\r\n</body>\r\n</html>"

View File

@ -0,0 +1,5 @@
<html>
<body>
<span data-val="@Hello" />
</body>
</html>"

View File

@ -0,0 +1,8 @@
Document - (0:0,0)
NamespaceDeclaration - (0:0,0) -
ClassDeclaration - (0:0,0) - - - -
RazorMethodDeclaration - (0:0,0) - - - -
HtmlContent - (0:0,0) - <html>\r\n<body>\r\n <span data\-val="
CSharpExpression - (36:2,20)
CSharpToken - (37:2,21) - Hello
HtmlContent - (42:2,26) - " />\r\n</body>\r\n</html>"