\n\nCommit migrated from a2d1ac4cea
This commit is contained in:
Ajay Bhargav Baaskaran 2018-12-04 16:04:20 -08:00 committed by GitHub
parent ebd37599b6
commit ad0f2a5af4
15 changed files with 674 additions and 181 deletions

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
internal class ClassifiedSpanRewriter : SyntaxRewriter
{
public override SyntaxNode VisitMarkupTagBlock(MarkupTagBlockSyntax node)
public override SyntaxNode VisitMarkupStartTag(MarkupStartTagSyntax node)
{
SpanContext latestSpanContext = null;
var newChildren = SyntaxListBuilder<RazorSyntaxNode>.Create();
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Razor.Language
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()
{

View File

@ -106,9 +106,14 @@ namespace Microsoft.AspNetCore.Razor.Language
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)

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Razor.Language.Syntax;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
@ -41,7 +42,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var diagnostics = context.ErrorSink.Errors;
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;
}
}
}

View File

@ -10,13 +10,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal static class TagHelperBlockRewriter
{
private static readonly string StringTypeName = typeof(string).FullName;
public static MarkupTagHelperStartTagSyntax Rewrite(
string tagName,
bool validStructure,
RazorParserFeatureFlags featureFlags,
MarkupTagBlockSyntax tag,
MarkupStartTagSyntax tag,
TagHelperBinding bindingResult,
ErrorSink errorSink,
RazorSourceDocument source)
@ -28,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
public static TagMode GetTagMode(
MarkupTagBlockSyntax tagBlock,
MarkupStartTagSyntax tagBlock,
TagHelperBinding bindingResult,
ErrorSink errorSink)
{
@ -57,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private static SyntaxList<RazorSyntaxNode> GetRewrittenChildren(
string tagName,
bool validStructure,
MarkupTagBlockSyntax tagBlock,
MarkupStartTagSyntax tagBlock,
TagHelperBinding bindingResult,
RazorParserFeatureFlags featureFlags,
ErrorSink errorSink,

View File

@ -15,7 +15,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelperPrefix, IEnumerable<TagHelperDescriptor> descriptors)
{
var errorSink = new ErrorSink();
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
var rewriter = new Rewriter(
syntaxTree.Source,
@ -33,8 +32,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var diagnostics = CombineErrors(syntaxTree.Diagnostics, errorList).OrderBy(error => error.Span.AbsoluteIndex);
var newSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, diagnostics, syntaxTree.Options);
newSyntaxTree = MarkupElementRewriter.RemoveMarkupElements(newSyntaxTree);
return newSyntaxTree;
}
@ -103,7 +100,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
TagHelperInfo tagHelperInfo = null;
// Visit the start tag.
var startTag = (MarkupTagBlockSyntax)Visit(node.StartTag);
var startTag = (MarkupStartTagSyntax)Visit(node.StartTag);
if (startTag != null)
{
var tagName = startTag.GetTagName();
@ -145,7 +142,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
else
{
// Non-TagHelper tag.
ValidateParentAllowsPlainTag(startTag);
ValidateParentAllowsPlainStartTag(startTag);
if (!startTag.IsSelfClosing() && !startTag.IsVoidElement())
{
@ -159,7 +156,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var body = VisitList(node.Body);
// Visit end tag.
var endTag = (MarkupTagBlockSyntax)Visit(node.EndTag);
var endTag = (MarkupEndTagSyntax)Visit(node.EndTag);
if (endTag != null)
{
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.
// 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.
// 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)
{
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;
if (!isPartofTagBlock)
{
@ -215,13 +212,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
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;
tagHelperInfo = null;
// 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.
if (tagName == null)
@ -231,7 +228,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
TagHelperBinding tagHelperBinding;
if (!IsPotentialTagHelper(tagName, tagBlock))
if (!IsPotentialTagHelperStart(tagName, startTag))
{
return false;
}
@ -240,7 +237,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
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.
var elementAttributes = GetAttributeNameValuePairs(tagBlock);
var elementAttributes = GetAttributeNameValuePairs(startTag);
tagHelperBinding = _tagHelperBinder.GetBinding(
tagName,
@ -264,29 +261,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return false;
}
ValidateParentAllowsTagHelper(tagName, tagBlock);
ValidateBinding(tagHelperBinding, tagName, tagBlock);
ValidateParentAllowsTagHelper(tagName, startTag);
ValidateBinding(tagHelperBinding, tagName, startTag);
// 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,
validTagStructure,
_featureFlags,
tagBlock,
startTag,
tagHelperBinding,
_errorSink,
_source);
var tagMode = TagHelperBlockRewriter.GetTagMode(tagBlock, tagHelperBinding, _errorSink);
var tagMode = TagHelperBlockRewriter.GetTagMode(startTag, tagHelperBinding, _errorSink);
tagHelperInfo = new TagHelperInfo(tagName, tagMode, tagHelperBinding);
rewritten = startTag;
rewritten = rewrittenStartTag;
return true;
}
private bool TryRewriteTagHelperEnd(MarkupTagBlockSyntax tagBlock, out MarkupTagHelperEndTagSyntax rewritten)
private bool TryRewriteTagHelperEnd(MarkupEndTagSyntax tagBlock, out MarkupTagHelperEndTagSyntax rewritten)
{
rewritten = null;
var tagName = tagBlock.GetTagName();
@ -298,7 +295,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var tracker = CurrentTagHelperTracker;
var tagNameScope = tracker?.TagName ?? string.Empty;
if (!IsPotentialTagHelper(tagName, tagBlock))
if (!IsPotentialTagHelperEnd(tagName, tagBlock))
{
return false;
}
@ -315,7 +312,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return false;
}
ValidateTagSyntax(tagName, tagBlock);
ValidateEndTagSyntax(tagName, tagBlock);
_trackerStack.Pop();
}
@ -360,10 +357,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
// 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.
var childrenOffset = IsPartialTag(tagBlock) ? 0 : 1;
var childrenOffset = IsPartialStartTag(tagBlock) ? 0 : 1;
var childCount = tagBlock.Children.Count - childrenOffset;
if (childCount <= 1)
@ -436,19 +433,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return attributes;
}
private void ValidateParentAllowsTagHelper(string tagName, MarkupTagBlockSyntax tagBlock)
private void ValidateParentAllowsTagHelper(string tagName, MarkupStartTagSyntax tagBlock)
{
if (HasAllowedChildren() &&
!CurrentTagHelperTracker.PrefixedAllowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase))
{
OnAllowedChildrenTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
OnAllowedChildrenStartTagError(CurrentTagHelperTracker, tagName, tagBlock, _errorSink, _source);
}
}
private void ValidateBinding(
TagHelperBinding bindingResult,
string tagName,
MarkupTagBlockSyntax tagBlock)
MarkupStartTagSyntax tagBlock)
{
// Ensure that all descriptors associated with this tag have appropriate TagStructures. Cannot have
// 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.
if (IsPartialTag(tag))
if (IsPartialStartTag(tag))
{
var errorStart = GetTagDeclarationErrorStart(tag);
var errorStart = GetStartTagDeclarationErrorStart(tag, _source);
_errorSink.OnError(
RazorDiagnosticFactory.CreateParsing_TagHelperMissingCloseAngle(
@ -496,7 +493,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
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);
var child = childBlock.Children[0];
@ -505,14 +519,37 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
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 '<'.
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();
@ -595,7 +632,40 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var allowedChildren = tagHelperBinding != null ? CurrentTagHelperTracker.PrefixedAllowedChildren : CurrentTagHelperTracker.AllowedChildren;
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;
}
private static void OnAllowedChildrenTagError(
private static void OnAllowedChildrenStartTagError(
TagHelperTracker tracker,
string tagName,
MarkupTagBlockSyntax tagBlock,
MarkupStartTagSyntax tagBlock,
ErrorSink errorSink,
RazorSourceDocument source)
{
var allowedChildrenString = string.Join(", ", tracker.AllowedChildren);
var errorStart = GetTagDeclarationErrorStart(tagBlock, source);
var errorStart = GetStartTagDeclarationErrorStart(tagBlock, source);
errorSink.OnError(
RazorDiagnosticFactory.CreateTagHelper_InvalidNestedTag(
@ -650,21 +720,32 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
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
var relevantToken = childSpan.LiteralTokens[childSpan.LiteralTokens.Count == 1 ? 0 : 1];
return relevantToken.Kind == SyntaxKind.ForwardSlash;
private static SourceLocation GetEndTagDeclarationErrorStart(MarkupEndTagSyntax tagBlock, RazorSourceDocument source)
{
return SourceLocationTracker.Advance(tagBlock.GetSourceLocation(source), "</");
}
private class TagTracker

View File

@ -1441,11 +1441,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
internal sealed partial class MarkupElementSyntax : MarkupSyntaxNode
{
private readonly MarkupTagBlockSyntax _startTag;
private readonly MarkupStartTagSyntax _startTag;
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)
{
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)
{
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 MarkupTagBlockSyntax EndTag { get { return _endTag; } }
public MarkupEndTagSyntax EndTag { get { return _endTag; } }
internal override GreenNode GetSlot(int index)
{
@ -1518,7 +1518,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
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)
{
@ -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
{
private readonly MarkupTagHelperStartTagSyntax _startTag;
@ -3383,6 +3545,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
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)
{
return DefaultVisit(node);
@ -3572,6 +3744,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
DefaultVisit(node);
}
public virtual void VisitMarkupStartTag(MarkupStartTagSyntax node)
{
DefaultVisit(node);
}
public virtual void VisitMarkupEndTag(MarkupEndTagSyntax node)
{
DefaultVisit(node);
}
public virtual void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
{
DefaultVisit(node);
@ -3786,12 +3968,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
public override GreenNode VisitMarkupElement(MarkupElementSyntax node)
{
var startTag = (MarkupTagBlockSyntax)Visit(node.StartTag);
var startTag = (MarkupStartTagSyntax)Visit(node.StartTag);
var body = VisitList(node.Body);
var endTag = (MarkupTagBlockSyntax)Visit(node.EndTag);
var endTag = (MarkupEndTagSyntax)Visit(node.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)
{
var startTag = (MarkupTagHelperStartTagSyntax)Visit(node.StartTag);
@ -4108,13 +4302,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
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);
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)
{
if (startTag == null)
@ -4343,6 +4551,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
typeof(MarkupLiteralAttributeValueSyntax),
typeof(MarkupDynamicAttributeValueSyntax),
typeof(MarkupElementSyntax),
typeof(MarkupStartTagSyntax),
typeof(MarkupEndTagSyntax),
typeof(MarkupTagHelperElementSyntax),
typeof(MarkupTagHelperStartTagSyntax),
typeof(MarkupTagHelperEndTagSyntax),

View File

@ -113,6 +113,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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>
public virtual TResult VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
{
@ -338,6 +350,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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>
public virtual void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
{
@ -572,12 +596,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
public override SyntaxNode VisitMarkupElement(MarkupElementSyntax node)
{
var startTag = (MarkupTagBlockSyntax)Visit(node.StartTag);
var startTag = (MarkupStartTagSyntax)Visit(node.StartTag);
var body = VisitList(node.Body);
var endTag = (MarkupTagBlockSyntax)Visit(node.EndTag);
var endTag = (MarkupEndTagSyntax)Visit(node.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)
{
var startTag = (MarkupTagHelperStartTagSyntax)Visit(node.StartTag);
@ -962,15 +998,39 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
}
/// <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>
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>

View File

@ -1382,16 +1382,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
internal sealed partial class MarkupElementSyntax : MarkupSyntaxNode
{
private MarkupTagBlockSyntax _startTag;
private MarkupStartTagSyntax _startTag;
private SyntaxNode _body;
private MarkupTagBlockSyntax _endTag;
private MarkupEndTagSyntax _endTag;
internal MarkupElementSyntax(GreenNode green, SyntaxNode parent, int position)
: base(green, parent, position)
{
}
public MarkupTagBlockSyntax StartTag
public MarkupStartTagSyntax StartTag
{
get
{
@ -1407,7 +1407,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
}
}
public MarkupTagBlockSyntax EndTag
public MarkupEndTagSyntax EndTag
{
get
{
@ -1446,7 +1446,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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)
{
@ -1460,7 +1460,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
return this;
}
public MarkupElementSyntax WithStartTag(MarkupTagBlockSyntax startTag)
public MarkupElementSyntax WithStartTag(MarkupStartTagSyntax startTag)
{
return Update(startTag, Body, EndTag);
}
@ -1470,14 +1470,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
return Update(StartTag, body, EndTag);
}
public MarkupElementSyntax WithEndTag(MarkupTagBlockSyntax endTag)
public MarkupElementSyntax WithEndTag(MarkupEndTagSyntax endTag)
{
return Update(StartTag, Body, endTag);
}
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)));
}
@ -1488,11 +1488,153 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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)));
}
}
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
{
private MarkupTagHelperStartTagSyntax _startTag;

View File

@ -19,15 +19,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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 readonly Stack<TagBlockTracker> _startTagTracker = new Stack<TagBlockTracker>();
@ -38,10 +29,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
public override SyntaxNode Visit(SyntaxNode node)
{
node = base.Visit(node);
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);
}
@ -71,7 +68,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
var tagName = tagBlock.GetTagName();
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.
if (IsEndTag(tagBlock))
{
@ -102,7 +99,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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.
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);
}
}
@ -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.
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 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("/");
}
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
{
public TagBlockTracker(MarkupTagBlockSyntax tagBlock)
@ -248,43 +269,5 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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;
}
}
}
}

View File

@ -102,9 +102,17 @@
</Node>
<Node Name="MarkupElementSyntax" Base="MarkupSyntaxNode">
<Kind Name="MarkupElement" />
<Field Name="StartTag" Type="MarkupTagBlockSyntax" Optional="true" />
<Field Name="StartTag" Type="MarkupStartTagSyntax" Optional="true" />
<Field Name="Body" Type="SyntaxList&lt;RazorSyntaxNode&gt;" />
<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&lt;RazorSyntaxNode&gt;" Override="true" />
</Node>
<Node Name="MarkupEndTagSyntax" Base="RazorBlockSyntax">
<Kind Name="MarkupEndTag" />
<Field Name="Children" Type="SyntaxList&lt;RazorSyntaxNode&gt;" Override="true" />
</Node>
<Node Name="MarkupTagHelperElementSyntax" Base="MarkupSyntaxNode">
<Kind Name="MarkupTagHelperElement" />

View File

@ -19,6 +19,8 @@ namespace Microsoft.AspNetCore.Razor.Language
MarkupBlock,
MarkupTransition,
MarkupElement,
MarkupStartTag,
MarkupEndTag,
MarkupTagBlock,
MarkupTextLiteral,
MarkupEphemeralTextLiteral,

View File

@ -223,55 +223,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
public static string GetTagName(this MarkupTagBlockSyntax tagBlock)
{
if (tagBlock == null)
{
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;
return GetTagNameCore(tagBlock);
}
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)
{
throw new ArgumentNullException(nameof(tagBlock));
}
var child = tagBlock.Children[0];
if (tagBlock.Children.Count == 0 || !(child is MarkupTextLiteralSyntax))
if (tagBlock.Children.Count == 0 || !(tagBlock.Children[0] is MarkupTextLiteralSyntax childLiteral))
{
return null;
}
var childLiteral = (MarkupTextLiteralSyntax)child;
SyntaxToken textToken = null;
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)
{
return IsSelfClosingCore(tagBlock);
}
public static bool IsSelfClosing(this MarkupStartTagSyntax startTag)
{
return IsSelfClosingCore(startTag);
}
private static bool IsSelfClosingCore(RazorBlockSyntax tagBlock)
{
if (tagBlock == null)
{
@ -305,14 +291,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
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());
}
}
}

