Group HTML tags (dotnet/aspnetcore-tooling#6)
\n\nCommit migrated from a2d1ac4cea
This commit is contained in:
parent
ebd37599b6
commit
ad0f2a5af4
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
internal class ClassifiedSpanRewriter : SyntaxRewriter
|
internal class ClassifiedSpanRewriter : SyntaxRewriter
|
||||||
{
|
{
|
||||||
public override SyntaxNode VisitMarkupTagBlock(MarkupTagBlockSyntax node)
|
public override SyntaxNode VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
{
|
{
|
||||||
SpanContext latestSpanContext = null;
|
SpanContext latestSpanContext = null;
|
||||||
var newChildren = SyntaxListBuilder<RazorSyntaxNode>.Create();
|
var newChildren = SyntaxListBuilder<RazorSyntaxNode>.Create();
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
AddLiteralIfExists();
|
AddLiteralIfExists();
|
||||||
|
|
||||||
return SyntaxFactory.MarkupTagBlock(newChildren.ToList()).Green.CreateRed(node.Parent, node.Position);
|
return SyntaxFactory.MarkupStartTag(newChildren.ToList()).Green.CreateRed(node.Parent, node.Position);
|
||||||
|
|
||||||
void AddLiteralIfExists()
|
void AddLiteralIfExists()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,14 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
base.VisitMarkupTagHelperAttributeValue(node);
|
base.VisitMarkupTagHelperAttributeValue(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void VisitMarkupTagBlock(MarkupTagBlockSyntax node)
|
public override void VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
{
|
{
|
||||||
WriteBlock(node, BlockKindInternal.Tag, base.VisitMarkupTagBlock);
|
WriteBlock(node, BlockKindInternal.Tag, base.VisitMarkupStartTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
WriteBlock(node, BlockKindInternal.Tag, base.VisitMarkupEndTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public override void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// 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;
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
|
|
@ -41,7 +42,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var diagnostics = context.ErrorSink.Errors;
|
var diagnostics = context.ErrorSink.Errors;
|
||||||
|
|
||||||
var root = markupParser.ParseDocument().CreateRed();
|
var root = markupParser.ParseDocument().CreateRed();
|
||||||
return RazorSyntaxTree.Create(root, source, diagnostics, Options);
|
|
||||||
|
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, Options);
|
||||||
|
|
||||||
|
// Group markup elements
|
||||||
|
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
|
||||||
|
return syntaxTree;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
internal static class TagHelperBlockRewriter
|
internal static class TagHelperBlockRewriter
|
||||||
{
|
{
|
||||||
private static readonly string StringTypeName = typeof(string).FullName;
|
|
||||||
|
|
||||||
public static MarkupTagHelperStartTagSyntax Rewrite(
|
public static MarkupTagHelperStartTagSyntax Rewrite(
|
||||||
string tagName,
|
string tagName,
|
||||||
bool validStructure,
|
bool validStructure,
|
||||||
RazorParserFeatureFlags featureFlags,
|
RazorParserFeatureFlags featureFlags,
|
||||||
MarkupTagBlockSyntax tag,
|
MarkupStartTagSyntax tag,
|
||||||
TagHelperBinding bindingResult,
|
TagHelperBinding bindingResult,
|
||||||
ErrorSink errorSink,
|
ErrorSink errorSink,
|
||||||
RazorSourceDocument source)
|
RazorSourceDocument source)
|
||||||
|
|
@ -28,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TagMode GetTagMode(
|
public static TagMode GetTagMode(
|
||||||
MarkupTagBlockSyntax tagBlock,
|
MarkupStartTagSyntax tagBlock,
|
||||||
TagHelperBinding bindingResult,
|
TagHelperBinding bindingResult,
|
||||||
ErrorSink errorSink)
|
ErrorSink errorSink)
|
||||||
{
|
{
|
||||||
|
|
@ -57,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
private static SyntaxList<RazorSyntaxNode> GetRewrittenChildren(
|
private static SyntaxList<RazorSyntaxNode> GetRewrittenChildren(
|
||||||
string tagName,
|
string tagName,
|
||||||
bool validStructure,
|
bool validStructure,
|
||||||
MarkupTagBlockSyntax tagBlock,
|
MarkupStartTagSyntax tagBlock,
|
||||||
TagHelperBinding bindingResult,
|
TagHelperBinding bindingResult,
|
||||||
RazorParserFeatureFlags featureFlags,
|
RazorParserFeatureFlags featureFlags,
|
||||||
ErrorSink errorSink,
|
ErrorSink errorSink,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelperPrefix, IEnumerable<TagHelperDescriptor> descriptors)
|
public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelperPrefix, IEnumerable<TagHelperDescriptor> descriptors)
|
||||||
{
|
{
|
||||||
var errorSink = new ErrorSink();
|
var errorSink = new ErrorSink();
|
||||||
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
|
|
||||||
|
|
||||||
var rewriter = new Rewriter(
|
var rewriter = new Rewriter(
|
||||||
syntaxTree.Source,
|
syntaxTree.Source,
|
||||||
|
|
@ -33,8 +32,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var diagnostics = CombineErrors(syntaxTree.Diagnostics, errorList).OrderBy(error => error.Span.AbsoluteIndex);
|
var diagnostics = CombineErrors(syntaxTree.Diagnostics, errorList).OrderBy(error => error.Span.AbsoluteIndex);
|
||||||
|
|
||||||
var newSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, diagnostics, syntaxTree.Options);
|
var newSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, diagnostics, syntaxTree.Options);
|
||||||
newSyntaxTree = MarkupElementRewriter.RemoveMarkupElements(newSyntaxTree);
|
|
||||||
|
|
||||||
return newSyntaxTree;
|
return newSyntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +100,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
TagHelperInfo tagHelperInfo = null;
|
TagHelperInfo tagHelperInfo = null;
|
||||||
|
|
||||||
// Visit the start tag.
|
// Visit the start tag.
|
||||||
var startTag = (MarkupTagBlockSyntax)Visit(node.StartTag);
|
var startTag = (MarkupStartTagSyntax)Visit(node.StartTag);
|
||||||
if (startTag != null)
|
if (startTag != null)
|
||||||
{
|
{
|
||||||
var tagName = startTag.GetTagName();
|
var tagName = startTag.GetTagName();
|
||||||
|
|
@ -145,7 +142,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Non-TagHelper tag.
|
// Non-TagHelper tag.
|
||||||
ValidateParentAllowsPlainTag(startTag);
|
ValidateParentAllowsPlainStartTag(startTag);
|
||||||
|
|
||||||
if (!startTag.IsSelfClosing() && !startTag.IsVoidElement())
|
if (!startTag.IsSelfClosing() && !startTag.IsVoidElement())
|
||||||
{
|
{
|
||||||
|
|
@ -159,7 +156,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var body = VisitList(node.Body);
|
var body = VisitList(node.Body);
|
||||||
|
|
||||||
// Visit end tag.
|
// Visit end tag.
|
||||||
var endTag = (MarkupTagBlockSyntax)Visit(node.EndTag);
|
var endTag = (MarkupEndTagSyntax)Visit(node.EndTag);
|
||||||
if (endTag != null)
|
if (endTag != null)
|
||||||
{
|
{
|
||||||
var tagName = endTag.GetTagName();
|
var tagName = endTag.GetTagName();
|
||||||
|
|
@ -181,9 +178,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
// Standalone end tag. We may need to error if it is not supposed to be here.
|
// Standalone end tag. We may need to error if it is not supposed to be here.
|
||||||
// If there was a corresponding start tag, we would have already added this error.
|
// If there was a corresponding start tag, we would have already added this error.
|
||||||
ValidateParentAllowsPlainTag(endTag);
|
ValidateParentAllowsPlainEndTag(endTag);
|
||||||
}
|
}
|
||||||
else if (!endTag.IsVoidElement())
|
else
|
||||||
{
|
{
|
||||||
// Since a start tag exists, we must already be tracking it.
|
// Since a start tag exists, we must already be tracking it.
|
||||||
// Pop the stack as we're done with the end tag.
|
// Pop the stack as we're done with the end tag.
|
||||||
|
|
@ -205,7 +202,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
public override SyntaxNode VisitMarkupTextLiteral(MarkupTextLiteralSyntax node)
|
public override SyntaxNode VisitMarkupTextLiteral(MarkupTextLiteralSyntax node)
|
||||||
{
|
{
|
||||||
var tagParent = node.FirstAncestorOrSelf<SyntaxNode>(n => n is MarkupTagBlockSyntax);
|
var tagParent = node.FirstAncestorOrSelf<SyntaxNode>(n => n is MarkupStartTagSyntax || n is MarkupEndTagSyntax);
|
||||||
var isPartofTagBlock = tagParent != null;
|
var isPartofTagBlock = tagParent != null;
|
||||||
if (!isPartofTagBlock)
|
if (!isPartofTagBlock)
|
||||||
{
|
{
|
||||||
|
|
@ -215,13 +212,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return base.VisitMarkupTextLiteral(node);
|
return base.VisitMarkupTextLiteral(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryRewriteTagHelperStart(MarkupTagBlockSyntax tagBlock, out MarkupTagHelperStartTagSyntax rewritten, out TagHelperInfo tagHelperInfo)
|
private bool TryRewriteTagHelperStart(MarkupStartTagSyntax startTag, out MarkupTagHelperStartTagSyntax rewritten, out TagHelperInfo tagHelperInfo)
|
||||||
{
|
{
|
||||||
rewritten = null;
|
rewritten = null;
|
||||||
tagHelperInfo = null;
|
tagHelperInfo = null;
|
||||||
|
|
||||||
// Get tag name of the current block
|
// Get tag name of the current block
|
||||||
var tagName = tagBlock.GetTagName();
|
var tagName = startTag.GetTagName();
|
||||||
|
|
||||||
// Could not determine tag name, it can't be a TagHelper, continue on and track the element.
|
// Could not determine tag name, it can't be a TagHelper, continue on and track the element.
|
||||||
if (tagName == null)
|
if (tagName == null)
|
||||||
|
|
@ -231,7 +228,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
TagHelperBinding tagHelperBinding;
|
TagHelperBinding tagHelperBinding;
|
||||||
|
|
||||||
if (!IsPotentialTagHelper(tagName, tagBlock))
|
if (!IsPotentialTagHelperStart(tagName, startTag))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +237,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var tagNameScope = tracker?.TagName ?? string.Empty;
|
var tagNameScope = tracker?.TagName ?? string.Empty;
|
||||||
|
|
||||||
// We're now in a start tag block, we first need to see if the tag block is a tag helper.
|
// We're now in a start tag block, we first need to see if the tag block is a tag helper.
|
||||||
var elementAttributes = GetAttributeNameValuePairs(tagBlock);
|
var elementAttributes = GetAttributeNameValuePairs(startTag);
|
||||||
|
|
||||||
tagHelperBinding = _tagHelperBinder.GetBinding(
|
tagHelperBinding = _tagHelperBinder.GetBinding(
|
||||||
tagName,
|
tagName,
|
||||||
|
|
@ -264,29 +261,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidateParentAllowsTagHelper(tagName, tagBlock);
|
ValidateParentAllowsTagHelper(tagName, startTag);
|
||||||
ValidateBinding(tagHelperBinding, tagName, tagBlock);
|
ValidateBinding(tagHelperBinding, tagName, startTag);
|
||||||
|
|
||||||
// We're in a start TagHelper block.
|
// We're in a start TagHelper block.
|
||||||
var validTagStructure = ValidateTagSyntax(tagName, tagBlock);
|
var validTagStructure = ValidateStartTagSyntax(tagName, startTag);
|
||||||
|
|
||||||
var startTag = TagHelperBlockRewriter.Rewrite(
|
var rewrittenStartTag = TagHelperBlockRewriter.Rewrite(
|
||||||
tagName,
|
tagName,
|
||||||
validTagStructure,
|
validTagStructure,
|
||||||
_featureFlags,
|
_featureFlags,
|
||||||
tagBlock,
|
startTag,
|
||||||
tagHelperBinding,
|
tagHelperBinding,
|
||||||
_errorSink,
|
_errorSink,
|
||||||
_source);
|
_source);
|
||||||
|
|
||||||
var tagMode = TagHelperBlockRewriter.GetTagMode(tagBlock, tagHelperBinding, _errorSink);
|
var tagMode = TagHelperBlockRewriter.GetTagMode(startTag, tagHelperBinding, _errorSink);
|
||||||
tagHelperInfo = new TagHelperInfo(tagName, tagMode, tagHelperBinding);
|
tagHelperInfo = new TagHelperInfo(tagName, tagMode, tagHelperBinding);
|
||||||
rewritten = startTag;
|
rewritten = rewrittenStartTag;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryRewriteTagHelperEnd(MarkupTagBlockSyntax tagBlock, out MarkupTagHelperEndTagSyntax rewritten)
|
private bool TryRewriteTagHelperEnd(MarkupEndTagSyntax tagBlock, out MarkupTagHelperEndTagSyntax rewritten)
|
||||||
{
|
{
|
||||||
rewritten = null;
|
rewritten = null;
|
||||||
var tagName = tagBlock.GetTagName();
|
var tagName = tagBlock.GetTagName();
|
||||||
|
|
@ -298,7 +295,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
var tracker = CurrentTagHelperTracker;
|
var tracker = CurrentTagHelperTracker;
|
||||||
var tagNameScope = tracker?.TagName ?? string.Empty;
|
var tagNameScope = tracker?.TagName ?? string.Empty;
|
||||||
if (!IsPotentialTagHelper(tagName, tagBlock))
|
if (!IsPotentialTagHelperEnd(tagName, tagBlock))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +312,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidateTagSyntax(tagName, tagBlock);
|
ValidateEndTagSyntax(tagName, tagBlock);
|
||||||
|
|
||||||
_trackerStack.Pop();
|
_trackerStack.Pop();
|
||||||
}
|
}
|
||||||
|
|
@ -360,10 +357,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal IReadOnlyList<KeyValuePair<string, string>> GetAttributeNameValuePairs(MarkupTagBlockSyntax tagBlock)
|
internal IReadOnlyList<KeyValuePair<string, string>> GetAttributeNameValuePairs(MarkupStartTagSyntax tagBlock)
|
||||||
{
|
{
|
||||||
// Need to calculate how many children we should take that represent the attributes.
|
// Need to calculate how many children we should take that represent the attributes.
|
||||||
var childrenOffset = IsPartialTag(tagBlock) ? 0 : 1;
|
var childrenOffset = IsPartialStartTag(tagBlock) ? 0 : 1;
|
||||||
var childCount = tagBlock.Children.Count - childrenOffset;
|
var childCount = tagBlock.Children.Count - childrenOffset;
|
||||||
|
|
||||||
if (childCount <= 1)
|
if (childCount <= 1)
|
||||||
|
|
@ -436,19 +433,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateParentAllowsTagHelper(string tagName, MarkupTagBlockSyntax tagBlock)
|
private void ValidateParentAllowsTagHelper(string tagName, MarkupStartTagSyntax tagBlock)
|
||||||
{
|
{
|
||||||
if (HasAllowedChildren() &&
|
if (HasAllowedChildren() &&
|
||||||
!CurrentTagHelperTracker.PrefixedAllowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase))
|
!CurrentTagHelperTracker.PrefixedAllowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
OnAllowedChildrenTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
|
OnAllowedChildrenStartTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateBinding(
|
private void ValidateBinding(
|
||||||
TagHelperBinding bindingResult,
|
TagHelperBinding bindingResult,
|
||||||
string tagName,
|
string tagName,
|
||||||
MarkupTagBlockSyntax tagBlock)
|
MarkupStartTagSyntax tagBlock)
|
||||||
{
|
{
|
||||||
// Ensure that all descriptors associated with this tag have appropriate TagStructures. Cannot have
|
// Ensure that all descriptors associated with this tag have appropriate TagStructures. Cannot have
|
||||||
// multiple descriptors that expect different TagStructures (other than TagStructure.Unspecified).
|
// multiple descriptors that expect different TagStructures (other than TagStructure.Unspecified).
|
||||||
|
|
@ -479,12 +476,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidateTagSyntax(string tagName, MarkupTagBlockSyntax tag)
|
private bool ValidateStartTagSyntax(string tagName, MarkupStartTagSyntax tag)
|
||||||
{
|
{
|
||||||
// We assume an invalid syntax until we verify that the tag meets all of our "valid syntax" criteria.
|
// We assume an invalid syntax until we verify that the tag meets all of our "valid syntax" criteria.
|
||||||
if (IsPartialTag(tag))
|
if (IsPartialStartTag(tag))
|
||||||
{
|
{
|
||||||
var errorStart = GetTagDeclarationErrorStart(tag);
|
var errorStart = GetStartTagDeclarationErrorStart(tag, _source);
|
||||||
|
|
||||||
_errorSink.OnError(
|
_errorSink.OnError(
|
||||||
RazorDiagnosticFactory.CreateParsing_TagHelperMissingCloseAngle(
|
RazorDiagnosticFactory.CreateParsing_TagHelperMissingCloseAngle(
|
||||||
|
|
@ -496,7 +493,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsPotentialTagHelper(string tagName, MarkupTagBlockSyntax childBlock)
|
private bool ValidateEndTagSyntax(string tagName, MarkupEndTagSyntax tag)
|
||||||
|
{
|
||||||
|
// We assume an invalid syntax until we verify that the tag meets all of our "valid syntax" criteria.
|
||||||
|
if (IsPartialEndTag(tag))
|
||||||
|
{
|
||||||
|
var errorStart = GetEndTagDeclarationErrorStart(tag, _source);
|
||||||
|
|
||||||
|
_errorSink.OnError(
|
||||||
|
RazorDiagnosticFactory.CreateParsing_TagHelperMissingCloseAngle(
|
||||||
|
new SourceSpan(errorStart, tagName.Length), tagName));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPotentialTagHelperStart(string tagName, MarkupStartTagSyntax childBlock)
|
||||||
{
|
{
|
||||||
Debug.Assert(childBlock.Children.Count > 0);
|
Debug.Assert(childBlock.Children.Count > 0);
|
||||||
var child = childBlock.Children[0];
|
var child = childBlock.Children[0];
|
||||||
|
|
@ -505,14 +519,37 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
child.Kind != SyntaxKind.MarkupTransition;
|
child.Kind != SyntaxKind.MarkupTransition;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceLocation GetTagDeclarationErrorStart(MarkupTagBlockSyntax tagBlock)
|
private bool IsPotentialTagHelperEnd(string tagName, MarkupEndTagSyntax childBlock)
|
||||||
{
|
{
|
||||||
var advanceBy = IsEndTag(tagBlock) ? "</" : "<";
|
Debug.Assert(childBlock.Children.Count > 0);
|
||||||
|
var child = childBlock.Children[0];
|
||||||
|
|
||||||
return SourceLocationTracker.Advance(tagBlock.GetSourceLocation(_source), advanceBy);
|
return !string.Equals(tagName, SyntaxConstants.TextTagName, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
child.Kind != SyntaxKind.MarkupTransition;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPartialTag(MarkupTagBlockSyntax tagBlock)
|
private static bool IsPartialStartTag(MarkupStartTagSyntax tagBlock)
|
||||||
|
{
|
||||||
|
// No need to validate the tag end because in order to be a tag block it must start with '<'.
|
||||||
|
var tagEnd = tagBlock.Children[tagBlock.Children.Count - 1];
|
||||||
|
|
||||||
|
// If our tag end is not a markup span it means it's some sort of code SyntaxTreeNode (not a valid format)
|
||||||
|
if (tagEnd != null && tagEnd is MarkupTextLiteralSyntax tagEndLiteral)
|
||||||
|
{
|
||||||
|
var endToken = tagEndLiteral.LiteralTokens.Count > 0 ?
|
||||||
|
tagEndLiteral.LiteralTokens[tagEndLiteral.LiteralTokens.Count - 1] :
|
||||||
|
null;
|
||||||
|
|
||||||
|
if (endToken != null && endToken.Kind == SyntaxKind.CloseAngle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsPartialEndTag(MarkupEndTagSyntax tagBlock)
|
||||||
{
|
{
|
||||||
// No need to validate the tag end because in order to be a tag block it must start with '<'.
|
// No need to validate the tag end because in order to be a tag block it must start with '<'.
|
||||||
var tagEnd = tagBlock.Children[tagBlock.Children.Count - 1];
|
var tagEnd = tagBlock.Children[tagBlock.Children.Count - 1];
|
||||||
|
|
@ -566,7 +603,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateParentAllowsPlainTag(MarkupTagBlockSyntax tagBlock)
|
private void ValidateParentAllowsPlainStartTag(MarkupStartTagSyntax tagBlock)
|
||||||
{
|
{
|
||||||
var tagName = tagBlock.GetTagName();
|
var tagName = tagBlock.GetTagName();
|
||||||
|
|
||||||
|
|
@ -595,7 +632,40 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var allowedChildren = tagHelperBinding != null ? CurrentTagHelperTracker.PrefixedAllowedChildren : CurrentTagHelperTracker.AllowedChildren;
|
var allowedChildren = tagHelperBinding != null ? CurrentTagHelperTracker.PrefixedAllowedChildren : CurrentTagHelperTracker.AllowedChildren;
|
||||||
if (!allowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase))
|
if (!allowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
OnAllowedChildrenTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
|
OnAllowedChildrenStartTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateParentAllowsPlainEndTag(MarkupEndTagSyntax tagBlock)
|
||||||
|
{
|
||||||
|
var tagName = tagBlock.GetTagName();
|
||||||
|
|
||||||
|
// Treat partial tags such as '</' which have no tag names as content.
|
||||||
|
if (string.IsNullOrEmpty(tagName))
|
||||||
|
{
|
||||||
|
var firstChild = tagBlock.Children.First();
|
||||||
|
Debug.Assert(firstChild is MarkupTextLiteralSyntax || firstChild is MarkupTransitionSyntax);
|
||||||
|
|
||||||
|
ValidateParentAllowsContent(tagBlock.Children.First());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasAllowedChildren())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagHelperBinding = _tagHelperBinder.GetBinding(
|
||||||
|
tagName,
|
||||||
|
attributes: Array.Empty<KeyValuePair<string, string>>(),
|
||||||
|
parentTagName: CurrentParentTagName,
|
||||||
|
parentIsTagHelper: CurrentParentIsTagHelper);
|
||||||
|
|
||||||
|
// If we found a binding for the current tag, then it is a tag helper. Use the prefixed allowed children to compare.
|
||||||
|
var allowedChildren = tagHelperBinding != null ? CurrentTagHelperTracker.PrefixedAllowedChildren : CurrentTagHelperTracker.AllowedChildren;
|
||||||
|
if (!allowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
OnAllowedChildrenEndTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -632,15 +702,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return commentParent != null;
|
return commentParent != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnAllowedChildrenTagError(
|
private static void OnAllowedChildrenStartTagError(
|
||||||
TagHelperTracker tracker,
|
TagHelperTracker tracker,
|
||||||
string tagName,
|
string tagName,
|
||||||
MarkupTagBlockSyntax tagBlock,
|
MarkupStartTagSyntax tagBlock,
|
||||||
ErrorSink errorSink,
|
ErrorSink errorSink,
|
||||||
RazorSourceDocument source)
|
RazorSourceDocument source)
|
||||||
{
|
{
|
||||||
var allowedChildrenString = string.Join(", ", tracker.AllowedChildren);
|
var allowedChildrenString = string.Join(", ", tracker.AllowedChildren);
|
||||||
var errorStart = GetTagDeclarationErrorStart(tagBlock, source);
|
var errorStart = GetStartTagDeclarationErrorStart(tagBlock, source);
|
||||||
|
|
||||||
errorSink.OnError(
|
errorSink.OnError(
|
||||||
RazorDiagnosticFactory.CreateTagHelper_InvalidNestedTag(
|
RazorDiagnosticFactory.CreateTagHelper_InvalidNestedTag(
|
||||||
|
|
@ -650,21 +720,32 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
allowedChildrenString));
|
allowedChildrenString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SourceLocation GetTagDeclarationErrorStart(MarkupTagBlockSyntax tagBlock, RazorSourceDocument source)
|
private static void OnAllowedChildrenEndTagError(
|
||||||
|
TagHelperTracker tracker,
|
||||||
|
string tagName,
|
||||||
|
MarkupEndTagSyntax tagBlock,
|
||||||
|
ErrorSink errorSink,
|
||||||
|
RazorSourceDocument source)
|
||||||
{
|
{
|
||||||
var advanceBy = IsEndTag(tagBlock) ? "</" : "<";
|
var allowedChildrenString = string.Join(", ", tracker.AllowedChildren);
|
||||||
|
var errorStart = GetEndTagDeclarationErrorStart(tagBlock, source);
|
||||||
|
|
||||||
return SourceLocationTracker.Advance(tagBlock.GetSourceLocation(source), advanceBy);
|
errorSink.OnError(
|
||||||
|
RazorDiagnosticFactory.CreateTagHelper_InvalidNestedTag(
|
||||||
|
new SourceSpan(errorStart, tagName.Length),
|
||||||
|
tagName,
|
||||||
|
tracker.TagName,
|
||||||
|
allowedChildrenString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsEndTag(MarkupTagBlockSyntax tagBlock)
|
private static SourceLocation GetStartTagDeclarationErrorStart(MarkupStartTagSyntax tagBlock, RazorSourceDocument source)
|
||||||
{
|
{
|
||||||
var childSpan = (MarkupTextLiteralSyntax)tagBlock.Children.First();
|
return SourceLocationTracker.Advance(tagBlock.GetSourceLocation(source), "<");
|
||||||
|
}
|
||||||
|
|
||||||
// We grab the token that could be forward slash
|
private static SourceLocation GetEndTagDeclarationErrorStart(MarkupEndTagSyntax tagBlock, RazorSourceDocument source)
|
||||||
var relevantToken = childSpan.LiteralTokens[childSpan.LiteralTokens.Count == 1 ? 0 : 1];
|
{
|
||||||
|
return SourceLocationTracker.Advance(tagBlock.GetSourceLocation(source), "</");
|
||||||
return relevantToken.Kind == SyntaxKind.ForwardSlash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TagTracker
|
private class TagTracker
|
||||||
|
|
|
||||||
|
|
@ -1441,11 +1441,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
|
|
||||||
internal sealed partial class MarkupElementSyntax : MarkupSyntaxNode
|
internal sealed partial class MarkupElementSyntax : MarkupSyntaxNode
|
||||||
{
|
{
|
||||||
private readonly MarkupTagBlockSyntax _startTag;
|
private readonly MarkupStartTagSyntax _startTag;
|
||||||
private readonly GreenNode _body;
|
private readonly GreenNode _body;
|
||||||
private readonly MarkupTagBlockSyntax _endTag;
|
private readonly MarkupEndTagSyntax _endTag;
|
||||||
|
|
||||||
internal MarkupElementSyntax(SyntaxKind kind, MarkupTagBlockSyntax startTag, GreenNode body, MarkupTagBlockSyntax endTag, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
internal MarkupElementSyntax(SyntaxKind kind, MarkupStartTagSyntax startTag, GreenNode body, MarkupEndTagSyntax endTag, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||||
: base(kind, diagnostics, annotations)
|
: base(kind, diagnostics, annotations)
|
||||||
{
|
{
|
||||||
SlotCount = 3;
|
SlotCount = 3;
|
||||||
|
|
@ -1467,7 +1467,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal MarkupElementSyntax(SyntaxKind kind, MarkupTagBlockSyntax startTag, GreenNode body, MarkupTagBlockSyntax endTag)
|
internal MarkupElementSyntax(SyntaxKind kind, MarkupStartTagSyntax startTag, GreenNode body, MarkupEndTagSyntax endTag)
|
||||||
: base(kind)
|
: base(kind)
|
||||||
{
|
{
|
||||||
SlotCount = 3;
|
SlotCount = 3;
|
||||||
|
|
@ -1488,9 +1488,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupTagBlockSyntax StartTag { get { return _startTag; } }
|
public MarkupStartTagSyntax StartTag { get { return _startTag; } }
|
||||||
public SyntaxList<RazorSyntaxNode> Body { get { return new SyntaxList<RazorSyntaxNode>(_body); } }
|
public SyntaxList<RazorSyntaxNode> Body { get { return new SyntaxList<RazorSyntaxNode>(_body); } }
|
||||||
public MarkupTagBlockSyntax EndTag { get { return _endTag; } }
|
public MarkupEndTagSyntax EndTag { get { return _endTag; } }
|
||||||
|
|
||||||
internal override GreenNode GetSlot(int index)
|
internal override GreenNode GetSlot(int index)
|
||||||
{
|
{
|
||||||
|
|
@ -1518,7 +1518,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
visitor.VisitMarkupElement(this);
|
visitor.VisitMarkupElement(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupElementSyntax Update(MarkupTagBlockSyntax startTag, Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> body, MarkupTagBlockSyntax endTag)
|
public MarkupElementSyntax Update(MarkupStartTagSyntax startTag, Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> body, MarkupEndTagSyntax endTag)
|
||||||
{
|
{
|
||||||
if (startTag != StartTag || body != Body || endTag != EndTag)
|
if (startTag != StartTag || body != Body || endTag != EndTag)
|
||||||
{
|
{
|
||||||
|
|
@ -1546,6 +1546,168 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed partial class MarkupStartTagSyntax : RazorBlockSyntax
|
||||||
|
{
|
||||||
|
private readonly GreenNode _children;
|
||||||
|
|
||||||
|
internal MarkupStartTagSyntax(SyntaxKind kind, GreenNode children, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||||
|
: base(kind, diagnostics, annotations)
|
||||||
|
{
|
||||||
|
SlotCount = 1;
|
||||||
|
if (children != null)
|
||||||
|
{
|
||||||
|
AdjustFlagsAndWidth(children);
|
||||||
|
_children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal MarkupStartTagSyntax(SyntaxKind kind, GreenNode children)
|
||||||
|
: base(kind)
|
||||||
|
{
|
||||||
|
SlotCount = 1;
|
||||||
|
if (children != null)
|
||||||
|
{
|
||||||
|
AdjustFlagsAndWidth(children);
|
||||||
|
_children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxList<RazorSyntaxNode> Children { get { return new SyntaxList<RazorSyntaxNode>(_children); } }
|
||||||
|
|
||||||
|
internal override GreenNode GetSlot(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return _children;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||||
|
{
|
||||||
|
return new Syntax.MarkupStartTagSyntax(this, parent, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TResult Accept<TResult>(SyntaxVisitor<TResult> visitor)
|
||||||
|
{
|
||||||
|
return visitor.VisitMarkupStartTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Accept(SyntaxVisitor visitor)
|
||||||
|
{
|
||||||
|
visitor.VisitMarkupStartTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkupStartTagSyntax Update(Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
if (children != Children)
|
||||||
|
{
|
||||||
|
var newNode = SyntaxFactory.MarkupStartTag(children);
|
||||||
|
var diags = GetDiagnostics();
|
||||||
|
if (diags != null && diags.Length > 0)
|
||||||
|
newNode = newNode.WithDiagnosticsGreen(diags);
|
||||||
|
var annotations = GetAnnotations();
|
||||||
|
if (annotations != null && annotations.Length > 0)
|
||||||
|
newNode = newNode.WithAnnotationsGreen(annotations);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||||
|
{
|
||||||
|
return new MarkupStartTagSyntax(Kind, _children, diagnostics, GetAnnotations());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||||
|
{
|
||||||
|
return new MarkupStartTagSyntax(Kind, _children, GetDiagnostics(), annotations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed partial class MarkupEndTagSyntax : RazorBlockSyntax
|
||||||
|
{
|
||||||
|
private readonly GreenNode _children;
|
||||||
|
|
||||||
|
internal MarkupEndTagSyntax(SyntaxKind kind, GreenNode children, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||||
|
: base(kind, diagnostics, annotations)
|
||||||
|
{
|
||||||
|
SlotCount = 1;
|
||||||
|
if (children != null)
|
||||||
|
{
|
||||||
|
AdjustFlagsAndWidth(children);
|
||||||
|
_children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal MarkupEndTagSyntax(SyntaxKind kind, GreenNode children)
|
||||||
|
: base(kind)
|
||||||
|
{
|
||||||
|
SlotCount = 1;
|
||||||
|
if (children != null)
|
||||||
|
{
|
||||||
|
AdjustFlagsAndWidth(children);
|
||||||
|
_children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxList<RazorSyntaxNode> Children { get { return new SyntaxList<RazorSyntaxNode>(_children); } }
|
||||||
|
|
||||||
|
internal override GreenNode GetSlot(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return _children;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||||
|
{
|
||||||
|
return new Syntax.MarkupEndTagSyntax(this, parent, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TResult Accept<TResult>(SyntaxVisitor<TResult> visitor)
|
||||||
|
{
|
||||||
|
return visitor.VisitMarkupEndTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Accept(SyntaxVisitor visitor)
|
||||||
|
{
|
||||||
|
visitor.VisitMarkupEndTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkupEndTagSyntax Update(Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
if (children != Children)
|
||||||
|
{
|
||||||
|
var newNode = SyntaxFactory.MarkupEndTag(children);
|
||||||
|
var diags = GetDiagnostics();
|
||||||
|
if (diags != null && diags.Length > 0)
|
||||||
|
newNode = newNode.WithDiagnosticsGreen(diags);
|
||||||
|
var annotations = GetAnnotations();
|
||||||
|
if (annotations != null && annotations.Length > 0)
|
||||||
|
newNode = newNode.WithAnnotationsGreen(annotations);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||||
|
{
|
||||||
|
return new MarkupEndTagSyntax(Kind, _children, diagnostics, GetAnnotations());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||||
|
{
|
||||||
|
return new MarkupEndTagSyntax(Kind, _children, GetDiagnostics(), annotations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed partial class MarkupTagHelperElementSyntax : MarkupSyntaxNode
|
internal sealed partial class MarkupTagHelperElementSyntax : MarkupSyntaxNode
|
||||||
{
|
{
|
||||||
private readonly MarkupTagHelperStartTagSyntax _startTag;
|
private readonly MarkupTagHelperStartTagSyntax _startTag;
|
||||||
|
|
@ -3383,6 +3545,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
return DefaultVisit(node);
|
return DefaultVisit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual TResult VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
|
{
|
||||||
|
return DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual TResult VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
return DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual TResult VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public virtual TResult VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
{
|
{
|
||||||
return DefaultVisit(node);
|
return DefaultVisit(node);
|
||||||
|
|
@ -3572,6 +3744,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
DefaultVisit(node);
|
DefaultVisit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
|
{
|
||||||
|
DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public virtual void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
{
|
{
|
||||||
DefaultVisit(node);
|
DefaultVisit(node);
|
||||||
|
|
@ -3786,12 +3968,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
|
|
||||||
public override GreenNode VisitMarkupElement(MarkupElementSyntax node)
|
public override GreenNode VisitMarkupElement(MarkupElementSyntax node)
|
||||||
{
|
{
|
||||||
var startTag = (MarkupTagBlockSyntax)Visit(node.StartTag);
|
var startTag = (MarkupStartTagSyntax)Visit(node.StartTag);
|
||||||
var body = VisitList(node.Body);
|
var body = VisitList(node.Body);
|
||||||
var endTag = (MarkupTagBlockSyntax)Visit(node.EndTag);
|
var endTag = (MarkupEndTagSyntax)Visit(node.EndTag);
|
||||||
return node.Update(startTag, body, endTag);
|
return node.Update(startTag, body, endTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override GreenNode VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
|
{
|
||||||
|
var children = VisitList(node.Children);
|
||||||
|
return node.Update(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override GreenNode VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
var children = VisitList(node.Children);
|
||||||
|
return node.Update(children);
|
||||||
|
}
|
||||||
|
|
||||||
public override GreenNode VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public override GreenNode VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
{
|
{
|
||||||
var startTag = (MarkupTagHelperStartTagSyntax)Visit(node.StartTag);
|
var startTag = (MarkupTagHelperStartTagSyntax)Visit(node.StartTag);
|
||||||
|
|
@ -4108,13 +4302,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MarkupElementSyntax MarkupElement(MarkupTagBlockSyntax startTag, Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> body, MarkupTagBlockSyntax endTag)
|
public static MarkupElementSyntax MarkupElement(MarkupStartTagSyntax startTag, Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> body, MarkupEndTagSyntax endTag)
|
||||||
{
|
{
|
||||||
var result = new MarkupElementSyntax(SyntaxKind.MarkupElement, startTag, body.Node, endTag);
|
var result = new MarkupElementSyntax(SyntaxKind.MarkupElement, startTag, body.Node, endTag);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MarkupStartTagSyntax MarkupStartTag(Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
var result = new MarkupStartTagSyntax(SyntaxKind.MarkupStartTag, children.Node);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MarkupEndTagSyntax MarkupEndTag(Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
var result = new MarkupEndTagSyntax(SyntaxKind.MarkupEndTag, children.Node);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static MarkupTagHelperElementSyntax MarkupTagHelperElement(MarkupTagHelperStartTagSyntax startTag, Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> body, MarkupTagHelperEndTagSyntax endTag)
|
public static MarkupTagHelperElementSyntax MarkupTagHelperElement(MarkupTagHelperStartTagSyntax startTag, Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax.SyntaxList<RazorSyntaxNode> body, MarkupTagHelperEndTagSyntax endTag)
|
||||||
{
|
{
|
||||||
if (startTag == null)
|
if (startTag == null)
|
||||||
|
|
@ -4343,6 +4551,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||||
typeof(MarkupLiteralAttributeValueSyntax),
|
typeof(MarkupLiteralAttributeValueSyntax),
|
||||||
typeof(MarkupDynamicAttributeValueSyntax),
|
typeof(MarkupDynamicAttributeValueSyntax),
|
||||||
typeof(MarkupElementSyntax),
|
typeof(MarkupElementSyntax),
|
||||||
|
typeof(MarkupStartTagSyntax),
|
||||||
|
typeof(MarkupEndTagSyntax),
|
||||||
typeof(MarkupTagHelperElementSyntax),
|
typeof(MarkupTagHelperElementSyntax),
|
||||||
typeof(MarkupTagHelperStartTagSyntax),
|
typeof(MarkupTagHelperStartTagSyntax),
|
||||||
typeof(MarkupTagHelperEndTagSyntax),
|
typeof(MarkupTagHelperEndTagSyntax),
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
return DefaultVisit(node);
|
return DefaultVisit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Called when the visitor visits a MarkupStartTagSyntax node.</summary>
|
||||||
|
public virtual TResult VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
|
{
|
||||||
|
return DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Called when the visitor visits a MarkupEndTagSyntax node.</summary>
|
||||||
|
public virtual TResult VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
return DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Called when the visitor visits a MarkupTagHelperElementSyntax node.</summary>
|
/// <summary>Called when the visitor visits a MarkupTagHelperElementSyntax node.</summary>
|
||||||
public virtual TResult VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public virtual TResult VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
{
|
{
|
||||||
|
|
@ -338,6 +350,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
DefaultVisit(node);
|
DefaultVisit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Called when the visitor visits a MarkupStartTagSyntax node.</summary>
|
||||||
|
public virtual void VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
|
{
|
||||||
|
DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Called when the visitor visits a MarkupEndTagSyntax node.</summary>
|
||||||
|
public virtual void VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
DefaultVisit(node);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Called when the visitor visits a MarkupTagHelperElementSyntax node.</summary>
|
/// <summary>Called when the visitor visits a MarkupTagHelperElementSyntax node.</summary>
|
||||||
public virtual void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public virtual void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
{
|
{
|
||||||
|
|
@ -572,12 +596,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
|
|
||||||
public override SyntaxNode VisitMarkupElement(MarkupElementSyntax node)
|
public override SyntaxNode VisitMarkupElement(MarkupElementSyntax node)
|
||||||
{
|
{
|
||||||
var startTag = (MarkupTagBlockSyntax)Visit(node.StartTag);
|
var startTag = (MarkupStartTagSyntax)Visit(node.StartTag);
|
||||||
var body = VisitList(node.Body);
|
var body = VisitList(node.Body);
|
||||||
var endTag = (MarkupTagBlockSyntax)Visit(node.EndTag);
|
var endTag = (MarkupEndTagSyntax)Visit(node.EndTag);
|
||||||
return node.Update(startTag, body, endTag);
|
return node.Update(startTag, body, endTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override SyntaxNode VisitMarkupStartTag(MarkupStartTagSyntax node)
|
||||||
|
{
|
||||||
|
var children = VisitList(node.Children);
|
||||||
|
return node.Update(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxNode VisitMarkupEndTag(MarkupEndTagSyntax node)
|
||||||
|
{
|
||||||
|
var children = VisitList(node.Children);
|
||||||
|
return node.Update(children);
|
||||||
|
}
|
||||||
|
|
||||||
public override SyntaxNode VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
public override SyntaxNode VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
|
||||||
{
|
{
|
||||||
var startTag = (MarkupTagHelperStartTagSyntax)Visit(node.StartTag);
|
var startTag = (MarkupTagHelperStartTagSyntax)Visit(node.StartTag);
|
||||||
|
|
@ -962,15 +998,39 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Creates a new MarkupElementSyntax instance.</summary>
|
/// <summary>Creates a new MarkupElementSyntax instance.</summary>
|
||||||
public static MarkupElementSyntax MarkupElement(MarkupTagBlockSyntax startTag, SyntaxList<RazorSyntaxNode> body, MarkupTagBlockSyntax endTag)
|
public static MarkupElementSyntax MarkupElement(MarkupStartTagSyntax startTag, SyntaxList<RazorSyntaxNode> body, MarkupEndTagSyntax endTag)
|
||||||
{
|
{
|
||||||
return (MarkupElementSyntax)InternalSyntax.SyntaxFactory.MarkupElement(startTag == null ? null : (InternalSyntax.MarkupTagBlockSyntax)startTag.Green, body.Node.ToGreenList<InternalSyntax.RazorSyntaxNode>(), endTag == null ? null : (InternalSyntax.MarkupTagBlockSyntax)endTag.Green).CreateRed();
|
return (MarkupElementSyntax)InternalSyntax.SyntaxFactory.MarkupElement(startTag == null ? null : (InternalSyntax.MarkupStartTagSyntax)startTag.Green, body.Node.ToGreenList<InternalSyntax.RazorSyntaxNode>(), endTag == null ? null : (InternalSyntax.MarkupEndTagSyntax)endTag.Green).CreateRed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Creates a new MarkupElementSyntax instance.</summary>
|
/// <summary>Creates a new MarkupElementSyntax instance.</summary>
|
||||||
public static MarkupElementSyntax MarkupElement(SyntaxList<RazorSyntaxNode> body = default(SyntaxList<RazorSyntaxNode>))
|
public static MarkupElementSyntax MarkupElement(SyntaxList<RazorSyntaxNode> body = default(SyntaxList<RazorSyntaxNode>))
|
||||||
{
|
{
|
||||||
return SyntaxFactory.MarkupElement(default(MarkupTagBlockSyntax), body, default(MarkupTagBlockSyntax));
|
return SyntaxFactory.MarkupElement(default(MarkupStartTagSyntax), body, default(MarkupEndTagSyntax));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a new MarkupStartTagSyntax instance.</summary>
|
||||||
|
public static MarkupStartTagSyntax MarkupStartTag(SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
return (MarkupStartTagSyntax)InternalSyntax.SyntaxFactory.MarkupStartTag(children.Node.ToGreenList<InternalSyntax.RazorSyntaxNode>()).CreateRed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a new MarkupStartTagSyntax instance.</summary>
|
||||||
|
public static MarkupStartTagSyntax MarkupStartTag()
|
||||||
|
{
|
||||||
|
return SyntaxFactory.MarkupStartTag(default(SyntaxList<RazorSyntaxNode>));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a new MarkupEndTagSyntax instance.</summary>
|
||||||
|
public static MarkupEndTagSyntax MarkupEndTag(SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
return (MarkupEndTagSyntax)InternalSyntax.SyntaxFactory.MarkupEndTag(children.Node.ToGreenList<InternalSyntax.RazorSyntaxNode>()).CreateRed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a new MarkupEndTagSyntax instance.</summary>
|
||||||
|
public static MarkupEndTagSyntax MarkupEndTag()
|
||||||
|
{
|
||||||
|
return SyntaxFactory.MarkupEndTag(default(SyntaxList<RazorSyntaxNode>));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Creates a new MarkupTagHelperElementSyntax instance.</summary>
|
/// <summary>Creates a new MarkupTagHelperElementSyntax instance.</summary>
|
||||||
|
|
|
||||||
|
|
@ -1382,16 +1382,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
|
|
||||||
internal sealed partial class MarkupElementSyntax : MarkupSyntaxNode
|
internal sealed partial class MarkupElementSyntax : MarkupSyntaxNode
|
||||||
{
|
{
|
||||||
private MarkupTagBlockSyntax _startTag;
|
private MarkupStartTagSyntax _startTag;
|
||||||
private SyntaxNode _body;
|
private SyntaxNode _body;
|
||||||
private MarkupTagBlockSyntax _endTag;
|
private MarkupEndTagSyntax _endTag;
|
||||||
|
|
||||||
internal MarkupElementSyntax(GreenNode green, SyntaxNode parent, int position)
|
internal MarkupElementSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||||
: base(green, parent, position)
|
: base(green, parent, position)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupTagBlockSyntax StartTag
|
public MarkupStartTagSyntax StartTag
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -1407,7 +1407,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupTagBlockSyntax EndTag
|
public MarkupEndTagSyntax EndTag
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -1446,7 +1446,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
visitor.VisitMarkupElement(this);
|
visitor.VisitMarkupElement(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupElementSyntax Update(MarkupTagBlockSyntax startTag, SyntaxList<RazorSyntaxNode> body, MarkupTagBlockSyntax endTag)
|
public MarkupElementSyntax Update(MarkupStartTagSyntax startTag, SyntaxList<RazorSyntaxNode> body, MarkupEndTagSyntax endTag)
|
||||||
{
|
{
|
||||||
if (startTag != StartTag || body != Body || endTag != EndTag)
|
if (startTag != StartTag || body != Body || endTag != EndTag)
|
||||||
{
|
{
|
||||||
|
|
@ -1460,7 +1460,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupElementSyntax WithStartTag(MarkupTagBlockSyntax startTag)
|
public MarkupElementSyntax WithStartTag(MarkupStartTagSyntax startTag)
|
||||||
{
|
{
|
||||||
return Update(startTag, Body, EndTag);
|
return Update(startTag, Body, EndTag);
|
||||||
}
|
}
|
||||||
|
|
@ -1470,14 +1470,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
return Update(StartTag, body, EndTag);
|
return Update(StartTag, body, EndTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupElementSyntax WithEndTag(MarkupTagBlockSyntax endTag)
|
public MarkupElementSyntax WithEndTag(MarkupEndTagSyntax endTag)
|
||||||
{
|
{
|
||||||
return Update(StartTag, Body, endTag);
|
return Update(StartTag, Body, endTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkupElementSyntax AddStartTagChildren(params RazorSyntaxNode[] items)
|
public MarkupElementSyntax AddStartTagChildren(params RazorSyntaxNode[] items)
|
||||||
{
|
{
|
||||||
var _startTag = this.StartTag ?? SyntaxFactory.MarkupTagBlock();
|
var _startTag = this.StartTag ?? SyntaxFactory.MarkupStartTag();
|
||||||
return this.WithStartTag(_startTag.WithChildren(_startTag.Children.AddRange(items)));
|
return this.WithStartTag(_startTag.WithChildren(_startTag.Children.AddRange(items)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1488,11 +1488,153 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
|
|
||||||
public MarkupElementSyntax AddEndTagChildren(params RazorSyntaxNode[] items)
|
public MarkupElementSyntax AddEndTagChildren(params RazorSyntaxNode[] items)
|
||||||
{
|
{
|
||||||
var _endTag = this.EndTag ?? SyntaxFactory.MarkupTagBlock();
|
var _endTag = this.EndTag ?? SyntaxFactory.MarkupEndTag();
|
||||||
return this.WithEndTag(_endTag.WithChildren(_endTag.Children.AddRange(items)));
|
return this.WithEndTag(_endTag.WithChildren(_endTag.Children.AddRange(items)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed partial class MarkupStartTagSyntax : RazorBlockSyntax
|
||||||
|
{
|
||||||
|
private SyntaxNode _children;
|
||||||
|
|
||||||
|
internal MarkupStartTagSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||||
|
: base(green, parent, position)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxList<RazorSyntaxNode> Children
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new SyntaxList<RazorSyntaxNode>(GetRed(ref _children, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override SyntaxNode GetNodeSlot(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return GetRedAtZero(ref _children);
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override SyntaxNode GetCachedSlot(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return _children;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TResult Accept<TResult>(SyntaxVisitor<TResult> visitor)
|
||||||
|
{
|
||||||
|
return visitor.VisitMarkupStartTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Accept(SyntaxVisitor visitor)
|
||||||
|
{
|
||||||
|
visitor.VisitMarkupStartTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkupStartTagSyntax Update(SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
if (children != Children)
|
||||||
|
{
|
||||||
|
var newNode = SyntaxFactory.MarkupStartTag(children);
|
||||||
|
var annotations = GetAnnotations();
|
||||||
|
if (annotations != null && annotations.Length > 0)
|
||||||
|
return newNode.WithAnnotations(annotations);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override RazorBlockSyntax WithChildrenCore(SyntaxList<RazorSyntaxNode> children) => WithChildren(children);
|
||||||
|
public new MarkupStartTagSyntax WithChildren(SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
return Update(children);
|
||||||
|
}
|
||||||
|
internal override RazorBlockSyntax AddChildrenCore(params RazorSyntaxNode[] items) => AddChildren(items);
|
||||||
|
|
||||||
|
public new MarkupStartTagSyntax AddChildren(params RazorSyntaxNode[] items)
|
||||||
|
{
|
||||||
|
return WithChildren(this.Children.AddRange(items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed partial class MarkupEndTagSyntax : RazorBlockSyntax
|
||||||
|
{
|
||||||
|
private SyntaxNode _children;
|
||||||
|
|
||||||
|
internal MarkupEndTagSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||||
|
: base(green, parent, position)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxList<RazorSyntaxNode> Children
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new SyntaxList<RazorSyntaxNode>(GetRed(ref _children, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override SyntaxNode GetNodeSlot(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return GetRedAtZero(ref _children);
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override SyntaxNode GetCachedSlot(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return _children;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TResult Accept<TResult>(SyntaxVisitor<TResult> visitor)
|
||||||
|
{
|
||||||
|
return visitor.VisitMarkupEndTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Accept(SyntaxVisitor visitor)
|
||||||
|
{
|
||||||
|
visitor.VisitMarkupEndTag(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkupEndTagSyntax Update(SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
if (children != Children)
|
||||||
|
{
|
||||||
|
var newNode = SyntaxFactory.MarkupEndTag(children);
|
||||||
|
var annotations = GetAnnotations();
|
||||||
|
if (annotations != null && annotations.Length > 0)
|
||||||
|
return newNode.WithAnnotations(annotations);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override RazorBlockSyntax WithChildrenCore(SyntaxList<RazorSyntaxNode> children) => WithChildren(children);
|
||||||
|
public new MarkupEndTagSyntax WithChildren(SyntaxList<RazorSyntaxNode> children)
|
||||||
|
{
|
||||||
|
return Update(children);
|
||||||
|
}
|
||||||
|
internal override RazorBlockSyntax AddChildrenCore(params RazorSyntaxNode[] items) => AddChildren(items);
|
||||||
|
|
||||||
|
public new MarkupEndTagSyntax AddChildren(params RazorSyntaxNode[] items)
|
||||||
|
{
|
||||||
|
return WithChildren(this.Children.AddRange(items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed partial class MarkupTagHelperElementSyntax : MarkupSyntaxNode
|
internal sealed partial class MarkupTagHelperElementSyntax : MarkupSyntaxNode
|
||||||
{
|
{
|
||||||
private MarkupTagHelperStartTagSyntax _startTag;
|
private MarkupTagHelperStartTagSyntax _startTag;
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
return newSyntaxTree;
|
return newSyntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RazorSyntaxTree RemoveMarkupElements(RazorSyntaxTree syntaxTree)
|
|
||||||
{
|
|
||||||
var rewriter = new RemoveMarkupElementRewriter();
|
|
||||||
var rewrittenRoot = rewriter.Visit(syntaxTree.Root);
|
|
||||||
|
|
||||||
var newSyntaxTree = RazorSyntaxTree.Create(rewrittenRoot, syntaxTree.Source, syntaxTree.Diagnostics, syntaxTree.Options);
|
|
||||||
return newSyntaxTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AddMarkupElementRewriter : SyntaxRewriter
|
private class AddMarkupElementRewriter : SyntaxRewriter
|
||||||
{
|
{
|
||||||
private readonly Stack<TagBlockTracker> _startTagTracker = new Stack<TagBlockTracker>();
|
private readonly Stack<TagBlockTracker> _startTagTracker = new Stack<TagBlockTracker>();
|
||||||
|
|
@ -38,10 +29,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
|
|
||||||
public override SyntaxNode Visit(SyntaxNode node)
|
public override SyntaxNode Visit(SyntaxNode node)
|
||||||
{
|
{
|
||||||
node = base.Visit(node);
|
|
||||||
|
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
|
var diagnostics = node.GetDiagnostics();
|
||||||
|
node = base.Visit(node);
|
||||||
|
if (diagnostics.Length > 0)
|
||||||
|
{
|
||||||
|
// Persist node diagnostics.
|
||||||
|
node = node.WithDiagnostics(diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
node = RewriteNode(node);
|
node = RewriteNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +68,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
var tagName = tagBlock.GetTagName();
|
var tagName = tagBlock.GetTagName();
|
||||||
if (string.IsNullOrWhiteSpace(tagName) || tagBlock.IsSelfClosing())
|
if (string.IsNullOrWhiteSpace(tagName) || tagBlock.IsSelfClosing())
|
||||||
{
|
{
|
||||||
// Don't want to track incomplete, invalid (Eg. </>, < >), void or self-closing tags.
|
// Don't want to track incomplete, invalid (Eg. </>, < >) or self-closing tags.
|
||||||
// Simply wrap it in a block with no body or start/end tag.
|
// Simply wrap it in a block with no body or start/end tag.
|
||||||
if (IsEndTag(tagBlock))
|
if (IsEndTag(tagBlock))
|
||||||
{
|
{
|
||||||
|
|
@ -102,7 +99,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
if (!TryRecoverStartTag(rewrittenChildren, tagName, tagBlock))
|
if (!TryRecoverStartTag(rewrittenChildren, tagName, tagBlock))
|
||||||
{
|
{
|
||||||
// Could not recover. The end tag doesn't have a corresponding start tag. Wrap it in a block and move on.
|
// Could not recover. The end tag doesn't have a corresponding start tag. Wrap it in a block and move on.
|
||||||
var rewritten = SyntaxFactory.MarkupElement(startTag: null, body: new SyntaxList<RazorSyntaxNode>(), endTag: tagBlock);
|
var rewritten = SyntaxFactory.MarkupElement(startTag: null, body: new SyntaxList<RazorSyntaxNode>(), endTag: GetEndTagSyntax(tagBlock));
|
||||||
TrackChild(rewritten, rewrittenChildren);
|
TrackChild(rewritten, rewrittenChildren);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +146,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
// The call to SyntaxNode.ReplaceNodes() later will take care removing the nodes whose replacement is null.
|
// The call to SyntaxNode.ReplaceNodes() later will take care removing the nodes whose replacement is null.
|
||||||
|
|
||||||
var body = tagChildren.Where(t => t != null).ToList();
|
var body = tagChildren.Where(t => t != null).ToList();
|
||||||
var rewritten = SyntaxFactory.MarkupElement(startTag, new SyntaxList<RazorSyntaxNode>(body), endTag);
|
var rewritten = SyntaxFactory.MarkupElement(
|
||||||
|
GetStartTagSyntax(startTag),
|
||||||
|
new SyntaxList<RazorSyntaxNode>(body),
|
||||||
|
GetEndTagSyntax(endTag));
|
||||||
|
|
||||||
if (startTag != null)
|
if (startTag != null)
|
||||||
{
|
{
|
||||||
// If there was a start tag, that is where we want to put our new element.
|
// If there was a start tag, that is where we want to put our new element.
|
||||||
|
|
@ -232,6 +233,26 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
return childContent.StartsWith("</") || childContent.StartsWith("/");
|
return childContent.StartsWith("</") || childContent.StartsWith("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MarkupStartTagSyntax GetStartTagSyntax(MarkupTagBlockSyntax tagBlock)
|
||||||
|
{
|
||||||
|
if (tagBlock == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SyntaxFactory.MarkupStartTag(tagBlock.Children);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MarkupEndTagSyntax GetEndTagSyntax(MarkupTagBlockSyntax tagBlock)
|
||||||
|
{
|
||||||
|
if (tagBlock == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SyntaxFactory.MarkupEndTag(tagBlock.Children);
|
||||||
|
}
|
||||||
|
|
||||||
private class TagBlockTracker
|
private class TagBlockTracker
|
||||||
{
|
{
|
||||||
public TagBlockTracker(MarkupTagBlockSyntax tagBlock)
|
public TagBlockTracker(MarkupTagBlockSyntax tagBlock)
|
||||||
|
|
@ -248,43 +269,5 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
public string TagName { get; }
|
public string TagName { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RemoveMarkupElementRewriter : SyntaxRewriter
|
|
||||||
{
|
|
||||||
public override SyntaxNode Visit(SyntaxNode node)
|
|
||||||
{
|
|
||||||
if (node != null)
|
|
||||||
{
|
|
||||||
node = RewriteNode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.Visit(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SyntaxNode RewriteNode(SyntaxNode node)
|
|
||||||
{
|
|
||||||
if (node.IsToken)
|
|
||||||
{
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
var children = node.ChildNodes();
|
|
||||||
for (var i = 0; i < children.Count; i++)
|
|
||||||
{
|
|
||||||
var child = children[i];
|
|
||||||
if (!(child is MarkupElementSyntax tagElement))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node.ReplaceNode(tagElement, tagElement.ChildNodes());
|
|
||||||
|
|
||||||
// Since we rewrote 'node', it's children are different. Update our collection.
|
|
||||||
children = node.ChildNodes();
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -102,9 +102,17 @@
|
||||||
</Node>
|
</Node>
|
||||||
<Node Name="MarkupElementSyntax" Base="MarkupSyntaxNode">
|
<Node Name="MarkupElementSyntax" Base="MarkupSyntaxNode">
|
||||||
<Kind Name="MarkupElement" />
|
<Kind Name="MarkupElement" />
|
||||||
<Field Name="StartTag" Type="MarkupTagBlockSyntax" Optional="true" />
|
<Field Name="StartTag" Type="MarkupStartTagSyntax" Optional="true" />
|
||||||
<Field Name="Body" Type="SyntaxList<RazorSyntaxNode>" />
|
<Field Name="Body" Type="SyntaxList<RazorSyntaxNode>" />
|
||||||
<Field Name="EndTag" Type="MarkupTagBlockSyntax" Optional="true" />
|
<Field Name="EndTag" Type="MarkupEndTagSyntax" Optional="true" />
|
||||||
|
</Node>
|
||||||
|
<Node Name="MarkupStartTagSyntax" Base="RazorBlockSyntax">
|
||||||
|
<Kind Name="MarkupStartTag" />
|
||||||
|
<Field Name="Children" Type="SyntaxList<RazorSyntaxNode>" Override="true" />
|
||||||
|
</Node>
|
||||||
|
<Node Name="MarkupEndTagSyntax" Base="RazorBlockSyntax">
|
||||||
|
<Kind Name="MarkupEndTag" />
|
||||||
|
<Field Name="Children" Type="SyntaxList<RazorSyntaxNode>" Override="true" />
|
||||||
</Node>
|
</Node>
|
||||||
<Node Name="MarkupTagHelperElementSyntax" Base="MarkupSyntaxNode">
|
<Node Name="MarkupTagHelperElementSyntax" Base="MarkupSyntaxNode">
|
||||||
<Kind Name="MarkupTagHelperElement" />
|
<Kind Name="MarkupTagHelperElement" />
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
MarkupBlock,
|
MarkupBlock,
|
||||||
MarkupTransition,
|
MarkupTransition,
|
||||||
MarkupElement,
|
MarkupElement,
|
||||||
|
MarkupStartTag,
|
||||||
|
MarkupEndTag,
|
||||||
MarkupTagBlock,
|
MarkupTagBlock,
|
||||||
MarkupTextLiteral,
|
MarkupTextLiteral,
|
||||||
MarkupEphemeralTextLiteral,
|
MarkupEphemeralTextLiteral,
|
||||||
|
|
|
||||||
|
|
@ -223,55 +223,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
|
|
||||||
public static string GetTagName(this MarkupTagBlockSyntax tagBlock)
|
public static string GetTagName(this MarkupTagBlockSyntax tagBlock)
|
||||||
{
|
{
|
||||||
if (tagBlock == null)
|
return GetTagNameCore(tagBlock);
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(tagBlock));
|
|
||||||
}
|
|
||||||
|
|
||||||
var child = tagBlock.Children[0];
|
|
||||||
|
|
||||||
if (tagBlock.Children.Count == 0 || !(child is MarkupTextLiteralSyntax))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var childLiteral = (MarkupTextLiteralSyntax)child;
|
|
||||||
SyntaxToken textToken = null;
|
|
||||||
for (var i = 0; i < childLiteral.LiteralTokens.Count; i++)
|
|
||||||
{
|
|
||||||
var token = childLiteral.LiteralTokens[i];
|
|
||||||
|
|
||||||
if (token != null &&
|
|
||||||
(token.Kind == SyntaxKind.Whitespace || token.Kind == SyntaxKind.Text))
|
|
||||||
{
|
|
||||||
textToken = token;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textToken == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return textToken.Kind == SyntaxKind.Whitespace ? null : textToken.Content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetTagName(this MarkupTagHelperStartTagSyntax tagBlock)
|
public static string GetTagName(this MarkupStartTagSyntax startTag)
|
||||||
|
{
|
||||||
|
return GetTagNameCore(startTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetTagName(this MarkupEndTagSyntax endTag)
|
||||||
|
{
|
||||||
|
return GetTagNameCore(endTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTagNameCore(RazorBlockSyntax tagBlock)
|
||||||
{
|
{
|
||||||
if (tagBlock == null)
|
if (tagBlock == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(tagBlock));
|
throw new ArgumentNullException(nameof(tagBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
var child = tagBlock.Children[0];
|
if (tagBlock.Children.Count == 0 || !(tagBlock.Children[0] is MarkupTextLiteralSyntax childLiteral))
|
||||||
|
|
||||||
if (tagBlock.Children.Count == 0 || !(child is MarkupTextLiteralSyntax))
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var childLiteral = (MarkupTextLiteralSyntax)child;
|
|
||||||
SyntaxToken textToken = null;
|
SyntaxToken textToken = null;
|
||||||
for (var i = 0; i < childLiteral.LiteralTokens.Count; i++)
|
for (var i = 0; i < childLiteral.LiteralTokens.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -294,6 +270,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsSelfClosing(this MarkupTagBlockSyntax tagBlock)
|
public static bool IsSelfClosing(this MarkupTagBlockSyntax tagBlock)
|
||||||
|
{
|
||||||
|
return IsSelfClosingCore(tagBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsSelfClosing(this MarkupStartTagSyntax startTag)
|
||||||
|
{
|
||||||
|
return IsSelfClosingCore(startTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSelfClosingCore(RazorBlockSyntax tagBlock)
|
||||||
{
|
{
|
||||||
if (tagBlock == null)
|
if (tagBlock == null)
|
||||||
{
|
{
|
||||||
|
|
@ -305,14 +291,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
return lastChild?.GetContent().EndsWith("/>", StringComparison.Ordinal) ?? false;
|
return lastChild?.GetContent().EndsWith("/>", StringComparison.Ordinal) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsVoidElement(this MarkupTagBlockSyntax tagBlock)
|
public static bool IsVoidElement(this MarkupStartTagSyntax startTag)
|
||||||
{
|
{
|
||||||
if (tagBlock == null)
|
if (startTag == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(tagBlock));
|
throw new ArgumentNullException(nameof(startTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParserHelpers.VoidElements.Contains(tagBlock.GetTagName());
|
return ParserHelpers.VoidElements.Contains(startTag.GetTagName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
{
|
{
|
||||||
return node.Kind == SyntaxKind.MarkupTextLiteral ||
|
return node.Kind == SyntaxKind.MarkupTextLiteral ||
|
||||||
node.Kind == SyntaxKind.MarkupEphemeralTextLiteral ||
|
node.Kind == SyntaxKind.MarkupEphemeralTextLiteral ||
|
||||||
node.Kind == SyntaxKind.MarkupTagBlock ||
|
node.Kind == SyntaxKind.MarkupStartTag ||
|
||||||
|
node.Kind == SyntaxKind.MarkupEndTag ||
|
||||||
node.Kind == SyntaxKind.MarkupAttributeBlock ||
|
node.Kind == SyntaxKind.MarkupAttributeBlock ||
|
||||||
node.Kind == SyntaxKind.MarkupMinimizedAttributeBlock ||
|
node.Kind == SyntaxKind.MarkupMinimizedAttributeBlock ||
|
||||||
node.Kind == SyntaxKind.MarkupTagHelperAttribute ||
|
node.Kind == SyntaxKind.MarkupTagHelperAttribute ||
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ using System.Text;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Sdk;
|
using Xunit.Sdk;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
|
|
@ -240,6 +241,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
||||||
codeDocument.SetSyntaxTree(syntaxTree);
|
codeDocument.SetSyntaxTree(syntaxTree);
|
||||||
|
|
||||||
|
// Group markup elements
|
||||||
|
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
|
||||||
|
|
||||||
var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass();
|
var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass();
|
||||||
syntaxTree = defaultDirectivePass.Execute(codeDocument, syntaxTree);
|
syntaxTree = defaultDirectivePass.Execute(codeDocument, syntaxTree);
|
||||||
|
|
||||||
|
|
@ -267,6 +271,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
||||||
|
|
||||||
|
// Group markup elements
|
||||||
|
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
|
||||||
|
|
||||||
return syntaxTree;
|
return syntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,6 +307,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
|
||||||
|
|
||||||
|
// Group markup elements
|
||||||
|
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
|
||||||
|
|
||||||
return syntaxTree;
|
return syntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||||
{
|
{
|
||||||
return node.Kind == SyntaxKind.MarkupTextLiteral ||
|
return node.Kind == SyntaxKind.MarkupTextLiteral ||
|
||||||
node.Kind == SyntaxKind.MarkupEphemeralTextLiteral ||
|
node.Kind == SyntaxKind.MarkupEphemeralTextLiteral ||
|
||||||
node.Kind == SyntaxKind.MarkupTagBlock ||
|
node.Kind == SyntaxKind.MarkupStartTag ||
|
||||||
|
node.Kind == SyntaxKind.MarkupEndTag ||
|
||||||
node.Kind == SyntaxKind.MarkupAttributeBlock ||
|
node.Kind == SyntaxKind.MarkupAttributeBlock ||
|
||||||
node.Kind == SyntaxKind.MarkupMinimizedAttributeBlock ||
|
node.Kind == SyntaxKind.MarkupMinimizedAttributeBlock ||
|
||||||
node.Kind == SyntaxKind.MarkupTagHelperAttribute ||
|
node.Kind == SyntaxKind.MarkupTagHelperAttribute ||
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue