Expose source start/end tags on TagHelperBlocks.
- This is to enable the DesignTime to understand TagHelperBlocks full source structure in order to auto format the document.
This commit is contained in:
parent
44b530dd22
commit
36f02690d2
|
|
@ -32,6 +32,8 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
Attributes = new Dictionary<string, SyntaxTreeNode>(source.Attributes);
|
Attributes = new Dictionary<string, SyntaxTreeNode>(source.Attributes);
|
||||||
_start = source.Start;
|
_start = source.Start;
|
||||||
SelfClosing = source.SelfClosing;
|
SelfClosing = source.SelfClosing;
|
||||||
|
SourceStartTag = source.SourceStartTag;
|
||||||
|
SourceEndTag = source.SourceEndTag;
|
||||||
|
|
||||||
source.Reset();
|
source.Reset();
|
||||||
|
|
||||||
|
|
@ -41,6 +43,18 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unrewritten source start tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This is used by design time to properly format <see cref="TagHelperBlock"/>s.</remarks>
|
||||||
|
public Block SourceStartTag { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unrewritten source end tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This is used by design time to properly format <see cref="TagHelperBlock"/>s.</remarks>
|
||||||
|
public Block SourceEndTag { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether or not the tag is self closing.
|
/// Indicates whether or not the tag is self closing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -70,6 +84,18 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TagName { get; private set; }
|
public string TagName { get; private set; }
|
||||||
|
|
||||||
|
public override int Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var startTagLength = SourceStartTag?.Length ?? 0;
|
||||||
|
var childrenLength = base.Length;
|
||||||
|
var endTagLength = SourceEndTag?.Length ?? 0;
|
||||||
|
|
||||||
|
return startTagLength + childrenLength + endTagLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
@ -99,11 +125,12 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCodeCombiner.Start()
|
return HashCodeCombiner
|
||||||
.Add(TagName)
|
.Start()
|
||||||
.Add(Attributes)
|
.Add(TagName)
|
||||||
.Add(base.GetHashCode())
|
.Add(Attributes)
|
||||||
.CombinedHash;
|
.Add(base.GetHashCode())
|
||||||
|
.CombinedHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,6 +74,18 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the unrewritten source start tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This is used by design time to properly format <see cref="TagHelperBlock"/>s.</remarks>
|
||||||
|
public Block SourceStartTag { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the unrewritten source end tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This is used by design time to properly format <see cref="TagHelperBlock"/>s.</remarks>
|
||||||
|
public Block SourceEndTag { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether or not the tag in the Razor source was self-closing.
|
/// Gets a value indicating whether or not the tag in the Razor source was self-closing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,12 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
{
|
{
|
||||||
private static readonly string StringTypeName = typeof(string).FullName;
|
private static readonly string StringTypeName = typeof(string).FullName;
|
||||||
|
|
||||||
public static TagHelperBlockBuilder Rewrite(string tagName,
|
public static TagHelperBlockBuilder Rewrite(
|
||||||
bool validStructure,
|
string tagName,
|
||||||
Block tag,
|
bool validStructure,
|
||||||
IEnumerable<TagHelperDescriptor> descriptors,
|
Block tag,
|
||||||
ParserErrorSink errorSink)
|
IEnumerable<TagHelperDescriptor> descriptors,
|
||||||
|
ParserErrorSink errorSink)
|
||||||
{
|
{
|
||||||
// There will always be at least one child for the '<'.
|
// There will always be at least one child for the '<'.
|
||||||
var start = tag.Children.First().Start;
|
var start = tag.Children.First().Start;
|
||||||
|
|
@ -74,8 +75,8 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
// Check if it's a bound attribute that is not of type string and happens to be null or whitespace.
|
// Check if it's a bound attribute that is not of type string and happens to be null or whitespace.
|
||||||
string attributeValueType;
|
string attributeValueType;
|
||||||
if (attributeValueTypes.TryGetValue(attribute.Key, out attributeValueType) &&
|
if (attributeValueTypes.TryGetValue(attribute.Key, out attributeValueType) &&
|
||||||
!IsStringAttribute(attributeValueType) &&
|
!IsStringAttribute(attributeValueType) &&
|
||||||
IsNullOrWhitespaceAttributeValue(attribute.Value))
|
IsNullOrWhitespaceAttributeValue(attribute.Value))
|
||||||
{
|
{
|
||||||
var errorLocation = GetAttributeNameStartLocation(child);
|
var errorLocation = GetAttributeNameStartLocation(child);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,11 +121,16 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
|
|
||||||
var validTagStructure = ValidTagStructure(tagName, tagBlock, context);
|
var validTagStructure = ValidTagStructure(tagName, tagBlock, context);
|
||||||
|
|
||||||
var builder = TagHelperBlockRewriter.Rewrite(tagName,
|
var builder = TagHelperBlockRewriter.Rewrite(
|
||||||
validTagStructure,
|
tagName,
|
||||||
tagBlock,
|
validTagStructure,
|
||||||
descriptors,
|
tagBlock,
|
||||||
context.ErrorSink);
|
descriptors,
|
||||||
|
context.ErrorSink);
|
||||||
|
|
||||||
|
// Track the original start tag so the editor knows where each piece of the TagHelperBlock lies
|
||||||
|
// for formatting.
|
||||||
|
builder.SourceStartTag = tagBlock;
|
||||||
|
|
||||||
// Found a new tag helper block
|
// Found a new tag helper block
|
||||||
TrackTagHelperBlock(builder);
|
TrackTagHelperBlock(builder);
|
||||||
|
|
@ -134,7 +139,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
// within the tag... complete it.
|
// within the tag... complete it.
|
||||||
if (builder.SelfClosing)
|
if (builder.SelfClosing)
|
||||||
{
|
{
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
BuildCurrentlyTrackedTagHelperBlock(endTag: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -149,14 +154,14 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
{
|
{
|
||||||
ValidTagStructure(tagName, tagBlock, context);
|
ValidTagStructure(tagName, tagBlock, context);
|
||||||
|
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
BuildCurrentlyTrackedTagHelperBlock(tagBlock);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Current tag helper scope does not match the end tag. Attempt to recover the tag
|
// Current tag helper scope does not match the end tag. Attempt to recover the tag
|
||||||
// helper by looking up the previous tag helper scopes for a matching tag. If we
|
// helper by looking up the previous tag helper scopes for a matching tag. If we
|
||||||
// can't recover it means there was no corresponding tag helper begin tag.
|
// can't recover it means there was no corresponding tag helper begin tag.
|
||||||
if (TryRecoverTagHelper(tagName, context))
|
if (TryRecoverTagHelper(tagName, tagBlock, context))
|
||||||
{
|
{
|
||||||
ValidTagStructure(tagName, tagBlock, context);
|
ValidTagStructure(tagName, tagBlock, context);
|
||||||
|
|
||||||
|
|
@ -230,9 +235,11 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildCurrentlyTrackedTagHelperBlock()
|
private void BuildCurrentlyTrackedTagHelperBlock(Block endTag)
|
||||||
{
|
{
|
||||||
_tagStack.Pop();
|
// Track the original end tag so the editor knows where each piece of the TagHelperBlock lies
|
||||||
|
// for formatting.
|
||||||
|
_tagStack.Pop().SourceEndTag = endTag;
|
||||||
|
|
||||||
BuildCurrentlyTrackedBlock();
|
BuildCurrentlyTrackedBlock();
|
||||||
}
|
}
|
||||||
|
|
@ -268,7 +275,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
TrackBlock(builder);
|
TrackBlock(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryRecoverTagHelper(string tagName, RewritingContext context)
|
private bool TryRecoverTagHelper(string tagName, Block endTag, RewritingContext context)
|
||||||
{
|
{
|
||||||
var malformedTagHelperCount = 0;
|
var malformedTagHelperCount = 0;
|
||||||
|
|
||||||
|
|
@ -289,7 +296,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
BuildMalformedTagHelpers(malformedTagHelperCount, context);
|
BuildMalformedTagHelpers(malformedTagHelperCount, context);
|
||||||
|
|
||||||
// One final build, this is the build that completes our target tag helper block which is not malformed.
|
// One final build, this is the build that completes our target tag helper block which is not malformed.
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
BuildCurrentlyTrackedTagHelperBlock(endTag);
|
||||||
|
|
||||||
// We were able to recover
|
// We were able to recover
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -310,7 +317,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
||||||
malformedTagHelper.TagName));
|
malformedTagHelper.TagName));
|
||||||
|
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
BuildCurrentlyTrackedTagHelperBlock(endTag: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue