Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit a2bf241

Browse files
N. Taylor Mullenajaybhargavb
authored andcommitted
Reacted to descriptor changes in product code.
- Added a new `RazorDiagnosticFactory` abstraction to handle `RazorDiagnostic`s and their corresponding errors/ids etc. This new API should allow for easy addition of new `RazorDiagnostic` errors. - Updated the `DefaultTagHelperDescriptorFactory` to construct `TagHelperDescriptor`s using the new builder APIs and in the new descriptor format (1 descriptor per type). - Updated `ViewComponentTagHelperDescriptorFactory` to construct `TagHelperDescriptor`s with the builder API. - With both factory implementations code was duplicated because the ViewComponent work will be moving outside of Razor once we have the proper hooks. - Updated `TagHelper` binding bits to capture a binding result in order to query which rules appy to a given tag name. - Still need to handle deserialization of `TagHelperDescriptor` types within the Razor extension. #973
1 parent b67ffd5 commit a2bf241

34 files changed

+1876
-1980
lines changed

src/Microsoft.AspNetCore.Razor.Evolution/CodeGeneration/DesignTimeCSharpRenderer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
191191
{
192192
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
193193
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
194-
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
194+
var propertyValueAccessor = GetTagHelperPropertyAccessor(node.IsIndexerNameMatch, tagHelperVariableName, node.AttributeName, node.Descriptor);
195195

196196
string previousValueAccessor;
197197
if (tagHelperRenderingContext.RenderedBoundAttributes.TryGetValue(node.AttributeName, out previousValueAccessor))
@@ -208,7 +208,7 @@ public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
208208
tagHelperRenderingContext.RenderedBoundAttributes[node.AttributeName] = propertyValueAccessor;
209209
}
210210

211-
if (node.Descriptor.IsStringProperty)
211+
if (node.Descriptor.IsStringProperty || (node.IsIndexerNameMatch && node.Descriptor.IsIndexerStringProperty))
212212
{
213213
VisitDefault(node);
214214

src/Microsoft.AspNetCore.Razor.Evolution/CodeGeneration/PageStructureCSharpRenderer.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,16 @@ protected static string BuildOffsetPadding(int generatedOffset, SourceSpan sourc
8383
protected static string GetTagHelperVariableName(string tagHelperTypeName) => "__" + tagHelperTypeName.Replace('.', '_');
8484

8585
protected static string GetTagHelperPropertyAccessor(
86+
bool isIndexerNameMatch,
8687
string tagHelperVariableName,
8788
string attributeName,
88-
TagHelperAttributeDescriptor descriptor)
89+
BoundAttributeDescriptor descriptor)
8990
{
90-
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.PropertyName}";
91+
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.Metadata[ITagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]}";
9192

92-
if (descriptor.IsIndexer)
93+
if (isIndexerNameMatch)
9394
{
94-
var dictionaryKey = attributeName.Substring(descriptor.Name.Length);
95+
var dictionaryKey = attributeName.Substring(descriptor.IndexerNamePrefix.Length);
9596
propertyAccessor += $"[\"{dictionaryKey}\"]";
9697
}
9798

