Remove ability to specify ignored '@' in the middle of non-string

TagHelper bound attributes.

Fixes #436
This commit is contained in:
Pranav K 2015-08-14 10:03:58 -07:00
parent 156f859edc
commit 3361507c29
9 changed files with 663 additions and 75 deletions

View File

@ -1,6 +1,7 @@
// 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 System.Diagnostics;
using System.Linq;
@ -271,10 +272,13 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
var result = CreateTryParseResult(name, descriptors);
// 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;
result.AttributeValueNode =
CreateMarkupAttribute(attributeValueBuilder, result.IsBoundNonStringAttribute);
Span attributeValue = null;
if (afterEquals)
{
attributeValue = CreateMarkupAttribute(builder, result.IsBoundNonStringAttribute);
}
result.AttributeValueNode = attributeValue;
return result;
}
@ -362,12 +366,58 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
}
}
result.AttributeValueNode = ConvertToMarkupAttributeBlock(block, result.IsBoundNonStringAttribute);
var isFirstSpan = true;
result.AttributeValueNode = ConvertToMarkupAttributeBlock(
block,
(parentBlock, span) =>
{
// If the attribute was requested by a tag helper but the corresponding property was not a
// string, then treat its value as code. A non-string value can be any C# value so we need
// to ensure the SyntaxTreeNode reflects that.
if (result.IsBoundNonStringAttribute)
{
// For bound non-string attributes, we'll only allow a transition span to appear at the very
// beginning of the attribute expression. All later transitions would appear as code so that
// they are part of the generated output. E.g.
// key="@value" -> MyTagHelper.key = value
// key=" @value" -> MyTagHelper.key = @value
// key="1 + @case" -> MyTagHelper.key = 1 + @case
// key="@int + @case" -> MyTagHelper.key = int + @case
// key="@(a + b) -> MyTagHelper.key = a + b
// key="4 + @(a + b)" -> MyTagHelper.key = 4 + @(a + b)
if (isFirstSpan && span.Kind == SpanKind.Transition)
{
// do nothing.
}
else
{
var spanBuilder = new SpanBuilder(span);
if (parentBlock.Type == BlockType.Expression &&
(spanBuilder.Kind == SpanKind.Transition ||
spanBuilder.Kind == SpanKind.MetaCode))
{
// Change to a MarkupChunkGenerator so that the '@' \ parenthesis is generated as part of the output.
spanBuilder.ChunkGenerator = new MarkupChunkGenerator();
}
spanBuilder.Kind = SpanKind.Code;
span = spanBuilder.Build();
}
}
isFirstSpan = false;
return span;
});
return result;
}
private static Block ConvertToMarkupAttributeBlock(Block block, bool isBoundNonStringAttribute)
private static Block ConvertToMarkupAttributeBlock(
Block block,
Func<Block, Span, Span> createMarkupAttribute)
{
var blockBuilder = new BlockBuilder
{
@ -381,12 +431,11 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
if (child.IsBlock)
{
markupAttributeChild = ConvertToMarkupAttributeBlock((Block)child, isBoundNonStringAttribute);
markupAttributeChild = ConvertToMarkupAttributeBlock((Block)child, createMarkupAttribute);
}
else
{
var spanBuilder = new SpanBuilder((Span)child);
markupAttributeChild = CreateMarkupAttribute(spanBuilder, isBoundNonStringAttribute);
markupAttributeChild = createMarkupAttribute(block, (Span)child);
}
blockBuilder.Children.Add(markupAttributeChild);
@ -504,25 +553,19 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
return nodeStart + firstNonWhitespaceSymbol.Start;
}
private static SyntaxTreeNode CreateMarkupAttribute(SpanBuilder builder, bool isBoundNonStringAttribute)
private static Span CreateMarkupAttribute(SpanBuilder builder, bool isBoundNonStringAttribute)
{
Span value = null;
Debug.Assert(builder != null);
// Builder will be null in the case of minimized attributes
if (builder != null)
// If the attribute was requested by a tag helper but the corresponding property was not a string,
// then treat its value as code. A non-string value can be any C# value so we need to ensure the
// SyntaxTreeNode reflects that.
if (isBoundNonStringAttribute)
{
// If the attribute was requested by a tag helper but the corresponding property was not a string,
// then treat its value as code. A non-string value can be any C# value so we need to ensure the
// SyntaxTreeNode reflects that.
if (isBoundNonStringAttribute)
{
builder.Kind = SpanKind.Code;
}
value = builder.Build();
builder.Kind = SpanKind.Code;
}
return value;
return builder.Build();
}
private static bool IsNullOrWhitespaceAttributeValue(SyntaxTreeNode attributeValue)

View File

@ -405,7 +405,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
get
{
// Test resource name, baseline resource name, expected TagHelperDescriptors, expected LineMappings
return new TheoryData<string, string, IEnumerable<TagHelperDescriptor>, List<LineMapping>>
return new TheoryData<string, string, IEnumerable<TagHelperDescriptor>, IList<LineMapping>>
{
{
"SingleTagHelper",
@ -622,18 +622,34 @@ namespace Microsoft.AspNet.Razor.Test.Generator
characterOffsetIndex: 14,
contentLength: 21),
BuildLineMapping(
documentAbsoluteIndex: 837,
documentAbsoluteIndex: 836,
documentLineIndex: 22,
documentCharacterOffsetIndex: 30,
documentCharacterOffsetIndex: 29,
generatedAbsoluteIndex: 3832,
generatedLineIndex: 154,
generatedCharacterOffsetIndex: 28,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 837,
documentLineIndex: 22,
documentCharacterOffsetIndex: 30,
generatedAbsoluteIndex: 3833,
generatedLineIndex: 154,
generatedCharacterOffsetIndex: 29,
contentLength: 7),
BuildLineMapping(
documentAbsoluteIndex: 844,
documentLineIndex: 22,
documentCharacterOffsetIndex: 37,
generatedAbsoluteIndex: 3840,
generatedLineIndex: 154,
generatedCharacterOffsetIndex: 36,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 711,
documentLineIndex: 20,
documentCharacterOffsetIndex: 39,
generatedAbsoluteIndex: 4007,
generatedAbsoluteIndex: 4009,
generatedLineIndex: 160,
generatedCharacterOffsetIndex: 38,
contentLength: 23),
@ -641,38 +657,62 @@ namespace Microsoft.AspNet.Razor.Test.Generator
documentAbsoluteIndex: 734,
documentLineIndex: 20,
documentCharacterOffsetIndex: 62,
generatedAbsoluteIndex: 4030,
generatedAbsoluteIndex: 4032,
generatedLineIndex: 160,
generatedCharacterOffsetIndex: 61,
contentLength: 7),
BuildLineMapping(
documentAbsoluteIndex: 976,
documentLineIndex: 25,
documentCharacterOffsetIndex: 61,
generatedAbsoluteIndex: 4306,
generatedLineIndex: 167,
generatedCharacterOffsetIndex: 60,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 977,
documentLineIndex: 25,
documentCharacterOffsetIndex: 62,
generatedAbsoluteIndex: 4304,
generatedAbsoluteIndex: 4307,
generatedLineIndex: 167,
generatedCharacterOffsetIndex: 60,
generatedCharacterOffsetIndex: 61,
contentLength: 30),
BuildLineMapping(
documentAbsoluteIndex: 1007,
documentLineIndex: 25,
documentCharacterOffsetIndex: 92,
generatedAbsoluteIndex: 4337,
generatedLineIndex: 167,
generatedCharacterOffsetIndex: 91,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 879,
documentLineIndex: 24,
documentCharacterOffsetIndex: 16,
generatedAbsoluteIndex: 4483,
generatedAbsoluteIndex: 4487,
generatedLineIndex: 173,
generatedCharacterOffsetIndex: 19,
contentLength: 8),
BuildLineMapping(
documentAbsoluteIndex: 887,
documentLineIndex: 24,
documentCharacterOffsetIndex: 24,
generatedAbsoluteIndex: 4495,
generatedLineIndex: 173,
generatedCharacterOffsetIndex: 27,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 888,
documentLineIndex: 24,
documentCharacterOffsetIndex: 25,
generatedAbsoluteIndex: 4491,
generatedAbsoluteIndex: 4496,
generatedLineIndex: 173,
generatedCharacterOffsetIndex: 27,
generatedCharacterOffsetIndex: 28,
contentLength: 23),
BuildLineMapping(
documentAbsoluteIndex: 1106,
documentLineIndex: 28,
generatedAbsoluteIndex: 4749,
generatedAbsoluteIndex: 4754,
generatedLineIndex: 180,
characterOffsetIndex: 28,
contentLength: 30),
@ -680,45 +720,73 @@ namespace Microsoft.AspNet.Razor.Test.Generator
documentAbsoluteIndex: 1044,
documentLineIndex: 27,
documentCharacterOffsetIndex: 16,
generatedAbsoluteIndex: 4928,
generatedAbsoluteIndex: 4933,
generatedLineIndex: 186,
generatedCharacterOffsetIndex: 19,
contentLength: 30),
BuildLineMapping(
documentAbsoluteIndex: 1234,
documentLineIndex: 31,
generatedAbsoluteIndex: 5193,
generatedAbsoluteIndex: 5198,
generatedLineIndex: 193,
characterOffsetIndex: 28,
contentLength: 3),
BuildLineMapping(
documentAbsoluteIndex: 1237,
documentLineIndex: 31,
generatedAbsoluteIndex: 5201,
generatedLineIndex: 193,
characterOffsetIndex: 31,
contentLength: 2),
BuildLineMapping(
documentAbsoluteIndex: 1239,
documentLineIndex: 31,
documentCharacterOffsetIndex: 33,
generatedAbsoluteIndex: 5196,
generatedAbsoluteIndex: 5203,
generatedLineIndex: 193,
generatedCharacterOffsetIndex: 31,
characterOffsetIndex: 33,
contentLength: 27),
BuildLineMapping(
documentAbsoluteIndex: 1266,
documentLineIndex: 31,
generatedAbsoluteIndex: 5230,
generatedLineIndex: 193,
characterOffsetIndex: 60,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 1267,
documentLineIndex: 31,
documentCharacterOffsetIndex: 61,
generatedAbsoluteIndex: 5223,
generatedAbsoluteIndex: 5231,
generatedLineIndex: 193,
generatedCharacterOffsetIndex: 58,
characterOffsetIndex: 61,
contentLength: 10),
BuildLineMapping(
documentAbsoluteIndex: 1171,
documentLineIndex: 30,
documentCharacterOffsetIndex: 17,
generatedAbsoluteIndex: 5390,
generatedLineIndex: 199,
generatedCharacterOffsetIndex: 19,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 1172,
documentLineIndex: 30,
documentCharacterOffsetIndex: 18,
generatedAbsoluteIndex: 5382,
generatedAbsoluteIndex: 5391,
generatedLineIndex: 199,
generatedCharacterOffsetIndex: 19,
generatedCharacterOffsetIndex: 20,
contentLength: 29),
BuildLineMapping(
documentAbsoluteIndex: 1201,
documentLineIndex: 30,
documentCharacterOffsetIndex: 47,
generatedAbsoluteIndex: 5420,
generatedLineIndex: 199,
generatedCharacterOffsetIndex: 49,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 1309,
documentLineIndex: 34,
generatedAbsoluteIndex: 5482,
generatedAbsoluteIndex: 5492,
generatedLineIndex: 204,
characterOffsetIndex: 0,
contentLength: 1),
@ -1204,6 +1272,139 @@ namespace Microsoft.AspNet.Razor.Test.Generator
contentLength: 2),
}
},
{
"TransitionsInTagHelperAttributes",
"TransitionsInTagHelperAttributes.DesignTime",
DefaultPAndInputTagHelperDescriptors,
new[]
{
BuildLineMapping(
documentAbsoluteIndex: 14,
documentLineIndex: 0,
generatedAbsoluteIndex: 509,
generatedLineIndex: 15,
characterOffsetIndex: 14,
contentLength: 17),
BuildLineMapping(
documentAbsoluteIndex: 35,
documentLineIndex: 1,
generatedAbsoluteIndex: 947,
generatedLineIndex: 33,
characterOffsetIndex: 2,
contentLength: 59),
BuildLineMapping(
documentAbsoluteIndex: 122,
documentLineIndex: 6,
generatedAbsoluteIndex: 1172,
generatedLineIndex: 42,
characterOffsetIndex: 23,
contentLength: 4),
BuildLineMapping(
documentAbsoluteIndex: 157,
documentLineIndex: 7,
documentCharacterOffsetIndex: 12,
generatedAbsoluteIndex: 1326,
generatedLineIndex: 48,
generatedCharacterOffsetIndex: 6,
contentLength: 6),
BuildLineMapping(
documentAbsoluteIndex: 171,
documentLineIndex: 7,
generatedAbsoluteIndex: 1443,
generatedLineIndex: 53,
characterOffsetIndex: 26,
contentLength: 2),
BuildLineMapping(
documentAbsoluteIndex: 202,
documentLineIndex: 8,
generatedAbsoluteIndex: 1610,
generatedLineIndex: 59,
characterOffsetIndex: 21,
contentLength: 5),
BuildLineMapping(
documentAbsoluteIndex: 207,
documentLineIndex: 8,
generatedAbsoluteIndex: 1615,
generatedLineIndex: 59,
characterOffsetIndex: 26,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 208,
documentLineIndex: 8,
generatedAbsoluteIndex: 1616,
generatedLineIndex: 59,
characterOffsetIndex: 27,
contentLength: 3),
BuildLineMapping(
documentAbsoluteIndex: 241,
documentLineIndex: 9,
documentCharacterOffsetIndex: 22,
generatedAbsoluteIndex: 1785,
generatedLineIndex: 65,
generatedCharacterOffsetIndex: 21,
contentLength: 3),
BuildLineMapping(
documentAbsoluteIndex: 274,
documentLineIndex: 10,
documentCharacterOffsetIndex: 22,
generatedAbsoluteIndex: 1954,
generatedLineIndex: 71,
generatedCharacterOffsetIndex: 21,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 275,
documentLineIndex: 10,
documentCharacterOffsetIndex: 23,
generatedAbsoluteIndex: 1955,
generatedLineIndex: 71,
generatedCharacterOffsetIndex: 22,
contentLength: 4),
BuildLineMapping(
documentAbsoluteIndex: 279,
documentLineIndex: 10,
documentCharacterOffsetIndex: 27,
generatedAbsoluteIndex: 1959,
generatedLineIndex: 71,
generatedCharacterOffsetIndex: 26,
contentLength: 1),
BuildLineMapping(
documentAbsoluteIndex: 307,
documentLineIndex: 11,
documentCharacterOffsetIndex: 19,
generatedAbsoluteIndex: 2111,
generatedLineIndex: 77,
generatedCharacterOffsetIndex: 6,
contentLength: 6),
BuildLineMapping(
documentAbsoluteIndex: 321,
documentLineIndex: 11,
generatedAbsoluteIndex: 2236,
generatedLineIndex: 82,
characterOffsetIndex: 33,
contentLength: 4),
BuildLineMapping(
documentAbsoluteIndex: 325,
documentLineIndex: 11,
generatedAbsoluteIndex: 2240,
generatedLineIndex: 82,
characterOffsetIndex: 37,
contentLength: 2),
BuildLineMapping(
documentAbsoluteIndex: 327,
documentLineIndex: 11,
generatedAbsoluteIndex: 2242,
generatedLineIndex: 82,
characterOffsetIndex: 39,
contentLength: 8),
BuildLineMapping(
documentAbsoluteIndex: 335,
documentLineIndex: 11,
generatedAbsoluteIndex: 2250,
generatedLineIndex: 82,
characterOffsetIndex: 47,
contentLength: 1),
}
},
};
}
}
@ -1213,7 +1414,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
public void TagHelpers_GenerateExpectedDesignTimeOutput(string testName,
string baseLineName,
IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
List<LineMapping> expectedDesignTimePragmas)
IList<LineMapping> expectedDesignTimePragmas)
{
// Act & Assert
RunTagHelperTest(testName,
@ -1248,6 +1449,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
},
{ "DuplicateAttributeTagHelpers", null, DefaultPAndInputTagHelperDescriptors },
{ "DynamicAttributeTagHelpers", null, DynamicAttributeTagHelpers_Descriptors },
{ "TransitionsInTagHelperAttributes", null, DefaultPAndInputTagHelperDescriptors }
};
}
}

