Fix C# design time projections for complex TagHelper attributes.
- TagHelper attributes that have expressions intermingled within them (resulting in Block elements) resulted in Spans in the attribute being falsely marked as SpanKind.Markup. - Updated tests to account for new SpanKind.Code behavior. - Added complex scenario to validate SpanKind.Code is flowed through to surround attributes. #387
This commit is contained in:
parent
a73867eabe
commit
039062c5eb
|
|
@ -254,7 +254,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
// If we're not after an equal then we should treat the value as if it were a minimized attribute.
|
// If we're not after an equal then we should treat the value as if it were a minimized attribute.
|
||||||
var attributeValueBuilder = afterEquals ? builder : null;
|
var attributeValueBuilder = afterEquals ? builder : null;
|
||||||
result.AttributeValueNode =
|
result.AttributeValueNode =
|
||||||
CreateMarkupAttribute(name, attributeValueBuilder, result.IsBoundNonStringAttribute);
|
CreateMarkupAttribute(attributeValueBuilder, result.IsBoundNonStringAttribute);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -337,17 +337,45 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
var spanBuilder = new SpanBuilder(child);
|
var spanBuilder = new SpanBuilder(child);
|
||||||
|
|
||||||
result.AttributeValueNode =
|
result.AttributeValueNode =
|
||||||
CreateMarkupAttribute(name, spanBuilder, result.IsBoundNonStringAttribute);
|
CreateMarkupAttribute(spanBuilder, result.IsBoundNonStringAttribute);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.AttributeValueNode = block;
|
result.AttributeValueNode = ConvertToMarkupAttributeBlock(block, result.IsBoundNonStringAttribute);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Block ConvertToMarkupAttributeBlock(Block block, bool isBoundNonStringAttribute)
|
||||||
|
{
|
||||||
|
var blockBuilder = new BlockBuilder
|
||||||
|
{
|
||||||
|
ChunkGenerator = block.ChunkGenerator,
|
||||||
|
Type = block.Type
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var child in block.Children)
|
||||||
|
{
|
||||||
|
SyntaxTreeNode markupAttributeChild;
|
||||||
|
|
||||||
|
if (child.IsBlock)
|
||||||
|
{
|
||||||
|
markupAttributeChild = ConvertToMarkupAttributeBlock((Block)child, isBoundNonStringAttribute);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var spanBuilder = new SpanBuilder((Span)child);
|
||||||
|
markupAttributeChild = CreateMarkupAttribute(spanBuilder, isBoundNonStringAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockBuilder.Children.Add(markupAttributeChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockBuilder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
private static Block RebuildChunkGenerators(Block block)
|
private static Block RebuildChunkGenerators(Block block)
|
||||||
{
|
{
|
||||||
var builder = new BlockBuilder(block);
|
var builder = new BlockBuilder(block);
|
||||||
|
|
@ -440,10 +468,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
return nodeStart + firstNonWhitespaceSymbol.Start;
|
return nodeStart + firstNonWhitespaceSymbol.Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SyntaxTreeNode CreateMarkupAttribute(
|
private static SyntaxTreeNode CreateMarkupAttribute(SpanBuilder builder, bool isBoundNonStringAttribute)
|
||||||
string name,
|
|
||||||
SpanBuilder builder,
|
|
||||||
bool isBoundNonStringAttribute)
|
|
||||||
{
|
{
|
||||||
Span value = null;
|
Span value = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -385,6 +385,12 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
return Builder.Build();
|
return Builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpanConstructor As(SpanKind spanKind)
|
||||||
|
{
|
||||||
|
Builder.Kind = spanKind;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SpanConstructor With(ISpanChunkGenerator generator)
|
public SpanConstructor With(ISpanChunkGenerator generator)
|
||||||
{
|
{
|
||||||
Builder.ChunkGenerator = generator;
|
Builder.ChunkGenerator = generator;
|
||||||
|
|
|
||||||
|
|
@ -603,6 +603,58 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
new MarkupBlock(factory.Markup("Time:"), dateTimeNow))
|
new MarkupBlock(factory.Markup("Time:"), dateTimeNow))
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"<person age=\"1 + @value + 2\" birthday='(bool)@Bag[\"val\"] ? @@DateTime : @DateTime.Now'/>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("person",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>(
|
||||||
|
"age",
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.CodeMarkup("1"),
|
||||||
|
factory.CodeMarkup(" +"),
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.CodeMarkup(" "),
|
||||||
|
new ExpressionBlock(
|
||||||
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
|
factory
|
||||||
|
.Code("value")
|
||||||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||||
|
factory.CodeMarkup(" +"),
|
||||||
|
factory.CodeMarkup(" 2"))),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>(
|
||||||
|
"birthday",
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.CodeMarkup("(bool)"),
|
||||||
|
new MarkupBlock(
|
||||||
|
new ExpressionBlock(
|
||||||
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
|
factory
|
||||||
|
.Code("Bag[\"val\"]")
|
||||||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||||
|
factory.CodeMarkup(" ?"),
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.CodeMarkup(" @").Accepts(AcceptedCharacters.None),
|
||||||
|
factory.CodeMarkup("@")
|
||||||
|
.With(SpanChunkGenerator.Null)
|
||||||
|
.Accepts(AcceptedCharacters.None)),
|
||||||
|
factory.CodeMarkup("DateTime"),
|
||||||
|
factory.CodeMarkup(" :"),
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.CodeMarkup(" "),
|
||||||
|
new ExpressionBlock(
|
||||||
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
|
factory
|
||||||
|
.Code("DateTime.Now")
|
||||||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
|
.Accepts(AcceptedCharacters.NonWhiteSpace)))
|
||||||
|
))
|
||||||
|
}))
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"<person age=\"12\" birthday=\"DateTime.Now\" name=\"Time: @DateTime.Now\" />",
|
"<person age=\"12\" birthday=\"DateTime.Now\" name=\"Time: @DateTime.Now\" />",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
|
|
@ -675,17 +727,21 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
"age",
|
"age",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
factory.Markup("@").Accepts(AcceptedCharacters.None),
|
factory.CodeMarkup("@").Accepts(AcceptedCharacters.None),
|
||||||
factory.Markup("@")
|
factory.CodeMarkup("@")
|
||||||
.With(SpanChunkGenerator.Null)
|
.With(SpanChunkGenerator.Null)
|
||||||
.Accepts(AcceptedCharacters.None)),
|
.Accepts(AcceptedCharacters.None)),
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
factory.EmptyHtml(),
|
factory.EmptyHtml().As(SpanKind.Code),
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
factory.MetaCode("(")
|
||||||
|
.Accepts(AcceptedCharacters.None)
|
||||||
|
.As(SpanKind.Code),
|
||||||
factory.Code("11+1").AsExpression(),
|
factory.Code("11+1").AsExpression(),
|
||||||
factory.MetaCode(")").Accepts(AcceptedCharacters.None))))),
|
factory.MetaCode(")")
|
||||||
|
.Accepts(AcceptedCharacters.None)
|
||||||
|
.As(SpanKind.Code))))),
|
||||||
new KeyValuePair<string, SyntaxTreeNode>(
|
new KeyValuePair<string, SyntaxTreeNode>(
|
||||||
"birthday",
|
"birthday",
|
||||||
factory.CodeMarkup("DateTime.Now")),
|
factory.CodeMarkup("DateTime.Now")),
|
||||||
|
|
@ -1653,13 +1709,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
"bound",
|
"bound",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
factory.Markup(" "),
|
factory.CodeMarkup(" "),
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
factory.Code("true")
|
factory.Code("true")
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||||
factory.Markup(" ")))
|
factory.CodeMarkup(" ")))
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
new RazorError[0]
|
new RazorError[0]
|
||||||
|
|
@ -1677,13 +1733,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
"bound",
|
"bound",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
factory.Markup(" "),
|
factory.CodeMarkup(" "),
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
factory.MetaCode("(")
|
||||||
|
.Accepts(AcceptedCharacters.None)
|
||||||
|
.As(SpanKind.Code),
|
||||||
factory.Code("true").AsExpression(),
|
factory.Code("true").AsExpression(),
|
||||||
factory.MetaCode(")").Accepts(AcceptedCharacters.None))),
|
factory.MetaCode(")")
|
||||||
factory.Markup(" ")))
|
.Accepts(AcceptedCharacters.None)
|
||||||
|
.As(SpanKind.Code))),
|
||||||
|
factory.CodeMarkup(" ")))
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
new RazorError[0]
|
new RazorError[0]
|
||||||
|
|
|
||||||
|
|
@ -1131,7 +1131,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
factory.Code("DateTime.Now")
|
factory.Code("DateTime.Now")
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
|
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
|
||||||
|
|
@ -1153,7 +1153,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
factory.Code("DateTime.Now")
|
factory.Code("DateTime.Now")
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
|
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
|
||||||
|
|
@ -1174,12 +1174,12 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
"bound",
|
"bound",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
factory.Markup("@").Accepts(AcceptedCharacters.None),
|
factory.CodeMarkup("@").Accepts(AcceptedCharacters.None),
|
||||||
factory.Markup("@").With(SpanChunkGenerator.Null).Accepts(AcceptedCharacters.None)),
|
factory.CodeMarkup("@").With(SpanChunkGenerator.Null).Accepts(AcceptedCharacters.None)),
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
factory.EmptyHtml(),
|
factory.EmptyHtml().As(SpanKind.Code),
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition().As(SpanKind.Code),
|
||||||
factory.Code("DateTime.Now")
|
factory.Code("DateTime.Now")
|
||||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
|
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue