Update `TagHelperDirectiveSpanVisitor` to properly capture TagHelper directive text.
- Added a test with optional quotes for each of the `TagHelperDirectiveDescriptor`s, add, remove and prefix. #744
This commit is contained in:
parent
cacd16fa85
commit
80ebb4a068
|
|
@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// </summary>
|
||||
public class AddTagHelperChunkGenerator : SpanChunkGenerator
|
||||
{
|
||||
private readonly string _lookupText;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AddTagHelperChunkGenerator"/>.
|
||||
/// </summary>
|
||||
|
|
@ -22,9 +20,14 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// </param>
|
||||
public AddTagHelperChunkGenerator(string lookupText)
|
||||
{
|
||||
_lookupText = lookupText;
|
||||
LookupText = lookupText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text used to look up <see cref="Compilation.TagHelpers.TagHelperDescriptor"/>s that should be added.
|
||||
/// </summary>
|
||||
public string LookupText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates <see cref="AddTagHelperChunk"/>s.
|
||||
/// </summary>
|
||||
|
|
@ -35,7 +38,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// the current chunk generation process.</param>
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
context.ChunkTreeBuilder.AddAddTagHelperChunk(_lookupText, target);
|
||||
context.ChunkTreeBuilder.AddAddTagHelperChunk(LookupText, target);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -43,7 +46,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
{
|
||||
var other = obj as AddTagHelperChunkGenerator;
|
||||
return base.Equals(other) &&
|
||||
string.Equals(_lookupText, other._lookupText, StringComparison.Ordinal);
|
||||
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -51,7 +54,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
{
|
||||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(base.GetHashCode());
|
||||
combiner.Add(_lookupText, StringComparer.Ordinal);
|
||||
combiner.Add(LookupText, StringComparer.Ordinal);
|
||||
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// </summary>
|
||||
public class RemoveTagHelperChunkGenerator : SpanChunkGenerator
|
||||
{
|
||||
private readonly string _lookupText;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="RemoveTagHelperChunkGenerator"/>.
|
||||
/// </summary>
|
||||
|
|
@ -22,9 +20,14 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// </param>
|
||||
public RemoveTagHelperChunkGenerator(string lookupText)
|
||||
{
|
||||
_lookupText = lookupText;
|
||||
LookupText = lookupText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Text used to look up <see cref="Compilation.TagHelpers.TagHelperDescriptor"/>s that should be removed.
|
||||
/// </summary>
|
||||
public string LookupText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates <see cref="RemoveTagHelperChunk"/>s.
|
||||
/// </summary>
|
||||
|
|
@ -35,7 +38,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// the current chunk generation process.</param>
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
context.ChunkTreeBuilder.AddRemoveTagHelperChunk(_lookupText, target);
|
||||
context.ChunkTreeBuilder.AddRemoveTagHelperChunk(LookupText, target);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -43,7 +46,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
{
|
||||
var other = obj as RemoveTagHelperChunkGenerator;
|
||||
return base.Equals(other) &&
|
||||
string.Equals(_lookupText, other._lookupText, StringComparison.Ordinal);
|
||||
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -51,7 +54,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
{
|
||||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(base.GetHashCode());
|
||||
combiner.Add(_lookupText, StringComparer.Ordinal);
|
||||
combiner.Add(LookupText, StringComparer.Ordinal);
|
||||
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// </summary>
|
||||
public class TagHelperPrefixDirectiveChunkGenerator : SpanChunkGenerator
|
||||
{
|
||||
private readonly string _prefix;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="TagHelperPrefixDirectiveChunkGenerator"/>.
|
||||
/// </summary>
|
||||
|
|
@ -23,9 +21,14 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// </param>
|
||||
public TagHelperPrefixDirectiveChunkGenerator(string prefix)
|
||||
{
|
||||
_prefix = prefix;
|
||||
Prefix = prefix;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Text used as a required prefix when matching HTML.
|
||||
/// </summary>
|
||||
public string Prefix { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates <see cref="TagHelperPrefixDirectiveChunk"/>s.
|
||||
/// </summary>
|
||||
|
|
@ -36,7 +39,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
/// the current chunk generation process.</param>
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
context.ChunkTreeBuilder.AddTagHelperPrefixDirectiveChunk(_prefix, target);
|
||||
context.ChunkTreeBuilder.AddTagHelperPrefixDirectiveChunk(Prefix, target);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -44,7 +47,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
{
|
||||
var other = obj as TagHelperPrefixDirectiveChunkGenerator;
|
||||
return base.Equals(other) &&
|
||||
string.Equals(_prefix, other._prefix, StringComparison.Ordinal);
|
||||
string.Equals(Prefix, other.Prefix, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -52,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators
|
|||
{
|
||||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(base.GetHashCode());
|
||||
combiner.Add(_prefix, StringComparer.Ordinal);
|
||||
combiner.Add(Prefix, StringComparer.Ordinal);
|
||||
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,18 +87,27 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers
|
|||
throw new ArgumentNullException(nameof(span));
|
||||
}
|
||||
|
||||
string directiveText;
|
||||
TagHelperDirectiveType directiveType;
|
||||
if (span.ChunkGenerator is AddTagHelperChunkGenerator)
|
||||
|
||||
var addTagHelperChunkGenerator = span.ChunkGenerator as AddTagHelperChunkGenerator;
|
||||
var removeTagHelperChunkGenerator = span.ChunkGenerator as RemoveTagHelperChunkGenerator;
|
||||
var tagHelperPrefixChunkGenerator = span.ChunkGenerator as TagHelperPrefixDirectiveChunkGenerator;
|
||||
|
||||
if (addTagHelperChunkGenerator != null)
|
||||
{
|
||||
directiveType = TagHelperDirectiveType.AddTagHelper;
|
||||
directiveText = addTagHelperChunkGenerator.LookupText;
|
||||
}
|
||||
else if (span.ChunkGenerator is RemoveTagHelperChunkGenerator)
|
||||
else if (removeTagHelperChunkGenerator != null)
|
||||
{
|
||||
directiveType = TagHelperDirectiveType.RemoveTagHelper;
|
||||
directiveText = removeTagHelperChunkGenerator.LookupText;
|
||||
}
|
||||
else if (span.ChunkGenerator is TagHelperPrefixDirectiveChunkGenerator)
|
||||
else if (tagHelperPrefixChunkGenerator != null)
|
||||
{
|
||||
directiveType = TagHelperDirectiveType.TagHelperPrefix;
|
||||
directiveText = tagHelperPrefixChunkGenerator.Prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -106,7 +115,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers
|
|||
return;
|
||||
}
|
||||
|
||||
var directiveText = span.Content.Trim();
|
||||
directiveText = directiveText.Trim();
|
||||
var startOffset = span.Content.IndexOf(directiveText, StringComparison.Ordinal);
|
||||
var offsetContent = span.Content.Substring(0, startOffset);
|
||||
var offsetTextLocation = SourceLocation.Advance(span.Start, offsetContent);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor.Parser;
|
|||
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNetCore.Razor.Parser.TagHelpers;
|
||||
using Microsoft.AspNetCore.Razor.Test.Framework;
|
||||
using Microsoft.AspNetCore.Razor.Tokenizer;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -18,6 +19,109 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers
|
|||
{
|
||||
private static readonly SpanFactory Factory = SpanFactory.CreateCsHtml();
|
||||
|
||||
public static TheoryData QuotedTagHelperDirectivesData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = new SpanFactory
|
||||
{
|
||||
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
|
||||
CodeTokenizerFactory = doc => new CSharpTokenizer(doc),
|
||||
};
|
||||
|
||||
// document, expectedDescriptors
|
||||
return new TheoryData<MarkupBlock, IEnumerable<TagHelperDirectiveDescriptor>>
|
||||
{
|
||||
{
|
||||
new MarkupBlock(factory.Code("\"*, someAssembly\"").AsAddTagHelper("*, someAssembly")),
|
||||
new[]
|
||||
{
|
||||
new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = "*, someAssembly",
|
||||
DirectiveType = TagHelperDirectiveType.AddTagHelper
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
new MarkupBlock(factory.Code("\"*, someAssembly\"").AsRemoveTagHelper("*, someAssembly")),
|
||||
new[]
|
||||
{
|
||||
new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = "*, someAssembly",
|
||||
DirectiveType = TagHelperDirectiveType.RemoveTagHelper
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
new MarkupBlock(factory.Code("\"th:\"").AsTagHelperPrefixDirective("th:")),
|
||||
new[]
|
||||
{
|
||||
new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = "th:",
|
||||
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
new MarkupBlock(factory.Code(" \"*, someAssembly \" ").AsAddTagHelper("*, someAssembly ")),
|
||||
new[]
|
||||
{
|
||||
new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = "*, someAssembly",
|
||||
DirectiveType = TagHelperDirectiveType.AddTagHelper
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
new MarkupBlock(factory.Code(" \"*, someAssembly \" ").AsRemoveTagHelper("*, someAssembly ")),
|
||||
new[]
|
||||
{
|
||||
new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = "*, someAssembly",
|
||||
DirectiveType = TagHelperDirectiveType.RemoveTagHelper
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
new MarkupBlock(factory.Code(" \" th :\"").AsTagHelperPrefixDirective(" th :")),
|
||||
new[]
|
||||
{
|
||||
new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = "th :",
|
||||
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(QuotedTagHelperDirectivesData))]
|
||||
public void GetDescriptors_LocatesQuotedTagHelperDirectives_CreatesDirectiveDescriptors(
|
||||
MarkupBlock document,
|
||||
IEnumerable<TagHelperDirectiveDescriptor> expectedDescriptors)
|
||||
{
|
||||
// Arrange
|
||||
var resolver = new TestTagHelperDescriptorResolver();
|
||||
var tagHelperDirectiveSpanVisitor = new TagHelperDirectiveSpanVisitor(resolver, new ErrorSink());
|
||||
|
||||
// Act
|
||||
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
expectedDescriptors,
|
||||
resolver.DirectiveDescriptors,
|
||||
TagHelperDirectiveDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_InvokesResolveOnceForAllDirectives()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue