diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/ViewComponentTagHelperTargetExtension.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/ViewComponentTagHelperTargetExtension.cs index e810b2a087..eb426d0607 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/ViewComponentTagHelperTargetExtension.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/ViewComponentTagHelperTargetExtension.cs @@ -60,7 +60,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X WriteTargetElementString(context.CodeWriter, node.TagHelper); // Initialize declaration. - using (context.CodeWriter.BuildClassDeclaration(PublicModifiers, node.ClassName, TagHelperTypeName, interfaces: null)) + using (context.CodeWriter.BuildClassDeclaration( + PublicModifiers, + node.ClassName, + TagHelperTypeName, + interfaces: null, + typeParameters: null)) { // Add view component helper. context.CodeWriter.WriteVariableDeclaration( diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorPageDocumentClassifierPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorPageDocumentClassifierPass.cs index 99b3ba8d19..b7721addc1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorPageDocumentClassifierPass.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorPageDocumentClassifierPass.cs @@ -112,11 +112,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions var leadingDirectiveCodeDocument = RazorCodeDocument.Create(codeDocument.Source); LeadingDirectiveParsingEngine.Engine.Process(leadingDirectiveCodeDocument); - var documentIRNode = leadingDirectiveCodeDocument.GetDocumentIntermediateNode(); - if (!PageDirective.TryGetPageDirective(documentIRNode, out var _)) + var leadingDirectiveDocumentNode = leadingDirectiveCodeDocument.GetDocumentIntermediateNode(); + if (!PageDirective.TryGetPageDirective(leadingDirectiveDocumentNode, out var _)) { // The page directive is not the leading directive. Add an error. - pageDirective.DirectiveNode.Diagnostics.Add( + // Note: Adding the error to the top-level document node because the directive node will be removed by a later optimization pass. + var originalDocumentNode = codeDocument.GetDocumentIntermediateNode(); + originalDocumentNode.Diagnostics.Add( RazorExtensionsDiagnosticFactory.CreatePageDirective_MustExistAtTheTopOfFile(pageDirective.DirectiveNode.Source.Value)); } } diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperTargetExtension.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperTargetExtension.cs index 298fe23e31..89aba13222 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperTargetExtension.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperTargetExtension.cs @@ -60,7 +60,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions WriteTargetElementString(context.CodeWriter, node.TagHelper); // Initialize declaration. - using (context.CodeWriter.BuildClassDeclaration(PublicModifiers, node.ClassName, TagHelperTypeName, interfaces: null)) + using (context.CodeWriter.BuildClassDeclaration( + PublicModifiers, + node.ClassName, + TagHelperTypeName, + interfaces: null, + typeParameters: null)) { // Add view component helper. context.CodeWriter.WriteVariableDeclaration( diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs index e6a749b269..f15acdeaf6 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs @@ -374,7 +374,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration IList modifiers, string name, string baseType, - IEnumerable interfaces) + IList interfaces, + IList typeParameters) { for (var i = 0; i < modifiers.Count; i++) { @@ -385,8 +386,15 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.Write("class "); writer.Write(name); + if (typeParameters != null && typeParameters.Count > 0) + { + writer.Write("<"); + writer.Write(string.Join(", ", typeParameters)); + writer.Write(">"); + } + var hasBaseType = !string.IsNullOrEmpty(baseType); - var hasInterfaces = interfaces != null && interfaces.Count() > 0; + var hasInterfaces = interfaces != null && interfaces.Count > 0; if (hasBaseType || hasInterfaces) { diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs index 09ed47b6fa..a47295143d 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DefaultDocumentWriter.cs @@ -78,8 +78,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration { algorithmId = "{8829d00f-11b8-4213-878b-770e8597ac16}"; } - else if (string.Equals(algorithm, HashAlgorithmName.SHA1.Name, StringComparison.Ordinal) || - + else if (string.Equals(algorithm, HashAlgorithmName.SHA1.Name, StringComparison.Ordinal) || + // In 2.0, we didn't actually expose the name of the algorithm, so it's possible we could get null here. // If that's the case, we just assume SHA1 since that's the only thing we supported in 2.0. algorithm == null) @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration } else { - var supportedAlgorithms = string.Join(" ", new string[] + var supportedAlgorithms = string.Join(" ", new string[] { HashAlgorithmName.SHA1.Name, HashAlgorithmName.SHA256.Name @@ -143,7 +143,12 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node) { - using (Context.CodeWriter.BuildClassDeclaration(node.Modifiers, node.ClassName, node.BaseType, node.Interfaces)) + using (Context.CodeWriter.BuildClassDeclaration( + node.Modifiers, + node.ClassName, + node.BaseType, + node.Interfaces, + node.TypeParameters.Select(p => p.ParameterName).ToArray())) { VisitDefault(node); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIntermediateNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIntermediateNode.cs index 3804ca8a4d..cf923eb429 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIntermediateNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIntermediateNode.cs @@ -16,7 +16,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public string BaseType { get; set; } - public IList Interfaces { get; set; } + public IList Interfaces { get; set; } = new List(); + + public IList TypeParameters { get; set; } = new List(); public override void Accept(IntermediateNodeVisitor visitor) { diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TypeParameter.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TypeParameter.cs new file mode 100644 index 0000000000..08f953e23a --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TypeParameter.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.Razor.Language.Intermediate +{ + public sealed class TypeParameter + { + public string ParameterName { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/HtmlMarkupParser.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/HtmlMarkupParser.cs index a23adbb28f..d038f58cc5 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/HtmlMarkupParser.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/HtmlMarkupParser.cs @@ -931,7 +931,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy { // First, determine if this is a 'data-' attribute (since those can't use conditional attributes) var name = string.Concat(nameSymbols.Select(s => s.Content)); - var attributeCanBeConditional = !name.StartsWith("data-", StringComparison.OrdinalIgnoreCase); + var attributeCanBeConditional = + Context.FeatureFlags.EXPERIMENTAL_AllowConditionalDataDashAttributes || + !name.StartsWith("data-", StringComparison.OrdinalIgnoreCase); // Accept the whitespace and name Accept(whitespace); diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs index 6035ccc81b..0bd3da36ff 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs @@ -23,6 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy Source = new SeekableTextReader(chars, source.FilePath); DesignTimeMode = options.DesignTime; + FeatureFlags = options.FeatureFlags; ParseLeadingDirectives = options.ParseLeadingDirectives; Builder = new SyntaxTreeBuilder(); ErrorSink = new ErrorSink(); @@ -33,6 +34,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy public ErrorSink ErrorSink { get; set; } + public RazorParserFeatureFlags FeatureFlags { get; } + public HashSet SeenDirectives { get; } public ITextDocument Source { get; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs index 409718b640..fbaa2708a2 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs @@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language { var allowMinimizedBooleanTagHelperAttributes = false; var allowHtmlCommentsInTagHelpers = false; + var experimental_AllowConditionalDataDashAttributes = false; if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0) { @@ -17,24 +18,40 @@ namespace Microsoft.AspNetCore.Razor.Language allowHtmlCommentsInTagHelpers = true; } - return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes, allowHtmlCommentsInTagHelpers); + if (version.CompareTo(RazorLanguageVersion.Experimental) >= 0) + { + experimental_AllowConditionalDataDashAttributes = true; + } + + return new DefaultRazorParserFeatureFlags( + allowMinimizedBooleanTagHelperAttributes, + allowHtmlCommentsInTagHelpers, + experimental_AllowConditionalDataDashAttributes); } public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; } public abstract bool AllowHtmlCommentsInTagHelpers { get; } + public abstract bool EXPERIMENTAL_AllowConditionalDataDashAttributes { get; } + private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags { - public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelpers) + public DefaultRazorParserFeatureFlags( + bool allowMinimizedBooleanTagHelperAttributes, + bool allowHtmlCommentsInTagHelpers, + bool experimental_AllowConditionalDataDashAttributes) { AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes; AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelpers; + EXPERIMENTAL_AllowConditionalDataDashAttributes = experimental_AllowConditionalDataDashAttributes; } public override bool AllowMinimizedBooleanTagHelperAttributes { get; } public override bool AllowHtmlCommentsInTagHelpers { get; } + + public override bool EXPERIMENTAL_AllowConditionalDataDashAttributes { get; } } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs index 2155b6c1a9..88ef8da1a0 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -290,6 +290,14 @@ public class AllTagHelper : {typeof(TagHelper).FullName} RunRuntimeTest(compilation); } + + [Fact] + public void RazorPageWithNoLeadingPageDirective_Runtime() + { + var compilation = BaseCompilation; + + RunRuntimeTest(compilation); + } #endregion #region DesignTime @@ -577,6 +585,14 @@ public class AllTagHelper : {typeof(TagHelper).FullName} RunDesignTimeTest(compilation); } + + [Fact] + public void RazorPageWithNoLeadingPageDirective_DesignTime() + { + var compilation = BaseCompilation; + + RunDesignTimeTest(compilation); + } #endregion private void RunRuntimeTest( diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/RazorPageDocumentClassifierPassTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/RazorPageDocumentClassifierPassTest.cs index 0ba9dd5178..526bf68a88 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/RazorPageDocumentClassifierPassTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/RazorPageDocumentClassifierPassTest.cs @@ -68,9 +68,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions visitor.Visit(irDocument); // Assert - var pageDirectives = irDocument.FindDirectiveReferences(PageDirective.Directive); - var directive = Assert.Single(pageDirectives); - var diagnostic = Assert.Single(directive.Node.Diagnostics); + var documentNode = codeDocument.GetDocumentIntermediateNode(); + var diagnostic = Assert.Single(documentNode.Diagnostics); Assert.Equal(expectedDiagnostic, diagnostic); } @@ -98,9 +97,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions visitor.Visit(irDocument); // Assert - var pageDirectives = irDocument.FindDirectiveReferences(PageDirective.Directive); - var directive = Assert.Single(pageDirectives); - Assert.Empty(directive.Node.Diagnostics); + var documentNode = codeDocument.GetDocumentIntermediateNode(); + Assert.Empty(documentNode.Diagnostics); } [Fact] diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml new file mode 100644 index 0000000000..5172f8f791 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml @@ -0,0 +1,2 @@ +
Some text here.
+@page diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.cs new file mode 100644 index 0000000000..ec8a4fd5c9 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.cs @@ -0,0 +1,42 @@ +// +#pragma warning disable 1591 +namespace AspNetCore +{ + #line hidden + using TModel = global::System.Object; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; + public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective : global::Microsoft.AspNetCore.Mvc.RazorPages.Page + { + #pragma warning disable 219 + private void __RazorDirectiveTokenHelpers__() { + } + #pragma warning restore 219 + #pragma warning disable 0414 + private static System.Object __o = null; + #pragma warning restore 0414 + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { + } + #pragma warning restore 1998 + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; + public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective Model => ViewData.Model; + } +} +#pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.diagnostics.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.diagnostics.txt new file mode 100644 index 0000000000..393b35646e --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.diagnostics.txt @@ -0,0 +1 @@ +TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml(2,1): Error RZ3906: The '@page' directive must precede all other elements defined in a Razor file. diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.ir.txt new file mode 100644 index 0000000000..c21d9fc82c --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.ir.txt @@ -0,0 +1,46 @@ +Document - + NamespaceDeclaration - - AspNetCore + UsingDirective - - TModel = global::System.Object + UsingDirective - (1:0,1 [12] ) - System + UsingDirective - (16:1,1 [32] ) - System.Collections.Generic + UsingDirective - (51:2,1 [17] ) - System.Linq + UsingDirective - (71:3,1 [28] ) - System.Threading.Tasks + UsingDirective - (102:4,1 [30] ) - Microsoft.AspNetCore.Mvc + UsingDirective - (135:5,1 [40] ) - Microsoft.AspNetCore.Mvc.Rendering + UsingDirective - (178:6,1 [43] ) - Microsoft.AspNetCore.Mvc.ViewFeatures + ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective - global::Microsoft.AspNetCore.Mvc.RazorPages.Page - + DesignTimeDirective - + DirectiveToken - (231:7,8 [62] ) - global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper + DirectiveToken - (294:7,71 [4] ) - Html + DirectiveToken - (308:8,8 [54] ) - global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper + DirectiveToken - (363:8,63 [4] ) - Json + DirectiveToken - (377:9,8 [53] ) - global::Microsoft.AspNetCore.Mvc.IViewComponentHelper + DirectiveToken - (431:9,62 [9] ) - Component + DirectiveToken - (450:10,8 [43] ) - global::Microsoft.AspNetCore.Mvc.IUrlHelper + DirectiveToken - (494:10,52 [3] ) - Url + DirectiveToken - (507:11,8 [70] ) - global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider + DirectiveToken - (578:11,79 [23] ) - ModelExpressionProvider + DirectiveToken - (617:12,14 [96] ) - Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor + DirectiveToken - (729:13,14 [87] ) - Microsoft.AspNetCore.Mvc.Razor.TagHelpers.HeadTagHelper, Microsoft.AspNetCore.Mvc.Razor + DirectiveToken - (832:14,14 [87] ) - Microsoft.AspNetCore.Mvc.Razor.TagHelpers.BodyTagHelper, Microsoft.AspNetCore.Mvc.Razor + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static System.Object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - public async override - global::System.Threading.Tasks.Task - ExecuteAsync + HtmlContent - (0:0,0 [28] RazorPageWithNoLeadingPageDirective.cshtml) + IntermediateToken - (0:0,0 [5] RazorPageWithNoLeadingPageDirective.cshtml) - Html -
+ IntermediateToken - (5:0,5 [15] RazorPageWithNoLeadingPageDirective.cshtml) - Html - Some text here. + IntermediateToken - (20:0,20 [6] RazorPageWithNoLeadingPageDirective.cshtml) - Html -
+ IntermediateToken - (26:0,26 [2] RazorPageWithNoLeadingPageDirective.cshtml) - Html - \n + Inject - + Inject - + Inject - + Inject - + Inject - + CSharpCode - + IntermediateToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; + CSharpCode - + IntermediateToken - - CSharp - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective Model => ViewData.Model; diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.mappings.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.mappings.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.codegen.cs new file mode 100644 index 0000000000..0b0bd358fa --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.codegen.cs @@ -0,0 +1,41 @@ +#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "1d35b023a80ffd4cbf92549aae24d6c47f4af7e5" +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective), @"mvc.1.0.razor-page", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml")] +[assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(@"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml", typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective), null)] +namespace AspNetCore +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; + [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"1d35b023a80ffd4cbf92549aae24d6c47f4af7e5", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml")] + public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective : global::Microsoft.AspNetCore.Mvc.RazorPages.Page + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { + BeginContext(0, 28, true); + WriteLiteral("
Some text here.
\r\n"); + EndContext(); + } + #pragma warning restore 1998 + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; + public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective Model => ViewData.Model; + } +} +#pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.diagnostics.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.diagnostics.txt new file mode 100644 index 0000000000..393b35646e --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.diagnostics.txt @@ -0,0 +1 @@ +TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml(2,1): Error RZ3906: The '@page' directive must precede all other elements defined in a Razor file. diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.ir.txt new file mode 100644 index 0000000000..764b704909 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_Runtime.ir.txt @@ -0,0 +1,33 @@ +Document - + RazorCompiledItemAttribute - + CSharpCode - + IntermediateToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(@"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective.cshtml", typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective), null)] + NamespaceDeclaration - - AspNetCore + UsingDirective - (1:0,1 [14] ) - System + UsingDirective - (16:1,1 [34] ) - System.Collections.Generic + UsingDirective - (51:2,1 [19] ) - System.Linq + UsingDirective - (71:3,1 [30] ) - System.Threading.Tasks + UsingDirective - (102:4,1 [32] ) - Microsoft.AspNetCore.Mvc + UsingDirective - (135:5,1 [42] ) - Microsoft.AspNetCore.Mvc.Rendering + UsingDirective - (178:6,1 [45] ) - Microsoft.AspNetCore.Mvc.ViewFeatures + RazorSourceChecksumAttribute - + ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective - global::Microsoft.AspNetCore.Mvc.RazorPages.Page - + MethodDeclaration - - public async override - global::System.Threading.Tasks.Task - ExecuteAsync + CSharpCode - + IntermediateToken - - CSharp - BeginContext(0, 28, true); + HtmlContent - (0:0,0 [28] RazorPageWithNoLeadingPageDirective.cshtml) + IntermediateToken - (0:0,0 [5] RazorPageWithNoLeadingPageDirective.cshtml) - Html -
+ IntermediateToken - (5:0,5 [15] RazorPageWithNoLeadingPageDirective.cshtml) - Html - Some text here. + IntermediateToken - (20:0,20 [6] RazorPageWithNoLeadingPageDirective.cshtml) - Html -
+ IntermediateToken - (26:0,26 [2] RazorPageWithNoLeadingPageDirective.cshtml) - Html - \n + CSharpCode - + IntermediateToken - - CSharp - EndContext(); + Inject - + Inject - + Inject - + Inject - + Inject - + CSharpCode - + IntermediateToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; + CSharpCode - + IntermediateToken - - CSharp - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorPageWithNoLeadingPageDirective Model => ViewData.Model; diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DefaultDocumentWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DefaultDocumentWriterTest.cs index 67b03f39b8..3537eea4f6 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DefaultDocumentWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DefaultDocumentWriterTest.cs @@ -218,6 +218,11 @@ namespace TestNamespace }, BaseType = "TestBase", Interfaces = new List { "IFoo", "IBar", }, + TypeParameters = new List + { + new TypeParameter() { ParameterName = "TKey", }, + new TypeParameter() { ParameterName = "TValue", }, + }, ClassName = "TestClass", }); @@ -236,7 +241,7 @@ namespace TestNamespace @"#pragma checksum ""test.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""da39a3ee5e6b4b0d3255bfef95601890afd80709"" // #pragma warning disable 1591 -internal class TestClass : TestBase, IFoo, IBar +internal class TestClass : TestBase, IFoo, IBar { } #pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs index ad26823b85..cf547f75e7 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; +using Microsoft.AspNetCore.Razor.Language.Intermediate; using Xunit; namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests @@ -66,6 +67,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests engine.ConfigureClass((document, @class) => { + @class.TypeParameters = new[] { new TypeParameter() { ParameterName = "TValue", }, }; @class.Interfaces = new[] { "global::System.IDisposable" }; @class.BaseType = "CustomBaseType"; }); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs index 82d72c82e0..23cda39e22 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs @@ -1957,7 +1957,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy Block expected, params RazorDiagnostic[] expectedErrors) { - var result = ParseCodeBlock(document, descriptors, designTime: false); + var result = ParseCodeBlock(RazorLanguageVersion.Latest, document, descriptors, designTime: false); EvaluateResults(result, expected, expectedErrors); } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CodeParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CodeParserTestBase.cs index f0af2d1530..923a25a441 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CodeParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CodeParserTestBase.cs @@ -9,9 +9,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy { internal abstract ISet KeywordSet { get; } - internal override RazorSyntaxTree ParseBlock(string document, IEnumerable directives, bool designTime) + internal override RazorSyntaxTree ParseBlock( + RazorLanguageVersion version, + string document, + IEnumerable directives, + bool designTime) { - return ParseCodeBlock(document, directives, designTime); + return ParseCodeBlock(version, document, directives, designTime); } internal void ImplicitExpressionTest(string input, params RazorDiagnostic[] errors) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/HtmlAttributeTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/HtmlAttributeTest.cs index 8687be85d3..64686c9fbb 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/HtmlAttributeTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/HtmlAttributeTest.cs @@ -559,6 +559,30 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy Assert.Equal(rewritten.Children.Count(), results.Root.Children.Count()); } + [Fact] + public void ConditionalAttributesAreEnabledForDataAttributesWithExperimentalFlag() + { + ParseBlockTest( + RazorLanguageVersion.Experimental, + "", + new MarkupBlock( + new MarkupTagBlock( + Factory.Markup("(" data-foo='", 5, 0, 5), new LocationTagged("'", 20, 0, 20)), + Factory.Markup(" data-foo='").With(SpanChunkGenerator.Null), + new MarkupBlock(new DynamicAttributeBlockChunkGenerator(new LocationTagged(string.Empty, 16, 0, 16), 16, 0, 16), + new ExpressionBlock( + Factory.CodeTransition(), + Factory.Code("foo") + .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) + .Accepts(AcceptedCharactersInternal.NonWhiteSpace))), + Factory.Markup("'").With(SpanChunkGenerator.Null)), + Factory.Markup(">").Accepts(AcceptedCharactersInternal.None)), + new MarkupTagBlock( + Factory.Markup("").Accepts(AcceptedCharactersInternal.None)))); + } + [Fact] public void ConditionalAttributesAreDisabledForDataAttributesInBlock() { diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/MarkupParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/MarkupParserTestBase.cs index 096681ed4c..16b1f43c1f 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/MarkupParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/MarkupParserTestBase.cs @@ -1,16 +1,19 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - using System.Collections.Generic; namespace Microsoft.AspNetCore.Razor.Language.Legacy { public abstract class MarkupParserTestBase : CodeParserTestBase { - internal override RazorSyntaxTree ParseBlock(string document, IEnumerable directives, bool designTime) + internal override RazorSyntaxTree ParseBlock( + RazorLanguageVersion version, + string document, + IEnumerable directives, + bool designTime) { - return ParseHtmlBlock(document, directives, designTime); + return ParseHtmlBlock(version, document, directives, designTime); } internal virtual void SingleSpanDocumentTest(string document, BlockKindInternal blockKind, SpanKindInternal spanType) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TagHelperBlockRewriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TagHelperBlockRewriterTest.cs index 88c774c93c..06131ae599 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TagHelperBlockRewriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TagHelperBlockRewriterTest.cs @@ -3962,7 +3962,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy .Build(), }; - var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false, allowHtmlCommentsInTagHelper: false); + var featureFlags = new TestRazorParserFeatureFlags(); var expectedOutput = new MarkupBlock( new MarkupTagHelperBlock( @@ -3994,15 +3994,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy private class TestRazorParserFeatureFlags : RazorParserFeatureFlags { - public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelper) + public TestRazorParserFeatureFlags( + bool allowMinimizedBooleanTagHelperAttributes = false, + bool allowHtmlCommentsInTagHelper = false, + bool experimental_AllowConditionalDataDashAttributes = false) { AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes; AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelper; + EXPERIMENTAL_AllowConditionalDataDashAttributes = experimental_AllowConditionalDataDashAttributes; } public override bool AllowMinimizedBooleanTagHelperAttributes { get; } public override bool AllowHtmlCommentsInTagHelpers { get; } + + public override bool EXPERIMENTAL_AllowConditionalDataDashAttributes { get; } } } } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs index 2baca26a3f..9c5c3a8a73 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs @@ -5,7 +5,7 @@ namespace Razor { #line hidden [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"38aa8e26c5d2a85c61d8e93fe69dd326fe82671b", @"/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml")] - protected internal class MyClass : CustomBaseType, global::System.IDisposable + protected internal class MyClass : CustomBaseType, global::System.IDisposable { #pragma warning disable 1998 public async override global::System.Threading.Tasks.Task ExecuteAsync() diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs index 783d021bf7..4329c0d02d 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -12,7 +13,7 @@ using Microsoft.AspNetCore.Razor.Language.Intermediate; namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests { // Serializes single IR nodes (shallow). - public class IntermediateNodeWriter : + public class IntermediateNodeWriter : IntermediateNodeVisitor, IExtensionIntermediateNodeVisitor { @@ -32,7 +33,21 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node) { - WriteContentNode(node, string.Join(" ", node.Modifiers), node.ClassName, node.BaseType, string.Join(", ", node.Interfaces ?? new List())); + var entries = new List() + { + string.Join(" ", node.Modifiers), + node.ClassName, + node.BaseType, + string.Join(", ", node.Interfaces ?? Array.Empty()) + }; + + // Avoid adding the type parameters to the baseline if they aren't present. + if (node.TypeParameters != null && node.TypeParameters.Count > 0) + { + entries.Add(string.Join(", ", node.TypeParameters)); + } + + WriteContentNode(node, entries.ToArray()); } public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node) diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs index 1f9ec8a407..4d80343ff3 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs @@ -32,23 +32,43 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy internal RazorSyntaxTree ParseBlock(string document, bool designTime) { - return ParseBlock(document, null, designTime); + return ParseBlock(RazorLanguageVersion.Latest, document, designTime); } - internal abstract RazorSyntaxTree ParseBlock(string document, IEnumerable directives, bool designTime); - - internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false) + internal RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, bool designTime) { - return ParseDocument(document, null, designTime); + return ParseBlock(version, document, null, designTime); } - internal virtual RazorSyntaxTree ParseDocument(string document, IEnumerable directives, bool designTime = false) + internal RazorSyntaxTree ParseBlock(string document, IEnumerable directives, bool designTime) + { + return ParseBlock(RazorLanguageVersion.Latest, document, directives, designTime); + } + + internal abstract RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, IEnumerable directives, bool designTime); + + internal RazorSyntaxTree ParseDocument(string document, bool designTime = false) + { + return ParseDocument(RazorLanguageVersion.Latest, document, designTime); + } + + internal RazorSyntaxTree ParseDocument(RazorLanguageVersion version, string document, bool designTime = false) + { + return ParseDocument(version, document, null, designTime); + } + + internal RazorSyntaxTree ParseDocument(string document, IEnumerable directives, bool designTime = false) + { + return ParseDocument(RazorLanguageVersion.Latest, document, directives, designTime); + } + + internal virtual RazorSyntaxTree ParseDocument(RazorLanguageVersion version, string document, IEnumerable directives, bool designTime = false) { directives = directives ?? Array.Empty(); var source = TestRazorSourceDocument.Create(document, filePath: null); - var options = CreateParserOptions(directives, designTime); + var options = CreateParserOptions(version, directives, designTime); var context = new ParserContext(source, options); var codeParser = new CSharpCodeParser(directives, context); @@ -73,12 +93,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy return syntaxTree; } - internal virtual RazorSyntaxTree ParseHtmlBlock(string document, IEnumerable directives, bool designTime = false) + internal virtual RazorSyntaxTree ParseHtmlBlock(RazorLanguageVersion version, string document, IEnumerable directives, bool designTime = false) { directives = directives ?? Array.Empty(); var source = TestRazorSourceDocument.Create(document, filePath: null); - var options = CreateParserOptions(directives, designTime); + var options = CreateParserOptions(version, directives, designTime); var context = new ParserContext(source, options); var parser = new HtmlMarkupParser(context); @@ -95,12 +115,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy return RazorSyntaxTree.Create(root, source, diagnostics, options); } - internal virtual RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false) + internal RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false) { - return ParseCodeBlock(document, Enumerable.Empty(), designTime); + return ParseCodeBlock(RazorLanguageVersion.Latest, document, Enumerable.Empty(), designTime); } internal virtual RazorSyntaxTree ParseCodeBlock( + RazorLanguageVersion version, string document, IEnumerable directives, bool designTime) @@ -108,7 +129,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy directives = directives ?? Array.Empty(); var source = TestRazorSourceDocument.Create(document, filePath: null); - var options = CreateParserOptions(directives, designTime); + var options = CreateParserOptions(version, directives, designTime); var context = new ParserContext(source, options); var parser = new CSharpCodeParser(directives, context); @@ -152,6 +173,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy ParseBlockTest(document, null, designTime, expectedErrors); } + internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, Block expectedRoot) + { + ParseBlockTest(version, document, expectedRoot, false, null); + } + internal virtual void ParseBlockTest(string document, Block expectedRoot) { ParseBlockTest(document, expectedRoot, false, null); @@ -182,9 +208,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy ParseBlockTest(document, null, expected, designTime, expectedErrors); } + internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, Block expected, bool designTime, params RazorDiagnostic[] expectedErrors) + { + ParseBlockTest(version, document, null, expected, designTime, expectedErrors); + } + internal virtual void ParseBlockTest(string document, IEnumerable directives, Block expected, bool designTime, params RazorDiagnostic[] expectedErrors) { - var result = ParseBlock(document, directives, designTime); + ParseBlockTest(RazorLanguageVersion.Latest, document, directives, expected, designTime, expectedErrors); + } + + internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, IEnumerable directives, Block expected, bool designTime, params RazorDiagnostic[] expectedErrors) + { + var result = ParseBlock(version, document, directives, designTime); if (FixupSpans) { @@ -604,24 +640,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy return block.Build(); } - private static RazorParserOptions CreateParserOptions(IEnumerable directives, bool designTime) + private static RazorParserOptions CreateParserOptions( + RazorLanguageVersion version, + IEnumerable directives, + bool designTime) { - if (designTime) - { - return RazorParserOptions.CreateDesignTime(ConfigureOptions); - } - else - { - return RazorParserOptions.Create(ConfigureOptions); - } - - void ConfigureOptions(RazorParserOptionsBuilder builder) - { - foreach (var directive in directives) - { - builder.Directives.Add(directive); - } - } + return new DefaultRazorParserOptions( + directives.ToArray(), + designTime, + parseLeadingDirectives: false, + version: version); } private class IgnoreOutputBlock : Block