Add tests to validate minimized attributes.
- Added parse level rewriting tests to validate new TagHelper rewritten structures for minimized attributes. - Updated existing parser tests to understand minimized attributes. - Added codegen test to validate understanding of minimized attributes. - Added TagHelperExecutionContext tests to validate maintaining of runtime TagHelperOutput tests. - Refactored part of the TagHelperParseTreeRewriterTest file into a base class file so we can make better rewriting tests. #220
This commit is contained in:
parent
6fa3e405af
commit
0882ff4a13
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Internal.Web.Utils;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -26,16 +25,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Normal comparer (TagHelperAttribute.Equals()) doesn't care about the Name case, in tests we do.
|
// Normal comparer (TagHelperAttribute.Equals()) doesn't care about the Name case, in tests we do.
|
||||||
return attributeX != null &&
|
return attributeX != null &&
|
||||||
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
|
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
|
||||||
Equals(attributeX.Value, attributeY.Value);
|
attributeX.Minimized == attributeY.Minimized &&
|
||||||
|
(attributeX.Minimized || Equals(attributeX.Value, attributeY.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCode(IReadOnlyTagHelperAttribute attribute)
|
public int GetHashCode(IReadOnlyTagHelperAttribute attribute)
|
||||||
{
|
{
|
||||||
return HashCodeCombiner
|
return attribute.GetHashCode();
|
||||||
.Start()
|
|
||||||
.Add(attribute.Name, StringComparer.Ordinal)
|
|
||||||
.Add(attribute.Value)
|
|
||||||
.CombinedHash;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Arrange & Act
|
// Arrange & Act
|
||||||
var executionContext = new TagHelperExecutionContext("p", selfClosing);
|
var executionContext = new TagHelperExecutionContext("p", selfClosing);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(selfClosing, executionContext.SelfClosing);
|
Assert.Equal(selfClosing, executionContext.SelfClosing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,6 +202,54 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
CaseSensitiveTagHelperAttributeComparer.Default);
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddMinimizedHtmlAttribute_MaintainsHTMLAttributes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var executionContext = new TagHelperExecutionContext("input", selfClosing: true);
|
||||||
|
var expectedAttributes = new TagHelperAttributeList
|
||||||
|
{
|
||||||
|
["checked"] = new TagHelperAttribute { Name = "checked", Minimized = true },
|
||||||
|
["visible"] = new TagHelperAttribute { Name = "visible", Minimized = true }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
executionContext.AddMinimizedHtmlAttribute("checked");
|
||||||
|
executionContext.AddMinimizedHtmlAttribute("visible");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(
|
||||||
|
expectedAttributes,
|
||||||
|
executionContext.HTMLAttributes,
|
||||||
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddMinimizedHtmlAttribute_MaintainsHTMLAttributes_SomeMinimized()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var executionContext = new TagHelperExecutionContext("input", selfClosing: true);
|
||||||
|
var expectedAttributes = new TagHelperAttributeList
|
||||||
|
{
|
||||||
|
{ "class", "btn" },
|
||||||
|
{ "foo", "bar" }
|
||||||
|
};
|
||||||
|
expectedAttributes.Add(new TagHelperAttribute { Name = "checked", Minimized = true });
|
||||||
|
expectedAttributes.Add(new TagHelperAttribute { Name = "visible", Minimized = true });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
executionContext.AddHtmlAttribute("class", "btn");
|
||||||
|
executionContext.AddHtmlAttribute("foo", "bar");
|
||||||
|
executionContext.AddMinimizedHtmlAttribute("checked");
|
||||||
|
executionContext.AddMinimizedHtmlAttribute("visible");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(
|
||||||
|
expectedAttributes,
|
||||||
|
executionContext.HTMLAttributes,
|
||||||
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TagHelperExecutionContext_MaintainsAllAttributes()
|
public void TagHelperExecutionContext_MaintainsAllAttributes()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
|
|
@ -19,12 +20,28 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
return EscapedMarkupTagBlock(prefix, suffix, AcceptedCharacters.Any);
|
return EscapedMarkupTagBlock(prefix, suffix, AcceptedCharacters.Any);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block EscapedMarkupTagBlock(string prefix, string suffix, AcceptedCharacters acceptedCharacters)
|
public Block EscapedMarkupTagBlock(string prefix, string suffix, params SyntaxTreeNode[] children)
|
||||||
{
|
{
|
||||||
return new MarkupTagBlock(
|
return EscapedMarkupTagBlock(prefix, suffix, AcceptedCharacters.Any, children);
|
||||||
_factory.Markup(prefix),
|
}
|
||||||
_factory.BangEscape(),
|
|
||||||
_factory.Markup(suffix).Accepts(acceptedCharacters));
|
public Block EscapedMarkupTagBlock(
|
||||||
|
string prefix,
|
||||||
|
string suffix,
|
||||||
|
AcceptedCharacters acceptedCharacters,
|
||||||
|
params SyntaxTreeNode[] children)
|
||||||
|
{
|
||||||
|
var newChildren = new List<SyntaxTreeNode>(
|
||||||
|
new SyntaxTreeNode[]
|
||||||
|
{
|
||||||
|
_factory.Markup(prefix),
|
||||||
|
_factory.BangEscape(),
|
||||||
|
_factory.Markup(suffix).Accepts(acceptedCharacters)
|
||||||
|
});
|
||||||
|
|
||||||
|
newChildren.AddRange(children);
|
||||||
|
|
||||||
|
return new MarkupTagBlock(newChildren.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block MarkupTagBlock(string content)
|
public Block MarkupTagBlock(string content)
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
if (actual == null)
|
if (actual == null)
|
||||||
{
|
{
|
||||||
AddNullActualError(collector, actual, expected);
|
AddNullActualError(collector, actual, expected);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual.IsBlock != expected.IsBlock)
|
if (actual.IsBlock != expected.IsBlock)
|
||||||
|
|
@ -335,7 +336,14 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
collector.AddMessage("{0} - PASSED :: Attribute names match", expected.Key);
|
collector.AddMessage("{0} - PASSED :: Attribute names match", expected.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
EvaluateSyntaxTreeNode(collector, actual.Value, expected.Value);
|
if (actual.Value == null && expected.Value == null)
|
||||||
|
{
|
||||||
|
collector.AddMessage("{0} - PASSED :: Minimized attribute values match", expected.Key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EvaluateSyntaxTreeNode(collector, actual.Value, expected.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EvaluateSpan(ErrorCollector collector, Span actual, Span expected)
|
private static void EvaluateSpan(ErrorCollector collector, Span actual, Span expected)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,44 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
private static IEnumerable<TagHelperDescriptor> PrefixedPAndInputTagHelperDescriptors
|
private static IEnumerable<TagHelperDescriptor> PrefixedPAndInputTagHelperDescriptors
|
||||||
=> BuildPAndInputTagHelperDescriptors("THS");
|
=> BuildPAndInputTagHelperDescriptors("THS");
|
||||||
|
|
||||||
|
private static IEnumerable<TagHelperDescriptor> MinimizedTagHelpers_Descriptors
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new TagHelperDescriptor(
|
||||||
|
tagName: "*",
|
||||||
|
typeName: "CatchAllTagHelper",
|
||||||
|
assemblyName: "SomeAssembly",
|
||||||
|
attributes: new[]
|
||||||
|
{
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"catchall-bound-string",
|
||||||
|
"BoundRequiredString",
|
||||||
|
typeof(string).FullName),
|
||||||
|
},
|
||||||
|
requiredAttributes: new[] { "catchall-unbound-required" }),
|
||||||
|
new TagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "SomeAssembly",
|
||||||
|
attributes: new[]
|
||||||
|
{
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"input-bound-required-string",
|
||||||
|
"BoundRequiredString",
|
||||||
|
typeof(string).FullName),
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"input-bound-string",
|
||||||
|
"BoundString",
|
||||||
|
typeof(string).FullName)
|
||||||
|
},
|
||||||
|
requiredAttributes: new[] { "input-bound-required-string", "input-unbound-required" }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerable<TagHelperDescriptor> DuplicateTargetTagHelperDescriptors
|
private static IEnumerable<TagHelperDescriptor> DuplicateTargetTagHelperDescriptors
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -207,6 +245,20 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
AttributeTargetingTagHelperDescriptors,
|
AttributeTargetingTagHelperDescriptors,
|
||||||
AttributeTargetingTagHelperDescriptors,
|
AttributeTargetingTagHelperDescriptors,
|
||||||
true
|
true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MinimizedTagHelpers",
|
||||||
|
"MinimizedTagHelpers",
|
||||||
|
MinimizedTagHelpers_Descriptors,
|
||||||
|
MinimizedTagHelpers_Descriptors,
|
||||||
|
false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MinimizedTagHelpers",
|
||||||
|
"MinimizedTagHelpers.DesignTime",
|
||||||
|
MinimizedTagHelpers_Descriptors,
|
||||||
|
MinimizedTagHelpers_Descriptors,
|
||||||
|
true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,9 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href=", 2, 0, 2), suffix: new LocationTagged<string>(string.Empty, 11, 0, 11)),
|
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href=", 2, 0, 2), suffix: new LocationTagged<string>(string.Empty, 11, 0, 11)),
|
||||||
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
||||||
Factory.Markup("Foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(string.Empty, 8, 0, 8), value: new LocationTagged<string>("Foo", 8, 0, 8)))),
|
Factory.Markup("Foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(string.Empty, 8, 0, 8), value: new LocationTagged<string>("Foo", 8, 0, 8)))),
|
||||||
Factory.Markup(" Bar Baz />").Accepts(AcceptedCharacters.None))));
|
new MarkupBlock(Factory.Markup(" Bar")),
|
||||||
|
new MarkupBlock(Factory.Markup(" Baz")),
|
||||||
|
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,11 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||||
ParseDocumentTest("<div ><p class = 'bar'> Foo </p></div >",
|
ParseDocumentTest("<div ><p class = 'bar'> Foo </p></div >",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
BlockFactory.MarkupTagBlock("<div >"),
|
BlockFactory.MarkupTagBlock("<div >"),
|
||||||
BlockFactory.MarkupTagBlock("<p class = 'bar'>"),
|
new MarkupTagBlock(
|
||||||
|
Factory.Markup("<p"),
|
||||||
|
new MarkupBlock(
|
||||||
|
Factory.Markup(" class")),
|
||||||
|
Factory.Markup(" = 'bar'>")),
|
||||||
Factory.Markup(" Foo "),
|
Factory.Markup(" Foo "),
|
||||||
BlockFactory.MarkupTagBlock("</p>"),
|
BlockFactory.MarkupTagBlock("</p>"),
|
||||||
BlockFactory.MarkupTagBlock("</div >")));
|
BlockFactory.MarkupTagBlock("</div >")));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,766 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
using Microsoft.AspNet.Razor.Test.Framework;
|
||||||
|
using Microsoft.AspNet.Razor.Test.TagHelpers;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
|
{
|
||||||
|
public class TagHelperBlockRewriterTest : TagHelperRewritingTestBase
|
||||||
|
{
|
||||||
|
public static TheoryData MinimizedAttributeData_Document
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
var noErrors = new RazorError[0];
|
||||||
|
var errorFormat = "Attribute '{0}' on tag helper element '{1}' requires a value. Tag helper bound " +
|
||||||
|
"attributes of type '{2}' cannot be empty or contain only whitespace.";
|
||||||
|
var stringType = typeof(string).FullName;
|
||||||
|
var intType = typeof(int).FullName;
|
||||||
|
var expressionString = "@DateTime.Now + 1";
|
||||||
|
var expression = new MarkupBlock(
|
||||||
|
new MarkupBlock(
|
||||||
|
new ExpressionBlock(
|
||||||
|
factory.CodeTransition(),
|
||||||
|
factory.Code("DateTime.Now")
|
||||||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||||
|
factory.Markup(" +"),
|
||||||
|
factory.Markup(" 1"));
|
||||||
|
|
||||||
|
// documentContent, expectedOutput, expectedErrors
|
||||||
|
return new TheoryData<string, MarkupBlock, RazorError[]>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"<input unbound-required />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
})),
|
||||||
|
noErrors
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-string></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-string", "p", stringType), 3, 0, 3, 12)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-string />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-string", "input", stringType), 7, 0, 7, 21)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-int />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-int", "input", intType), 7, 0, 7, 18)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-int></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
})),
|
||||||
|
new[] { new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 3, 0, 3, 9) }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input unbound-required bound-required-string />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 24,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 24,
|
||||||
|
length: 21)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-int bound-string></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 3, 0, 3, 9),
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-string", "p", stringType), 13, 0, 13, 12),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-int unbound-required bound-required-string />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-int", "input", intType), 7, 0, 7, 18),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 43,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 43,
|
||||||
|
length: 21)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-int bound-string bound-string></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 3, 0, 3, 9),
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-string", "p", stringType), 13, 0, 13, 12),
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-string", "p", stringType), 26, 0, 26, 12),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input unbound-required class='btn' />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
})),
|
||||||
|
noErrors
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-string class='btn'></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-string", "p", stringType),
|
||||||
|
absoluteIndex: 3,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 3,
|
||||||
|
length: 12)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input class='btn' unbound-required />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
})),
|
||||||
|
noErrors
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class='btn' bound-string></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-string", "p", stringType),
|
||||||
|
absoluteIndex: 15,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 15,
|
||||||
|
length: 12)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-string class='btn' />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 7,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 7,
|
||||||
|
length: 21)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input class='btn' bound-required-string />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 19,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 19,
|
||||||
|
length: 21)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-int class='btn' />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-int", "input", intType), 7, 0, 7, 18)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-int class='btn'></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 3, 0, 3, 9)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input class='btn' bound-required-int />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-required-int", "input", intType), 19, 0, 19, 18)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class='btn' bound-int></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", factory.Markup("btn")),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 15, 0, 15, 9)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$"<input class='{expressionString}' bound-required-int />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", expression),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-int", "input", intType), 33, 0, 33, 18)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$"<p class='{expressionString}' bound-int></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", expression),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 29, 0, 29, 9)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$"<input bound-required-int class='{expressionString}' bound-required-string " +
|
||||||
|
$"class='{expressionString}' unbound-required />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: true,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", expression),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", expression),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-int", "input", intType), 10, 0, 10, 18),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormat, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 57,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 57,
|
||||||
|
length: 21),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$"<p bound-int class='{expressionString}' bound-string " +
|
||||||
|
$"class='{expressionString}' bound-string></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", expression),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("class", expression),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-int", "p", intType), 6, 0, 6, 9),
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-string", "p", stringType), 44, 0, 44, 12),
|
||||||
|
new RazorError(string.Format(errorFormat, "bound-string", "p", stringType), 84, 0, 84, 12),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData MinimizedAttributeData_CSharpBlock
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
var documentData = MinimizedAttributeData_Document;
|
||||||
|
Func<Func<MarkupBlock>, MarkupBlock> buildStatementBlock = (insideBuilder) =>
|
||||||
|
{
|
||||||
|
return new MarkupBlock(
|
||||||
|
factory.EmptyHtml(),
|
||||||
|
new StatementBlock(
|
||||||
|
factory.CodeTransition(),
|
||||||
|
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||||
|
insideBuilder(),
|
||||||
|
factory.EmptyCSharp().AsStatement(),
|
||||||
|
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||||
|
factory.EmptyHtml());
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var data in documentData)
|
||||||
|
{
|
||||||
|
data[0] = $"@{{{data[0]}}}";
|
||||||
|
data[1] = buildStatementBlock(() => data[1] as MarkupBlock);
|
||||||
|
|
||||||
|
var errors = data[2] as RazorError[];
|
||||||
|
|
||||||
|
for (var i = 0; i < errors.Length; i++)
|
||||||
|
{
|
||||||
|
var error = errors[i];
|
||||||
|
error.Location = SourceLocation.Advance(error.Location, "@{");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return documentData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData MinimizedAttributeData_PartialTags
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
var noErrors = new RazorError[0];
|
||||||
|
var errorFormatUnclosed = "Found a malformed '{0}' tag helper. Tag helpers must have a start and " +
|
||||||
|
"end tag or be self closing.";
|
||||||
|
var errorFormatNoCloseAngle = "Missing close angle for tag helper '{0}'.";
|
||||||
|
var errorFormatNoValue = "Attribute '{0}' on tag helper element '{1}' requires a value. Tag helper bound " +
|
||||||
|
"attributes of type '{2}' cannot be empty or contain only whitespace.";
|
||||||
|
var stringType = typeof(string).FullName;
|
||||||
|
var intType = typeof(int).FullName;
|
||||||
|
|
||||||
|
// documentContent, expectedOutput, expectedErrors
|
||||||
|
return new TheoryData<string, MarkupBlock, RazorError[]>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"<input unbound-required",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "input"), SourceLocation.Zero),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-string",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 7,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 7,
|
||||||
|
length: 21),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-int",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-required-int", "input", intType),
|
||||||
|
absoluteIndex: 7,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 7,
|
||||||
|
length: 18),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-int unbound-required bound-required-string",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-required-int", "input", intType),
|
||||||
|
absoluteIndex: 7,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 7,
|
||||||
|
length: 18),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 43,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 43,
|
||||||
|
length: 21),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-string",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "p"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "p"), SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-string", "p", stringType), 3, 0, 3, 12),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-int",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "p"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "p"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatNoValue, "bound-int", "p", intType), 3, 0, 3, 9),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bound-int bound-string",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
})),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "p"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "p"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatNoValue, "bound-int", "p", intType), 3, 0, 3, 9),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-string", "p", stringType), 13, 0, 13, 12),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<input bound-required-int unbound-required bound-required-string<p bound-int bound-string",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("unbound-required", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-required-string", null),
|
||||||
|
},
|
||||||
|
children: new MarkupTagHelperBlock(
|
||||||
|
"p",
|
||||||
|
selfClosing: false,
|
||||||
|
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>()
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-int", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bound-string", null),
|
||||||
|
}))),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "input"), SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-required-int", "input", intType), 7, 0, 7, 18),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-required-string", "input", stringType),
|
||||||
|
absoluteIndex: 43,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 43,
|
||||||
|
length: 21),
|
||||||
|
new RazorError(string.Format(errorFormatNoCloseAngle, "p"), 64, 0, 64),
|
||||||
|
new RazorError(string.Format(errorFormatUnclosed, "p"), 64, 0, 64),
|
||||||
|
new RazorError(string.Format(errorFormatNoValue, "bound-int", "p", intType), 67, 0, 67, 9),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(errorFormatNoValue, "bound-string", "p", stringType),
|
||||||
|
absoluteIndex: 77,
|
||||||
|
lineIndex: 0,
|
||||||
|
columnIndex: 77,
|
||||||
|
length: 12),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(MinimizedAttributeData_Document))]
|
||||||
|
[MemberData(nameof(MinimizedAttributeData_CSharpBlock))]
|
||||||
|
[MemberData(nameof(MinimizedAttributeData_PartialTags))]
|
||||||
|
public void Rewrite_UnderstandsMinimizedAttributes(
|
||||||
|
string documentContent,
|
||||||
|
MarkupBlock expectedOutput,
|
||||||
|
RazorError[] expectedErrors)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptors = new TagHelperDescriptor[]
|
||||||
|
{
|
||||||
|
new TagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "SomeAssembly",
|
||||||
|
attributes: new TagHelperAttributeDescriptor[0],
|
||||||
|
requiredAttributes: new[] { "unbound-required" }),
|
||||||
|
new TagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "SomeAssembly",
|
||||||
|
attributes: new[]
|
||||||
|
{
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"bound-required-string",
|
||||||
|
"BoundRequiredString",
|
||||||
|
typeof(string).FullName)
|
||||||
|
},
|
||||||
|
requiredAttributes: new[] { "bound-required-string" }),
|
||||||
|
new TagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "SomeAssembly",
|
||||||
|
attributes: new[]
|
||||||
|
{
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"bound-required-int",
|
||||||
|
"BoundRequiredInt",
|
||||||
|
typeof(int).FullName)
|
||||||
|
},
|
||||||
|
requiredAttributes: new[] { "bound-required-int" }),
|
||||||
|
new TagHelperDescriptor(
|
||||||
|
tagName: "p",
|
||||||
|
typeName: "PTagHelper",
|
||||||
|
assemblyName: "SomeAssembly",
|
||||||
|
attributes: new[]
|
||||||
|
{
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"bound-string",
|
||||||
|
"BoundRequiredString",
|
||||||
|
typeof(string).FullName),
|
||||||
|
new TagHelperAttributeDescriptor(
|
||||||
|
"bound-int",
|
||||||
|
"BoundRequiredString",
|
||||||
|
typeof(int).FullName)
|
||||||
|
},
|
||||||
|
requiredAttributes: Enumerable.Empty<string>()),
|
||||||
|
};
|
||||||
|
var descriptorProvider = new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,16 +8,14 @@ using System.Linq;
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.Parser.TagHelpers.Internal;
|
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
using Microsoft.AspNet.Razor.Test.Framework;
|
using Microsoft.AspNet.Razor.Test.Framework;
|
||||||
using Microsoft.AspNet.Razor.Text;
|
using Microsoft.AspNet.Razor.Text;
|
||||||
using Microsoft.AspNet.Razor.Tokenizer;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
|
public class TagHelperParseTreeRewriterTest : TagHelperRewritingTestBase
|
||||||
{
|
{
|
||||||
public static TheoryData RequiredAttributeData
|
public static TheoryData RequiredAttributeData
|
||||||
{
|
{
|
||||||
|
|
@ -1949,7 +1947,11 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
"@{<!text /}",
|
"@{<!text /}",
|
||||||
buildPartialStatementBlock(
|
buildPartialStatementBlock(
|
||||||
() => new MarkupBlock(blockFactory.EscapedMarkupTagBlock("<", "text /}"))),
|
() => new MarkupBlock(
|
||||||
|
blockFactory.EscapedMarkupTagBlock(
|
||||||
|
"<",
|
||||||
|
"text /",
|
||||||
|
new MarkupBlock(factory.Markup("}"))))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
new RazorError(
|
new RazorError(
|
||||||
|
|
@ -2036,7 +2038,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
prefix: new LocationTagged<string>(string.Empty, 16, 0, 16),
|
prefix: new LocationTagged<string>(string.Empty, 16, 0, 16),
|
||||||
value: new LocationTagged<string>("btn", 16, 0, 16))),
|
value: new LocationTagged<string>("btn", 16, 0, 16))),
|
||||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||||
factory.Markup("}")))),
|
new MarkupBlock(factory.Markup("}"))))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
new RazorError(
|
new RazorError(
|
||||||
|
|
@ -2067,7 +2069,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
prefix: new LocationTagged<string>(string.Empty, 16, 0, 16),
|
prefix: new LocationTagged<string>(string.Empty, 16, 0, 16),
|
||||||
value: new LocationTagged<string>("btn", 16, 0, 16))),
|
value: new LocationTagged<string>("btn", 16, 0, 16))),
|
||||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||||
factory.Markup(" /}")))),
|
factory.Markup(" /"),
|
||||||
|
new MarkupBlock(factory.Markup("}"))))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
new RazorError(
|
new RazorError(
|
||||||
|
|
@ -2152,7 +2155,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
"@{<!p /}",
|
"@{<!p /}",
|
||||||
buildPartialStatementBlock(
|
buildPartialStatementBlock(
|
||||||
() => new MarkupBlock(blockFactory.EscapedMarkupTagBlock("<", "p /}"))),
|
() => new MarkupBlock(
|
||||||
|
blockFactory.EscapedMarkupTagBlock("<", "p /", new MarkupBlock(factory.Markup("}"))))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
new RazorError(
|
new RazorError(
|
||||||
|
|
@ -2274,7 +2278,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
prefix: new LocationTagged<string>(string.Empty, 13, 0, 13),
|
prefix: new LocationTagged<string>(string.Empty, 13, 0, 13),
|
||||||
value: new LocationTagged<string>("btn", 13, 0, 13))),
|
value: new LocationTagged<string>("btn", 13, 0, 13))),
|
||||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||||
factory.Markup("}")))),
|
new MarkupBlock(factory.Markup("}"))))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
new RazorError(
|
new RazorError(
|
||||||
|
|
@ -2305,7 +2309,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
prefix: new LocationTagged<string>(string.Empty, 13, 0, 13),
|
prefix: new LocationTagged<string>(string.Empty, 13, 0, 13),
|
||||||
value: new LocationTagged<string>("btn", 13, 0, 13))),
|
value: new LocationTagged<string>("btn", 13, 0, 13))),
|
||||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||||
factory.Markup(" /}")))),
|
factory.Markup(" /"),
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.Markup("}"))))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
new RazorError(
|
new RazorError(
|
||||||
|
|
@ -3353,6 +3359,11 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
"<p foo bar<strong>",
|
"<p foo bar<strong>",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagHelperBlock("p",
|
new MarkupTagHelperBlock("p",
|
||||||
|
new List<KeyValuePair<string, SyntaxTreeNode>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("foo", null),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("bar", null)
|
||||||
|
},
|
||||||
new MarkupTagHelperBlock("strong"))),
|
new MarkupTagHelperBlock("strong"))),
|
||||||
new []
|
new []
|
||||||
{
|
{
|
||||||
|
|
@ -3406,7 +3417,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
new KeyValuePair<string, SyntaxTreeNode>(
|
new KeyValuePair<string, SyntaxTreeNode>(
|
||||||
"class",
|
"class",
|
||||||
new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))),
|
new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))),
|
||||||
new KeyValuePair<string, SyntaxTreeNode>("foo", factory.Markup(string.Empty))
|
new KeyValuePair<string, SyntaxTreeNode>("foo", null)
|
||||||
},
|
},
|
||||||
new MarkupTagHelperBlock("strong"))),
|
new MarkupTagHelperBlock("strong"))),
|
||||||
new []
|
new []
|
||||||
|
|
@ -3429,6 +3440,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
new List<KeyValuePair<string, SyntaxTreeNode>>
|
new List<KeyValuePair<string, SyntaxTreeNode>>
|
||||||
{
|
{
|
||||||
new KeyValuePair<string, SyntaxTreeNode>("class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))),
|
new KeyValuePair<string, SyntaxTreeNode>("class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))),
|
||||||
|
new KeyValuePair<string, SyntaxTreeNode>("foo", null),
|
||||||
})),
|
})),
|
||||||
new RazorError[0]
|
new RazorError[0]
|
||||||
},
|
},
|
||||||
|
|
@ -4013,7 +4025,11 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
"< p />",
|
"< p />",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
blockFactory.MarkupTagBlock("< p />"))
|
new MarkupTagBlock(
|
||||||
|
factory.Markup("<"),
|
||||||
|
new MarkupBlock(
|
||||||
|
factory.Markup(" p")),
|
||||||
|
factory.Markup(" />")))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"<input <p />",
|
"<input <p />",
|
||||||
|
|
@ -5076,74 +5092,5 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div");
|
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunParseTreeRewriterTest(string documentContent,
|
|
||||||
MarkupBlock expectedOutput,
|
|
||||||
params string[] tagNames)
|
|
||||||
{
|
|
||||||
RunParseTreeRewriterTest(documentContent,
|
|
||||||
expectedOutput,
|
|
||||||
errors: Enumerable.Empty<RazorError>(),
|
|
||||||
tagNames: tagNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RunParseTreeRewriterTest(string documentContent,
|
|
||||||
MarkupBlock expectedOutput,
|
|
||||||
IEnumerable<RazorError> errors,
|
|
||||||
params string[] tagNames)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var providerContext = BuildProviderContext(tagNames);
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
EvaluateData(providerContext, documentContent, expectedOutput, errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TagHelperDescriptorProvider BuildProviderContext(params string[] tagNames)
|
|
||||||
{
|
|
||||||
var descriptors = new List<TagHelperDescriptor>();
|
|
||||||
|
|
||||||
foreach (var tagName in tagNames)
|
|
||||||
{
|
|
||||||
descriptors.Add(
|
|
||||||
new TagHelperDescriptor(tagName, tagName + "taghelper", "SomeAssembly"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TagHelperDescriptorProvider(descriptors);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ParserContext CreateParserContext(ITextDocument input,
|
|
||||||
ParserBase codeParser,
|
|
||||||
ParserBase markupParser,
|
|
||||||
ErrorSink errorSink)
|
|
||||||
{
|
|
||||||
return base.CreateParserContext(input, codeParser, markupParser, errorSink);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EvaluateData(TagHelperDescriptorProvider provider,
|
|
||||||
string documentContent,
|
|
||||||
MarkupBlock expectedOutput,
|
|
||||||
IEnumerable<RazorError> expectedErrors)
|
|
||||||
{
|
|
||||||
var errorSink = new ErrorSink();
|
|
||||||
var results = ParseDocument(documentContent, errorSink);
|
|
||||||
var rewritingContext = new RewritingContext(results.Document, errorSink);
|
|
||||||
new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext);
|
|
||||||
var rewritten = rewritingContext.SyntaxTree;
|
|
||||||
var actualErrors = errorSink.Errors.OrderBy(error => error.Location.AbsoluteIndex)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
EvaluateRazorErrors(actualErrors, expectedErrors.ToList());
|
|
||||||
EvaluateParseTree(rewritten, expectedOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SpanFactory CreateDefaultSpanFactory()
|
|
||||||
{
|
|
||||||
return new SpanFactory
|
|
||||||
{
|
|
||||||
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
|
|
||||||
CodeTokenizerFactory = doc => new CSharpTokenizer(doc)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
|
using Microsoft.AspNet.Razor.Parser.TagHelpers.Internal;
|
||||||
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
using Microsoft.AspNet.Razor.Test.Framework;
|
||||||
|
using Microsoft.AspNet.Razor.Text;
|
||||||
|
using Microsoft.AspNet.Razor.Tokenizer;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
|
{
|
||||||
|
public class TagHelperRewritingTestBase : CsHtmlMarkupParserTestBase
|
||||||
|
{
|
||||||
|
public void RunParseTreeRewriterTest(
|
||||||
|
string documentContent,
|
||||||
|
MarkupBlock expectedOutput,
|
||||||
|
params string[] tagNames)
|
||||||
|
{
|
||||||
|
RunParseTreeRewriterTest(
|
||||||
|
documentContent,
|
||||||
|
expectedOutput,
|
||||||
|
errors: Enumerable.Empty<RazorError>(),
|
||||||
|
tagNames: tagNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunParseTreeRewriterTest(
|
||||||
|
string documentContent,
|
||||||
|
MarkupBlock expectedOutput,
|
||||||
|
IEnumerable<RazorError> errors,
|
||||||
|
params string[] tagNames)
|
||||||
|
{
|
||||||
|
var providerContext = BuildProviderContext(tagNames);
|
||||||
|
|
||||||
|
EvaluateData(providerContext, documentContent, expectedOutput, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TagHelperDescriptorProvider BuildProviderContext(params string[] tagNames)
|
||||||
|
{
|
||||||
|
var descriptors = new List<TagHelperDescriptor>();
|
||||||
|
|
||||||
|
foreach (var tagName in tagNames)
|
||||||
|
{
|
||||||
|
descriptors.Add(
|
||||||
|
new TagHelperDescriptor(tagName, tagName + "taghelper", "SomeAssembly"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TagHelperDescriptorProvider(descriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ParserContext CreateParserContext(
|
||||||
|
ITextDocument input,
|
||||||
|
ParserBase codeParser,
|
||||||
|
ParserBase markupParser,
|
||||||
|
ErrorSink errorSink)
|
||||||
|
{
|
||||||
|
return base.CreateParserContext(input, codeParser, markupParser, errorSink);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EvaluateData(
|
||||||
|
TagHelperDescriptorProvider provider,
|
||||||
|
string documentContent,
|
||||||
|
MarkupBlock expectedOutput,
|
||||||
|
IEnumerable<RazorError> expectedErrors)
|
||||||
|
{
|
||||||
|
var errorSink = new ErrorSink();
|
||||||
|
var results = ParseDocument(documentContent, errorSink);
|
||||||
|
var rewritingContext = new RewritingContext(results.Document, errorSink);
|
||||||
|
new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext);
|
||||||
|
var rewritten = rewritingContext.SyntaxTree;
|
||||||
|
var actualErrors = errorSink.Errors.OrderBy(error => error.Location.AbsoluteIndex)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
EvaluateRazorErrors(actualErrors, expectedErrors.ToList());
|
||||||
|
EvaluateParseTree(rewritten, expectedOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpanFactory CreateDefaultSpanFactory()
|
||||||
|
{
|
||||||
|
return new SpanFactory
|
||||||
|
{
|
||||||
|
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
|
||||||
|
CodeTokenizerFactory = doc => new CSharpTokenizer(doc)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
namespace TestOutput
|
||||||
|
{
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class MinimizedTagHelpers
|
||||||
|
{
|
||||||
|
private static object @__o;
|
||||||
|
private void @__RazorDesignTimeHelpers__()
|
||||||
|
{
|
||||||
|
#pragma warning disable 219
|
||||||
|
string __tagHelperDirectiveSyntaxHelper = null;
|
||||||
|
__tagHelperDirectiveSyntaxHelper =
|
||||||
|
#line 1 "MinimizedTagHelpers.cshtml"
|
||||||
|
"something, nice"
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
;
|
||||||
|
#pragma warning restore 219
|
||||||
|
}
|
||||||
|
#line hidden
|
||||||
|
private CatchAllTagHelper __CatchAllTagHelper = null;
|
||||||
|
private InputTagHelper __InputTagHelper = null;
|
||||||
|
#line hidden
|
||||||
|
public MinimizedTagHelpers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper.BoundRequiredString = "hello";
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper.BoundRequiredString = "hello2";
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__CatchAllTagHelper.BoundRequiredString = "world";
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper.BoundRequiredString = "world";
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
#pragma checksum "MinimizedTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "07839be4304797e30b19b50b95e2247c93cdff06"
|
||||||
|
namespace TestOutput
|
||||||
|
{
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class MinimizedTagHelpers
|
||||||
|
{
|
||||||
|
#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 CatchAllTagHelper __CatchAllTagHelper = null;
|
||||||
|
private InputTagHelper __InputTagHelper = null;
|
||||||
|
#line hidden
|
||||||
|
public MinimizedTagHelpers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner();
|
||||||
|
Instrumentation.BeginContext(33, 2, true);
|
||||||
|
WriteLiteral("\r\n");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", false, "test", async() => {
|
||||||
|
WriteLiteral("\r\n <input nottaghelper />\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", true, "test", async() => {
|
||||||
|
}
|
||||||
|
, StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("btn"));
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("catchall-unbound-required");
|
||||||
|
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
await WriteTagHelperAsync(__tagHelperExecutionContext);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", true, "test", async() => {
|
||||||
|
}
|
||||||
|
, StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.BoundRequiredString = "hello";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("input-bound-required-string", __InputTagHelper.BoundRequiredString);
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("btn"));
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("catchall-unbound-required");
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("input-unbound-required");
|
||||||
|
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
await WriteTagHelperAsync(__tagHelperExecutionContext);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", true, "test", async() => {
|
||||||
|
}
|
||||||
|
, StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.BoundRequiredString = "hello2";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("input-bound-required-string", __InputTagHelper.BoundRequiredString);
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
|
||||||
|
__CatchAllTagHelper.BoundRequiredString = "world";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("catchall-bound-string", __CatchAllTagHelper.BoundRequiredString);
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("btn"));
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("catchall-unbound-required");
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("input-unbound-required");
|
||||||
|
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
await WriteTagHelperAsync(__tagHelperExecutionContext);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", true, "test", async() => {
|
||||||
|
}
|
||||||
|
, StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.BoundRequiredString = "world";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("input-bound-required-string", __InputTagHelper.BoundRequiredString);
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("btn"));
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("catchall-unbound-required", Html.Raw("hello"));
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("input-unbound-required", Html.Raw("hello2"));
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("catchall-unbound-required");
|
||||||
|
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
await WriteTagHelperAsync(__tagHelperExecutionContext);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n");
|
||||||
|
}
|
||||||
|
, StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||||
|
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
|
||||||
|
__tagHelperExecutionContext.AddMinimizedHtmlAttribute("catchall-unbound-required");
|
||||||
|
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
await WriteTagHelperAsync(__tagHelperExecutionContext);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
@addTagHelper "something, nice"
|
||||||
|
|
||||||
|
<p catchall-unbound-required>
|
||||||
|
<input nottaghelper />
|
||||||
|
<input class="btn"
|
||||||
|
catchall-unbound-required />
|
||||||
|
<input
|
||||||
|
class="btn" catchall-unbound-required input-unbound-required input-bound-required-string="hello" />
|
||||||
|
<input
|
||||||
|
class="btn"
|
||||||
|
catchall-unbound-required
|
||||||
|
input-unbound-required catchall-bound-string="world" input-bound-required-string="hello2" />
|
||||||
|
<input class="btn"
|
||||||
|
catchall-unbound-required="hello"
|
||||||
|
input-unbound-required="hello2"
|
||||||
|
catchall-unbound-required
|
||||||
|
input-bound-required-string="world" />
|
||||||
|
</p>
|
||||||
Loading…
Reference in New Issue