From 68650a7d94261bc56a1f4bc522c2ee35314b1abb Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Tue, 20 Aug 2024 17:50:58 +0000 Subject: [PATCH] Allow @@ as a fallback (#10752) * Added new tests for the specific regressed scenario. * Allow `@@` sequences. Fixes https://github.com/dotnet/sdk/issues/42730 for now. When we move to the new lexer, these will once again be disallowed; attempting to use runtime compilation will necessitate using the native lexer. * Fixup legacy test baselines --- ...rFirstPairAsPartOfCSharpStatement.diag.txt | 5 -- ...FirstPairAsPartOfCSharpStatement.stree.txt | 2 +- ...ctlyParsesAtSignInDelimitedBlock.stree.txt | 3 +- ...ock_DoesNotParseWhenNotSupported.stree.txt | 3 +- .../ComponentCodeGenerationTestBase.cs | 15 ++++ .../test/Legacy/CSharpBlockTest.cs | 26 +++++++ .../AtAtHandled/TestComponent.codegen.cs | 45 +++++++++++ .../AtAtHandled/TestComponent.ir.txt | 20 +++++ .../AtAtHandled/TestComponent.mappings.txt | 10 +++ .../AtAtHandled/TestComponent.codegen.cs | 40 ++++++++++ .../AtAtHandled/TestComponent.ir.txt | 13 ++++ .../AtAtHandled/TestComponent.mappings.txt | 10 +++ .../EscapedIdentifiers_01.stree.txt | 3 +- .../EscapedIdentifiers_03.diag.txt | 10 --- .../EscapedIdentifiers_03.stree.txt | 4 +- .../EscapedIdentifiers_04.stree.txt | 3 +- .../EscapedIdentifiers_05.stree.txt | 3 +- .../EscapedIdentifiers_06.stree.txt | 3 +- .../EscapedIdentifiers_07.stree.txt | 3 +- .../EscapedIdentifiers_11.cspans.txt | 9 +++ .../EscapedIdentifiers_11.stree.txt | 59 +++++++++++++++ .../EscapedIdentifiers_12.cspans.txt | 6 ++ .../EscapedIdentifiers_12.diag.txt | 1 + .../EscapedIdentifiers_12.stree.txt | 22 ++++++ .../EscapedIdentifiers_13.cspans.txt | 7 ++ .../EscapedIdentifiers_13.diag.txt | 1 + .../EscapedIdentifiers_13.stree.txt | 33 ++++++++ ...rFirstPairAsPartOfCSharpStatement.diag.txt | 5 -- ...FirstPairAsPartOfCSharpStatement.stree.txt | 2 +- ...ctlyParsesAtSignInDelimitedBlock.stree.txt | 3 +- ...ock_DoesNotParseWhenNotSupported.stree.txt | 3 +- ...upCodeSpans_EscapedExpression_08.stree.txt | 3 +- .../src/Language/Legacy/CSharpCodeParser.cs | 75 +++++++++++++++---- .../ErrorCode.cs | 1 + 34 files changed, 391 insertions(+), 60 deletions(-) delete mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt delete mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.diag.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.diag.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.diag.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.stree.txt delete mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt deleted file mode 100644 index bd189123b2f..00000000000 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt +++ /dev/null @@ -1,5 +0,0 @@ -(1,14): Error RZ1009: The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example: - -@if(isLoggedIn) { -

Hello, @user!

-} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt index 92e7344e94e..9f8276b72d0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt @@ -17,7 +17,7 @@ Transition;[@]; CSharpStatementLiteral - [12..28)::16 - [@@@class.Foo() }] - Gen - SpanEditHandler;Accepts:Any Transition;[@]; - Identifier;[@]; + Transition;[@]; Identifier;[@class]; Dot;[.]; Identifier;[Foo]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt index 674020e0368..77685bb6951 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt @@ -18,8 +18,7 @@ Whitespace;[ ]; NullCoalesce;[??]; Whitespace;[ ]; - Transition;[@]; - Identifier;[photo]; + Identifier;[@photo]; Dot;[.]; Identifier;[Description]; RazorMetaCode - [46..47)::1 - Gen - SpanEditHandler;Accepts:None diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt index 57850417909..fe9d19cced0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt @@ -34,8 +34,7 @@ LessThan;[<]; Identifier;[h3]; GreaterThan;[>]; - Transition;[@]; - Identifier;[message]; + Identifier;[@message]; LessThan;[<]; Slash;[/]; Identifier;[h3]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs index 8c948743a59..a0eb48526e9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs @@ -10516,6 +10516,21 @@ public void AtTransitions() CompileToAssembly(generated); } + [IntegrationTestFact, WorkItem("https://github.com/dotnet/sdk/issues/42730")] + public void AtAtHandled() + { + var generated = CompileToCSharp(""" + @{ var validationMessage = @Html.ValidationMessage("test", "", new { @@class = "invalid-feedback" }, "div"); } + """); + + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated, + // x:\dir\subdir\Test\TestComponent.cshtml(1,28): error CS0103: The name 'Html' does not exist in the current context + // var validationMessage = @Html.ValidationMessage("test", "", new { @@class = "invalid-feedback" }, "div"); + Diagnostic(ErrorCode.ERR_NameNotInContext, "@Html").WithArguments("Html").WithLocation(1, 28)); + } + #endregion #region LinePragmas diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpBlockTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpBlockTest.cs index cdf7bb2aa6c..e1fa97a2bcf 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpBlockTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpBlockTest.cs @@ -3,6 +3,7 @@ #nullable disable +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.AspNetCore.Razor.Language.Legacy; @@ -880,6 +881,31 @@ public void EscapedIdentifiers_10() """); } + [Fact, WorkItem("https://github.com/dotnet/sdk/issues/42730")] + public void EscapedIdentifiers_11() + { + ParseDocumentTest(""" + @{ var validationMessage = @Html.ValidationMessage(Model.Binding, "", new { @@class = "invalid-feedback" }, "div"); } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/sdk/issues/42730")] + public void EscapedIdentifiers_12() + { + ParseDocumentTest(""" + @{ + @@ + """); + } + + [Fact, WorkItem("https://github.com/dotnet/sdk/issues/42730")] + public void EscapedIdentifiers_13() + { + ParseDocumentTest(""" + @{ var validationMessage = new { @@ + """); + } + private void RunRazorCommentBetweenClausesTest(string preComment, string postComment, AcceptedCharactersInternal acceptedCharacters = AcceptedCharactersInternal.Any) { ParseDocumentTest(preComment + "@* Foo *@ @* Bar *@" + postComment); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs new file mode 100644 index 00000000000..4ff0f219262 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs @@ -0,0 +1,45 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 219 + private void __RazorDirectiveTokenHelpers__() { + } + #pragma warning restore 219 + #pragma warning disable 0414 + private static object __o = null; + #pragma warning restore 0414 + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + var validationMessage = @Html.ValidationMessage("test", "", new { + +#line default +#line hidden +#nullable disable +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + @class = "invalid-feedback" }, "div"); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt new file mode 100644 index 00000000000..201966d5adb --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt @@ -0,0 +1,20 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + CSharpCode - (2:0,2 [67] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (2:0,2 [67] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - var validationMessage = @Html.ValidationMessage("test", "", new { + CSharpCode - (70:0,70 [39] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (70:0,70 [39] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - @class = "invalid-feedback" }, "div"); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt new file mode 100644 index 00000000000..de670e4cb86 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt @@ -0,0 +1,10 @@ +Source Location: (2:0,2 [67] x:\dir\subdir\Test\TestComponent.cshtml) +| var validationMessage = @Html.ValidationMessage("test", "", new { | +Generated Location: (987:28,2 [67] ) +| var validationMessage = @Html.ValidationMessage("test", "", new { | + +Source Location: (70:0,70 [39] x:\dir\subdir\Test\TestComponent.cshtml) +|@class = "invalid-feedback" }, "div"); | +Generated Location: (1246:35,70 [39] ) +|@class = "invalid-feedback" }, "div"); | + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs new file mode 100644 index 00000000000..a8821bf5df7 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.codegen.cs @@ -0,0 +1,40 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { +#nullable restore +#line (1,3)-(1,70) "x:\dir\subdir\Test\TestComponent.cshtml" + var validationMessage = @Html.ValidationMessage("test", "", new { + +#line default +#line hidden +#nullable disable + +#nullable restore +#line (1,71)-(1,110) "x:\dir\subdir\Test\TestComponent.cshtml" +@class = "invalid-feedback" }, "div"); + +#line default +#line hidden +#nullable disable + + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt new file mode 100644 index 00000000000..d62cb6bcb2f --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.ir.txt @@ -0,0 +1,13 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + CSharpCode - (2:0,2 [67] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (2:0,2 [67] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - var validationMessage = @Html.ValidationMessage("test", "", new { + CSharpCode - (70:0,70 [39] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (70:0,70 [39] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - @class = "invalid-feedback" }, "div"); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt new file mode 100644 index 00000000000..0cad3f4b3f4 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AtAtHandled/TestComponent.mappings.txt @@ -0,0 +1,10 @@ +Source Location: (2:0,2 [67] x:\dir\subdir\Test\TestComponent.cshtml) +| var validationMessage = @Html.ValidationMessage("test", "", new { | +Generated Location: (735:21,0 [67] ) +| var validationMessage = @Html.ValidationMessage("test", "", new { | + +Source Location: (70:0,70 [39] x:\dir\subdir\Test\TestComponent.cshtml) +|@class = "invalid-feedback" }, "div"); | +Generated Location: (939:29,0 [39] ) +|@class = "invalid-feedback" }, "div"); | + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_01.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_01.stree.txt index f00da6ee152..1d6cb7d5a50 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_01.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_01.stree.txt @@ -37,8 +37,7 @@ LeftParenthesis;[(]; CSharpCodeBlock - [38..45)::7 CSharpExpressionLiteral - [38..45)::7 - [@string] - Gen - Transition;[@]; - Keyword;[string]; + Identifier;[@string]; RazorMetaCode - [45..46)::1 - Gen RightParenthesis;[)]; MarkupTextLiteral - [46..46)::0 - [] - Gen diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.diag.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.diag.txt deleted file mode 100644 index 73ab857191a..00000000000 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.diag.txt +++ /dev/null @@ -1,10 +0,0 @@ -(2,9): Error RZ1009: The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example: - -@if(isLoggedIn) { -

Hello, @user!

-} -(3,13): Error RZ1009: The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example: - -@if(isLoggedIn) { -

Hello, @user!

-} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.stree.txt index 121bf6fed21..d981280da8c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_03.stree.txt @@ -15,7 +15,7 @@ Whitespace;[ ]; Identifier;[var]; Whitespace;[ ]; - Identifier;[@]; + Transition;[@]; Identifier;[@class]; Whitespace;[ ]; Assign;[=]; @@ -30,7 +30,7 @@ Whitespace;[ ]; Assign;[=]; Whitespace;[ ]; - Identifier;[@]; + Transition;[@]; Identifier;[@class]; Semicolon;[;]; NewLine;[LF]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_04.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_04.stree.txt index 264730983f5..925ba941821 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_04.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_04.stree.txt @@ -53,8 +53,7 @@ LeftParenthesis;[(]; CSharpCodeBlock - [74..81)::7 CSharpExpressionLiteral - [74..81)::7 - [@string] - Gen - Transition;[@]; - Keyword;[string]; + Identifier;[@string]; RazorMetaCode - [81..82)::1 - Gen RightParenthesis;[)]; MarkupTextLiteral - [82..82)::0 - [] - Gen diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_05.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_05.stree.txt index 084ec8ffed9..01f88cdc7c3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_05.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_05.stree.txt @@ -49,8 +49,7 @@ LeftParenthesis;[(]; CSharpCodeBlock - [75..82)::7 CSharpExpressionLiteral - [75..82)::7 - [@string] - Gen - Transition;[@]; - Keyword;[string]; + Identifier;[@string]; RazorMetaCode - [82..83)::1 - Gen RightParenthesis;[)]; MarkupTextLiteral - [83..83)::0 - [] - Gen diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_06.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_06.stree.txt index df0971af655..455c1823c53 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_06.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_06.stree.txt @@ -75,8 +75,7 @@ LeftParenthesis;[(]; CSharpCodeBlock - [115..122)::7 CSharpExpressionLiteral - [115..122)::7 - [@string] - Gen - Transition;[@]; - Keyword;[string]; + Identifier;[@string]; RazorMetaCode - [122..123)::1 - Gen RightParenthesis;[)]; MarkupTextLiteral - [123..123)::0 - [] - Gen diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_07.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_07.stree.txt index 11a0d918c07..6a50645544d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_07.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_07.stree.txt @@ -67,8 +67,7 @@ LeftParenthesis;[(]; CSharpCodeBlock - [117..124)::7 CSharpExpressionLiteral - [117..124)::7 - [@string] - Gen - Transition;[@]; - Keyword;[string]; + Identifier;[@string]; RazorMetaCode - [124..125)::1 - Gen RightParenthesis;[)]; MarkupTextLiteral - [125..125)::0 - [] - Gen diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.cspans.txt new file mode 100644 index 00000000000..73091dcf9f5 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.cspans.txt @@ -0,0 +1,9 @@ +Markup span at (0:0,0 [0] ) - Parent: Markup block at (0:0,0 [118] ) +Code span at (0:0,0 [1] ) - Parent: Statement block at (0:0,0 [118] ) +Transition span at (1:0,1 [1] ) - Parent: Statement block at (1:0,1 [117] ) +MetaCode span at (2:0,2 [1] ) - Parent: Statement block at (1:0,1 [117] ) +Code span at (3:0,3 [74] ) - Parent: Statement block at (1:0,1 [117] ) +Code span at (77:0,77 [1] ) - Parent: Statement block at (1:0,1 [117] ) +Code span at (78:0,78 [39] ) - Parent: Statement block at (1:0,1 [117] ) +MetaCode span at (117:0,117 [1] ) - Parent: Statement block at (1:0,1 [117] ) +Markup span at (118:0,118 [0] ) - Parent: Markup block at (0:0,0 [118] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.stree.txt new file mode 100644 index 00000000000..c4820879c0d --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_11.stree.txt @@ -0,0 +1,59 @@ +RazorDocument - [0..118)::118 - [ @{ var validationMessage = @Html.ValidationMessage(Model.Binding, "", new { @@class = "invalid-feedback" }, "div"); }] + MarkupBlock - [0..118)::118 + MarkupTextLiteral - [0..0)::0 - [] - Gen + Marker;[]; + CSharpCodeBlock - [0..118)::118 + CSharpStatementLiteral - [0..1)::1 - [ ] - Gen + Whitespace;[ ]; + CSharpStatement - [1..118)::117 + CSharpTransition - [1..2)::1 - Gen + Transition;[@]; + CSharpStatementBody - [2..118)::116 + RazorMetaCode - [2..3)::1 - Gen + LeftBrace;[{]; + CSharpCodeBlock - [3..117)::114 + CSharpStatementLiteral - [3..77)::74 - [ var validationMessage = @Html.ValidationMessage(Model.Binding, "", new { ] - Gen + Whitespace;[ ]; + Identifier;[var]; + Whitespace;[ ]; + Identifier;[validationMessage]; + Whitespace;[ ]; + Assign;[=]; + Whitespace;[ ]; + Identifier;[@Html]; + Dot;[.]; + Identifier;[ValidationMessage]; + LeftParenthesis;[(]; + Identifier;[Model]; + Dot;[.]; + Identifier;[Binding]; + Comma;[,]; + Whitespace;[ ]; + StringLiteral;[""]; + Comma;[,]; + Whitespace;[ ]; + Keyword;[new]; + Whitespace;[ ]; + LeftBrace;[{]; + Whitespace;[ ]; + CSharpEphemeralTextLiteral - [77..78)::1 - [@] - Gen + Transition;[@]; + CSharpStatementLiteral - [78..117)::39 - [@class = "invalid-feedback" }, "div"); ] - Gen + Identifier;[@class]; + Whitespace;[ ]; + Assign;[=]; + Whitespace;[ ]; + StringLiteral;["invalid-feedback"]; + Whitespace;[ ]; + RightBrace;[}]; + Comma;[,]; + Whitespace;[ ]; + StringLiteral;["div"]; + RightParenthesis;[)]; + Semicolon;[;]; + Whitespace;[ ]; + RazorMetaCode - [117..118)::1 - Gen + RightBrace;[}]; + MarkupTextLiteral - [118..118)::0 - [] - Gen + Marker;[]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.cspans.txt new file mode 100644 index 00000000000..b14c838247e --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.cspans.txt @@ -0,0 +1,6 @@ +Markup span at (0:0,0 [0] ) - Parent: Markup block at (0:0,0 [10] ) +Transition span at (0:0,0 [1] ) - Parent: Statement block at (0:0,0 [10] ) +MetaCode span at (1:0,1 [1] ) - Parent: Statement block at (0:0,0 [10] ) +Code span at (2:0,2 [6] ) - Parent: Statement block at (0:0,0 [10] ) +Code span at (8:1,4 [1] ) - Parent: Statement block at (0:0,0 [10] ) +Code span at (9:1,5 [1] ) - Parent: Statement block at (0:0,0 [10] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.diag.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.diag.txt new file mode 100644 index 00000000000..bcd37730bb1 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.diag.txt @@ -0,0 +1 @@ +(1,2): Error RZ1006: The code block is missing a closing "}" character. Make sure you have a matching "}" character for all the "{" characters within this block, and that none of the "}" characters are being interpreted as markup. diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.stree.txt new file mode 100644 index 00000000000..f125c4283f7 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_12.stree.txt @@ -0,0 +1,22 @@ +RazorDocument - [0..10)::10 - [@{LF @@] + MarkupBlock - [0..10)::10 + MarkupTextLiteral - [0..0)::0 - [] - Gen + Marker;[]; + CSharpCodeBlock - [0..10)::10 + CSharpStatement - [0..10)::10 + CSharpTransition - [0..1)::1 - Gen + Transition;[@]; + CSharpStatementBody - [1..10)::9 + RazorMetaCode - [1..2)::1 - Gen + LeftBrace;[{]; + CSharpCodeBlock - [2..10)::8 + CSharpStatementLiteral - [2..8)::6 - [LF ] - Gen + NewLine;[LF]; + Whitespace;[ ]; + CSharpEphemeralTextLiteral - [8..9)::1 - [@] - Gen + Transition;[@]; + CSharpStatementLiteral - [9..10)::1 - [@] - Gen + Transition;[@]; + RazorMetaCode - [10..10)::0 - Gen + RightBrace;[]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.cspans.txt new file mode 100644 index 00000000000..6a88f160a69 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.cspans.txt @@ -0,0 +1,7 @@ +Markup span at (0:0,0 [0] ) - Parent: Markup block at (0:0,0 [36] ) +Code span at (0:0,0 [1] ) - Parent: Statement block at (0:0,0 [36] ) +Transition span at (1:0,1 [1] ) - Parent: Statement block at (1:0,1 [35] ) +MetaCode span at (2:0,2 [1] ) - Parent: Statement block at (1:0,1 [35] ) +Code span at (3:0,3 [31] ) - Parent: Statement block at (1:0,1 [35] ) +Code span at (34:0,34 [1] ) - Parent: Statement block at (1:0,1 [35] ) +Code span at (35:0,35 [1] ) - Parent: Statement block at (1:0,1 [35] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.diag.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.diag.txt new file mode 100644 index 00000000000..196c59fd122 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.diag.txt @@ -0,0 +1 @@ +(1,3): Error RZ1006: The code block is missing a closing "}" character. Make sure you have a matching "}" character for all the "{" characters within this block, and that none of the "}" characters are being interpreted as markup. diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.stree.txt new file mode 100644 index 00000000000..fcb53c9dd50 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_13.stree.txt @@ -0,0 +1,33 @@ +RazorDocument - [0..36)::36 - [ @{ var validationMessage = new { @@] + MarkupBlock - [0..36)::36 + MarkupTextLiteral - [0..0)::0 - [] - Gen + Marker;[]; + CSharpCodeBlock - [0..36)::36 + CSharpStatementLiteral - [0..1)::1 - [ ] - Gen + Whitespace;[ ]; + CSharpStatement - [1..36)::35 + CSharpTransition - [1..2)::1 - Gen + Transition;[@]; + CSharpStatementBody - [2..36)::34 + RazorMetaCode - [2..3)::1 - Gen + LeftBrace;[{]; + CSharpCodeBlock - [3..36)::33 + CSharpStatementLiteral - [3..34)::31 - [ var validationMessage = new { ] - Gen + Whitespace;[ ]; + Identifier;[var]; + Whitespace;[ ]; + Identifier;[validationMessage]; + Whitespace;[ ]; + Assign;[=]; + Whitespace;[ ]; + Keyword;[new]; + Whitespace;[ ]; + LeftBrace;[{]; + Whitespace;[ ]; + CSharpEphemeralTextLiteral - [34..35)::1 - [@] - Gen + Transition;[@]; + CSharpStatementLiteral - [35..36)::1 - [@] - Gen + Transition;[@]; + RazorMetaCode - [36..36)::0 - Gen + RightBrace;[]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt deleted file mode 100644 index bd189123b2f..00000000000 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.diag.txt +++ /dev/null @@ -1,5 +0,0 @@ -(1,14): Error RZ1009: The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example: - -@if(isLoggedIn) { -

Hello, @user!

-} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt index 89ff4c9b8bc..e6fc333bcc1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/TreatsAtSignsAfterFirstPairAsPartOfCSharpStatement.stree.txt @@ -17,7 +17,7 @@ Transition;[@]; CSharpStatementLiteral - [12..28)::16 - [@@@class.Foo() }] - Gen Transition;[@]; - Identifier;[@]; + Transition;[@]; Identifier;[@class]; Dot;[.]; Identifier;[Foo]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt index 7b35848f649..2ead9519b58 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpErrorTest/CorrectlyParsesAtSignInDelimitedBlock.stree.txt @@ -18,8 +18,7 @@ Whitespace;[ ]; NullCoalesce;[??]; Whitespace;[ ]; - Transition;[@]; - Identifier;[photo]; + Identifier;[@photo]; Dot;[.]; Identifier;[Description]; RazorMetaCode - [46..47)::1 - Gen diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt index af91a84ac2f..eacb5cfc6c2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpFunctionsTest/MarkupInFunctionsBlock_DoesNotParseWhenNotSupported.stree.txt @@ -34,8 +34,7 @@ LessThan;[<]; Identifier;[h3]; GreaterThan;[>]; - Transition;[@]; - Identifier;[message]; + Identifier;[@message]; LessThan;[<]; Slash;[/]; Identifier;[h3]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesMarkupCodeSpans_EscapedExpression_08.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesMarkupCodeSpans_EscapedExpression_08.stree.txt index abe13766e5d..9a7c790bf0f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesMarkupCodeSpans_EscapedExpression_08.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesMarkupCodeSpans_EscapedExpression_08.stree.txt @@ -27,8 +27,7 @@ Whitespace;[ ]; Keyword;[string]; LeftParenthesis;[(]; - Transition;[@]; - Identifier;[x]; + Identifier;[@x]; LeftParenthesis;[(]; StringLiteral;["1 2"]; RightParenthesis;[)]; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/CSharpCodeParser.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/CSharpCodeParser.cs index 2f19316adec..0d91e46a2f6 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/CSharpCodeParser.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/CSharpCodeParser.cs @@ -977,23 +977,28 @@ not SyntaxKind.LeftBracket and case SyntaxKind.Keyword: // We want to stitch together `@text`. Accept(in read); + Accept(NextAsEscapedIdentifier()); + continue; - var transition = CurrentToken; - NextToken(); - var identifier = CurrentToken; - NextToken(); - Debug.Assert(transition.Kind == SyntaxKind.Transition); - Debug.Assert(identifier.Kind is SyntaxKind.Identifier or SyntaxKind.Keyword); + // We special case @@identifier because the old compiler behavior was to simply accept it and treat it as if it was @identifier. While + // this isn't legal, the runtime compiler doesn't handle @identifier correctly. We'll continue to accept this for now, but will potentially + // break it in the future when we move to the roslyn lexer and the runtime/compiletime split is much greater. + case SyntaxKind.Transition: + if (Lookahead(2) is not { Kind: SyntaxKind.Identifier or SyntaxKind.Keyword }) + { + goto default; + } - var finalIdentifier = SyntaxFactory.Token(SyntaxKind.Identifier, $"{transition.Content}{identifier.Content}"); - Accept(finalIdentifier); + Accept(in read); + AcceptAndMoveNext(); + Accept(NextAsEscapedIdentifier()); continue; default: // Accept a broken identifier `@` and mark an error Accept(in read); - transition = CurrentToken; + var transition = CurrentToken; Debug.Assert(transition.Kind == SyntaxKind.Transition); @@ -1002,7 +1007,7 @@ not SyntaxKind.LeftBracket and new SourceSpan(CurrentStart, contentLength: 1 /* @ */))); NextToken(); - finalIdentifier = SyntaxFactory.Token(SyntaxKind.Identifier, transition.Content); + var finalIdentifier = SyntaxFactory.Token(SyntaxKind.Identifier, transition.Content); Accept(finalIdentifier); continue; } @@ -2639,7 +2644,7 @@ private void ParseReservedDirective(SyntaxListBuilder builder, } protected void CompleteBlock() - { + { AcceptMarkerTokenIfNecessary(); CaptureWhitespaceToEndOfLine(); } @@ -2822,8 +2827,7 @@ private bool Balance(SyntaxListBuilder builder, BalancingModes do { if (IsAtEmbeddedTransition( - (mode & BalancingModes.AllowCommentsAndTemplates) == BalancingModes.AllowCommentsAndTemplates, - (mode & BalancingModes.AllowEmbeddedTransitions) == BalancingModes.AllowEmbeddedTransitions)) + (mode & BalancingModes.AllowCommentsAndTemplates) == BalancingModes.AllowCommentsAndTemplates)) { Accept(in tokens); tokens.Clear(); @@ -2832,6 +2836,31 @@ private bool Balance(SyntaxListBuilder builder, BalancingModes // Reset backtracking since we've already outputted some spans. startPosition = CurrentStart.AbsoluteIndex; } + + if (At(SyntaxKind.Transition)) + { + // We special case @@identifier because the old compiler behavior was to simply accept it and treat it as if it was @identifier. While + // this isn't legal, the runtime compiler doesn't handle @identifier correctly. We'll continue to accept this for now, but will potentially + // break it in the future when we move to the roslyn lexer and the runtime/compiletime split is much greater. + if (NextIs(SyntaxKind.Transition) && Lookahead(2) is { Kind: SyntaxKind.Identifier or SyntaxKind.Keyword }) + { + Accept(in tokens); + tokens.Clear(); + builder.Add(OutputTokensAsStatementLiteral()); + AcceptAndMoveNext(); + builder.Add(OutputTokensAsEphemeralLiteral()); + + // Reset backtracking since we've already outputted some spans. + startPosition = CurrentStart.AbsoluteIndex; + continue; + } + else if (NextIs(SyntaxKind.Keyword, SyntaxKind.Identifier)) + { + tokens.Add(NextAsEscapedIdentifier()); + continue; + } + } + if (At(left)) { nesting++; @@ -2840,12 +2869,14 @@ private bool Balance(SyntaxListBuilder builder, BalancingModes { nesting--; } + if (nesting > 0) { tokens.Add(CurrentToken); + NextToken(); } } - while (nesting > 0 && NextToken() && !(stopAtEndOfLine && At(SyntaxKind.NewLine))); + while (nesting > 0 && EnsureCurrent() && !(stopAtEndOfLine && At(SyntaxKind.NewLine))); if (nesting > 0) { @@ -2876,9 +2907,8 @@ private bool Balance(SyntaxListBuilder builder, BalancingModes return nesting == 0; } - private bool IsAtEmbeddedTransition(bool allowTemplatesAndComments, bool allowTransitions) + private bool IsAtEmbeddedTransition(bool allowTemplatesAndComments) { - // No embedded transitions in C#, so ignore that param return allowTemplatesAndComments && ((Language.IsTransition(CurrentToken) && NextIs(SyntaxKind.LessThan, SyntaxKind.Colon, SyntaxKind.DoubleColon)) @@ -2910,6 +2940,19 @@ private void ParseEmbeddedTransition(in SyntaxListBuilder build } } + private SyntaxToken NextAsEscapedIdentifier() + { + Debug.Assert(CurrentToken.Kind == SyntaxKind.Transition); + var transition = CurrentToken; + NextToken(); + Debug.Assert(CurrentToken.Kind is SyntaxKind.Identifier or SyntaxKind.Keyword); + var identifier = CurrentToken; + NextToken(); + + var finalIdentifier = SyntaxFactory.Token(SyntaxKind.Identifier, $"{transition.Content}{identifier.Content}"); + return finalIdentifier; + } + [Conditional("DEBUG")] internal void Assert(CSharpKeyword expectedKeyword) { diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/ErrorCode.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/ErrorCode.cs index 642478e173c..feb1b0102b5 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/ErrorCode.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/ErrorCode.cs @@ -36,4 +36,5 @@ public enum ErrorCode WRN_NullReferenceReceiver = 8602, WRN_UninitializedNonNullableField = 8618, WRN_MissingNonNullTypesContextForAnnotationInGeneratedCode = 8669, + ERR_IllegalAtSequence = 9008, }