View File

@ -782,6 +782,48 @@ namespace Microsoft.AspNet.Razor.TagHelpers
factory.CodeMarkup("DateTime.Now"))
}))
},
{
"<person age=\"@DateTime.Now.Year\" />",
new MarkupBlock(
new MarkupTagHelperBlock("person",
TagMode.SelfClosing,
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>
{
new KeyValuePair<string, SyntaxTreeNode>(
"age",
new MarkupBlock(
new MarkupBlock(
new ExpressionBlock(
factory.CodeTransition(),
factory
.Code("DateTime.Now.Year")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
}))
},
{
"<person age=\" @DateTime.Now.Year\" />",
new MarkupBlock(
new MarkupTagHelperBlock("person",
TagMode.SelfClosing,
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>
{
new KeyValuePair<string, SyntaxTreeNode>(
"age",
new MarkupBlock(
new MarkupBlock(
factory.CodeMarkup(" "),
new ExpressionBlock(
factory
.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory
.Code("DateTime.Now.Year")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
}))
},
{
"<person name=\"John\" />",
new MarkupBlock(
@ -819,7 +861,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new MarkupBlock(
factory.CodeMarkup(" "),
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory
.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory
.Code("value")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
@ -832,7 +877,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
factory.CodeMarkup("(bool)"),
new MarkupBlock(
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory
.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory
.Code("Bag[\"val\"]")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
@ -848,11 +896,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new MarkupBlock(
factory.CodeMarkup(" "),
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory
.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))
factory
.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory
.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))
))
}))
},
@ -928,21 +979,27 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"age",
new MarkupBlock(
new MarkupBlock(
factory.CodeMarkup("@").Accepts(AcceptedCharacters.None),
factory.CodeMarkup("@")
.Accepts(AcceptedCharacters.None)
.With(new MarkupChunkGenerator()),
factory.CodeMarkup("@")
.With(SpanChunkGenerator.Null)
.Accepts(AcceptedCharacters.None)),
new MarkupBlock(
factory.EmptyHtml().As(SpanKind.Code),
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory.MetaCode("(")
.Accepts(AcceptedCharacters.None)
.As(SpanKind.Code),
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory.Code("11+1").AsExpression(),
factory.MetaCode(")")
.Accepts(AcceptedCharacters.None)
.As(SpanKind.Code))))),
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()))))),
new KeyValuePair<string, SyntaxTreeNode>(
"birthday",
factory.CodeMarkup("DateTime.Now")),
@ -1950,7 +2007,9 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new MarkupBlock(
factory.CodeMarkup(" "),
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory.Code("true")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace))),
@ -1974,14 +2033,18 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new MarkupBlock(
factory.CodeMarkup(" "),
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory.MetaCode("(")
.Accepts(AcceptedCharacters.None)
.As(SpanKind.Code),
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory.Code("true").AsExpression(),
factory.MetaCode(")")
.Accepts(AcceptedCharacters.None)
.As(SpanKind.Code))),
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()))),
factory.CodeMarkup(" ")))
}
})),

