[Fixes #980] Generate parser error for unquoted string token directives

This commit is contained in:
Ajay Bhargav Baaskaran 2017-03-17 16:45:35 -07:00
parent ca6f988bd9
commit 4a71b1d57d
4 changed files with 160 additions and 29 deletions

View File

@ -1553,7 +1553,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
outputKind = SpanKind.Code; outputKind = SpanKind.Code;
break; break;
case DirectiveTokenKind.String: case DirectiveTokenKind.String:
AcceptUntil(CSharpSymbolType.WhiteSpace, CSharpSymbolType.NewLine); if (At(CSharpSymbolType.StringLiteral))
{
AcceptAndMoveNext();
}
else
{
var startLocation = CurrentStart;
AcceptUntil(CSharpSymbolType.WhiteSpace, CSharpSymbolType.NewLine);
Context.ErrorSink.OnError(
startLocation,
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral(descriptor.Name),
Span.End.AbsoluteIndex - Span.Start.AbsoluteIndex);
}
break; break;
} }

View File

@ -182,6 +182,9 @@
<data name="DirectiveExpectsIdentifier" xml:space="preserve"> <data name="DirectiveExpectsIdentifier" xml:space="preserve">
<value>The '{0}' directive expects an identifier.</value> <value>The '{0}' directive expects an identifier.</value>
</data> </data>
<data name="DirectiveExpectsQuotedStringLiteral" xml:space="preserve">
<value>The '{0}' directive expects a string surrounded by double quotes.</value>
</data>
<data name="DirectiveExpectsTypeName" xml:space="preserve"> <data name="DirectiveExpectsTypeName" xml:space="preserve">
<value>The '{0}' directive expects a type name.</value> <value>The '{0}' directive expects a type name.</value>
</data> </data>

View File

