diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/InjectTargetExtensionTest.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/InjectTargetExtensionTest.cs index ec36da6564..65a632d613 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/InjectTargetExtensionTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/InjectTargetExtensionTest.cs @@ -56,12 +56,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions target.WriteInjectProperty(context, node); // Assert - Assert.Equal( + Assert.Equal(Environment.NewLine + + "#nullable restore" + Environment.NewLine + "#line 2 \"test-path\"" + Environment.NewLine + "[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine + "public PropertyType PropertyName { get; private set; }" + Environment.NewLine + Environment.NewLine + "#line default" + Environment.NewLine + - "#line hidden" + Environment.NewLine, + "#line hidden" + Environment.NewLine + + "#nullable disable" + Environment.NewLine, context.CodeWriter.GenerateCode()); } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/CodeWriterExtensions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/CodeWriterExtensions.cs index dedecfda82..4f9c78d526 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/CodeWriterExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/CodeWriterExtensions.cs @@ -616,6 +616,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration if (!_codeGenerationOptions.SuppressNullabilityEnforcement) { + var endsWithNewline = _writer.Length > 0 && _writer[_writer.Length - 1] == '\n'; + if (!endsWithNewline) + { + _writer.WriteLine(); + } _writer.WriteLine("#nullable restore"); } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs index 359baefc66..648c958d8f 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs @@ -462,7 +462,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components // the "usings directive is unnecessary" message. // Looks like: // __o = typeof(SomeNamespace.SomeComponent); - using (context.CodeWriter.BuildLinePragma(node.Source.Value)) + using (context.CodeWriter.BuildLinePragma(node.Source.Value, context)) { context.CodeWriter.Write(DesignTimeVariable); context.CodeWriter.Write(" = "); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptions.cs index bb0179fc0b..5addb92cf2 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptions.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Razor.Language bool designTime, string rootNamespace, bool suppressChecksum, - bool supressMetadataAttributes, + bool suppressMetadataAttributes, bool suppressPrimaryMethodBody, bool suppressNullabilityEnforcement) { @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Language DesignTime = designTime; RootNamespace = rootNamespace; SuppressChecksum = suppressChecksum; - SuppressMetadataAttributes = supressMetadataAttributes; + SuppressMetadataAttributes = suppressMetadataAttributes; SuppressPrimaryMethodBody = suppressPrimaryMethodBody; SuppressNullabilityEnforcement = suppressNullabilityEnforcement; } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs index 7eeb15388e..36a8499ba9 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Razor.Language designTime: false, suppressChecksum: false, rootNamespace: null, - supressMetadataAttributes: false, + suppressMetadataAttributes: false, suppressPrimaryMethodBody: false, suppressNullabilityEnforcement: false); } @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Razor.Language designTime: true, rootNamespace: null, suppressChecksum: false, - supressMetadataAttributes: true, + suppressMetadataAttributes: true, suppressPrimaryMethodBody: false, suppressNullabilityEnforcement: false); } @@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Razor.Language public virtual bool SuppressPrimaryMethodBody { get; protected set; } /// - /// Gets or sets a value that determines if nullability type enforcement is restored to project settings for user code. + /// Gets a value that determines if nullability type enforcement should be suppressed for user code. /// public virtual bool SuppressNullabilityEnforcement { get; } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs index 1493832ca9..ed6914aebe 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs @@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Language public virtual bool SuppressPrimaryMethodBody { get; set; } /// - /// Gets or sets a value that determines if nullability type enforcement is restored to project settings for user code. + /// Gets or sets a value that determines if nullability type enforcement should be suppressed for user code. /// public virtual bool SuppressNullabilityEnforcement { get; set; } diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs index 30def1be7c..642110102d 100644 --- a/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs +++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/RazorProjectEngineBuilderExtensions.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.Razor public static class RazorProjectEngineBuilderExtensions { /// - /// Sets the C# language version to respect when generating code. + /// Sets the C# language version to target when generating code. /// /// The . /// The C# . @@ -26,12 +26,6 @@ namespace Microsoft.CodeAnalysis.Razor throw new ArgumentNullException(nameof(builder)); } - if (builder.Configuration.LanguageVersion.Major < 3) - { - // Prior to 3.0 there were no C# version specific controlled features so there's no value in setting a CSharp language version, noop. - return builder; - } - var existingFeature = builder.Features.OfType().FirstOrDefault(); if (existingFeature != null) { @@ -63,8 +57,16 @@ namespace Microsoft.CodeAnalysis.Razor throw new ArgumentNullException(nameof(options)); } + if (options.Configuration.LanguageVersion.Major < 3) + { + // Prior to 3.0 there were no C# version specific controlled features. Suppress nullability enforcement. + options.SuppressNullabilityEnforcement = true; + return; + } + if (CSharpLanguageVersion < LanguageVersion.CSharp8) { + // Having nullable flags < C# 8.0 would cause compile errors. options.SuppressNullabilityEnforcement = true; } else @@ -73,10 +75,11 @@ namespace Microsoft.CodeAnalysis.Razor // cases in tooling when the project isn't fully configured yet at which point the CSharpLanguageVersion // may be Default (value 0). In those cases that C# version is equivalently "unspecified" and is up to the consumer // to act in a safe manner to not cause unneeded errors for older compilers. Therefore if the version isn't - // >= 8.0 (or Latest) then nullability enforcement is suppressed. + // >= 8.0 (Latest has a higher value) then nullability enforcement is suppressed. // // Once the project finishes configuration the C# language version will be updated to reflect the effective - // language version for the project. + // language version for the project by our workspace change detectors. That mechanism extracts the correlated + // Roslyn project and acquires the effective C# version at that point. options.SuppressNullabilityEnforcement = false; } } diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets index 102315ebc4..487ffb348a 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets +++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets @@ -13,7 +13,7 @@ Copyright (c) .NET Foundation. All rights reserved. - $(NoWarn);2008 - - - - - - @@ -104,6 +111,12 @@ Copyright (c) .NET Foundation. All rights reserved. true + + 8.0 + + $(NoWarn);2008 - - - - - - @@ -181,6 +175,12 @@ Copyright (c) .NET Foundation. All rights reserved. true + + 8.0 + + /// Gets the parse options applied when using . /// - protected virtual CSharpParseOptions CSharpParseOptions { get; } = new CSharpParseOptions(LanguageVersion.Latest); + protected virtual CSharpParseOptions CSharpParseOptions { get; } = new CSharpParseOptions(LanguageVersion.Preview); /// /// Gets the compilation options applied when compiling assemblies. @@ -323,6 +323,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests } b.Features.Add(new DefaultTypeNameFeature()); + b.SetCSharpLanguageVersion(CSharpParseOptions.LanguageVersion); // Decorate each import feature so we can normalize line endings. foreach (var feature in b.Features.OfType().ToArray()) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs index 8a9c10aa8c..75440d18f4 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs @@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests referenceAssemblies, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - CSharpParseOptions = new CSharpParseOptions(LanguageVersion.CSharp7_3); + CSharpParseOptions = new CSharpParseOptions(LanguageVersion.Preview); } public RazorIntegrationTestBase() @@ -129,6 +129,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests References = references, }); + b.SetCSharpLanguageVersion(CSharpParseOptions.LanguageVersion); + CompilerFeatures.Register(b); }); }