Add Multiple attribute same name understanding to TagHelperChunk.

- This also involved adding understanding to CSharpTagHelperCodeRenderer.
- When rebasing this commit was lost as part of: 7c604d2b11 .

#279
This commit is contained in:
N. Taylor Mullen 2015-04-30 14:57:23 -07:00
parent 6384977e96
commit e3fdb8886a
4 changed files with 19 additions and 17 deletions

View File

@ -61,7 +61,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
public void RenderTagHelper(TagHelperChunk chunk)
{
// Remove any duplicate TagHelperDescriptors that reference the same type name. Duplicates can occur when
// multiple TargetElement attributes are on a TagHelper type and matchs overlap for an HTML element.
// multiple TargetElement attributes are on a TagHelper type and matches overlap for an HTML element.
// Having more than one descriptor with the same TagHelper type results in generated code that runs
// the same TagHelper X many times (instead of once) over a single HTML element.
var tagHelperDescriptors = chunk.Descriptors.Distinct(TypeNameTagHelperDescriptorComparer.Default);
@ -190,20 +190,21 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
}
}
private void RenderBoundHTMLAttributes(IDictionary<string, Chunk> chunkAttributes,
private void RenderBoundHTMLAttributes(IList<KeyValuePair<string, Chunk>> chunkAttributes,
string tagHelperVariableName,
IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors,
Dictionary<string, string> htmlAttributeValues)
{
foreach (var attributeDescriptor in attributeDescriptors)
{
Chunk attributeValueChunk;
var matchingAttributes = chunkAttributes.Where(
attr => string.Equals(attr.Key, attributeDescriptor.Name, StringComparison.OrdinalIgnoreCase));
var providedAttribute = chunkAttributes.TryGetValue(attributeDescriptor.Name,
out attributeValueChunk);
if (providedAttribute)
if (matchingAttributes.Any())
{
// First attribute wins, even if there's duplicates.
var attributeValueChunk = matchingAttributes.First().Value;
var attributeValueRecorded = htmlAttributeValues.ContainsKey(attributeDescriptor.Name);
// Bufferable attributes are attributes that can have Razor code inside of them.

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
public TagHelperChunk(
string tagName,
bool selfClosing,
IDictionary<string, Chunk> attributes,
IList<KeyValuePair<string, Chunk>> attributes,
IEnumerable<TagHelperDescriptor> descriptors)
{
TagName = tagName;
@ -41,7 +41,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
/// These attributes are <see cref="string"/> => <see cref="Chunk"/> so attribute values can consist
/// of all sorts of Razor specific pieces.
/// </remarks>
public IDictionary<string, Chunk> Attributes { get; set; }
public IList<KeyValuePair<string, Chunk>> Attributes { get; set; }
/// <summary>
/// The <see cref="TagHelperDescriptor"/>s that are associated with the tag helpers HTML element.

View File

@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Razor.Generator
RazorResources.TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock);
}
var attributes = new Dictionary<string, Chunk>(StringComparer.OrdinalIgnoreCase);
var attributes = new List<KeyValuePair<string, Chunk>>();
// We need to create a code generator to create chunks for each of the attributes.
var codeGenerator = context.Host.CreateCodeGenerator(
@ -63,12 +63,13 @@ namespace Microsoft.AspNet.Razor.Generator
var chunks = codeGenerator.Context.CodeTreeBuilder.CodeTree.Chunks;
var first = chunks.FirstOrDefault();
attributes[attribute.Key] = new ChunkBlock
{
Association = first?.Association,
Children = chunks,
Start = first == null ? SourceLocation.Zero : first.Start
};
attributes.Add(new KeyValuePair<string, Chunk>(attribute.Key,
new ChunkBlock
{
Association = first?.Association,
Children = chunks,
Start = first == null ? SourceLocation.Zero : first.Start
}));
// Reset the code tree builder so we can build a new one for the next attribute
codeGenerator.Context.CodeTreeBuilder = new CodeTreeBuilder();

View File

@ -133,7 +133,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
return new TagHelperChunk(
tagName,
selfClosing: false,
attributes: new Dictionary<string, Chunk>(),
attributes: new List<KeyValuePair<string, Chunk>>(),
descriptors: tagHelperDescriptors)
{
Children = new List<Chunk>(),