src/Microsoft.AspNetCore.Razor.Evolution/CodeGeneration/RuntimeCSharpRenderer.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRN
373373
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
374374
{
375375
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
376-
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
376+
var propertyValueAccessor = GetTagHelperPropertyAccessor(node.IsIndexerNameMatch, tagHelperVariableName, node.AttributeName, node.Descriptor);
377377
var attributeValueAccessor = $"{node.VariableName}.Value" /* ORIGINAL: TagHelperAttributeValuePropertyName */;
378378
Context.Writer
379379
.WriteStartAssignment(propertyValueAccessor)
@@ -391,17 +391,18 @@ public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
391391
{
392392
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
393393
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
394+
var propertyName = node.Descriptor.Metadata[ITagHelperBoundAttributeDescriptorBuilder.PropertyNameKey];
394395

395396
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
396-
if (node.Descriptor.IsIndexer &&
397-
tagHelperRenderingContext.VerifiedPropertyDictionaries.Add(node.Descriptor.PropertyName))
397+
if (node.IsIndexerNameMatch &&
398+
tagHelperRenderingContext.VerifiedPropertyDictionaries.Add(propertyName))
398399
{
399400
// Throw a reasonable Exception at runtime if the dictionary property is null.
400401
Context.Writer
401402
.Write("if (")
402403
.Write(tagHelperVariableName)
403404
.Write(".")
404-
.Write(node.Descriptor.PropertyName)
405+
.Write(propertyName)
405406
.WriteLine(" == null)");
406407
using (Context.Writer.BuildScope())
407408
{
@@ -415,13 +416,13 @@ public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
415416
.WriteParameterSeparator()
416417
.WriteStringLiteral(node.TagHelperTypeName)
417418
.WriteParameterSeparator()
418-
.WriteStringLiteral(node.Descriptor.PropertyName)
419+
.WriteStringLiteral(propertyName)
419420
.WriteEndMethodInvocation(endLine: false) // End of method call
420421
.WriteEndMethodInvocation(); // End of new expression / throw statement
421422
}
422423
}
423424

424-
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
425+
var propertyValueAccessor = GetTagHelperPropertyAccessor(node.IsIndexerNameMatch, tagHelperVariableName, node.AttributeName, node.Descriptor);
425426

426427
string previousValueAccessor;
427428
if (tagHelperRenderingContext.RenderedBoundAttributes.TryGetValue(node.AttributeName, out previousValueAccessor))
@@ -438,7 +439,7 @@ public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
438439
tagHelperRenderingContext.RenderedBoundAttributes[node.AttributeName] = propertyValueAccessor;
439440
}
440441

441-
if (node.Descriptor.IsStringProperty)
442+
if (node.Descriptor.IsStringProperty || (node.IsIndexerNameMatch && node.Descriptor.IsIndexerStringProperty))
442443
{
443444
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);
444445

@@ -683,8 +684,11 @@ private void RenderTagHelperAttributeInline(
683684
else if (node is TemplateIRNode)
684685
{
685686
var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent;
687+
var expectedTypeName = attributeValueNode.IsIndexerNameMatch ?
688+
attributeValueNode.Descriptor.IndexerTypeName :
689+
attributeValueNode.Descriptor.TypeName;
686690
var error = new RazorError(
687-
LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(attributeValueNode.Descriptor.TypeName),
691+
LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(expectedTypeName),
688692
new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length),
689693
documentLocation.Length);
690694
Context.Diagnostics.Add(RazorDiagnostic.Create(error));

src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorIRLoweringPhase.cs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument)
1818
ThrowForMissingDependency(syntaxTree);
1919

2020
var builder = RazorIRBuilder.Document();
21-
2221
var document = (DocumentIRNode)builder.Current;
22+
2323
document.Options = syntaxTree.Options;
2424

2525
var namespaces = new HashSet<string>();
@@ -56,7 +56,8 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument)
5656
}
5757
}
5858