View File

@ -1254,7 +1254,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
new MarkupBlock(
new MarkupBlock(
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory.CodeTransition(),
factory.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
@ -1276,7 +1276,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
new MarkupBlock(
new MarkupBlock(
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory.CodeTransition(),
factory.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))))
@ -1297,12 +1297,21 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
"bound",
new MarkupBlock(
new MarkupBlock(
factory.CodeMarkup("@").Accepts(AcceptedCharacters.None),
factory.CodeMarkup("@").With(SpanChunkGenerator.Null).Accepts(AcceptedCharacters.None)),
factory
.CodeMarkup("@")
.With(new MarkupChunkGenerator())
.Accepts(AcceptedCharacters.None),
factory
.CodeMarkup("@")
.With(SpanChunkGenerator.Null)
.Accepts(AcceptedCharacters.None)),
new MarkupBlock(
factory.EmptyHtml().As(SpanKind.Code),
new ExpressionBlock(
factory.CodeTransition().As(SpanKind.Code),
factory
.CodeTransition()
.As(SpanKind.Code)
.With(new MarkupChunkGenerator()),
factory.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))))

View File

@ -152,7 +152,7 @@ __o = DateTime.Now;
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
#line 23 "ComplexTagHelpers.cshtml"
__InputTagHelper2.Checked = @object;
__InputTagHelper2.Checked = (@object);
#line default
#line hidden
@ -165,13 +165,13 @@ __InputTagHelper2.Checked = @object;
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
#line 26 "ComplexTagHelpers.cshtml"
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014;
__InputTagHelper2.Checked = (DateTimeOffset.Now.Year > 2014);
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 25 "ComplexTagHelpers.cshtml"
__PTagHelper.Age = -1970 + DateTimeOffset.Now.Year;
__PTagHelper.Age = -1970 + @DateTimeOffset.Now.Year;
#line default
#line hidden
@ -191,13 +191,13 @@ __PTagHelper.Age = DateTimeOffset.Now.Year - 1970;
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
#line 32 "ComplexTagHelpers.cshtml"
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014 ;
__InputTagHelper2.Checked = @( DateTimeOffset.Now.Year ) > 2014 ;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 31 "ComplexTagHelpers.cshtml"
__PTagHelper.Age = "My age is this long.".Length;
__PTagHelper.Age = ("My age is this long.".Length);
#line default
#line hidden

