Change `RazorError`s to consistently provide error lengths.
- Updated `TagHelper` errors to no longer highlight the entire tag as an error, instead just the tag name is marked as an error. This is now consistent with nested tags in `@{ ... }` errors.
- Updated `RazorError` and corresponding error logging constructs to disallow creation without providing lengths.
- Updated `TagHelperDescriptorResolver` and related classes to properly determine assembly locations within directives. This allows for exact error locations in the `@addTagHelper` directive.
#386
This commit is contained in:
parent
43fce8c927
commit
ad5bfc5b66
|
|
@ -315,7 +315,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
errorSink.OnError(SourceLocation.Zero, whitespaceError);
|
||||
errorSink.OnError(SourceLocation.Zero, whitespaceError, length: 0);
|
||||
|
||||
validName = false;
|
||||
}
|
||||
|
|
@ -327,7 +327,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
InvalidNonWhitespaceNameCharacters.Contains(character))
|
||||
{
|
||||
var error = characterErrorBuilder(character);
|
||||
errorSink.OnError(SourceLocation.Zero, error);
|
||||
errorSink.OnError(SourceLocation.Zero, error, length: 0);
|
||||
|
||||
validName = false;
|
||||
}
|
||||
|
|
@ -379,7 +379,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
type.FullName,
|
||||
property.Name,
|
||||
typeof(HtmlAttributeNameAttribute).FullName,
|
||||
nameof(HtmlAttributeNameAttribute.Name)));
|
||||
nameof(HtmlAttributeNameAttribute.Name)),
|
||||
length: 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +439,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
SourceLocation.Zero,
|
||||
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNullOrEmpty(
|
||||
parentType.FullName,
|
||||
attributeDescriptor.PropertyName));
|
||||
attributeDescriptor.PropertyName),
|
||||
length: 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -492,7 +494,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixWhitespace(
|
||||
parentType.FullName,
|
||||
propertyName,
|
||||
nameOrPrefix));
|
||||
nameOrPrefix),
|
||||
length: 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -508,7 +511,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
propertyName,
|
||||
nameOrPrefix,
|
||||
attributeNameOrPrefix,
|
||||
DataDashPrefix));
|
||||
DataDashPrefix),
|
||||
length: 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -525,7 +529,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
propertyName,
|
||||
nameOrPrefix,
|
||||
attributeNameOrPrefix,
|
||||
character));
|
||||
character),
|
||||
length: 0);
|
||||
|
||||
isValid = false;
|
||||
}
|
||||
|
|
@ -576,7 +581,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
property.Name,
|
||||
nameof(HtmlAttributeNameAttribute),
|
||||
nameof(HtmlAttributeNameAttribute.DictionaryAttributePrefix),
|
||||
"IDictionary<string, TValue>"));
|
||||
"IDictionary<string, TValue>"),
|
||||
length: 0);
|
||||
}
|
||||
else if (attributeNameAttribute != null && !hasPublicSetter)
|
||||
{
|
||||
|
|
@ -589,7 +595,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
parentType.FullName,
|
||||
property.Name,
|
||||
nameof(HtmlAttributeNameAttribute),
|
||||
"IDictionary<string, TValue>"));
|
||||
"IDictionary<string, TValue>"),
|
||||
length: 0);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -608,7 +615,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
property.Name,
|
||||
nameof(HtmlAttributeNameAttribute),
|
||||
nameof(HtmlAttributeNameAttribute.DictionaryAttributePrefix),
|
||||
"IDictionary<string, TValue>"));
|
||||
"IDictionary<string, TValue>"),
|
||||
length: 0);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
{
|
||||
var descriptors = ResolveDescriptorsInAssembly(
|
||||
lookupInfo.AssemblyName,
|
||||
directiveDescriptor.Location,
|
||||
lookupInfo.AssemblyNameLocation,
|
||||
context.ErrorSink);
|
||||
|
||||
// Only use descriptors that match our lookup info
|
||||
|
|
@ -101,7 +101,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
Resources.FormatTagHelperDescriptorResolver_EncounteredUnexpectedError(
|
||||
"@" + directiveName,
|
||||
directiveDescriptor.DirectiveText,
|
||||
ex.Message));
|
||||
ex.Message),
|
||||
GetErrorLength(directiveDescriptor.DirectiveText));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +184,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
context.ErrorSink.OnError(
|
||||
directive.Location,
|
||||
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperDirective(
|
||||
SyntaxConstants.CSharp.TagHelperPrefixKeyword));
|
||||
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
|
||||
GetErrorLength(directive.DirectiveText));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +215,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperPrefixValue(
|
||||
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||
character,
|
||||
prefix));
|
||||
prefix),
|
||||
prefix.Length);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -241,8 +244,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
return regex.IsMatch(descriptor.TypeName);
|
||||
}
|
||||
|
||||
private static LookupInfo GetLookupInfo(TagHelperDirectiveDescriptor directiveDescriptor,
|
||||
ErrorSink errorSink)
|
||||
private static LookupInfo GetLookupInfo(
|
||||
TagHelperDirectiveDescriptor directiveDescriptor,
|
||||
ErrorSink errorSink)
|
||||
{
|
||||
var lookupText = directiveDescriptor.DirectiveText;
|
||||
var lookupStrings = lookupText?.Split(new[] { ',' });
|
||||
|
|
@ -256,23 +260,42 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
{
|
||||
errorSink.OnError(
|
||||
directiveDescriptor.Location,
|
||||
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText));
|
||||
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText),
|
||||
GetErrorLength(lookupText));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var trimmedAssemblyName = lookupStrings[1].Trim();
|
||||
|
||||
// + 1 is for the comma separator in the lookup text.
|
||||
var assemblyNameIndex = lookupStrings[0].Length + 1 + lookupStrings[1].IndexOf(trimmedAssemblyName);
|
||||
var assemblyNamePrefix = directiveDescriptor.DirectiveText.Substring(0, assemblyNameIndex);
|
||||
var assemblyNameLocation = SourceLocation.Advance(directiveDescriptor.Location, assemblyNamePrefix);
|
||||
|
||||
return new LookupInfo
|
||||
{
|
||||
TypePattern = lookupStrings[0].Trim(),
|
||||
AssemblyName = lookupStrings[1].Trim()
|
||||
AssemblyName = trimmedAssemblyName,
|
||||
AssemblyNameLocation = assemblyNameLocation,
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetErrorLength(string directiveText)
|
||||
{
|
||||
var nonNullLength = directiveText == null ? 1 : directiveText.Length;
|
||||
var normalizeEmptyStringLength = Math.Max(nonNullLength, 1);
|
||||
|
||||
return normalizeEmptyStringLength;
|
||||
}
|
||||
|
||||
private class LookupInfo
|
||||
{
|
||||
public string AssemblyName { get; set; }
|
||||
|
||||
public string TypePattern { get; set; }
|
||||
|
||||
public SourceLocation AssemblyNameLocation { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,14 +35,18 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
/// <see cref="ITagHelper"/> <see cref="Type"/>s.</param>
|
||||
/// <returns>An <see cref="IEnumerable{Type}"/> of valid <see cref="ITagHelper"/> <see cref="Type"/>s.
|
||||
/// </returns>
|
||||
public IEnumerable<Type> Resolve(string name,
|
||||
SourceLocation documentLocation,
|
||||
[NotNull] ErrorSink errorSink)
|
||||
public IEnumerable<Type> Resolve(
|
||||
string name,
|
||||
SourceLocation documentLocation,
|
||||
[NotNull] ErrorSink errorSink)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
errorSink.OnError(documentLocation,
|
||||
Resources.TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull);
|
||||
var errorLength = name == null ? 1 : Math.Max(name.Length, 1);
|
||||
errorSink.OnError(
|
||||
documentLocation,
|
||||
Resources.TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull,
|
||||
errorLength);
|
||||
|
||||
return Type.EmptyTypes;
|
||||
}
|
||||
|
|
@ -60,7 +64,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
documentLocation,
|
||||
Resources.FormatTagHelperTypeResolver_CannotResolveTagHelperAssembly(
|
||||
assemblyName.Name,
|
||||
ex.Message));
|
||||
ex.Message),
|
||||
name.Length);
|
||||
|
||||
return Type.EmptyTypes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,16 +40,6 @@ namespace Microsoft.AspNet.Razor
|
|||
_errors.Add(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and tracks a new <see cref="RazorError"/>.
|
||||
/// </summary>
|
||||
/// <param name="location"><see cref="SourceLocation"/> of the error.</param>
|
||||
/// <param name="message">A message describing the error.</param>
|
||||
public void OnError(SourceLocation location, string message)
|
||||
{
|
||||
OnError(location, message, RazorError.DefaultErrorLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and tracks a new <see cref="RazorError"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -102,7 +102,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
if (!errorReported)
|
||||
{
|
||||
errorReported = true;
|
||||
Context.OnError(errorLocation, RazorResources.ParseError_MissingOpenBraceAfterSection);
|
||||
Context.OnError(
|
||||
errorLocation,
|
||||
RazorResources.ParseError_MissingOpenBraceAfterSection,
|
||||
length: 1 /* { */);
|
||||
}
|
||||
|
||||
PutCurrentBack();
|
||||
|
|
@ -133,9 +136,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
if (!Optional(CSharpSymbolType.RightBrace))
|
||||
{
|
||||
editHandler.AutoCompleteString = "}";
|
||||
Context.OnError(CurrentLocation,
|
||||
RazorResources.FormatParseError_Expected_X(
|
||||
Language.GetSample(CSharpSymbolType.RightBrace)));
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.FormatParseError_Expected_X(Language.GetSample(CSharpSymbolType.RightBrace)),
|
||||
length: 1 /* } */);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -160,8 +164,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
|
||||
if (!At(CSharpSymbolType.LeftBrace))
|
||||
{
|
||||
Context.OnError(CurrentLocation,
|
||||
RazorResources.FormatParseError_Expected_X(Language.GetSample(CSharpSymbolType.LeftBrace)));
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.FormatParseError_Expected_X(Language.GetSample(CSharpSymbolType.LeftBrace)),
|
||||
length: 1 /* { */);
|
||||
CompleteBlock();
|
||||
Output(SpanKind.MetaCode);
|
||||
return;
|
||||
|
|
@ -186,7 +192,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
if (!At(CSharpSymbolType.RightBrace))
|
||||
{
|
||||
editHandler.AutoCompleteString = "}";
|
||||
Context.OnError(blockStart, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, "}", "{"));
|
||||
Context.OnError(
|
||||
blockStart,
|
||||
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, "}", "{"),
|
||||
length: 1 /* } */);
|
||||
CompleteBlock();
|
||||
Output(SpanKind.Code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
|
||||
protected virtual void ReservedDirective(bool topLevel)
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.FormatParseError_ReservedWord(CurrentSymbol.Content));
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.FormatParseError_ReservedWord(CurrentSymbol.Content),
|
||||
CurrentSymbol.Content.Length);
|
||||
AcceptAndMoveNext();
|
||||
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
|
||||
Span.ChunkGenerator = SpanChunkGenerator.Null;
|
||||
|
|
@ -109,7 +112,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
// using Identifier ==> Using Declaration
|
||||
if (!topLevel)
|
||||
{
|
||||
Context.OnError(block.Start, RazorResources.ParseError_NamespaceImportAndTypeAlias_Cannot_Exist_Within_CodeBlock);
|
||||
Context.OnError(
|
||||
block.Start,
|
||||
RazorResources.ParseError_NamespaceImportAndTypeAlias_Cannot_Exist_Within_CodeBlock,
|
||||
block.Name.Length);
|
||||
StandardStatement();
|
||||
}
|
||||
else
|
||||
|
|
@ -327,10 +333,12 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
// Check for "{" to make sure we're at a block
|
||||
if (!At(CSharpSymbolType.LeftBrace))
|
||||
{
|
||||
Context.OnError(CurrentLocation,
|
||||
RazorResources.FormatParseError_SingleLine_ControlFlowStatements_Not_Allowed(
|
||||
Language.GetSample(CSharpSymbolType.LeftBrace),
|
||||
CurrentSymbol.Content));
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.FormatParseError_SingleLine_ControlFlowStatements_Not_Allowed(
|
||||
Language.GetSample(CSharpSymbolType.LeftBrace),
|
||||
CurrentSymbol.Content),
|
||||
CurrentSymbol.Content.Length);
|
||||
}
|
||||
|
||||
// Parse the statement and then we're done
|
||||
|
|
@ -480,7 +488,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
{
|
||||
if (type == CSharpSymbolType.Transition && !isSingleLineMarkup)
|
||||
{
|
||||
Context.OnError(loc, RazorResources.ParseError_AtInCode_Must_Be_Followed_By_Colon_Paren_Or_Identifier_Start);
|
||||
Context.OnError(
|
||||
loc,
|
||||
RazorResources.ParseError_AtInCode_Must_Be_Followed_By_Colon_Paren_Or_Identifier_Start,
|
||||
length: 1 /* @ */);
|
||||
}
|
||||
|
||||
// Markup block
|
||||
|
|
@ -560,7 +571,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
// Throw errors as necessary, but continue parsing
|
||||
if (At(CSharpSymbolType.LeftBrace))
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.ParseError_Unexpected_Nested_CodeBlock);
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.ParseError_Unexpected_Nested_CodeBlock,
|
||||
length: 1 /* { */);
|
||||
}
|
||||
|
||||
// @( or @foo - Nested expression, parse a child block
|
||||
|
|
@ -649,7 +663,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
|
||||
if (EndOfFile)
|
||||
{
|
||||
Context.OnError(block.Start, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, '}', '{'));
|
||||
Context.OnError(
|
||||
block.Start,
|
||||
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, '}', '{'),
|
||||
length: 1 /* { OR } */);
|
||||
}
|
||||
else if (acceptTerminatingBrace)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -256,15 +256,25 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
};
|
||||
if (At(CSharpSymbolType.WhiteSpace) || At(CSharpSymbolType.NewLine))
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS);
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS,
|
||||
CurrentSymbol.Content.Length);
|
||||
}
|
||||
else if (EndOfFile)
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock);
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock,
|
||||
length: 1 /* end of file */);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.FormatParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS(CurrentSymbol.Content));
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.FormatParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS(
|
||||
CurrentSymbol.Content),
|
||||
CurrentSymbol.Content.Length);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
|
@ -529,7 +539,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
if (!success)
|
||||
{
|
||||
AcceptUntil(CSharpSymbolType.LessThan);
|
||||
Context.OnError(block.Start, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, ")", "("));
|
||||
Context.OnError(
|
||||
block.Start,
|
||||
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, ")", "("),
|
||||
length: 1 /* ( */);
|
||||
}
|
||||
|
||||
// If necessary, put an empty-content marker symbol here
|
||||
|
|
@ -556,7 +569,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
{
|
||||
if (Context.IsWithin(BlockType.Template))
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.ParseError_InlineMarkup_Blocks_Cannot_Be_Nested);
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.ParseError_InlineMarkup_Blocks_Cannot_Be_Nested,
|
||||
length: 1 /* @ */);
|
||||
}
|
||||
Output(SpanKind.Code);
|
||||
using (Context.StartBlock(BlockType.Template))
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
{
|
||||
public partial class HtmlMarkupParser
|
||||
{
|
||||
private const string ScriptTagName = "script";
|
||||
|
||||
private SourceLocation _lastTagStart = SourceLocation.Zero;
|
||||
private HtmlSymbol _bufferedOpenAngle;
|
||||
|
||||
|
|
@ -62,7 +64,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
}
|
||||
else
|
||||
{
|
||||
Context.OnError(CurrentSymbol.Start, RazorResources.ParseError_MarkupBlock_Must_Start_With_Tag);
|
||||
Context.OnError(
|
||||
CurrentSymbol.Start,
|
||||
RazorResources.ParseError_MarkupBlock_Must_Start_With_Tag,
|
||||
CurrentSymbol.Content.Length);
|
||||
}
|
||||
Output(SpanKind.Markup);
|
||||
}
|
||||
|
|
@ -221,7 +226,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
}
|
||||
if (tags.Count == 0)
|
||||
{
|
||||
Context.OnError(CurrentLocation, RazorResources.ParseError_OuterTagMissingName);
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
RazorResources.ParseError_OuterTagMissingName,
|
||||
length: 1 /* end of file */);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -346,11 +354,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
|
||||
private bool EndTextTag(HtmlSymbol solidus, IDisposable tagBlockWrapper)
|
||||
{
|
||||
var start = _bufferedOpenAngle.Start;
|
||||
|
||||
Accept(_bufferedOpenAngle);
|
||||
Accept(solidus);
|
||||
|
||||
var textLocation = CurrentLocation;
|
||||
Assert(HtmlSymbolType.Text);
|
||||
AcceptAndMoveNext();
|
||||
|
||||
|
|
@ -358,7 +365,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
|
||||
if (!seenCloseAngle)
|
||||
{
|
||||
Context.OnError(start, RazorResources.ParseError_TextTagCannotContainAttributes);
|
||||
Context.OnError(
|
||||
textLocation,
|
||||
RazorResources.ParseError_TextTagCannotContainAttributes,
|
||||
length: 4 /* text */);
|
||||
|
||||
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.Any;
|
||||
RecoverTextTag();
|
||||
|
|
@ -751,6 +761,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
Span.ChunkGenerator = SpanChunkGenerator.Null;
|
||||
|
||||
Accept(_bufferedOpenAngle);
|
||||
var textLocation = CurrentLocation;
|
||||
Assert(HtmlSymbolType.Text);
|
||||
|
||||
AcceptAndMoveNext();
|
||||
|
|
@ -771,7 +782,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
{
|
||||
Context.Source.Position = bookmark;
|
||||
NextToken();
|
||||
Context.OnError(tag.Item2, RazorResources.ParseError_TextTagCannotContainAttributes);
|
||||
Context.OnError(
|
||||
textLocation,
|
||||
RazorResources.ParseError_TextTagCannotContainAttributes,
|
||||
length: 4 /* text */);
|
||||
|
||||
RecoverTextTag();
|
||||
}
|
||||
|
|
@ -821,7 +835,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
var seenClose = Optional(HtmlSymbolType.CloseAngle);
|
||||
if (!seenClose)
|
||||
{
|
||||
Context.OnError(tag.Item2, RazorResources.FormatParseError_UnfinishedTag(tag.Item1.Content));
|
||||
Context.OnError(
|
||||
SourceLocation.Advance(tag.Item2, "<"),
|
||||
RazorResources.FormatParseError_UnfinishedTag(tag.Item1.Content),
|
||||
Math.Max(tag.Item1.Content.Length, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -883,7 +900,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
Context.Source.Position = bookmark;
|
||||
NextToken();
|
||||
}
|
||||
else if (string.Equals(tagName, "script", StringComparison.OrdinalIgnoreCase))
|
||||
else if (string.Equals(tagName, ScriptTagName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
CompleteTagBlockWithSpan(tagBlockWrapper, AcceptedCharacters.None, SpanKind.Markup);
|
||||
|
||||
|
|
@ -916,7 +933,8 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
var solidus = CurrentSymbol;
|
||||
NextToken(); // Skip over '/', current should be text
|
||||
|
||||
if (At(HtmlSymbolType.Text) && string.Equals(CurrentSymbol.Content, "script", StringComparison.OrdinalIgnoreCase))
|
||||
if (At(HtmlSymbolType.Text) &&
|
||||
string.Equals(CurrentSymbol.Content, ScriptTagName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
seenEndScript = true;
|
||||
}
|
||||
|
|
@ -944,7 +962,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
SkipToAndParseCode(HtmlSymbolType.CloseAngle);
|
||||
if (!Optional(HtmlSymbolType.CloseAngle))
|
||||
{
|
||||
Context.OnError(tagStart, RazorResources.FormatParseError_UnfinishedTag("script"));
|
||||
Context.OnError(
|
||||
SourceLocation.Advance(tagStart, "</"),
|
||||
RazorResources.FormatParseError_UnfinishedTag(ScriptTagName),
|
||||
ScriptTagName.Length);
|
||||
}
|
||||
Output(SpanKind.Markup);
|
||||
}
|
||||
|
|
@ -999,11 +1020,17 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
}
|
||||
if (currentTag != null)
|
||||
{
|
||||
Context.OnError(currentTag.Item2, RazorResources.FormatParseError_MissingEndTag(currentTag.Item1.Content));
|
||||
Context.OnError(
|
||||
SourceLocation.Advance(currentTag.Item2, "<"),
|
||||
RazorResources.FormatParseError_MissingEndTag(currentTag.Item1.Content),
|
||||
currentTag.Item1.Content.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.OnError(tagStart, RazorResources.FormatParseError_UnexpectedEndTag(tagName));
|
||||
Context.OnError(
|
||||
SourceLocation.Advance(tagStart, "</"),
|
||||
RazorResources.FormatParseError_UnexpectedEndTag(tagName),
|
||||
tagName.Length);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1018,7 +1045,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
tags.Pop();
|
||||
}
|
||||
var tag = tags.Pop();
|
||||
Context.OnError(tag.Item2, RazorResources.FormatParseError_MissingEndTag(tag.Item1.Content));
|
||||
Context.OnError(
|
||||
SourceLocation.Advance(tag.Item2, "<"),
|
||||
RazorResources.FormatParseError_MissingEndTag(tag.Item1.Content),
|
||||
tag.Item1.Content.Length);
|
||||
}
|
||||
else if (complete)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -200,14 +200,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
_errorSink.OnError(error);
|
||||
}
|
||||
|
||||
public void OnError(SourceLocation location, string message)
|
||||
{
|
||||
EnusreNotTerminated();
|
||||
AssertOnOwnerTask();
|
||||
|
||||
_errorSink.OnError(location, message);
|
||||
}
|
||||
|
||||
public void OnError(SourceLocation location, string message, int length)
|
||||
{
|
||||
EnusreNotTerminated();
|
||||
|
|
@ -216,12 +208,12 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
_errorSink.OnError(location, message, length);
|
||||
}
|
||||
|
||||
public void OnError(SourceLocation location, string message, params object[] args)
|
||||
public void OnError(SourceLocation location, string message, int length, params object[] args)
|
||||
{
|
||||
EnusreNotTerminated();
|
||||
AssertOnOwnerTask();
|
||||
|
||||
OnError(location, string.Format(CultureInfo.CurrentCulture, message, args));
|
||||
OnError(location, string.Format(CultureInfo.CurrentCulture, message, args), length);
|
||||
}
|
||||
|
||||
public ParserResults CompleteParse()
|
||||
|
|
|
|||
|
|
@ -296,8 +296,10 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
|
||||
if (childSpan == null || childSpan.Kind != SpanKind.Markup)
|
||||
{
|
||||
errorSink.OnError(block.Children.First().Start,
|
||||
RazorResources.FormatTagHelpers_CannotHaveCSharpInTagDeclaration(tagName));
|
||||
errorSink.OnError(
|
||||
block.Start,
|
||||
RazorResources.FormatTagHelpers_CannotHaveCSharpInTagDeclaration(tagName),
|
||||
block.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
@ -316,7 +318,10 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
|
||||
if (name == null)
|
||||
{
|
||||
errorSink.OnError(childSpan.Start, RazorResources.FormatTagHelpers_AttributesMustHaveAName(tagName));
|
||||
errorSink.OnError(
|
||||
childSpan.Start,
|
||||
RazorResources.FormatTagHelpers_AttributesMustHaveAName(tagName),
|
||||
childSpan.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,11 +67,12 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
chunkGenerator.RemoveTagHelperDescriptors ?
|
||||
TagHelperDirectiveType.RemoveTagHelper :
|
||||
TagHelperDirectiveType.AddTagHelper;
|
||||
var textLocation = GetSubTextSourceLocation(span, chunkGenerator.LookupText);
|
||||
|
||||
var directiveDescriptor = new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = chunkGenerator.LookupText,
|
||||
Location = span.Start,
|
||||
Location = textLocation,
|
||||
DirectiveType = directive
|
||||
};
|
||||
|
||||
|
|
@ -80,16 +81,26 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
else if (span.ChunkGenerator is TagHelperPrefixDirectiveChunkGenerator)
|
||||
{
|
||||
var chunkGenerator = (TagHelperPrefixDirectiveChunkGenerator)span.ChunkGenerator;
|
||||
var textLocation = GetSubTextSourceLocation(span, chunkGenerator.Prefix);
|
||||
|
||||
var directiveDescriptor = new TagHelperDirectiveDescriptor
|
||||
{
|
||||
DirectiveText = chunkGenerator.Prefix,
|
||||
Location = span.Start,
|
||||
Location = textLocation,
|
||||
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
|
||||
};
|
||||
|
||||
_directiveDescriptors.Add(directiveDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private static SourceLocation GetSubTextSourceLocation(Span span, string text)
|
||||
{
|
||||
var startOffset = span.Content.IndexOf(text);
|
||||
var offsetContent = span.Content.Substring(0, startOffset);
|
||||
var offsetTextLocation = SourceLocation.Advance(span.Start, offsetContent);
|
||||
|
||||
return offsetTextLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -208,12 +208,12 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
{
|
||||
// End tag TagHelper that states it shouldn't have an end tag.
|
||||
context.ErrorSink.OnError(
|
||||
tagBlock.Start,
|
||||
SourceLocation.Advance(tagBlock.Start, "</"),
|
||||
RazorResources.FormatTagHelperParseTreeRewriter_EndTagTagHelperMustNotHaveAnEndTag(
|
||||
tagName,
|
||||
invalidDescriptor.TypeName,
|
||||
invalidDescriptor.TagStructure),
|
||||
tagBlock.Length);
|
||||
tagName.Length);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -233,8 +233,9 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
// Could not recover, the end tag helper has no corresponding start tag, create
|
||||
// an error based on the current childBlock.
|
||||
context.ErrorSink.OnError(
|
||||
tagBlock.Start,
|
||||
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(tagName));
|
||||
SourceLocation.Advance(tagBlock.Start, "</"),
|
||||
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(tagName),
|
||||
tagName.Length);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -333,8 +334,9 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
tagName,
|
||||
tracker.Builder.TagName,
|
||||
allowedChildrenString);
|
||||
var errorStart = GetTagDeclarationErrorStart(tagBlock);
|
||||
|
||||
errorSink.OnError(tagBlock.Start, errorMessage, tagBlock.Length);
|
||||
errorSink.OnError(errorStart, errorMessage, tagName.Length);
|
||||
}
|
||||
|
||||
private static void ValidateDescriptors(
|
||||
|
|
@ -373,9 +375,12 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
// We assume an invalid syntax until we verify that the tag meets all of our "valid syntax" criteria.
|
||||
if (IsPartialTag(tag))
|
||||
{
|
||||
var errorStart = GetTagDeclarationErrorStart(tag);
|
||||
|
||||
context.ErrorSink.OnError(
|
||||
tag.Start,
|
||||
RazorResources.FormatTagHelpersParseTreeRewriter_MissingCloseAngle(tagName));
|
||||
errorStart,
|
||||
RazorResources.FormatTagHelpersParseTreeRewriter_MissingCloseAngle(tagName),
|
||||
tagName.Length);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -383,6 +388,13 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
return true;
|
||||
}
|
||||
|
||||
private static SourceLocation GetTagDeclarationErrorStart(Block tagBlock)
|
||||
{
|
||||
var advanceBy = IsEndTag(tagBlock) ? "</" : "<";
|
||||
|
||||
return SourceLocation.Advance(tagBlock.Start, advanceBy);
|
||||
}
|
||||
|
||||
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 '<'.
|
||||
|
|
@ -501,9 +513,10 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
var malformedTagHelper = _trackerStack.Peek().Builder;
|
||||
|
||||
context.ErrorSink.OnError(
|
||||
malformedTagHelper.Start,
|
||||
SourceLocation.Advance(malformedTagHelper.Start, "<"),
|
||||
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
||||
malformedTagHelper.TagName));
|
||||
malformedTagHelper.TagName),
|
||||
malformedTagHelper.TagName.Length);
|
||||
|
||||
BuildCurrentlyTrackedTagHelperBlock(endTag: null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,10 +71,12 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
AcceptAndMoveNext();
|
||||
if (EndOfFile && ((mode & BalancingModes.NoErrorOnFailure) != BalancingModes.NoErrorOnFailure))
|
||||
{
|
||||
Context.OnError(start,
|
||||
RazorResources.FormatParseError_Expected_CloseBracket_Before_EOF(
|
||||
Language.GetSample(left),
|
||||
Language.GetSample(right)));
|
||||
Context.OnError(
|
||||
start,
|
||||
RazorResources.FormatParseError_Expected_CloseBracket_Before_EOF(
|
||||
Language.GetSample(left),
|
||||
Language.GetSample(right)),
|
||||
length: 1 /* { OR } */);
|
||||
}
|
||||
|
||||
return Balance(mode, left, right, start);
|
||||
|
|
@ -119,10 +121,12 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
{
|
||||
if ((mode & BalancingModes.NoErrorOnFailure) != BalancingModes.NoErrorOnFailure)
|
||||
{
|
||||
Context.OnError(start,
|
||||
RazorResources.FormatParseError_Expected_CloseBracket_Before_EOF(
|
||||
Language.GetSample(left),
|
||||
Language.GetSample(right)));
|
||||
Context.OnError(
|
||||
start,
|
||||
RazorResources.FormatParseError_Expected_CloseBracket_Before_EOF(
|
||||
Language.GetSample(left),
|
||||
Language.GetSample(right)),
|
||||
length: 1 /* { OR } */);
|
||||
}
|
||||
if ((mode & BalancingModes.BacktrackOnFailure) == BalancingModes.BacktrackOnFailure)
|
||||
{
|
||||
|
|
@ -355,9 +359,17 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
error = RazorResources.FormatErrorComponent_Character(CurrentSymbol.Content);
|
||||
}
|
||||
|
||||
Context.OnError(
|
||||
CurrentLocation,
|
||||
errorBase(error));
|
||||
int errorLength;
|
||||
if (CurrentSymbol == null || CurrentSymbol.Content == null)
|
||||
{
|
||||
errorLength = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorLength = Math.Max(CurrentSymbol.Content.Length, 1);
|
||||
}
|
||||
|
||||
Context.OnError(CurrentLocation, errorBase(error), errorLength);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
|
@ -521,7 +533,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
if (!Optional(KnownSymbolType.CommentStar))
|
||||
{
|
||||
errorReported = true;
|
||||
Context.OnError(start, RazorResources.ParseError_RazorComment_Not_Terminated);
|
||||
Context.OnError(
|
||||
start,
|
||||
RazorResources.ParseError_RazorComment_Not_Terminated,
|
||||
length: 2 /* @* */);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -533,7 +548,10 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
if (!errorReported)
|
||||
{
|
||||
errorReported = true;
|
||||
Context.OnError(start, RazorResources.ParseError_RazorComment_Not_Terminated);
|
||||
Context.OnError(
|
||||
start,
|
||||
RazorResources.ParseError_RazorComment_Not_Terminated,
|
||||
length: 2 /* @* */);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -11,18 +11,16 @@ namespace Microsoft.AspNet.Razor
|
|||
{
|
||||
internal const int DefaultErrorLength = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Used only for deserialization.
|
||||
/// </summary>
|
||||
public RazorError()
|
||||
: this(message: string.Empty, location: SourceLocation.Undefined)
|
||||
: this(message: string.Empty, location: SourceLocation.Undefined, length: -1)
|
||||
{
|
||||
}
|
||||
|
||||
public RazorError(string message, SourceLocation location)
|
||||
: this(message, location, DefaultErrorLength)
|
||||
{
|
||||
}
|
||||
|
||||
public RazorError(string message, int absoluteIndex, int lineIndex, int columnIndex)
|
||||
: this(message, new SourceLocation(absoluteIndex, lineIndex, columnIndex))
|
||||
public RazorError(string message, int absoluteIndex, int lineIndex, int columnIndex, int length)
|
||||
: this(message, new SourceLocation(absoluteIndex, lineIndex, columnIndex), length)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -33,11 +31,6 @@ namespace Microsoft.AspNet.Razor
|
|||
Length = length;
|
||||
}
|
||||
|
||||
public RazorError(string message, int absoluteIndex, int lineIndex, int columnIndex, int length)
|
||||
: this(message, new SourceLocation(absoluteIndex, lineIndex, columnIndex), length)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (or sets) the message describing the error.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -264,7 +264,11 @@ namespace Microsoft.AspNet.Razor.Tokenizer
|
|||
}
|
||||
else if (EndOfFile)
|
||||
{
|
||||
CurrentErrors.Add(new RazorError(RazorResources.ParseError_Unterminated_String_Literal, CurrentStart));
|
||||
CurrentErrors.Add(
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Unterminated_String_Literal,
|
||||
CurrentStart,
|
||||
length: 1 /* end of file */));
|
||||
}
|
||||
return Transition(EndSymbol(CSharpSymbolType.StringLiteral), Data);
|
||||
}
|
||||
|
|
@ -285,7 +289,11 @@ namespace Microsoft.AspNet.Razor.Tokenizer
|
|||
}
|
||||
else if (EndOfFile || ParserHelpers.IsNewLine(CurrentCharacter))
|
||||
{
|
||||
CurrentErrors.Add(new RazorError(RazorResources.ParseError_Unterminated_String_Literal, CurrentStart));
|
||||
CurrentErrors.Add(
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Unterminated_String_Literal,
|
||||
CurrentStart,
|
||||
length: 1 /* " */));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -300,7 +308,11 @@ namespace Microsoft.AspNet.Razor.Tokenizer
|
|||
TakeUntil(c => c == '*');
|
||||
if (EndOfFile)
|
||||
{
|
||||
CurrentErrors.Add(new RazorError(RazorResources.ParseError_BlockComment_Not_Terminated, CurrentStart));
|
||||
CurrentErrors.Add(
|
||||
new RazorError(
|
||||
RazorResources.ParseError_BlockComment_Not_Terminated,
|
||||
CurrentStart,
|
||||
length: 1 /* end of file */));
|
||||
return Transition(EndSymbol(CSharpSymbolType.Comment), Data);
|
||||
}
|
||||
if (CurrentCharacter == '*')
|
||||
|
|
|
|||
Loading…
Reference in New Issue