[Fixes #881] Added TagHelper IR support
This commit is contained in:
parent
61b2b0d4e7
commit
e2dd09c918
|
|
@ -159,7 +159,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
contentLength,
|
||||
sourceRangeStart.FilePath ?? _codeDocument.Source.Filename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void VisitExpressionSpan(ExpressionChunkGenerator chunkGenerator, Span span)
|
||||
|
|
@ -253,6 +252,145 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
Builder.Pop();
|
||||
}
|
||||
|
||||
public override void VisitStartTagHelperBlock(TagHelperChunkGenerator chunkGenerator, Block block)
|
||||
{
|
||||
var tagHelperBlock = block as TagHelperBlock;
|
||||
if (tagHelperBlock == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeclareTagHelperFields(tagHelperBlock);
|
||||
|
||||
Builder.Push(new TagHelperIRNode());
|
||||
|
||||
Builder.Push(new InitializeTagHelperStructureIRNode()
|
||||
{
|
||||
TagName = tagHelperBlock.TagName,
|
||||
TagMode = tagHelperBlock.TagMode
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitEndTagHelperBlock(TagHelperChunkGenerator chunkGenerator, Block block)
|
||||
{
|
||||
var tagHelperBlock = block as TagHelperBlock;
|
||||
if (tagHelperBlock == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Builder.Pop(); // Pop InitializeTagHelperStructureIRNode
|
||||
|
||||
AddTagHelperCreation(tagHelperBlock.Descriptors);
|
||||
AddTagHelperAttributes(tagHelperBlock.Attributes, tagHelperBlock.Descriptors);
|
||||
AddExecuteTagHelpers();
|
||||
|
||||
Builder.Pop(); // Pop TagHelperIRNode
|
||||
}
|
||||
|
||||
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public override void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public override void VisitTagHelperPrefixDirectiveSpan(TagHelperPrefixDirectiveChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
private void DeclareTagHelperFields(TagHelperBlock block)
|
||||
{
|
||||
var declareFieldsNode = Class.Children.OfType<DeclareTagHelperFieldsIRNode>().SingleOrDefault();
|
||||
if (declareFieldsNode == null)
|
||||
{
|
||||
declareFieldsNode = new DeclareTagHelperFieldsIRNode();
|
||||
declareFieldsNode.Parent = Class;
|
||||
|
||||
var methodIndex = Class.Children.IndexOf(Method);
|
||||
Class.Children.Insert(methodIndex, declareFieldsNode);
|
||||
}
|
||||
|
||||
foreach (var descriptor in block.Descriptors)
|
||||
{
|
||||
declareFieldsNode.UsedTagHelperTypeNames.Add(descriptor.TypeName);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTagHelperCreation(IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
var createTagHelper = new CreateTagHelperIRNode()
|
||||
{
|
||||
TagHelperTypeName = descriptor.TypeName,
|
||||
Descriptor = descriptor
|
||||
};
|
||||
|
||||
Builder.Add(createTagHelper);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTagHelperAttributes(IList<TagHelperAttributeNode> attributes, IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
var renderedBoundAttributeNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
var attributeValueNode = attribute.Value;
|
||||
var associatedDescriptors = descriptors.Where(descriptor =>
|
||||
descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name)));
|
||||
|
||||
if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attribute.Name))
|
||||
{
|
||||
if (attributeValueNode == null)
|
||||
{
|
||||
// Minimized attributes are not valid for bound attributes. TagHelperBlockRewriter has already
|
||||
// logged an error if it was a bound attribute; so we can skip.
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var associatedDescriptor in associatedDescriptors)
|
||||
{
|
||||
var associatedAttributeDescriptor = associatedDescriptor.Attributes.First(
|
||||
attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name));
|
||||
var setTagHelperProperty = new SetTagHelperPropertyIRNode()
|
||||
{
|
||||
PropertyName = associatedAttributeDescriptor.PropertyName,
|
||||
AttributeName = attribute.Name,
|
||||
TagHelperTypeName = associatedDescriptor.TypeName,
|
||||
Descriptor = associatedAttributeDescriptor,
|
||||
ValueStyle = attribute.ValueStyle
|
||||
};
|
||||
|
||||
Builder.Push(setTagHelperProperty);
|
||||
attributeValueNode.Accept(this);
|
||||
Builder.Pop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var addHtmlAttribute = new AddTagHelperHtmlAttributeIRNode()
|
||||
{
|
||||
Name = attribute.Name,
|
||||
ValueStyle = attribute.ValueStyle
|
||||
};
|
||||
|
||||
Builder.Push(addHtmlAttribute);
|
||||
if (attributeValueNode != null)
|
||||
{
|
||||
attributeValueNode.Accept(this);
|
||||
}
|
||||
Builder.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddExecuteTagHelpers()
|
||||
{
|
||||
Builder.Add(new ExecuteTagHelpersIRNode());
|
||||
}
|
||||
|
||||
private MappingLocation BuildSourceRangeFromNode(SyntaxTreeNode node)
|
||||
{
|
||||
var location = node.Start;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
{
|
||||
public RazorEngine Engine { get; set; }
|
||||
|
||||
public int Order => 150;
|
||||
public int Order => 100;
|
||||
|
||||
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class AddTagHelperHtmlAttributeIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
internal HtmlAttributeValueStyle ValueStyle { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitAddTagHelperHtmlAttribute(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitAddTagHelperHtmlAttribute(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class CreateTagHelperIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = EmptyArray;
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public string TagHelperTypeName { get; set; }
|
||||
|
||||
internal TagHelperDescriptor Descriptor { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitCreateTagHelper(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitCreateTagHelper(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class DeclareTagHelperFieldsIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = EmptyArray;
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public ISet<string> UsedTagHelperTypeNames { get; set; } = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitDeclareTagHelperFields(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitDeclareTagHelperFields(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class ExecuteTagHelpersIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitExecuteTagHelpers(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitExecuteTagHelpers(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class InitializeTagHelperStructureIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public string TagName { get; set; }
|
||||
|
||||
internal TagMode TagMode { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitInitializeTagHelperStructure(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitInitializeTagHelperStructure(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,5 +93,40 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,5 +94,40 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
internal virtual TResult VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class SetTagHelperPropertyIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public string TagHelperTypeName { get; set; }
|
||||
|
||||
public string PropertyName { get; set; }
|
||||
|
||||
public string AttributeName { get; set; }
|
||||
|
||||
internal HtmlAttributeValueStyle ValueStyle { get; set; }
|
||||
|
||||
internal TagHelperAttributeDescriptor Descriptor { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitSetTagHelperProperty(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitSetTagHelperProperty(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
internal class TagHelperIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override MappingLocation SourceRange { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitTagHelper(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitTagHelper(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitAddTagHelperSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
|
|
|
|||
|
|
@ -112,5 +112,25 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
public virtual void VisitStartCommentBlock(RazorCommentChunkGenerator chunkGenerator, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStartTagHelperBlock(TagHelperChunkGenerator chunkGenerator, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndTagHelperBlock(TagHelperChunkGenerator chunkGenerator, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitTagHelperPrefixDirectiveSpan(TagHelperPrefixDirectiveChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitRemoveTagHelperSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
|
|
|
|||
|
|
@ -86,10 +86,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public override void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartTagHelperBlock(this, block);
|
||||
}
|
||||
|
||||
public override void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndTagHelperBlock(this, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitTagHelperPrefixDirectiveSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
|
||||
// Syntax Tree passes
|
||||
builder.Features.Add(new DefaultDirectiveSyntaxTreePass());
|
||||
builder.Features.Add(new TagHelperBinderSyntaxTreePass());
|
||||
builder.Features.Add(new HtmlNodeOptimizationPass());
|
||||
builder.Features.Add(new TagHelperBinderSyntaxTreePass());
|
||||
|
||||
// IR Passes
|
||||
builder.Features.Add(new DefaultDirectiveIRPass());
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
{
|
||||
public RazorEngine Engine { get; set; }
|
||||
|
||||
public int Order => 100;
|
||||
public int Order => 150;
|
||||
|
||||
public RazorSyntaxTree Execute(RazorCodeDocument document, RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||
{
|
||||
|
|
@ -86,6 +87,31 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
|||
WriteContentNode(node, node.Content);
|
||||
}
|
||||
|
||||
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
WriteContentNode(node, node.UsedTagHelperTypeNames.ToArray());
|
||||
}
|
||||
|
||||
internal override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TagName, string.Format("{0}.{1}", nameof(TagMode), node.TagMode));
|
||||
}
|
||||
|
||||
internal override void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TagHelperTypeName);
|
||||
}
|
||||
|
||||
internal override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
WriteContentNode(node, node.AttributeName, node.PropertyName, string.Format("HtmlAttributeValueStyle.{0}", node.ValueStyle));
|
||||
}
|
||||
|
||||
internal override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Name, string.Format("{0}.{1}", nameof(HtmlAttributeValueStyle), node.ValueStyle));
|
||||
}
|
||||
|
||||
protected void WriteBasicNode(RazorIRNode node)
|
||||
{
|
||||
WriteIndent();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||
{
|
||||
public class TagHelpersIntegrationTest : IntegrationTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void SimpleTagHelpers()
|
||||
{
|
||||
// Arrange
|
||||
var descriptors = new[]
|
||||
{
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
TagName = "input",
|
||||
TypeName = "InputTagHelper"
|
||||
}
|
||||
};
|
||||
|
||||
var engine = RazorEngine.Create(
|
||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
||||
var document = CreateCodeDocument();
|
||||
|
||||
// Act
|
||||
engine.Process(document);
|
||||
|
||||
// Assert
|
||||
AssertIRMatchesBaseline(document.GetIRDocument());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TagHelpersWithBoundAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var descriptors = new[]
|
||||
{
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
TagName = "input",
|
||||
TypeName = "InputTagHelper",
|
||||
Attributes = new[] { new TagHelperAttributeDescriptor
|
||||
{
|
||||
Name = "bound",
|
||||
PropertyName = "FooProp",
|
||||
TypeName = "System.String"
|
||||
} }
|
||||
}
|
||||
};
|
||||
|
||||
var engine = RazorEngine.Create(
|
||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
||||
var document = CreateCodeDocument();
|
||||
|
||||
// Act
|
||||
engine.Process(document);
|
||||
|
||||
// Assert
|
||||
AssertIRMatchesBaseline(document.GetIRDocument());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedTagHelpers()
|
||||
{
|
||||
// Arrange
|
||||
var descriptors = new[]
|
||||
{
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
TagName = "p",
|
||||
TypeName = "PTagHelper"
|
||||
},
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
TagName = "form",
|
||||
TypeName = "FormTagHelper"
|
||||
},
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
TagName = "input",
|
||||
TypeName = "InputTagHelper",
|
||||
Attributes = new[] { new TagHelperAttributeDescriptor
|
||||
{
|
||||
Name = "value",
|
||||
PropertyName = "FooProp",
|
||||
TypeName = "System.String"
|
||||
} }
|
||||
}
|
||||
};
|
||||
|
||||
var engine = RazorEngine.Create(
|
||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
||||
var document = CreateCodeDocument();
|
||||
|
||||
// Act
|
||||
engine.Process(document);
|
||||
|
||||
// Assert
|
||||
AssertIRMatchesBaseline(document.GetIRDocument());
|
||||
}
|
||||
|
||||
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
||||
{
|
||||
private readonly IEnumerable<TagHelperDescriptor> _descriptors;
|
||||
|
||||
public TestTagHelperDescriptorResolver(IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
_descriptors = descriptors;
|
||||
}
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> Resolve(TagHelperDescriptorResolutionContext resolutionContext)
|
||||
{
|
||||
return _descriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,9 @@ using static Microsoft.AspNetCore.Razor.Evolution.Intermediate.RazorIRAssert;
|
|||
using Xunit;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
|
|
@ -188,9 +191,106 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
n => Assert.IsType<ClassDeclarationIRNode>(n));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_TagHelpers()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.Create(@"<span val=""@Hello World""></span>");
|
||||
var descriptors = new[]
|
||||
{
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
TagName = "span",
|
||||
TypeName = "SpanTagHelper"
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
var irDocument = Lower(codeDocument, descriptors);
|
||||
|
||||
// Assert
|
||||
Children(irDocument,
|
||||
n => Assert.IsType<ChecksumIRNode>(n),
|
||||
n => Assert.IsType<NamespaceDeclarationIRNode>(n));
|
||||
var @namespace = irDocument.Children[1];
|
||||
Children(@namespace,
|
||||
n => Using("System", n),
|
||||
n => Using(typeof(Task).Namespace, n),
|
||||
n => Assert.IsType<ClassDeclarationIRNode>(n));
|
||||
var @class = @namespace.Children[2];
|
||||
Children(@class,
|
||||
n => TagHelperFieldDeclaration(n, "SpanTagHelper"),
|
||||
n => Assert.IsType<RazorMethodDeclarationIRNode>(n));
|
||||
var method = @class.Children[1];
|
||||
var tagHelperNode = SingleChild<TagHelperIRNode>(method);
|
||||
Children(tagHelperNode,
|
||||
n => TagHelperStructure("span", TagMode.StartTagAndEndTag, n),
|
||||
n => Assert.IsType<CreateTagHelperIRNode>(n),
|
||||
n => TagHelperHtmlAttribute(
|
||||
"val",
|
||||
HtmlAttributeValueStyle.DoubleQuotes,
|
||||
n,
|
||||
v => CSharpAttributeValue(string.Empty, "Hello", v),
|
||||
v => LiteralAttributeValue(" ", "World", v)),
|
||||
n => Assert.IsType<ExecuteTagHelpersIRNode>(n));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_TagHelpersWithBoundAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.Create("<input bound='foo' />");
|
||||
var descriptor = new TagHelperDescriptor
|
||||
{
|
||||
TagName = "input",
|
||||
TypeName = "InputTagHelper",
|
||||
Attributes = new[] { new TagHelperAttributeDescriptor
|
||||
{
|
||||
Name = "bound",
|
||||
PropertyName = "FooProp",
|
||||
TypeName = "System.String"
|
||||
} }
|
||||
};
|
||||
|
||||
// Act
|
||||
var irDocument = Lower(codeDocument, new[] { descriptor });
|
||||
|
||||
// Assert
|
||||
Children(irDocument,
|
||||
n => Assert.IsType<ChecksumIRNode>(n),
|
||||
n => Assert.IsType<NamespaceDeclarationIRNode>(n));
|
||||
var @namespace = irDocument.Children[1];
|
||||
Children(@namespace,
|
||||
n => Using("System", n),
|
||||
n => Using(typeof(Task).Namespace, n),
|
||||
n => Assert.IsType<ClassDeclarationIRNode>(n));
|
||||
var @class = @namespace.Children[2];
|
||||
Children(@class,
|
||||
n => TagHelperFieldDeclaration(n, "InputTagHelper"),
|
||||
n => Assert.IsType<RazorMethodDeclarationIRNode>(n));
|
||||
var method = @class.Children[1];
|
||||
var tagHelperNode = SingleChild<TagHelperIRNode>(method);
|
||||
Children(tagHelperNode,
|
||||
n => TagHelperStructure("input", TagMode.SelfClosing, n),
|
||||
n => Assert.IsType<CreateTagHelperIRNode>(n),
|
||||
n => SetTagHelperProperty(
|
||||
"bound",
|
||||
"FooProp",
|
||||
HtmlAttributeValueStyle.SingleQuotes,
|
||||
n,
|
||||
v => Html("foo", v)),
|
||||
n => Assert.IsType<ExecuteTagHelpersIRNode>(n));
|
||||
}
|
||||
|
||||
private DocumentIRNode Lower(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var engine = RazorEngine.Create();
|
||||
return Lower(codeDocument, Enumerable.Empty<TagHelperDescriptor>());
|
||||
}
|
||||
|
||||
private DocumentIRNode Lower(RazorCodeDocument codeDocument, IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
var engine = RazorEngine.Create(
|
||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
||||
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
|
|
@ -207,5 +307,20 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
Assert.NotNull(irDocument);
|
||||
return irDocument;
|
||||
}
|
||||
|
||||
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
||||
{
|
||||
private readonly IEnumerable<TagHelperDescriptor> _descriptors;
|
||||
|
||||
public TestTagHelperDescriptorResolver(IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
_descriptors = descriptors;
|
||||
}
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> Resolve(TagHelperDescriptorResolutionContext resolutionContext)
|
||||
{
|
||||
return _descriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
|
|
@ -188,6 +189,77 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
internal static void TagHelperFieldDeclaration(RazorIRNode node, params string[] tagHelperTypes)
|
||||
{
|
||||
var declareTagHelperFields = Assert.IsType<DeclareTagHelperFieldsIRNode>(node);
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Equal(tagHelperTypes, declareTagHelperFields.UsedTagHelperTypeNames);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(declareTagHelperFields, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void TagHelperStructure(string tagName, TagMode tagMode, RazorIRNode node)
|
||||
{
|
||||
var tagHelperStructureNode = Assert.IsType<InitializeTagHelperStructureIRNode>(node);
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Equal(tagName, tagHelperStructureNode.TagName);
|
||||
Assert.Equal(tagMode, tagHelperStructureNode.TagMode);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(tagHelperStructureNode, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void TagHelperHtmlAttribute(
|
||||
string name,
|
||||
HtmlAttributeValueStyle valueStyle,
|
||||
RazorIRNode node,
|
||||
params Action<RazorIRNode>[] valueValidators)
|
||||
{
|
||||
var tagHelperHtmlAttribute = Assert.IsType<AddTagHelperHtmlAttributeIRNode>(node);
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Equal(name, tagHelperHtmlAttribute.Name);
|
||||
Assert.Equal(valueStyle, tagHelperHtmlAttribute.ValueStyle);
|
||||
Children(tagHelperHtmlAttribute, valueValidators);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(tagHelperHtmlAttribute, tagHelperHtmlAttribute.Children, e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetTagHelperProperty(
|
||||
string name,
|
||||
string propertyName,
|
||||
HtmlAttributeValueStyle valueStyle,
|
||||
RazorIRNode node,
|
||||
params Action<RazorIRNode>[] valueValidators)
|
||||
{
|
||||
var tagHelperBoundAttribute = Assert.IsType<SetTagHelperPropertyIRNode>(node);
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Equal(name, tagHelperBoundAttribute.AttributeName);
|
||||
Assert.Equal(propertyName, tagHelperBoundAttribute.PropertyName);
|
||||
Assert.Equal(valueStyle, tagHelperBoundAttribute.ValueStyle);
|
||||
Children(tagHelperBoundAttribute, valueValidators);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(tagHelperBoundAttribute, tagHelperBoundAttribute.Children, e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class IRAssertException : XunitException
|
||||
{
|
||||
public IRAssertException(RazorIRNode node, string userMessage)
|
||||
|
|
|
|||
|
|
@ -137,8 +137,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
Assert.Collection(
|
||||
features,
|
||||
feature => Assert.IsType<DefaultDirectiveSyntaxTreePass>(feature),
|
||||
feature => Assert.IsType<TagHelperBinderSyntaxTreePass>(feature),
|
||||
feature => Assert.IsType<HtmlNodeOptimizationPass>(feature),
|
||||
feature => Assert.IsType<TagHelperBinderSyntaxTreePass>(feature),
|
||||
feature => Assert.IsType<DefaultDirectiveIRPass>(feature));
|
||||
}
|
||||
|
||||
|
|
@ -158,8 +158,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
Assert.Collection(
|
||||
features,
|
||||
feature => Assert.IsType<DefaultDirectiveSyntaxTreePass>(feature),
|
||||
feature => Assert.IsType<TagHelperBinderSyntaxTreePass>(feature),
|
||||
feature => Assert.IsType<HtmlNodeOptimizationPass>(feature),
|
||||
feature => Assert.IsType<TagHelperBinderSyntaxTreePass>(feature),
|
||||
feature => Assert.IsType<DefaultDirectiveIRPass>(feature),
|
||||
feature => Assert.IsType<RazorEngine.ConfigureDesignTimeOptions>(feature));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
@addTagHelper *, TestAssembly
|
||||
<p someattr>Hola</p>
|
||||
<form unbound="foo">
|
||||
<input value=Hello type='text' />
|
||||
</form>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
Document -
|
||||
Checksum -
|
||||
NamespaceDeclaration - -
|
||||
UsingStatement - - System
|
||||
UsingStatement - - System.Threading.Tasks
|
||||
ClassDeclaration - - - - -
|
||||
DeclareTagHelperFields - - PTagHelper - FormTagHelper - InputTagHelper
|
||||
RazorMethodDeclaration - - - - -
|
||||
HtmlContent - (0:0,0 [0] NestedTagHelpers.cshtml) -
|
||||
TagHelper -
|
||||
InitializeTagHelperStructure - - p - TagMode.StartTagAndEndTag
|
||||
HtmlContent - (43:1,12 [4] NestedTagHelpers.cshtml) - Hola
|
||||
CreateTagHelper - - PTagHelper
|
||||
AddTagHelperHtmlAttribute - - someattr - HtmlAttributeValueStyle.Minimized
|
||||
ExecuteTagHelpers -
|
||||
HtmlContent - (51:1,20 [2] NestedTagHelpers.cshtml) - \n
|
||||
TagHelper -
|
||||
InitializeTagHelperStructure - - form - TagMode.StartTagAndEndTag
|
||||
HtmlContent - (73:2,20 [6] NestedTagHelpers.cshtml) - \n
|
||||
TagHelper -
|
||||
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
||||
CreateTagHelper - - InputTagHelper
|
||||
SetTagHelperProperty - - value - FooProp - HtmlAttributeValueStyle.DoubleQuotes
|
||||
HtmlContent - (92:3,17 [5] NestedTagHelpers.cshtml) - Hello
|
||||
AddTagHelperHtmlAttribute - - type - HtmlAttributeValueStyle.SingleQuotes
|
||||
HtmlContent - (104:3,29 [4] NestedTagHelpers.cshtml) - text
|
||||
ExecuteTagHelpers -
|
||||
HtmlContent - (112:3,37 [2] NestedTagHelpers.cshtml) - \n
|
||||
CreateTagHelper - - FormTagHelper
|
||||
AddTagHelperHtmlAttribute - - unbound - HtmlAttributeValueStyle.DoubleQuotes
|
||||
HtmlContent - (68:2,15 [3] NestedTagHelpers.cshtml) - foo
|
||||
ExecuteTagHelpers -
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
@addTagHelper *, TestAssembly
|
||||
<p>Hola</p>
|
||||
<form>
|
||||
<input value='Hello' type='text' />
|
||||
</form>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
Document -
|
||||
Checksum -
|
||||
NamespaceDeclaration - -
|
||||
UsingStatement - - System
|
||||
UsingStatement - - System.Threading.Tasks
|
||||
ClassDeclaration - - - - -
|
||||
DeclareTagHelperFields - - InputTagHelper
|
||||
RazorMethodDeclaration - - - - -
|
||||
HtmlContent - (0:0,0 [0] SimpleTagHelpers.cshtml) - <p>Hola</p>\n<form>\n
|
||||
TagHelper -
|
||||
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
||||
CreateTagHelper - - InputTagHelper
|
||||
AddTagHelperHtmlAttribute - - value - HtmlAttributeValueStyle.SingleQuotes
|
||||
HtmlContent - (70:3,18 [5] SimpleTagHelpers.cshtml) - Hello
|
||||
AddTagHelperHtmlAttribute - - type - HtmlAttributeValueStyle.SingleQuotes
|
||||
HtmlContent - (83:3,31 [4] SimpleTagHelpers.cshtml) - text
|
||||
ExecuteTagHelpers -
|
||||
HtmlContent - (91:3,39 [2] SimpleTagHelpers.cshtml) - \n</form>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
@addTagHelper *, TestAssembly
|
||||
<form>
|
||||
<input bound=@Hello type='text' />
|
||||
</form>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
Document -
|
||||
Checksum -
|
||||
NamespaceDeclaration - -
|
||||
UsingStatement - - System
|
||||
UsingStatement - - System.Threading.Tasks
|
||||
ClassDeclaration - - - - -
|
||||
DeclareTagHelperFields - - InputTagHelper
|
||||
RazorMethodDeclaration - - - - -
|
||||
HtmlContent - (0:0,0 [0] TagHelpersWithBoundAttributes.cshtml) - <form>\n
|
||||
TagHelper -
|
||||
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
||||
CreateTagHelper - - InputTagHelper
|
||||
SetTagHelperProperty - - bound - FooProp - HtmlAttributeValueStyle.DoubleQuotes
|
||||
CSharpExpression - (57:2,18 [5] TagHelpersWithBoundAttributes.cshtml)
|
||||
CSharpToken - (57:2,18 [5] TagHelpersWithBoundAttributes.cshtml) - Hello
|
||||
AddTagHelperHtmlAttribute - - type - HtmlAttributeValueStyle.SingleQuotes
|
||||
HtmlContent - (69:2,30 [4] TagHelpersWithBoundAttributes.cshtml) - text
|
||||
ExecuteTagHelpers -
|
||||
HtmlContent - (77:2,38 [2] TagHelpersWithBoundAttributes.cshtml) - \n</form>
|
||||
Loading…
Reference in New Issue