View File

@ -276,7 +276,7 @@ if(true) {
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
#line 23 "ComplexTagHelpers.cshtml"
__InputTagHelper2.Checked = @object;
__InputTagHelper2.Checked = (@object);
#line default
#line hidden
@ -323,7 +323,7 @@ __InputTagHelper2.Checked = @object;
__tagHelperExecutionContext.AddHtmlAttribute("unbound", Html.Raw("hello"));
__tagHelperExecutionContext.AddHtmlAttribute("unbound", Html.Raw("world"));
#line 26 "ComplexTagHelpers.cshtml"
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014;
__InputTagHelper2.Checked = (DateTimeOffset.Now.Year > 2014);
#line default
#line hidden
@ -341,7 +341,7 @@ __InputTagHelper2.Checked = @object;
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
#line 25 "ComplexTagHelpers.cshtml"
__PTagHelper.Age = -1970 + DateTimeOffset.Now.Year;
__PTagHelper.Age = -1970 + @DateTimeOffset.Now.Year;
#line default
#line hidden
@ -409,7 +409,7 @@ __PTagHelper.Age = DateTimeOffset.Now.Year - 1970;
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
#line 32 "ComplexTagHelpers.cshtml"
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014 ;
__InputTagHelper2.Checked = @( DateTimeOffset.Now.Year ) > 2014 ;
#line default
#line hidden
@ -427,7 +427,7 @@ __InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014 ;
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
#line 31 "ComplexTagHelpers.cshtml"
__PTagHelper.Age = "My age is this long.".Length;
__PTagHelper.Age = ("My age is this long.".Length);
#line default
#line hidden

View File

@ -0,0 +1,90 @@
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class TransitionsInTagHelperAttributes
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
string __tagHelperDirectiveSyntaxHelper = null;
__tagHelperDirectiveSyntaxHelper =
#line 1 "TransitionsInTagHelperAttributes.cshtml"
"something, nice"
#line default
#line hidden
;
#pragma warning restore 219
}
#line hidden
private PTagHelper __PTagHelper = null;
#line hidden
public TransitionsInTagHelperAttributes()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
#line 2 "TransitionsInTagHelperAttributes.cshtml"
var @class = "container-fluid";
var @int = 1;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 7 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 1337;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 8 "TransitionsInTagHelperAttributes.cshtml"
__o = @class;
#line default
#line hidden
#line 8 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 42;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 9 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 42 + @int;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 10 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = int;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 11 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = (@int);
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
#line 12 "TransitionsInTagHelperAttributes.cshtml"
__o = @class;
#line default
#line hidden
#line 12 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 4 * @(@int + 2);
#line default
#line hidden
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,169 @@
#pragma checksum "TransitionsInTagHelperAttributes.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "050ce5cabf326eaa117aa12f5a1a10dbf82a8917"
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class TransitionsInTagHelperAttributes
{
#line hidden
#pragma warning disable 0414
private TagHelperContent __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
#line hidden
public TransitionsInTagHelperAttributes()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner();
#line 2 "TransitionsInTagHelperAttributes.cshtml"
var @class = "container-fluid";
var @int = 1;
#line default
#line hidden
Instrumentation.BeginContext(95, 4, true);
WriteLiteral("\r\n\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
Instrumentation.BeginContext(128, 11, true);
WriteLiteral("Body of Tag");
Instrumentation.EndContext();
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
AddHtmlAttributeValues("class", __tagHelperExecutionContext,
Tuple.Create(Tuple.Create("", 109), Tuple.Create<System.Object, System.Int32>(new Template((__razor_attribute_value_writer) => {
}
), 109), false));
#line 7 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 1337;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(99, 44, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(143, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
AddHtmlAttributeValues("class", __tagHelperExecutionContext,
Tuple.Create(Tuple.Create("", 155), Tuple.Create<System.Object, System.Int32>(@class, 155), false));
#line 8 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 42;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(145, 34, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(179, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("test"));
#line 9 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 42 + @int;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(181, 36, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(217, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("test"));
#line 10 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = int;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(219, 31, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(250, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("test"));
#line 11 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = (@int);
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(252, 34, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(286, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
AddHtmlAttributeValues("class", __tagHelperExecutionContext, Tuple.Create(Tuple.Create("", 298), Tuple.Create("custom-", 298), true),
Tuple.Create(Tuple.Create("", 305), Tuple.Create<System.Object, System.Int32>(@class, 305), false));
#line 12 "TransitionsInTagHelperAttributes.cshtml"
__PTagHelper.Age = 4 * @(@int + 2);
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(288, 54, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(342, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,12 @@
@addTagHelper "something, nice"
@{
var @class = "container-fluid";
var @int = 1;
}
<p class="@class" age="1337">Body of Tag</p>
<p class="@(@class)" age="42"></p>
<p class="test" age="42 + @int"></p>
<p class="test" age="@int"></p>
<p class="test" age="@(@int)"></p>
<p class="custom-@(@class)" age="4 * @(@int + 2)"></p>