diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/RazorExtensions.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/RazorExtensions.cs index f8cf7f5cb4..6fe73b57ae 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/RazorExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/RazorExtensions.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Extensions; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X @@ -38,6 +39,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X builder.Features.Add(new MvcViewDocumentClassifierPass()); builder.Features.Add(new MvcImportProjectFeature()); + + // The default C# language version for what this Razor configuration supports. + builder.SetCSharpLanguageVersion(LanguageVersion.CSharp7_3); } public static void RegisterViewComponentTagHelpers(RazorProjectEngineBuilder builder) diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorExtensions.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorExtensions.cs index 0e52eb00d1..afb0e896e0 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorExtensions.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Extensions; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X @@ -44,6 +45,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X builder.Features.Add(new InstrumentationPass()); builder.Features.Add(new MvcImportProjectFeature()); + + // The default C# language version for what this Razor configuration supports. + builder.SetCSharpLanguageVersion(LanguageVersion.CSharp7_3); } } } 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 867586db5c..dfaebba007 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/RazorExtensions.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Extensions; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Mvc.Razor.Extensions @@ -39,6 +40,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions builder.Features.Add(new MvcViewDocumentClassifierPass()); builder.Features.Add(new MvcImportProjectFeature()); + + // The default C# language version for what this Razor configuration supports. + builder.SetCSharpLanguageVersion(LanguageVersion.CSharp8); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs b/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs index ba38782ceb..7ebc74cb73 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs @@ -176,20 +176,6 @@ namespace Microsoft.AspNetCore.Razor.Tools }); var success = true; - var csharpLanguageVersion = LanguageVersion.Default; - if (CSharpLanguageVersion.HasValue()) - { - var rawLanguageVersion = CSharpLanguageVersion.Value(); - if (!LanguageVersionFacts.TryParse(CSharpLanguageVersion.Value(), out var parsedLanguageVersion)) - { - success = false; - Error.WriteLine($"Unknown C# language version {rawLanguageVersion}."); - } - else - { - csharpLanguageVersion = parsedLanguageVersion; - } - } var engine = RazorProjectEngine.Create(configuration, compositeFileSystem, b => { @@ -206,7 +192,22 @@ namespace Microsoft.AspNetCore.Razor.Tools b.SetRootNamespace(RootNamespace.Value()); } - b.SetCSharpLanguageVersion(csharpLanguageVersion); + if (CSharpLanguageVersion.HasValue()) + { + // Only set the C# language version if one was specified, otherwise it defaults to whatever + // value was set in the corresponding RazorConfiguration's extensions. + + var rawLanguageVersion = CSharpLanguageVersion.Value(); + if (LanguageVersionFacts.TryParse(rawLanguageVersion, out var csharpLanguageVersion)) + { + b.SetCSharpLanguageVersion(csharpLanguageVersion); + } + else + { + success = false; + Error.WriteLine($"Unknown C# language version {rawLanguageVersion}."); + } + } }); var results = GenerateCode(engine, sourceItems); diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs index 6e57ab1016..e492643723 100644 --- a/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs +++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs @@ -60,7 +60,7 @@ namespace Microsoft.CodeAnalysis.Razor throw new ArgumentNullException(nameof(options)); } - if (options.Configuration.LanguageVersion.Major < 3) + if (options.Configuration != null && options.Configuration.LanguageVersion.Major < 3) { // Prior to 3.0 there were no C# version specific controlled features. Suppress nullability enforcement. options.SuppressNullabilityEnforcement = true; diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/BuildIntegrationTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/BuildIntegrationTest.cs index 839f7da92b..9c9bce24d5 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/BuildIntegrationTest.cs +++ b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/BuildIntegrationTest.cs @@ -641,7 +641,38 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests [Fact] [InitializeTestProject("SimpleMvc")] - public async Task Build_CSharp8_NullableEnforcement_WarningsDuringBuild_BuildServer() + public async Task Build_ImplicitCSharp8_NullableEnforcement_WarningsDuringBuild_NoBuildServer() + { + var result = await DotnetMSBuild( + "Build", + "/p:Nullable=enable", + suppressBuildServer: true); + var indexFilePath = Path.Combine(RazorIntermediateOutputPath, "Views", "Home", "Index.cshtml.g.cs"); + + Assert.BuildPassed(result, allowWarnings: true); + Assert.BuildWarning(result, "CS8618"); + Assert.FileContainsLine(result, indexFilePath, "#nullable restore"); + Assert.FileContainsLine(result, indexFilePath, "#nullable disable"); + } + + [Fact] + [InitializeTestProject("SimpleMvc")] + public async Task Build_ExplicitCSharp73_NullableEnforcement_Disabled_NoNullableFeature_NoBuildServer() + { + var result = await DotnetMSBuild( + "Build", + "/p:LangVersion=7.3", + suppressBuildServer: true); + var indexFilePath = Path.Combine(RazorIntermediateOutputPath, "Views", "Home", "Index.cshtml.g.cs"); + + Assert.BuildPassed(result, allowWarnings: false); + Assert.FileDoesNotContainLine(result, indexFilePath, "#nullable restore"); + Assert.FileDoesNotContainLine(result, indexFilePath, "#nullable disable"); + } + + [Fact] + [InitializeTestProject("SimpleMvc")] + public async Task Build_ExplicitCSharp8_NullableEnforcement_WarningsDuringBuild_BuildServer() { var result = await DotnetMSBuild( "Build",