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:
N. Taylor Mullen 2015-03-16 21:17:43 -07:00
parent 44b530dd22
commit 36f02690d2
4 changed files with 72 additions and 25 deletions

View File

@ -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,7 +125,8 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
/// <inheritdoc /> /// <inheritdoc />
public override int GetHashCode() public override int GetHashCode()
{ {
return HashCodeCombiner.Start() return HashCodeCombiner
.Start()
.Add(TagName) .Add(TagName)
.Add(Attributes) .Add(Attributes)
.Add(base.GetHashCode()) .Add(base.GetHashCode())

View File

@ -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>

View File

@ -17,7 +17,8 @@ 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(
string tagName,
bool validStructure, bool validStructure,
Block tag, Block tag,
IEnumerable<TagHelperDescriptor> descriptors, IEnumerable<TagHelperDescriptor> descriptors,

View File

@ -121,12 +121,17 @@ 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(
tagName,
validTagStructure, validTagStructure,
tagBlock, tagBlock,
descriptors, descriptors,
context.ErrorSink); 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);
} }
} }