Log errors if directives do not start at beginning of line.
- Updated tests to validate expectations. - Added two additional tests to validate extensible directives and built-in directives get start at line verification.
This commit is contained in:
parent
3b53f04518
commit
0688cd3ef7
|
|
@ -101,7 +101,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
foreach (var directive in directives)
|
||||
{
|
||||
_directiveParsers.Add(directive, handler);
|
||||
_directiveParsers.Add(directive, () =>
|
||||
{
|
||||
EnsureDirectiveIsAtStartOfLine();
|
||||
handler();
|
||||
});
|
||||
Keywords.Add(directive);
|
||||
|
||||
// These C# keywords are reserved for use in directives. It's an error to use them outside of
|
||||
|
|
@ -1519,6 +1523,30 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
MapDirectives(RemoveTagHelperDirective, SyntaxConstants.CSharp.RemoveTagHelperKeyword);
|
||||
}
|
||||
|
||||
private void EnsureDirectiveIsAtStartOfLine()
|
||||
{
|
||||
// 1 is the offset of the @ transition for the directive.
|
||||
if (CurrentStart.CharacterIndex > 1)
|
||||
{
|
||||
var index = CurrentStart.AbsoluteIndex - 1;
|
||||
var lineStart = CurrentStart.AbsoluteIndex - CurrentStart.CharacterIndex;
|
||||
while (--index >= lineStart)
|
||||
{
|
||||
var @char = Context.SourceDocument[index];
|
||||
|
||||
if (!char.IsWhiteSpace(@char))
|
||||
{
|
||||
var currentDirective = CurrentSymbol.Content;
|
||||
Context.ErrorSink.OnError(
|
||||
CurrentStart,
|
||||
Resources.FormatDirectiveMustAppearAtStartOfLine(currentDirective),
|
||||
length: currentDirective.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDirective(DirectiveDescriptor descriptor)
|
||||
{
|
||||
Context.Builder.CurrentBlock.Type = BlockKindInternal.Directive;
|
||||
|
|
|
|||
|
|
@ -430,6 +430,20 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
internal static string FormatDiagnostic_CodeTarget_UnsupportedExtension(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("Diagnostic_CodeTarget_UnsupportedExtension"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// The '{0}` directive must appear at the start of the line.
|
||||
/// </summary>
|
||||
internal static string DirectiveMustAppearAtStartOfLine
|
||||
{
|
||||
get => GetString("DirectiveMustAppearAtStartOfLine");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The '{0}` directive must appear at the start of the line.
|
||||
/// </summary>
|
||||
internal static string FormatDirectiveMustAppearAtStartOfLine(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveMustAppearAtStartOfLine"), p0);
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -207,4 +207,7 @@
|
|||
<data name="Diagnostic_CodeTarget_UnsupportedExtension" xml:space="preserve">
|
||||
<value>The document type '{0}' does not support the extension '{1}'.</value>
|
||||
</data>
|
||||
<data name="DirectiveMustAppearAtStartOfLine" xml:space="preserve">
|
||||
<value>The '{0}` directive must appear at the start of the line.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -10,6 +10,104 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
public class CSharpDirectivesTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ExtensibleDirectiveDoesNotErorrIfNotAtStartOfLineBecauseOfWhitespace()
|
||||
{
|
||||
// Arrange
|
||||
var descriptor = DirectiveDescriptor.CreateDirective(
|
||||
"custom",
|
||||
DirectiveKind.SingleLine,
|
||||
b => b.AddTypeToken());
|
||||
|
||||
// Act & Assert
|
||||
ParseCodeBlockTest(Environment.NewLine + " @custom System.Text.Encoding.ASCIIEncoding",
|
||||
new[] { descriptor },
|
||||
new DirectiveBlock(
|
||||
new DirectiveChunkGenerator(descriptor),
|
||||
Factory.Code(Environment.NewLine + " ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||
Factory.Span(SpanKindInternal.Code, "System.Text.Encoding.ASCIIEncoding", markup: false)
|
||||
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuiltInDirectiveDoesNotErorrIfNotAtStartOfLineBecauseOfWhitespace()
|
||||
{
|
||||
// Act & Assert
|
||||
ParseCodeBlockTest(Environment.NewLine + " @addTagHelper \"*, Foo\"",
|
||||
Enumerable.Empty<DirectiveDescriptor>(),
|
||||
new DirectiveBlock(
|
||||
Factory.Code(Environment.NewLine + " ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"*, Foo\"")
|
||||
.AsAddTagHelper("\"*, Foo\"")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuiltInDirectiveErorrsIfNotAtStartOfLine()
|
||||
{
|
||||
// Act & Assert
|
||||
ParseCodeBlockTest("{ @addTagHelper \"*, Foo\"" + Environment.NewLine + "}",
|
||||
Enumerable.Empty<DirectiveDescriptor>(),
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code(" ")
|
||||
.AsStatement()
|
||||
.AutoCompleteWith(autoCompleteString: null, atEndOfSpan: false),
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"*, Foo\"")
|
||||
.AsAddTagHelper("\"*, Foo\"")),
|
||||
Factory.Code(Environment.NewLine).AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
new RazorError(
|
||||
Resources.FormatDirectiveMustAppearAtStartOfLine("addTagHelper"),
|
||||
new SourceLocation(4, 0, 4),
|
||||
12));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtensibleDirectiveErorrsIfNotAtStartOfLine()
|
||||
{
|
||||
// Arrange
|
||||
var descriptor = DirectiveDescriptor.CreateDirective(
|
||||
"custom",
|
||||
DirectiveKind.SingleLine,
|
||||
b => b.AddTypeToken());
|
||||
|
||||
// Act & Assert
|
||||
ParseCodeBlockTest(
|
||||
"{ @custom System.Text.Encoding.ASCIIEncoding" + Environment.NewLine + "}",
|
||||
new[] { descriptor },
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code(" ")
|
||||
.AsStatement()
|
||||
.AutoCompleteWith(autoCompleteString: null, atEndOfSpan: false),
|
||||
new DirectiveBlock(
|
||||
new DirectiveChunkGenerator(descriptor),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
|
||||
Factory.Span(SpanKindInternal.Code, "System.Text.Encoding.ASCIIEncoding", markup: false)
|
||||
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace),
|
||||
Factory.Span(SpanKindInternal.Markup, Environment.NewLine, markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
new RazorError(
|
||||
Resources.FormatDirectiveMustAppearAtStartOfLine("custom"),
|
||||
new SourceLocation(4, 0, 4),
|
||||
6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DirectiveDescriptor_UnderstandsTypeTokens()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.Markup(" ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(
|
||||
Resources.FormatDirectiveMustAppearAtStartOfLine("section"),
|
||||
new SourceLocation(16, 0, 16),
|
||||
7),
|
||||
new RazorError(
|
||||
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
|
||||
new SourceLocation(15, 0, 15),
|
||||
|
|
|
|||
Loading…
Reference in New Issue