@ -304,6 +304,20 @@ namespace Microsoft.AspNetCore.Razor.Evolution
internal static string FormatDirectiveExpectsIdentifier(object p0) internal static string FormatDirectiveExpectsIdentifier(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveExpectsIdentifier"), p0); => string.Format(CultureInfo.CurrentCulture, GetString("DirectiveExpectsIdentifier"), p0);
/// <summary>
/// The '{0}' directive expects a string surrounded by double quotes.
/// </summary>
internal static string DirectiveExpectsQuotedStringLiteral
{
get => GetString("DirectiveExpectsQuotedStringLiteral");
}
/// <summary>
/// The '{0}' directive expects a string surrounded by double quotes.
/// </summary>
internal static string FormatDirectiveExpectsQuotedStringLiteral(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveExpectsQuotedStringLiteral"), p0);
/// <summary> /// <summary>
/// The '{0}' directive expects a type name. /// The '{0}' directive expects a type name.
/// </summary> /// </summary>

View File

@ -56,6 +56,30 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build();
// Act & Assert
ParseCodeBlockTest(
"@custom \"AString\"",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "\"AString\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace)));
}
[Fact]
public void DirectiveDescriptor_StringToken_ParserErrorForUnquotedValue()
{
// Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build();
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 7);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom AString", "@custom AString",
@ -67,7 +91,85 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "AString", markup: false) Factory.Span(SpanKind.Markup, "AString", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace))); .Accepts(AcceptedCharacters.NonWhiteSpace)), expectedError);
}
[Fact]
public void DirectiveDescriptor_StringToken_ParserErrorForNonStringValue()
{
// Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build();
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 6);
// Act & Assert
ParseCodeBlockTest(
"@custom {foo?}",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "{foo?}", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace)), expectedError);
}
[Fact]
public void DirectiveDescriptor_StringToken_ParserErrorForSingleQuotedValue()
{
// Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build();
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 9);
// Act & Assert
ParseCodeBlockTest(
"@custom 'AString'",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "'AString'", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace)), expectedError);
}
[Fact]
public void DirectiveDescriptor_StringToken_ParserErrorForPartialQuotedValue()
{
// Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build();
var expectedError1 = new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
new SourceLocation(15, 0, 15),
length: 1);
var expectedError2 = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 8);
// Act & Assert
ParseCodeBlockTest(
"@custom AString\"",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "AString\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace)),
expectedError1,
expectedError2);
} }
[Fact] [Fact]
@ -82,7 +184,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom System.Text.Encoding.ASCIIEncoding Some_Member AString", "@custom System.Text.Encoding.ASCIIEncoding Some_Member \"AString\"",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
@ -100,7 +202,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "AString", markup: false) Factory.Span(SpanKind.Markup, "\"AString\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[2])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[2]))
.Accepts(AcceptedCharacters.NonWhiteSpace))); .Accepts(AcceptedCharacters.NonWhiteSpace)));
} }
@ -113,14 +215,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom Header { <p>F{o}o</p> }", "@custom \"Header\" { <p>F{o}o</p> }",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "Header", markup: false) Factory.Span(SpanKind.Markup, "\"Header\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.AllWhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.AllWhiteSpace),
@ -146,14 +248,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom Name { foo(); bar(); }", "@custom \"Name\" { foo(); bar(); }",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "Name", markup: false) Factory.Span(SpanKind.Markup, "\"Name\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.AllWhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.AllWhiteSpace),
@ -226,14 +328,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom hello ; ", "@custom \"hello\" ; ",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "hello", markup: false) Factory.Span(SpanKind.Markup, "\"hello\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
Factory.Span(SpanKind.Markup, " ; ", markup: false).Accepts(AcceptedCharacters.WhiteSpace))); Factory.Span(SpanKind.Markup, " ; ", markup: false).Accepts(AcceptedCharacters.WhiteSpace)));
@ -246,19 +348,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build();
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", Environment.NewLine), LegacyResources.FormatUnexpectedDirectiveLiteral("custom", Environment.NewLine),
new SourceLocation(14, 0, 14), new SourceLocation(16, 0, 16),
length: 5); length: 7);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom hello world", "@custom \"hello\" \"world\"",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "hello", markup: false) Factory.Span(SpanKind.Markup, "\"hello\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
@ -273,19 +375,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build();
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "{"), LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "{"),
new SourceLocation(14, 0, 14), new SourceLocation(16, 0, 16),
length: 5); length: 5);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom Hello World { foo(); bar(); }", "@custom \"Hello\" World { foo(); bar(); }",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "Hello", markup: false) Factory.Span(SpanKind.Markup, "\"Hello\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
@ -300,19 +402,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build();
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective("custom", "{"), LegacyResources.FormatUnexpectedEOFAfterDirective("custom", "{"),
new SourceLocation(13, 0, 13), new SourceLocation(15, 0, 15),
length: 1); length: 1);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom Hello", "@custom \"Hello\"",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "Hello", markup: false) Factory.Span(SpanKind.Markup, "\"Hello\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace)), .Accepts(AcceptedCharacters.NonWhiteSpace)),
expectedErorr); expectedErorr);
@ -325,19 +427,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build();
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("custom", "}", "{"), LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("custom", "}", "{"),
new SourceLocation(14, 0, 14), new SourceLocation(16, 0, 16),
length: 1); length: 1);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom Hello {", "@custom \"Hello\" {",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "Hello", markup: false) Factory.Span(SpanKind.Markup, "\"Hello\"", markup: false)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0])) .With(new DirectiveTokenChunkGenerator(descriptor.Tokens[0]))
.Accepts(AcceptedCharacters.NonWhiteSpace), .Accepts(AcceptedCharacters.NonWhiteSpace),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.AllWhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.AllWhiteSpace),
@ -781,14 +883,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom simple-value", "@custom \"simple-value\"",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "simple-value", markup: false) Factory.Span(SpanKind.Markup, "\"simple-value\"", markup: false)
.Accepts(AcceptedCharacters.NonWhiteSpace) .Accepts(AcceptedCharacters.NonWhiteSpace)
.With(chunkGenerator))); .With(chunkGenerator)));
} }
@ -802,14 +904,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom {formaction}?/{id}?", "@custom \"{formaction}?/{id}?\"",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "{formaction}?/{id}?", markup: false) Factory.Span(SpanKind.Markup, "\"{formaction}?/{id}?\"", markup: false)
.Accepts(AcceptedCharacters.NonWhiteSpace) .Accepts(AcceptedCharacters.NonWhiteSpace)
.With(chunkGenerator))); .With(chunkGenerator)));
} }
@ -822,14 +924,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
"@custom {formaction}?/{id}? System.String", "@custom \"{formaction}?/{id}?\" System.String",
new[] { descriptor }, new[] { descriptor },
new DirectiveBlock( new DirectiveBlock(
new DirectiveChunkGenerator(descriptor), new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(), Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharacters.None), Factory.MetaCode("custom").Accepts(AcceptedCharacters.None),
Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Markup, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),
Factory.Span(SpanKind.Markup, "{formaction}?/{id}?", markup: false) Factory.Span(SpanKind.Markup, "\"{formaction}?/{id}?\"", markup: false)
.Accepts(AcceptedCharacters.NonWhiteSpace) .Accepts(AcceptedCharacters.NonWhiteSpace)
.With(new DirectiveTokenChunkGenerator(descriptor.Tokens.First())), .With(new DirectiveTokenChunkGenerator(descriptor.Tokens.First())),
Factory.Span(SpanKind.Code, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace), Factory.Span(SpanKind.Code, " ", markup: false).Accepts(AcceptedCharacters.WhiteSpace),