diff --git a/Razor.sln b/Razor.sln index 354061090e..cc4f3efc44 100644 --- a/Razor.sln +++ b/Razor.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26208.0 +VisualStudioVersion = 15.0.26222.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C0D6505-79B3-49D0-B4C3-176F0F1836ED}" EndProject @@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServices.Razor", "src\Microsoft.VisualStudio.LanguageServices.Razor\Microsoft.VisualStudio.LanguageServices.Razor.csproj", "{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageGenerator.Test", "test\RazorPageGenerator.Test\RazorPageGenerator.Test.csproj", "{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -151,6 +153,14 @@ Global {E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Release|Any CPU.Build.0 = Release|Any CPU {E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU {E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Release|Any CPU.Build.0 = Release|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -169,5 +179,6 @@ Global {42403DAF-F0BC-4F3A-B7F2-46D7013345D8} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED} {7A8A1664-37CE-4376-81CA-1862CF5F91D9} = {92463391-81BE-462B-AC3C-78C6C760741F} {E5D92DB7-5CBF-410A-9685-FF76F71EC96F} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED} + {96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63} = {92463391-81BE-462B-AC3C-78C6C760741F} EndGlobalSection EndGlobal diff --git a/src/RazorPageGenerator/Program.cs b/src/RazorPageGenerator/Program.cs index 9680ff590e..2a2fdb17d1 100644 --- a/src/RazorPageGenerator/Program.cs +++ b/src/RazorPageGenerator/Program.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; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -11,18 +12,33 @@ namespace RazorPageGenerator { public class Program { - public static void Main(string[] args) + public static int Main(string[] args) { if (args == null || args.Length != 1) { Console.WriteLine("Invalid argument(s)."); Console.WriteLine("Usage: dotnet razorpagegenerator "); Console.WriteLine("Example: dotnet razorpagegenerator Microsoft.AspNetCore.Diagnostics.RazorViews"); - return; + return 1; } var rootNamespace = args[0]; var targetProjectDirectory = Directory.GetCurrentDirectory(); + var results = MainCore(rootNamespace, targetProjectDirectory); + + foreach (var result in results) + { + File.WriteAllText(result.FilePath, result.GeneratedCode); + } + + Console.WriteLine(); + Console.WriteLine($"{results.Count} files successfully generated."); + Console.WriteLine(); + return 0; + } + + public static IList MainCore(string rootNamespace, string targetProjectDirectory) + { var razorEngine = RazorEngine.Create(builder => { builder @@ -43,6 +59,8 @@ namespace RazorPageGenerator var templateEngine = new RazorTemplateEngine(razorEngine, razorProject); var fileCount = 0; + + var results = new List(); foreach (var viewDir in viewDirectories) { Console.WriteLine(); @@ -59,18 +77,16 @@ namespace RazorPageGenerator foreach (var item in cshtmlFiles) { Console.WriteLine(" Generating code file for view {0}...", item.Filename); - GenerateCodeFile(templateEngine, item); + results.Add(GenerateCodeFile(templateEngine, item)); Console.WriteLine(" Done!"); fileCount++; } } - Console.WriteLine(); - Console.WriteLine("{0} files successfully generated.", fileCount); - Console.WriteLine(); + return results; } - private static void GenerateCodeFile(RazorTemplateEngine templateEngine, FileSystemRazorProjectItem projectItem) + private static RazorPageGeneratorResult GenerateCodeFile(RazorTemplateEngine templateEngine, FileSystemRazorProjectItem projectItem) { var projectItemWrapper = new FileSystemRazorProjectItemWrapper(projectItem); var cSharpDocument = templateEngine.GenerateCode(projectItemWrapper); @@ -81,7 +97,11 @@ namespace RazorPageGenerator } var generatedCodeFilePath = Path.ChangeExtension(projectItem.PhysicalPath, ".Designer.cs"); - File.WriteAllText(generatedCodeFilePath, cSharpDocument.GeneratedCode); + return new RazorPageGeneratorResult + { + FilePath = generatedCodeFilePath, + GeneratedCode = cSharpDocument.GeneratedCode, + }; } private class FileSystemRazorProjectItemWrapper : RazorProjectItem diff --git a/src/RazorPageGenerator/RazorPageGeneratorResult.cs b/src/RazorPageGenerator/RazorPageGeneratorResult.cs new file mode 100644 index 0000000000..e68e1706a0 --- /dev/null +++ b/src/RazorPageGenerator/RazorPageGeneratorResult.cs @@ -0,0 +1,12 @@ +// 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 RazorPageGenerator +{ + public class RazorPageGeneratorResult + { + public string FilePath { get; set; } + + public string GeneratedCode { get; set; } + } +} diff --git a/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs b/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs index bc6386ce25..eb06a4c000 100644 --- a/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs +++ b/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs @@ -1,10 +1,13 @@ -using System; +// 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.Evolution; using Microsoft.AspNetCore.Razor.Evolution.Intermediate; namespace RazorPageGenerator { - class RemovePragmaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass + public class RemovePragmaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass { public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument) { diff --git a/test/RazorPageGenerator.Test/RazorPageGenerator.Test.csproj b/test/RazorPageGenerator.Test/RazorPageGenerator.Test.csproj new file mode 100644 index 0000000000..45859e37eb --- /dev/null +++ b/test/RazorPageGenerator.Test/RazorPageGenerator.Test.csproj @@ -0,0 +1,30 @@ + + + + netcoreapp1.1 + + $(DefineConstants);GENERATE_BASELINES + $(DefineConstants);__RemoveThisBitTo__GENERATE_BASELINES + $(DefaultItemExcludes);TestFiles\**\* + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs b/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs new file mode 100644 index 0000000000..de22fee183 --- /dev/null +++ b/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs @@ -0,0 +1,69 @@ +// 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.IO; +using Microsoft.AspNetCore.Razor.Evolution; +using Xunit; + +namespace RazorPageGenerator.Test +{ + public class RazorPageGeneratorTest + { + +#if GENERATE_BASELINES + private static readonly bool GenerateBaselines = true; +#else + private static readonly bool GenerateBaselines = false; +#endif + + + [Fact] + public void Generator_ReturnsNonZeroExitCode_WhenArgsAreNotSupplied() + { + // Arrange + var args = new string[0]; + + // Act + var exitCode = Program.Main(args); + + // Assert + Assert.NotEqual(0, exitCode); + } + + [Fact] + public void Generator_GeneratesCodeForFilesIntheViewsDirectory() + { + // Arrange + var projectDirectory = TestProject.GetProjectDirectory(); + + + // Act + var results = Program.MainCore("Microsoft.AspNetCore.TestGenerated", projectDirectory); + + // Assert + Assert.Collection(results, + result => + { + var expectedPath = Path.Combine(projectDirectory, "TestFiles", "Views", "TestView.Designer.cs"); + var expectedFile = Path.ChangeExtension(expectedPath, ".expected.cs"); + Assert.Equal(expectedPath, result.FilePath); + + var generatedCode = result.GeneratedCode + .Replace("\r", "") + .Replace("\n", "\r\n") + .Replace("\\r", "") + .Replace("\\n", "\\r\\n"); + + if (GenerateBaselines) + { + File.WriteAllText(expectedFile, generatedCode); + } + else + { + var expectedContent = File.ReadAllText(expectedFile).Replace("\r", "").Replace("\n", "\r\n"); + Assert.Equal(expectedContent, generatedCode); + } + }); + } + } +} diff --git a/test/RazorPageGenerator.Test/TestFiles/Views/TestFile.js b/test/RazorPageGenerator.Test/TestFiles/Views/TestFile.js new file mode 100644 index 0000000000..694294cae2 --- /dev/null +++ b/test/RazorPageGenerator.Test/TestFiles/Views/TestFile.js @@ -0,0 +1 @@ +window.alert("Hello world"); \ No newline at end of file diff --git a/test/RazorPageGenerator.Test/TestFiles/Views/TestView.Designer.expected.cs b/test/RazorPageGenerator.Test/TestFiles/Views/TestView.Designer.expected.cs new file mode 100644 index 0000000000..708c1883ad --- /dev/null +++ b/test/RazorPageGenerator.Test/TestFiles/Views/TestView.Designer.expected.cs @@ -0,0 +1,21 @@ +namespace Microsoft.AspNetCore.TestGenerated +{ + #line hidden + using System; + using System.Threading.Tasks; + internal class TestView : Microsoft.Extensions.RazorViews.BaseView + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { + WriteLiteral("The time is "); +#line 1 "TestView.cshtml" + Write(DateTime.UtcNow); + +#line default +#line hidden + WriteLiteral("\r\nwindow.alert(\"Hello world\");\r\nFooter goes here."); + } + #pragma warning restore 1998 + } +} diff --git a/test/RazorPageGenerator.Test/TestFiles/Views/TestView.cshtml b/test/RazorPageGenerator.Test/TestFiles/Views/TestView.cshtml new file mode 100644 index 0000000000..75074862cc --- /dev/null +++ b/test/RazorPageGenerator.Test/TestFiles/Views/TestView.cshtml @@ -0,0 +1,3 @@ +The time is @DateTime.UtcNow +<%$ include: TestFile.js %> +Footer goes here. \ No newline at end of file