View File

@ -287,7 +287,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
{
return node.Kind == SyntaxKind.MarkupTextLiteral ||
node.Kind == SyntaxKind.MarkupEphemeralTextLiteral ||
node.Kind == SyntaxKind.MarkupTagBlock ||
node.Kind == SyntaxKind.MarkupStartTag ||
node.Kind == SyntaxKind.MarkupEndTag ||
node.Kind == SyntaxKind.MarkupAttributeBlock ||
node.Kind == SyntaxKind.MarkupMinimizedAttributeBlock ||
node.Kind == SyntaxKind.MarkupTagHelperAttribute ||

View File

@ -13,6 +13,7 @@ using System.Text;
using Xunit;
using Xunit.Sdk;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Razor.Language.Syntax;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
@ -240,6 +241,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
codeDocument.SetSyntaxTree(syntaxTree);
// Group markup elements
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass();
syntaxTree = defaultDirectivePass.Execute(codeDocument, syntaxTree);
@ -267,6 +271,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
// Group markup elements
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
return syntaxTree;
}
@ -300,6 +307,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
// Group markup elements
syntaxTree = MarkupElementRewriter.AddMarkupElements(syntaxTree);
return syntaxTree;
}

View File

@ -203,7 +203,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax
{
return node.Kind == SyntaxKind.MarkupTextLiteral ||
node.Kind == SyntaxKind.MarkupEphemeralTextLiteral ||
node.Kind == SyntaxKind.MarkupTagBlock ||
node.Kind == SyntaxKind.MarkupStartTag ||
node.Kind == SyntaxKind.MarkupEndTag ||
node.Kind == SyntaxKind.MarkupAttributeBlock ||
node.Kind == SyntaxKind.MarkupMinimizedAttributeBlock ||
node.Kind == SyntaxKind.MarkupTagHelperAttribute ||