59-
var visitor = new MainSourceVisitor(document, builder, namespaces)
59+
var tagHelperPrefix = codeDocument.GetTagHelperPrefix();
60+
var visitor = new MainSourceVisitor(document, builder, namespaces, tagHelperPrefix)
6061
{
6162
FileName = syntaxTree.Source.FileName,
6263
};
@@ -220,10 +221,12 @@ public override void VisitDirectiveBlock(DirectiveChunkGenerator chunkGenerator,
220221
private class MainSourceVisitor : LoweringVisitor
221222
{
222223
private DeclareTagHelperFieldsIRNode _tagHelperFields;
224+
private readonly string _tagHelperPrefix;
223225

224-
public MainSourceVisitor(DocumentIRNode document, RazorIRBuilder builder, HashSet<string> namespaces)
226+
public MainSourceVisitor(DocumentIRNode document, RazorIRBuilder builder, HashSet<string> namespaces, string tagHelperPrefix)
225227
: base(document, builder, namespaces)
226228
{
229+
_tagHelperPrefix = tagHelperPrefix;
227230
}
228231

229232
public override void VisitDirectiveToken(DirectiveTokenChunkGenerator chunkGenerator, Span span)
@@ -467,9 +470,9 @@ public override void VisitTagHelperBlock(TagHelperChunkGenerator chunkGenerator,
467470
});
468471

469472
var tagName = tagHelperBlock.TagName;
470-
if (tagHelperBlock.Descriptors.First().Prefix != null)
473+
if (_tagHelperPrefix != null)
471474
{
472-
tagName = tagName.Substring(tagHelperBlock.Descriptors.First().Prefix.Length);
475+
tagName = tagName.Substring(_tagHelperPrefix.Length);
473476
}
474477

475478
_builder.Push(new InitializeTagHelperStructureIRNode()
@@ -482,8 +485,9 @@ public override void VisitTagHelperBlock(TagHelperChunkGenerator chunkGenerator,
482485

483486
_builder.Pop(); // Pop InitializeTagHelperStructureIRNode
484487

485-
AddTagHelperCreation(tagHelperBlock.Descriptors);
486-
AddTagHelperAttributes(tagHelperBlock.Attributes, tagHelperBlock.Descriptors);
488+
var descriptors = tagHelperBlock.BindingResult.Descriptors;
489+
AddTagHelperCreation(descriptors);
490+
AddTagHelperAttributes(tagHelperBlock.Attributes, descriptors);
487491
AddExecuteTagHelpers();
488492

489493
_builder.Pop(); // Pop TagHelperIRNode
@@ -497,19 +501,21 @@ private void DeclareTagHelperFields(TagHelperBlock block)
497501
_document.Children.Add(_tagHelperFields);
498502
}
499503

500-
foreach (var descriptor in block.Descriptors)
504+
foreach (var descriptor in block.BindingResult.Descriptors)
501505
{
502-
_tagHelperFields.UsedTagHelperTypeNames.Add(descriptor.TypeName);
506+
var typeName = descriptor.Metadata[ITagHelperDescriptorBuilder.TypeNameKey];
507+
_tagHelperFields.UsedTagHelperTypeNames.Add(typeName);
503508
}
504509
}
505510

506511
private void AddTagHelperCreation(IEnumerable<TagHelperDescriptor> descriptors)
507512
{
508513
foreach (var descriptor in descriptors)
509514
{
515+
var typeName = descriptor.Metadata[ITagHelperDescriptorBuilder.TypeNameKey];
510516
var createTagHelper = new CreateTagHelperIRNode()
511517
{
512-
TagHelperTypeName = descriptor.TypeName,
518+
TagHelperTypeName = typeName,
513519
Descriptor = descriptor
514520
};
515521

@@ -524,7 +530,7 @@ private void AddTagHelperAttributes(IList<TagHelperAttributeNode> attributes, IE
524530
{
525531
var attributeValueNode = attribute.Value;
526532
var associatedDescriptors = descriptors.Where(descriptor =>
527-
descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name)));
533+
descriptor.BoundAttributes.Any(attributeDescriptor => attributeDescriptor.CanMatchName(attribute.Name)));
528534

529535
if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attribute.Name))
530536
{
@@ -537,16 +543,20 @@ private void AddTagHelperAttributes(IList<TagHelperAttributeNode> attributes, IE
537543

538544
foreach (var associatedDescriptor in associatedDescriptors)
539545
{
540-
var associatedAttributeDescriptor = associatedDescriptor.Attributes.First(
541-
attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name));
546+
var associatedAttributeDescriptor = associatedDescriptor.BoundAttributes.First(
547+
attributeDescriptor => attributeDescriptor.CanMatchName(attribute.Name));
548+
var tagHelperTypeName = associatedDescriptor.Metadata[ITagHelperDescriptorBuilder.TypeNameKey];
549+
var attributePropertyName = associatedAttributeDescriptor.Metadata[ITagHelperBoundAttributeDescriptorBuilder.PropertyNameKey];
550+
542551
var setTagHelperProperty = new SetTagHelperPropertyIRNode()
543552
{
544-
PropertyName = associatedAttributeDescriptor.PropertyName,
553+
PropertyName = attributePropertyName,
545554
AttributeName = attribute.Name,
546-
TagHelperTypeName = associatedDescriptor.TypeName,
555+
TagHelperTypeName = tagHelperTypeName,
547556
Descriptor = associatedAttributeDescriptor,
548557
ValueStyle = attribute.ValueStyle,
549-
Source = BuildSourceSpanFromNode(attributeValueNode)
558+
Source = BuildSourceSpanFromNode(attributeValueNode),
559+
IsIndexerNameMatch = associatedAttributeDescriptor.IsIndexerNameMatch(attribute.Name),
550560
};
551561

552562
_builder.Push(setTagHelperProperty);

src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CreateTagHelperIRNode.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Collections.Generic;
6-
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
76

87
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
98
{

src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ public class SetPreallocatedTagHelperPropertyIRNode : RazorIRNode
2121

2222
public string PropertyName { get; set; }
2323

24-
public TagHelperAttributeDescriptor Descriptor { get; set; }
24+
public BoundAttributeDescriptor Descriptor { get; set; }
25+
26+
public bool IsIndexerNameMatch { get; set; }
2527

2628
public override void Accept(RazorIRNodeVisitor visitor)
2729
{

src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetTagHelperPropertyIRNode.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ public class SetTagHelperPropertyIRNode : RazorIRNode
2323

2424
internal HtmlAttributeValueStyle ValueStyle { get; set; }
2525

26-
public TagHelperAttributeDescriptor Descriptor { get; set; }
26+
public BoundAttributeDescriptor Descriptor { get; set; }
27+
28+
public bool IsIndexerNameMatch { get; set; }
2729

2830
public override void Accept(RazorIRNodeVisitor visitor)
2931
{
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
6+
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
7+
{
8+
internal sealed class TagBindingResult
9+
{
10+
public IReadOnlyDictionary<TagHelperDescriptor, IEnumerable<TagMatchingRule>> _applicableDescriptorMappings;
11+
12+
public TagBindingResult(IReadOnlyDictionary<TagHelperDescriptor, IEnumerable<TagMatchingRule>> applicableDescriptorMappings)
13+
{
14+
_applicableDescriptorMappings = applicableDescriptorMappings;
15+
Descriptors = _applicableDescriptorMappings.Keys;
16+
}
17+
18+
public IEnumerable<TagHelperDescriptor> Descriptors { get; }
19+
20+
public IEnumerable<TagMatchingRule> GetBoundRules(TagHelperDescriptor descriptor)
21+
{
22+
return _applicableDescriptorMappings[descriptor];
23+
}
24+
}
25+
}

src/Microsoft.AspNetCore.Razor.Evolution/Legacy/TagHelperBlock.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public TagHelperBlock(TagHelperBlockBuilder source)
2525
: base(source.Type, source.Children, source.ChunkGenerator)
2626
{
2727
TagName = source.TagName;
28-
Descriptors = source.Descriptors;
28+
BindingResult = source.BindingResult;
2929
Attributes = new List<TagHelperAttributeNode>(source.Attributes);
3030
_start = source.Start;
3131
TagMode = source.TagMode;
@@ -61,9 +61,9 @@ public TagHelperBlock(TagHelperBlockBuilder source)
6161
public TagMode TagMode { get; }
6262

6363
/// <summary>
64-
/// <see cref="TagHelperDescriptor"/>s for the HTML element.
64+
/// <see cref="TagHelperDescriptor"/> bindings for the HTML element.
6565
/// </summary>
66-
public IEnumerable<TagHelperDescriptor> Descriptors { get; }
66+
public TagBindingResult BindingResult { get; }
6767

6868
/// <summary>
6969
/// The HTML attributes.

src/Microsoft.AspNetCore.Razor.Evolution/Legacy/TagHelperBlockBuilder.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public TagHelperBlockBuilder(TagHelperBlock original)
1919
: base(original)
2020
{
2121
TagName = original.TagName;
22-
Descriptors = original.Descriptors;
22+
BindingResult = original.BindingResult;
2323
Attributes = new List<TagHelperAttributeNode>(original.Attributes);
2424
}
2525

@@ -31,22 +31,21 @@ public TagHelperBlockBuilder(TagHelperBlock original)
3131
/// <param name="tagMode">HTML syntax of the element in the Razor source.</param>
3232
/// <param name="start">Starting location of the <see cref="TagHelperBlock"/>.</param>
3333
/// <param name="attributes">Attributes of the <see cref="TagHelperBlock"/>.</param>
34-
/// <param name="descriptors">The <see cref="TagHelperDescriptor"/>s associated with the current HTML
35-
/// tag.</param>
34+
/// <param name="bindingResult"></param>
3635
public TagHelperBlockBuilder(
3736
string tagName,
3837
TagMode tagMode,
3938
SourceLocation start,
4039
IList<TagHelperAttributeNode> attributes,
41-
IEnumerable<TagHelperDescriptor> descriptors)
40+
TagBindingResult bindingResult)
4241
{
4342
TagName = tagName;
4443
TagMode = tagMode;
4544
Start = start;
46-
Descriptors = descriptors;
45+
BindingResult = bindingResult;
4746
Attributes = new List<TagHelperAttributeNode>(attributes);
4847
Type = BlockType.Tag;
49-
ChunkGenerator = new TagHelperChunkGenerator(descriptors);
48+
ChunkGenerator = new TagHelperChunkGenerator();
5049
}
5150

5251
// Internal for testing
@@ -60,7 +59,7 @@ internal TagHelperBlockBuilder(
6059
TagMode = tagMode;
6160
Attributes = attributes;
6261
Type = BlockType.Tag;
63-
ChunkGenerator = new TagHelperChunkGenerator(tagHelperDescriptors: null);
62+
ChunkGenerator = new TagHelperChunkGenerator();
6463

6564
// Children is IList, no AddRange
6665
foreach (var child in children)
@@ -89,7 +88,7 @@ internal TagHelperBlockBuilder(
8988
/// <summary>
9089
/// <see cref="TagHelperDescriptor"/>s for the HTML element.
9190
/// </summary>
92-
public IEnumerable<TagHelperDescriptor> Descriptors { get; }
91+
public TagBindingResult BindingResult { get; }
9392

9493
/// <summary>
9594
/// The HTML attributes.

0 commit comments

Comments
 (0)