diff --git a/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs b/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs index da2af99f91..8de9a03f23 100644 --- a/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs +++ b/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs @@ -181,9 +181,12 @@ namespace Microsoft.AspNetCore.Razor.Tools } } } - - var outputFilePath = result.InputItem.OutputPath; - File.WriteAllText(outputFilePath, result.CSharpDocument.GeneratedCode); + else + { + // Only output the file if we generated it without errors. + var outputFilePath = result.InputItem.OutputPath; + File.WriteAllText(outputFilePath, result.CSharpDocument.GeneratedCode); + } } return success ? 0 : -1; diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs index 29ec529f59..e208a95bc5 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Xunit; @@ -90,5 +91,43 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests Assert.NotEqual(fileThumbPrint, newThumbPrint); } + [Fact] + [InitializeTestProject("SimpleMvc")] + public async Task Build_ErrorInGeneratedCode_ReportsMSBuildError_OnIncrementalBuild() + { + // Introducing a Razor semantic error + ReplaceContent("@{ // Unterminated code block", "Views", "Home", "Index.cshtml"); + + // Regular build + await VerifyError(); + + // Incremental build + await VerifyError(); + + async Task VerifyError() + { + var result = await DotnetMSBuild("Build"); + + Assert.BuildFailed(result); + + // This needs to be relative path. Tracked by https://github.com/aspnet/Razor/issues/2187. + var filePath = Path.Combine(Project.DirectoryPath, "Views", "Home", "Index.cshtml"); + var location = filePath + "(1,2)"; + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + // Absolute paths on OSX don't work well. + location = null; + } + + Assert.BuildError(result, "RZ1006", location: location); + + // Compilation failed without creating the views assembly + Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll"); + Assert.FileDoesNotExist(result, IntermediateOutputPath, "SimpleMvc.Views.dll"); + + // File with error does not get written to disk. + Assert.FileDoesNotExist(result, IntermediateOutputPath, "Razor", "Views", "Home", "Index.cshtml.g.cs"); + } + } } } diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs index 9406841130..8ae83dbd39 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs @@ -69,8 +69,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll"); Assert.FileDoesNotExist(result, IntermediateOutputPath, "SimpleMvc.Views.dll"); - // The file should still be generated even if we had a Razor syntax error. - Assert.FileExists(result, RazorIntermediateOutputPath, "Views", "Home", "Index.g.cshtml.cs"); + // If there's a parser error, the generated file contents is likely incorrect. The file should not be written to disk. + Assert.FileDoesNotExist(result, RazorIntermediateOutputPath, "Views", "Home", "Index.g.cshtml.cs"); } [Fact] @@ -90,9 +90,6 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests // RazorGenerate should compile the assembly, but not the views. Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll"); Assert.FileDoesNotExist(result, IntermediateOutputPath, "SimpleMvc.Views.dll"); - - // The file should still be generated even if we had a Razor syntax error. - Assert.FileExists(result, RazorIntermediateOutputPath, "Views", "Home", "Index.g.cshtml.cs"); } [ConditionalFact]