From e640e7908321b730ec65e7fe5f03cf69c55fd628 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 17 Mar 2021 19:01:10 -0700 Subject: [PATCH] Respect consolidated views in all document classifiers (#31008) * Respect consolidated views in all document classifiers * Address feedback from peer review --- ...nsolidatedMvcViewDocumentClassifierPass.cs | 90 ------------------- .../src/MvcViewDocumentClassifierPass.cs | 23 ++++- .../src/PublicAPI.Unshipped.txt | 5 +- .../src/RazorExtensions.cs | 12 +-- .../src/RazorPageDocumentClassifierPass.cs | 23 ++++- ...idatedMvcViewDocumentClassifierPassTest.cs | 12 +-- 6 files changed, 51 insertions(+), 114 deletions(-) delete mode 100644 src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/ConsolidatedMvcViewDocumentClassifierPass.cs diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/ConsolidatedMvcViewDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/ConsolidatedMvcViewDocumentClassifierPass.cs deleted file mode 100644 index 715ae3496e89..000000000000 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/ConsolidatedMvcViewDocumentClassifierPass.cs +++ /dev/null @@ -1,90 +0,0 @@ -// 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 Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.Intermediate; - -namespace Microsoft.AspNetCore.Mvc.Razor.Extensions -{ - public sealed class ConsolidatedMvcViewDocumentClassifierPass : DocumentClassifierPassBase - { - public static readonly string MvcViewDocumentKind = "mvc.1.0.view"; - - protected override string DocumentKind => MvcViewDocumentKind; - - protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) => true; - - protected override void OnDocumentStructureCreated( - RazorCodeDocument codeDocument, - NamespaceDeclarationIntermediateNode @namespace, - ClassDeclarationIntermediateNode @class, - MethodDeclarationIntermediateNode method) - { - base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method); - - if (!codeDocument.TryComputeNamespace(fallbackToRootNamespace: false, out var namespaceName)) - { - @namespace.Content = "AspNetCoreGeneratedDocument"; - } - else - { - @namespace.Content = namespaceName; - } - - if (!TryComputeClassName(codeDocument, out var className)) - { - // It's possible for a Razor document to not have a file path. - // Eg. When we try to generate code for an in memory document like default imports. - var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum()); - @class.ClassName = $"AspNetCore_{checksum}"; - } - else - { - @class.ClassName = className; - } - - @class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage"; - @class.Modifiers.Clear(); - @class.Modifiers.Add("internal"); - @class.Modifiers.Add("sealed"); - - method.MethodName = "ExecuteAsync"; - method.Modifiers.Clear(); - method.Modifiers.Add("public"); - method.Modifiers.Add("async"); - method.Modifiers.Add("override"); - method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}"; - } - - private bool TryComputeClassName(RazorCodeDocument codeDocument, out string className) - { - var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath; - if (string.IsNullOrEmpty(filePath)) - { - className = null; - return false; - } - - className = GetClassNameFromPath(filePath); - return true; - } - - private static string GetClassNameFromPath(string path) - { - const string cshtmlExtension = ".cshtml"; - - if (string.IsNullOrEmpty(path)) - { - return path; - } - - if (path.EndsWith(cshtmlExtension, StringComparison.OrdinalIgnoreCase)) - { - path = path.Substring(0, path.Length - cshtmlExtension.Length); - } - - return CSharpIdentifier.SanitizeIdentifier(path); - } - } -} \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/MvcViewDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/MvcViewDocumentClassifierPass.cs index 7ab07afc8ba2..7f0a09f729e7 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/MvcViewDocumentClassifierPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/MvcViewDocumentClassifierPass.cs @@ -9,12 +9,21 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions { public class MvcViewDocumentClassifierPass : DocumentClassifierPassBase { + private bool _useConsolidatedMvcViews = false; + public static readonly string MvcViewDocumentKind = "mvc.1.0.view"; protected override string DocumentKind => MvcViewDocumentKind; protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) => true; + public MvcViewDocumentClassifierPass() : this(false) { } + + public MvcViewDocumentClassifierPass(bool useConsolidatedMvcViews) + { + _useConsolidatedMvcViews = useConsolidatedMvcViews; + } + protected override void OnDocumentStructureCreated( RazorCodeDocument codeDocument, NamespaceDeclarationIntermediateNode @namespace, @@ -25,7 +34,7 @@ protected override void OnDocumentStructureCreated( if (!codeDocument.TryComputeNamespace(fallbackToRootNamespace: false, out var namespaceName)) { - @namespace.Content = "AspNetCore"; + @namespace.Content = _useConsolidatedMvcViews ? "AspNetCoreGeneratedDocument" : "AspNetCore"; } else { @@ -47,7 +56,15 @@ protected override void OnDocumentStructureCreated( @class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage"; @class.Modifiers.Clear(); - @class.Modifiers.Add("public"); + if (_useConsolidatedMvcViews) + { + @class.Modifiers.Add("internal"); + @class.Modifiers.Add("sealed"); + } + else + { + @class.Modifiers.Add("public"); + } method.MethodName = "ExecuteAsync"; method.Modifiers.Clear(); @@ -87,4 +104,4 @@ private static string GetClassNameFromPath(string path) return CSharpIdentifier.SanitizeIdentifier(path); } } -} +} \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/PublicAPI.Unshipped.txt b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/PublicAPI.Unshipped.txt index e4a5fa72ae36..84adfeccba4f 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/PublicAPI.Unshipped.txt +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/PublicAPI.Unshipped.txt @@ -1,4 +1,3 @@ #nullable enable -Microsoft.AspNetCore.Mvc.Razor.Extensions.ConsolidatedMvcViewDocumentClassifierPass -Microsoft.AspNetCore.Mvc.Razor.Extensions.ConsolidatedMvcViewDocumentClassifierPass.ConsolidatedMvcViewDocumentClassifierPass() -> void -~static readonly Microsoft.AspNetCore.Mvc.Razor.Extensions.ConsolidatedMvcViewDocumentClassifierPass.MvcViewDocumentKind -> string \ No newline at end of file +Microsoft.AspNetCore.Mvc.Razor.Extensions.MvcViewDocumentClassifierPass.MvcViewDocumentClassifierPass(bool useConsolidatedMvcViews) -> void +Microsoft.AspNetCore.Mvc.Razor.Extensions.RazorPageDocumentClassifierPass.RazorPageDocumentClassifierPass(bool useConsolidatedMvcViews) -> void \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorExtensions.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorExtensions.cs index 0c7b298aa738..48b31377c439 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorExtensions.cs @@ -37,15 +37,9 @@ public static void Register(RazorProjectEngineBuilder builder) builder.Features.Add(new PagesPropertyInjectionPass()); builder.Features.Add(new ViewComponentTagHelperPass()); builder.Features.Add(new RazorPageDocumentClassifierPass()); - - if (builder.Configuration.UseConsolidatedMvcViews) - { - builder.Features.Add(new ConsolidatedMvcViewDocumentClassifierPass()); - } - else - { - builder.Features.Add(new MvcViewDocumentClassifierPass()); - } + + builder.Features.Add(new RazorPageDocumentClassifierPass(builder.Configuration.UseConsolidatedMvcViews)); + builder.Features.Add(new MvcViewDocumentClassifierPass(builder.Configuration.UseConsolidatedMvcViews)); builder.Features.Add(new MvcImportProjectFeature()); diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorPageDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorPageDocumentClassifierPass.cs index 567754cd663a..c2889be5f66e 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorPageDocumentClassifierPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorPageDocumentClassifierPass.cs @@ -11,9 +11,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions { public class RazorPageDocumentClassifierPass : DocumentClassifierPassBase { + private bool _useConsolidatedMvcViews = false; + public static readonly string RazorPageDocumentKind = "mvc.1.0.razor-page"; public static readonly string RouteTemplateKey = "RouteTemplate"; + public RazorPageDocumentClassifierPass() : this(false) { } + + public RazorPageDocumentClassifierPass(bool useConsolidatedMvcViews) + { + _useConsolidatedMvcViews = useConsolidatedMvcViews; + } + private static readonly RazorProjectEngine LeadingDirectiveParsingEngine = RazorProjectEngine.Create( RazorConfiguration.Create(RazorLanguageVersion.Version_3_0, "leading-directive-parser", Array.Empty()), RazorProjectFileSystem.Create("/"), @@ -50,7 +59,7 @@ protected override void OnDocumentStructureCreated( if (!codeDocument.TryComputeNamespace(fallbackToRootNamespace: false, out var namespaceName)) { - @namespace.Content = "AspNetCore"; + @namespace.Content = _useConsolidatedMvcViews ? "AspNetCoreGeneratedDocument" : "AspNetCore"; } else { @@ -71,7 +80,15 @@ protected override void OnDocumentStructureCreated( @class.BaseType = "global::Microsoft.AspNetCore.Mvc.RazorPages.Page"; @class.Modifiers.Clear(); - @class.Modifiers.Add("public"); + if (_useConsolidatedMvcViews) + { + @class.Modifiers.Add("internal"); + @class.Modifiers.Add("sealed"); + } + else + { + @class.Modifiers.Add("public"); + } method.MethodName = "ExecuteAsync"; method.Modifiers.Clear(); @@ -178,4 +195,4 @@ private static string GetClassNameFromPath(string path) return CSharpIdentifier.SanitizeIdentifier(path); } } -} +} \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ConsolidatedMvcViewDocumentClassifierPassTest.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ConsolidatedMvcViewDocumentClassifierPassTest.cs index b4c6ed145ed7..d8d5751f60b9 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ConsolidatedMvcViewDocumentClassifierPassTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ConsolidatedMvcViewDocumentClassifierPassTest.cs @@ -19,7 +19,7 @@ public void ConsolidatedMvcViewDocumentClassifierPass_SetsDifferentNamespace() var projectEngine = CreateProjectEngine(); var irDocument = CreateIRDocument(projectEngine, codeDocument); - var pass = new ConsolidatedMvcViewDocumentClassifierPass + var pass = new MvcViewDocumentClassifierPass(useConsolidatedMvcViews: true) { Engine = projectEngine.Engine }; @@ -42,7 +42,7 @@ public void ConsolidatedMvcViewDocumentClassifierPass_SetsClass() var projectEngine = CreateProjectEngine(); var irDocument = CreateIRDocument(projectEngine, codeDocument); - var pass = new ConsolidatedMvcViewDocumentClassifierPass + var pass = new MvcViewDocumentClassifierPass(useConsolidatedMvcViews: true) { Engine = projectEngine.Engine }; @@ -67,7 +67,7 @@ public void MvcViewDocumentClassifierPass_NullFilePath_SetsClass() var projectEngine = CreateProjectEngine(); var irDocument = CreateIRDocument(projectEngine, codeDocument); - var pass = new ConsolidatedMvcViewDocumentClassifierPass + var pass = new MvcViewDocumentClassifierPass(useConsolidatedMvcViews: true) { Engine = projectEngine.Engine }; @@ -86,7 +86,7 @@ public void MvcViewDocumentClassifierPass_NullFilePath_SetsClass() [Theory] [InlineData("/Views/Home/Index.cshtml", "_Views_Home_Index")] [InlineData("/Areas/MyArea/Views/Home/About.cshtml", "_Areas_MyArea_Views_Home_About")] - public void MvcViewDocumentClassifierPass_UsesRelativePathToGenerateTypeName(string relativePath, string expected) + public void ConsolidatedMvcViewDocumentClassifierPass_UsesRelativePathToGenerateTypeName(string relativePath, string expected) { // Arrange var properties = new RazorSourceDocumentProperties(filePath: "ignored", relativePath: relativePath); @@ -94,7 +94,7 @@ public void MvcViewDocumentClassifierPass_UsesRelativePathToGenerateTypeName(str var projectEngine = CreateProjectEngine(); var irDocument = CreateIRDocument(projectEngine, codeDocument); - var pass = new ConsolidatedMvcViewDocumentClassifierPass + var pass = new MvcViewDocumentClassifierPass(useConsolidatedMvcViews: true) { Engine = projectEngine.Engine }; @@ -117,7 +117,7 @@ public void ConsolidatedMvcViewDocumentClassifierPass_SetsUpExecuteAsyncMethod() var projectEngine = CreateProjectEngine(); var irDocument = CreateIRDocument(projectEngine, codeDocument); - var pass = new ConsolidatedMvcViewDocumentClassifierPass + var pass = new MvcViewDocumentClassifierPass(useConsolidatedMvcViews: true) { Engine = projectEngine.Engine };