Small perf fixes to improve precompilation times
This commit is contained in:
parent
d19845730f
commit
5944dd6f87
|
|
@ -190,21 +190,21 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
|
|
||||||
foreach (var name in allowedChildren)
|
foreach (var name in allowedChildren)
|
||||||
{
|
{
|
||||||
var valid = TryValidateName(
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
var whitespaceError = Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeNameNullWhitespace(
|
||||||
|
nameof(RestrictChildrenAttribute),
|
||||||
|
tagHelperName);
|
||||||
|
errorSink.OnError(SourceLocation.Zero, whitespaceError, length: 0);
|
||||||
|
}
|
||||||
|
else if (TryValidateName(
|
||||||
name,
|
name,
|
||||||
whitespaceError:
|
invalidCharacter => Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeName(
|
||||||
Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeNameNullWhitespace(
|
nameof(RestrictChildrenAttribute),
|
||||||
nameof(RestrictChildrenAttribute),
|
name,
|
||||||
tagHelperName),
|
tagHelperName,
|
||||||
characterErrorBuilder: (invalidCharacter) =>
|
invalidCharacter),
|
||||||
Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeName(
|
errorSink))
|
||||||
nameof(RestrictChildrenAttribute),
|
|
||||||
name,
|
|
||||||
tagHelperName,
|
|
||||||
invalidCharacter),
|
|
||||||
errorSink: errorSink);
|
|
||||||
|
|
||||||
if (valid)
|
|
||||||
{
|
{
|
||||||
validAllowedChildren.Add(name);
|
validAllowedChildren.Add(name);
|
||||||
}
|
}
|
||||||
|
|
@ -281,17 +281,29 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static bool ValidateParentTagName(string parentTag, ErrorSink errorSink)
|
internal static bool ValidateParentTagName(string parentTag, ErrorSink errorSink)
|
||||||
{
|
{
|
||||||
return parentTag == null ||
|
if (parentTag == null)
|
||||||
TryValidateName(
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (string.IsNullOrWhiteSpace(parentTag))
|
||||||
|
{
|
||||||
|
var error = Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(
|
||||||
|
Resources.TagHelperDescriptorFactory_ParentTag);
|
||||||
|
errorSink.OnError(SourceLocation.Zero, error, length: 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!TryValidateName(
|
||||||
|
parentTag,
|
||||||
|
invalidCharacter => Resources.FormatHtmlTargetElementAttribute_InvalidName(
|
||||||
|
Resources.TagHelperDescriptorFactory_ParentTag.ToLower(),
|
||||||
parentTag,
|
parentTag,
|
||||||
Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(
|
invalidCharacter),
|
||||||
Resources.TagHelperDescriptorFactory_ParentTag),
|
errorSink))
|
||||||
characterErrorBuilder: (invalidCharacter) =>
|
{
|
||||||
Resources.FormatHtmlTargetElementAttribute_InvalidName(
|
return false;
|
||||||
Resources.TagHelperDescriptorFactory_ParentTag.ToLower(),
|
}
|
||||||
parentTag,
|
|
||||||
invalidCharacter),
|
return true;
|
||||||
errorSink: errorSink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryGetRequiredAttributeDescriptors(
|
private static bool TryGetRequiredAttributeDescriptors(
|
||||||
|
|
@ -320,45 +332,42 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
Resources.TagHelperDescriptorFactory_Attribute :
|
Resources.TagHelperDescriptorFactory_Attribute :
|
||||||
Resources.TagHelperDescriptorFactory_Tag;
|
Resources.TagHelperDescriptorFactory_Tag;
|
||||||
|
|
||||||
var validName = TryValidateName(
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
var error = Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName);
|
||||||
|
errorSink.OnError(SourceLocation.Zero, error, length: 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!TryValidateName(
|
||||||
name,
|
name,
|
||||||
whitespaceError: Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName),
|
invalidCharacter => Resources.FormatHtmlTargetElementAttribute_InvalidName(
|
||||||
characterErrorBuilder: (invalidCharacter) =>
|
targetName.ToLower(),
|
||||||
Resources.FormatHtmlTargetElementAttribute_InvalidName(
|
name,
|
||||||
targetName.ToLower(),
|
invalidCharacter),
|
||||||
name,
|
errorSink))
|
||||||
invalidCharacter),
|
{
|
||||||
errorSink: errorSink);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return validName;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryValidateName(
|
private static bool TryValidateName(
|
||||||
string name,
|
string name,
|
||||||
string whitespaceError,
|
|
||||||
Func<char, string> characterErrorBuilder,
|
Func<char, string> characterErrorBuilder,
|
||||||
ErrorSink errorSink)
|
ErrorSink errorSink)
|
||||||
{
|
{
|
||||||
var validName = true;
|
var validName = true;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
foreach (var character in name)
|
||||||
{
|
{
|
||||||
errorSink.OnError(SourceLocation.Zero, whitespaceError, length: 0);
|
if (char.IsWhiteSpace(character) ||
|
||||||
|
InvalidNonWhitespaceNameCharacters.Contains(character))
|
||||||
validName = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var character in name)
|
|
||||||
{
|
{
|
||||||
if (char.IsWhiteSpace(character) ||
|
var error = characterErrorBuilder(character);
|
||||||
InvalidNonWhitespaceNameCharacters.Contains(character))
|
errorSink.OnError(SourceLocation.Zero, error, length: 0);
|
||||||
{
|
|
||||||
var error = characterErrorBuilder(character);
|
|
||||||
errorSink.OnError(SourceLocation.Zero, error, length: 0);
|
|
||||||
|
|
||||||
validName = false;
|
validName = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -696,7 +705,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
return property.GetIndexParameters().Length == 0 &&
|
return property.GetIndexParameters().Length == 0 &&
|
||||||
property.GetMethod != null &&
|
property.GetMethod != null &&
|
||||||
property.GetMethod.IsPublic &&
|
property.GetMethod.IsPublic &&
|
||||||
property.GetCustomAttribute<HtmlAttributeNotBoundAttribute>(inherit: false) == null;
|
!property.IsDefined(typeof(HtmlAttributeNotBoundAttribute), inherit: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Parser.TagHelpers;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers
|
namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -77,29 +76,34 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers
|
||||||
descriptors = matchingDescriptors.Concat(descriptors);
|
descriptors = matchingDescriptors.Concat(descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
var applicableDescriptors = ApplyRequiredAttributes(descriptors, attributes);
|
var applicableDescriptors = new List<TagHelperDescriptor>();
|
||||||
applicableDescriptors = ApplyParentTagFilter(applicableDescriptors, parentTagName);
|
foreach (var descriptor in descriptors)
|
||||||
|
{
|
||||||
|
if (HasRequiredAttributes(descriptor, attributes) &&
|
||||||
|
HasRequiredParentTag(descriptor, parentTagName))
|
||||||
|
{
|
||||||
|
applicableDescriptors.Add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return applicableDescriptors.ToArray();
|
return applicableDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<TagHelperDescriptor> ApplyParentTagFilter(
|
private bool HasRequiredParentTag(
|
||||||
IEnumerable<TagHelperDescriptor> descriptors,
|
TagHelperDescriptor descriptor,
|
||||||
string parentTagName)
|
string parentTagName)
|
||||||
{
|
{
|
||||||
return descriptors.Where(descriptor =>
|
return descriptor.RequiredParent == null ||
|
||||||
descriptor.RequiredParent == null ||
|
string.Equals(parentTagName, descriptor.RequiredParent, StringComparison.OrdinalIgnoreCase);
|
||||||
string.Equals(parentTagName, descriptor.RequiredParent, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<TagHelperDescriptor> ApplyRequiredAttributes(
|
private bool HasRequiredAttributes(
|
||||||
IEnumerable<TagHelperDescriptor> descriptors,
|
TagHelperDescriptor descriptor,
|
||||||
IEnumerable<KeyValuePair<string, string>> attributes)
|
IEnumerable<KeyValuePair<string, string>> attributes)
|
||||||
{
|
{
|
||||||
return descriptors.Where(
|
return descriptor.RequiredAttributes.All(
|
||||||
descriptor => descriptor.RequiredAttributes.All(
|
requiredAttribute => attributes.Any(
|
||||||
requiredAttribute => attributes.Any(
|
attribute => requiredAttribute.IsMatch(attribute.Key, attribute.Value)));
|
||||||
attribute => requiredAttribute.IsMatch(attribute.Key, attribute.Value))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Register(TagHelperDescriptor descriptor)
|
private void Register(TagHelperDescriptor descriptor)
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,9 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Razor.Chunks.Generators;
|
using Microsoft.AspNetCore.Razor.Chunks.Generators;
|
||||||
using Microsoft.AspNetCore.Razor.Editor;
|
using Microsoft.AspNetCore.Razor.Editor;
|
||||||
using Microsoft.AspNetCore.Razor.Parser.Internal;
|
|
||||||
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNetCore.Razor.Tokenizer.Internal;
|
using Microsoft.AspNetCore.Razor.Tokenizer.Internal;
|
||||||
|
|
||||||
|
|
@ -41,12 +40,19 @@ namespace Microsoft.AspNetCore.Razor.Parser
|
||||||
protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block)
|
protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block)
|
||||||
{
|
{
|
||||||
// Collect the content of this node
|
// Collect the content of this node
|
||||||
var content = string.Concat(block.Children.Cast<Span>().Select(s => s.Content));
|
var builder = new StringBuilder();
|
||||||
|
for (var i = 0; i < block.Children.Count; i++)
|
||||||
|
{
|
||||||
|
var childSpan = (Span)block.Children[i];
|
||||||
|
builder.Append(childSpan.Content);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new span containing this content
|
// Create a new span containing this content
|
||||||
var span = new SpanBuilder();
|
var span = new SpanBuilder();
|
||||||
span.EditHandler = new SpanEditHandler(HtmlTokenizer.Tokenize);
|
span.EditHandler = new SpanEditHandler(HtmlTokenizer.Tokenize);
|
||||||
FillSpan(span, block.Children.Cast<Span>().First().Start, content);
|
Debug.Assert(block.Children.Count > 0);
|
||||||
|
var start = ((Span)block.Children[0]).Start;
|
||||||
|
FillSpan(span, start, builder.ToString());
|
||||||
return span.Build();
|
return span.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Razor.Chunks.Generators;
|
using Microsoft.AspNetCore.Razor.Chunks.Generators;
|
||||||
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
|
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
|
||||||
using Microsoft.AspNetCore.Razor.Editor;
|
using Microsoft.AspNetCore.Razor.Editor;
|
||||||
|
|
@ -207,15 +208,23 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
|
||||||
// We're now at: " |asp-for='...'" or " |asp-for=..."
|
// We're now at: " |asp-for='...'" or " |asp-for=..."
|
||||||
// The goal here is to capture the attribute name.
|
// The goal here is to capture the attribute name.
|
||||||
|
|
||||||
var symbolContents = htmlSymbols
|
var nameBuilder = new StringBuilder();
|
||||||
.Skip(i) // Skip prefix
|
|
||||||
.TakeWhile(nameSymbol => HtmlMarkupParser.IsValidAttributeNameSymbol(nameSymbol))
|
|
||||||
.Select(nameSymbol => nameSymbol.Content);
|
|
||||||
|
|
||||||
// Move the indexer past the attribute name symbols.
|
// Move the indexer past the attribute name symbols.
|
||||||
i += symbolContents.Count() - 1;
|
for (var j = i; j < htmlSymbols.Length; j++)
|
||||||
|
{
|
||||||
|
var nameSymbol = htmlSymbols[j];
|
||||||
|
if (!HtmlMarkupParser.IsValidAttributeNameSymbol(nameSymbol))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
name = string.Concat(symbolContents);
|
nameBuilder.Append(nameSymbol.Content);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i--;
|
||||||
|
|
||||||
|
name = nameBuilder.ToString();
|
||||||
attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, name);
|
attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, name);
|
||||||
}
|
}
|
||||||
else if (symbol.Type == HtmlSymbolType.Equals)
|
else if (symbol.Type == HtmlSymbolType.Equals)
|
||||||
|
|
|
||||||
|
|
@ -597,12 +597,14 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
|
||||||
private static bool IsPartialTag(Block tagBlock)
|
private static bool IsPartialTag(Block 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.Last() as Span;
|
var tagEnd = tagBlock.Children[tagBlock.Children.Count - 1] as Span;
|
||||||
|
|
||||||
// If our tag end is not a markup span it means it's some sort of code SyntaxTreeNode (not a valid format)
|
// 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.Kind == SpanKind.Markup)
|
if (tagEnd != null && tagEnd.Kind == SpanKind.Markup)
|
||||||
{
|
{
|
||||||
var endSymbol = tagEnd.Symbols.LastOrDefault() as HtmlSymbol;
|
var endSymbol = tagEnd.Symbols.Count > 0 ?
|
||||||
|
tagEnd.Symbols[tagEnd.Symbols.Count - 1] as HtmlSymbol :
|
||||||
|
null;
|
||||||
|
|
||||||
if (endSymbol != null && endSymbol.Type == HtmlSymbolType.CloseAngle)
|
if (endSymbol != null && endSymbol.Type == HtmlSymbolType.CloseAngle)
|
||||||
{
|
{
|
||||||
|
|
@ -661,8 +663,8 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
|
||||||
|
|
||||||
private bool IsPotentialTagHelper(string tagName, Block childBlock)
|
private bool IsPotentialTagHelper(string tagName, Block childBlock)
|
||||||
{
|
{
|
||||||
var child = childBlock.Children.FirstOrDefault();
|
Debug.Assert(childBlock.Children.Count > 0);
|
||||||
Debug.Assert(child != null);
|
var child = childBlock.Children[0];
|
||||||
|
|
||||||
var childSpan = (Span)child;
|
var childSpan = (Span)child;
|
||||||
|
|
||||||
|
|
@ -752,7 +754,18 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
var childSpan = (Span)child;
|
var childSpan = (Span)child;
|
||||||
var textSymbol = childSpan.Symbols.FirstHtmlSymbolAs(HtmlSymbolType.WhiteSpace | HtmlSymbolType.Text);
|
HtmlSymbol textSymbol = null;
|
||||||
|
for (var i = 0; i < childSpan.Symbols.Count; i++)
|
||||||
|
{
|
||||||
|
var symbol = childSpan.Symbols[i] as HtmlSymbol;
|
||||||
|
|
||||||
|
if (symbol != null &&
|
||||||
|
(symbol.Type & (HtmlSymbolType.WhiteSpace | HtmlSymbolType.Text)) == symbol.Type)
|
||||||
|
{
|
||||||
|
textSymbol = symbol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (textSymbol == null)
|
if (textSymbol == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,24 @@ namespace Microsoft.AspNetCore.Razor.Text
|
||||||
|
|
||||||
public void Append(string content)
|
public void Append(string content)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < content.Length; i++)
|
var previousIndex = 0;
|
||||||
|
for (var i = 0; i < content.Length; i++)
|
||||||
{
|
{
|
||||||
AppendCore(content[i]);
|
|
||||||
|
|
||||||
// \r on it's own: Start a new line, otherwise wait for \n
|
// \r on it's own: Start a new line, otherwise wait for \n
|
||||||
// Other Newline: Start a new line
|
// Other Newline: Start a new line
|
||||||
if ((content[i] == '\r' && (i + 1 == content.Length || content[i + 1] != '\n')) || (content[i] != '\r' && ParserHelpers.IsNewLine(content[i])))
|
if ((content[i] == '\r' && (i + 1 == content.Length || content[i + 1] != '\n')) ||
|
||||||
|
(content[i] != '\r' && ParserHelpers.IsNewLine(content[i])))
|
||||||
{
|
{
|
||||||
|
AppendCore(content, previousIndex, i - previousIndex + 1);
|
||||||
|
previousIndex = i + 1;
|
||||||
PushNewLine();
|
PushNewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (previousIndex < content.Length)
|
||||||
|
{
|
||||||
|
AppendCore(content, previousIndex, content.Length - previousIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharacterReference CharAt(int absoluteIndex)
|
public CharacterReference CharAt(int absoluteIndex)
|
||||||
|
|
@ -63,6 +70,12 @@ namespace Microsoft.AspNetCore.Razor.Text
|
||||||
_lines.Add(_endLine);
|
_lines.Add(_endLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AppendCore(string content, int index, int length)
|
||||||
|
{
|
||||||
|
Debug.Assert(_lines.Count > 0);
|
||||||
|
_lines[_lines.Count - 1].Content.Append(content, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
private void AppendCore(char chr)
|
private void AppendCore(char chr)
|
||||||
{
|
{
|
||||||
Debug.Assert(_lines.Count > 0);
|
Debug.Assert(_lines.Count > 0);
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Tokenizer.Symbols.Internal
|
|
||||||
{
|
|
||||||
public static class HtmlSymbolExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Converts the generic <see cref="IEnumerable{ISymbol}"/> to a <see cref="IEnumerable{HtmlSymbol}"/> and
|
|
||||||
/// finds the first <see cref="HtmlSymbol"/> with type <paramref name="type"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="symbols">The <see cref="IEnumerable{ISymbol}"/> instance this method extends.</param>
|
|
||||||
/// <param name="type">The <see cref="HtmlSymbolType"/> to search for.</param>
|
|
||||||
/// <returns>The first <see cref="HtmlSymbol"/> of type <paramref name="type"/>.</returns>
|
|
||||||
public static HtmlSymbol FirstHtmlSymbolAs(this IEnumerable<ISymbol> symbols, HtmlSymbolType type)
|
|
||||||
{
|
|
||||||
return symbols.OfType<HtmlSymbol>().FirstOrDefault(sym => (type & sym.Type) == sym.Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNetCore.Razor.Text;
|
using Microsoft.AspNetCore.Razor.Text;
|
||||||
|
|
||||||
|
|
@ -13,7 +13,21 @@ namespace Microsoft.AspNetCore.Razor.Tokenizer.Symbols
|
||||||
{
|
{
|
||||||
public static LocationTagged<string> GetContent(this SpanBuilder span)
|
public static LocationTagged<string> GetContent(this SpanBuilder span)
|
||||||
{
|
{
|
||||||
return GetContent(span, e => e);
|
var symbols = span.Symbols;
|
||||||
|
if (symbols.Count > 0)
|
||||||
|
{
|
||||||
|
var text = new StringBuilder();
|
||||||
|
for (var i = 0; i < symbols.Count; i++)
|
||||||
|
{
|
||||||
|
text.Append(symbols[i].Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LocationTagged<string>(text.ToString(), span.Start + symbols[0].Start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new LocationTagged<string>(string.Empty, span.Start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocationTagged<string> GetContent(this SpanBuilder span, Func<IEnumerable<ISymbol>, IEnumerable<ISymbol>> filter)
|
public static LocationTagged<string> GetContent(this SpanBuilder span, Func<IEnumerable<ISymbol>, IEnumerable<ISymbol>> filter)
|
||||||
|
|
@ -23,14 +37,21 @@ namespace Microsoft.AspNetCore.Razor.Tokenizer.Symbols
|
||||||
|
|
||||||
public static LocationTagged<string> GetContent(this IEnumerable<ISymbol> symbols, SourceLocation spanStart)
|
public static LocationTagged<string> GetContent(this IEnumerable<ISymbol> symbols, SourceLocation spanStart)
|
||||||
{
|
{
|
||||||
if (symbols.Any())
|
StringBuilder builder = null;
|
||||||
|
var location = spanStart;
|
||||||
|
|
||||||
|
foreach (var symbol in symbols)
|
||||||
{
|
{
|
||||||
return new LocationTagged<string>(string.Concat(symbols.Select(s => s.Content)), spanStart + symbols.First().Start);
|
if (builder == null)
|
||||||
}
|
{
|
||||||
else
|
builder = new StringBuilder();
|
||||||
{
|
location += symbol.Start;
|
||||||
return new LocationTagged<string>(string.Empty, spanStart);
|
}
|
||||||
|
|
||||||
|
builder.Append(symbol.Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new LocationTagged<string>(builder?.ToString() ?? string.Empty, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocationTagged<string> GetContent(this ISymbol symbol)
|
public static LocationTagged<string> GetContent(this ISymbol symbol)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue