Enforce nullability for user code.
- Expanded the `ProjectWorkspaceStateGenerator` to extract the C# language version when building the `ProjectWorkspaceState`. This approach enables all platforms to get nullability support without any changes (as long as they support `ProjectWorkspaceState`, which they do). Also, Roslyn suggested that we avoid dealing with LangVersion directly because there are several factors that impact its "effective" value on a project when run in tooling.
- Updated the `LinePragma` code generation to include `#nullable restore` and `#nullable disable` lines to allow for project restored nullability state for user code.
- Added a new `RazorProjectEngineBuilderExtensions` class that adds Roslyn specific project engine modifications. In this case it allows us to set the C# language version for a project engine and configure underlying features accordingly.
- Added a `SuppressNullabilityEnforcement` flag that only turns on if C# < 8 is specified.
- Updated LiveShare, VS4Mac and RazorGenerate to understand CSharpLanguageVersion.
- Added a single test output to show the change.
dotnet/aspnetcore-tooling#5092
\n\nCommit migrated from 1df8128b87
This commit is contained in:
parent
31e916cdfd
commit
f33e1fca53
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
|||
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
context.CodeWriter
|
||||
.WriteLine(RazorInjectAttribute)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
|
|||
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
context.CodeWriter
|
||||
.WriteLine(RazorInjectAttribute)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
|||
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
context.CodeWriter
|
||||
.WriteLine(RazorInjectAttribute)
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
return new CSharpCodeWritingScope(writer);
|
||||
}
|
||||
|
||||
public static IDisposable BuildLinePragma(this CodeWriter writer, SourceSpan? span)
|
||||
public static IDisposable BuildLinePragma(this CodeWriter writer, SourceSpan? span, CodeRenderingContext context)
|
||||
{
|
||||
if (string.IsNullOrEmpty(span?.FilePath))
|
||||
{
|
||||
|
|
@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
return NullDisposable.Default;
|
||||
}
|
||||
|
||||
return new LinePragmaWriter(writer, span.Value);
|
||||
return new LinePragmaWriter(writer, span.Value, context.Options);
|
||||
}
|
||||
|
||||
private static void WriteVerbatimStringLiteral(CodeWriter writer, string literal)
|
||||
|
|
@ -596,9 +596,13 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
private class LinePragmaWriter : IDisposable
|
||||
{
|
||||
private readonly CodeWriter _writer;
|
||||
private readonly RazorCodeGenerationOptions _codeGenerationOptions;
|
||||
private readonly int _startIndent;
|
||||
|
||||
public LinePragmaWriter(CodeWriter writer, SourceSpan span)
|
||||
public LinePragmaWriter(
|
||||
CodeWriter writer,
|
||||
SourceSpan span,
|
||||
RazorCodeGenerationOptions codeGenerationOptions)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
|
|
@ -606,8 +610,15 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
}
|
||||
|
||||
_writer = writer;
|
||||
_codeGenerationOptions = codeGenerationOptions;
|
||||
_startIndent = _writer.CurrentIndent;
|
||||
_writer.CurrentIndent = 0;
|
||||
|
||||
if (!_codeGenerationOptions.SuppressNullabilityEnforcement)
|
||||
{
|
||||
_writer.WriteLine("#nullable restore");
|
||||
}
|
||||
|
||||
WriteLineNumberDirective(writer, span);
|
||||
}
|
||||
|
||||
|
|
@ -630,6 +641,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
.WriteLine("#line default")
|
||||
.WriteLine("#line hidden");
|
||||
|
||||
if (!_codeGenerationOptions.SuppressNullabilityEnforcement)
|
||||
{
|
||||
_writer.WriteLine("#nullable disable");
|
||||
}
|
||||
|
||||
_writer.CurrentIndent = _startIndent;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
{
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
context.AddSourceMappingFor(node);
|
||||
context.CodeWriter.WriteUsing(node.Content);
|
||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
var offset = DesignTimeDirectivePass.DesignTimeVariable.Length + " = ".Length;
|
||||
context.CodeWriter.WritePadding(offset, node.Source, context);
|
||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
IDisposable linePragmaScope = null;
|
||||
if (node.Source != null)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value, context);
|
||||
|
||||
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
var firstChild = node.Children[0];
|
||||
if (firstChild.Source != null)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(firstChild.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(firstChild.Source.Value, context))
|
||||
{
|
||||
var offset = DesignTimeDirectivePass.DesignTimeVariable.Length + " = ".Length;
|
||||
context.CodeWriter.WritePadding(offset, firstChild.Source, context);
|
||||
|
|
@ -210,7 +210,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
{
|
||||
if (!isWhitespaceStatement)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(token.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(token.Source.Value, context);
|
||||
}
|
||||
|
||||
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
{
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
context.CodeWriter.WriteUsing(node.Content);
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
IDisposable linePragmaScope = null;
|
||||
if (node.Source != null)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value, context);
|
||||
context.CodeWriter.WritePadding(WriteCSharpExpressionMethod.Length + 1, node.Source, context);
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
IDisposable linePragmaScope = null;
|
||||
if (node.Source != null)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value, context);
|
||||
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
|
||||
public override void WriteCSharpExpressionAttributeValue(CodeRenderingContext context, CSharpExpressionAttributeValueIntermediateNode node)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||
context.CodeWriter
|
||||
|
|
@ -266,7 +266,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
|||
{
|
||||
if (!isWhitespaceStatement)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(token.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(token.Source.Value, context);
|
||||
}
|
||||
|
||||
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
context.AddSourceMappingFor(node);
|
||||
context.CodeWriter.WriteUsing(node.Content);
|
||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
|
||||
if (node.Source != null)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||
{
|
||||
var offset = DesignTimeVariable.Length + " = ".Length;
|
||||
context.CodeWriter.WritePadding(offset, node.Source, context);
|
||||
|
|
@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
{
|
||||
if (!isWhitespaceStatement)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value, context);
|
||||
}
|
||||
|
||||
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||
|
|
@ -247,7 +247,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
var firstChild = node.Children[0];
|
||||
if (firstChild.Source != null)
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(firstChild.Source.Value))
|
||||
using (context.CodeWriter.BuildLinePragma(firstChild.Source.Value, context))
|
||||
{
|
||||
var offset = DesignTimeVariable.Length + " = ".Length;
|
||||
context.CodeWriter.WritePadding(offset, firstChild.Source, context);
|
||||
|
|
@ -835,7 +835,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
return;
|
||||
}
|
||||
|
||||
using (context.CodeWriter.BuildLinePragma(token.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(token.Source, context))
|
||||
{
|
||||
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
||||
context.AddSourceMappingFor(token);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
IDisposable linePragmaScope = null;
|
||||
if (node.Source != null)
|
||||
{
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
|
||||
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value, context);
|
||||
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
string rootNamespace,
|
||||
bool suppressChecksum,
|
||||
bool supressMetadataAttributes,
|
||||
bool suppressPrimaryMethodBody)
|
||||
bool suppressPrimaryMethodBody,
|
||||
bool suppressNullabilityEnforcement)
|
||||
{
|
||||
IndentWithTabs = indentWithTabs;
|
||||
IndentSize = indentSize;
|
||||
|
|
@ -21,6 +22,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
SuppressChecksum = suppressChecksum;
|
||||
SuppressMetadataAttributes = supressMetadataAttributes;
|
||||
SuppressPrimaryMethodBody = suppressPrimaryMethodBody;
|
||||
SuppressNullabilityEnforcement = suppressNullabilityEnforcement;
|
||||
}
|
||||
|
||||
public override bool DesignTime { get; }
|
||||
|
|
@ -32,5 +34,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
public override string RootNamespace { get; }
|
||||
|
||||
public override bool SuppressChecksum { get; }
|
||||
|
||||
public override bool SuppressNullabilityEnforcement { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
public override bool SuppressChecksum { get; set; }
|
||||
|
||||
public override bool SuppressNullabilityEnforcement { get; set; }
|
||||
|
||||
public override RazorCodeGenerationOptions Build()
|
||||
{
|
||||
return new DefaultRazorCodeGenerationOptions(
|
||||
|
|
@ -46,7 +48,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
RootNamespace,
|
||||
SuppressChecksum,
|
||||
SuppressMetadataAttributes,
|
||||
SuppressPrimaryMethodBody);
|
||||
SuppressPrimaryMethodBody,
|
||||
SuppressNullabilityEnforcement);
|
||||
}
|
||||
|
||||
public override void SetDesignTime(bool designTime)
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
var firstMappedChild = node.Children.FirstOrDefault(child => child.Source != null) as IntermediateNode;
|
||||
var valueStart = firstMappedChild?.Source;
|
||||
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
var accessor = GetPropertyAccessor(node);
|
||||
var assignmentPrefixLength = accessor.Length + " = ".Length;
|
||||
|
|
@ -422,7 +422,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
}
|
||||
else
|
||||
{
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
context.CodeWriter.WriteStartAssignment(GetPropertyAccessor(node));
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
}
|
||||
|
||||
// {node.Content} __typeHelper = default({node.Content});
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
context.AddSourceMappingFor(node);
|
||||
context.CodeWriter
|
||||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
}
|
||||
|
||||
// global::System.Object {node.content} = null;
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
context.CodeWriter
|
||||
.Write("global::")
|
||||
|
|
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
}
|
||||
|
||||
// global::System.Object __typeHelper = nameof({node.Content});
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
context.CodeWriter
|
||||
.Write("global::")
|
||||
|
|
@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
case DirectiveTokenKind.String:
|
||||
|
||||
// global::System.Object __typeHelper = "{node.Content}";
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
context.CodeWriter
|
||||
.Write("global::")
|
||||
|
|
@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
|||
// for consistency so when a C# completion session starts, filling user code doesn't result in
|
||||
// a previously non-existent line pragma from being added and destroying the context in which
|
||||
// the completion session was started.
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
||||
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||
{
|
||||
context.AddSourceMappingFor(node);
|
||||
context.CodeWriter.Write(" ");
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
suppressChecksum: false,
|
||||
rootNamespace: null,
|
||||
supressMetadataAttributes: false,
|
||||
suppressPrimaryMethodBody: false);
|
||||
suppressPrimaryMethodBody: false,
|
||||
suppressNullabilityEnforcement: false);
|
||||
}
|
||||
|
||||
public static RazorCodeGenerationOptions CreateDesignTimeDefault()
|
||||
|
|
@ -28,7 +29,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
rootNamespace: null,
|
||||
suppressChecksum: false,
|
||||
supressMetadataAttributes: true,
|
||||
suppressPrimaryMethodBody: false);
|
||||
suppressPrimaryMethodBody: false,
|
||||
suppressNullabilityEnforcement: false);
|
||||
}
|
||||
|
||||
public static RazorCodeGenerationOptions Create(Action<RazorCodeGenerationOptionsBuilder> configure)
|
||||
|
|
@ -107,5 +109,10 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
/// Gets or sets a value that determines if an empty body is generated for the primary method.
|
||||
/// </summary>
|
||||
public virtual bool SuppressPrimaryMethodBody { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if nullability type enforcement is restored to project settings for user code.
|
||||
/// </summary>
|
||||
public virtual bool SuppressNullabilityEnforcement { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
/// </summary>
|
||||
public virtual bool SuppressPrimaryMethodBody { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if nullability type enforcement is restored to project settings for user code.
|
||||
/// </summary>
|
||||
public virtual bool SuppressNullabilityEnforcement { get; set; }
|
||||
|
||||
public abstract RazorCodeGenerationOptions Build();
|
||||
|
||||
public virtual void SetDesignTime(bool designTime)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
||||
|
|
@ -30,6 +31,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
ExtensionNames = Option("-n", "extension name", CommandOptionType.MultipleValue);
|
||||
ExtensionFilePaths = Option("-e", "extension file path", CommandOptionType.MultipleValue);
|
||||
RootNamespace = Option("--root-namespace", "root namespace for generated code", CommandOptionType.SingleValue);
|
||||
CSharpLanguageVersion = Option("--csharp-language-version", "csharp language version generated code", CommandOptionType.SingleValue);
|
||||
GenerateDeclaration = Option("--generate-declaration", "Generate declaration", CommandOptionType.NoValue);
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +57,8 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
|
||||
public CommandOption RootNamespace { get; }
|
||||
|
||||
public CommandOption CSharpLanguageVersion { get; }
|
||||
|
||||
public CommandOption GenerateDeclaration { get; }
|
||||
|
||||
protected override Task<int> ExecuteCoreAsync()
|
||||
|
|
@ -170,6 +174,22 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
RazorProjectFileSystem.Create(projectDirectory),
|
||||
});
|
||||
|
||||
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 =>
|
||||
{
|
||||
b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, });
|
||||
|
|
@ -184,12 +204,12 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
{
|
||||
b.SetRootNamespace(RootNamespace.Value());
|
||||
}
|
||||
|
||||
b.SetCSharpLanguageVersion(csharpLanguageVersion);
|
||||
});
|
||||
|
||||
var results = GenerateCode(engine, sourceItems);
|
||||
|
||||
var success = true;
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
var errorCount = result.CSharpDocument.Diagnostics.Count;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
// 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 System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Roslyn specific <see cref="RazorProjectEngineBuilder"/> extensions.
|
||||
/// </summary>
|
||||
public static class RazorProjectEngineBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the C# language version to respect when generating code.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="RazorProjectEngineBuilder"/>.</param>
|
||||
/// <param name="csharpLanguageVersion">The C# <see cref="LanguageVersion"/>.</param>
|
||||
/// <returns>The <see cref="RazorProjectEngineBuilder"/>.</returns>
|
||||
public static RazorProjectEngineBuilder SetCSharpLanguageVersion(this RazorProjectEngineBuilder builder, LanguageVersion csharpLanguageVersion)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
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<ConfigureParserForCSharpVersionFeature>().FirstOrDefault();
|
||||
if (existingFeature != null)
|
||||
{
|
||||
builder.Features.Remove(existingFeature);
|
||||
}
|
||||
|
||||
builder.Features.Add(new ConfigureParserForCSharpVersionFeature(csharpLanguageVersion));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private class ConfigureParserForCSharpVersionFeature : IConfigureRazorCodeGenerationOptionsFeature
|
||||
{
|
||||
public ConfigureParserForCSharpVersionFeature(LanguageVersion csharpLanguageVersion)
|
||||
{
|
||||
CSharpLanguageVersion = csharpLanguageVersion;
|
||||
}
|
||||
|
||||
public LanguageVersion CSharpLanguageVersion { get; }
|
||||
|
||||
public int Order { get; set; }
|
||||
|
||||
public RazorEngine Engine { get; set; }
|
||||
|
||||
public void Configure(RazorCodeGenerationOptionsBuilder options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if (CSharpLanguageVersion < LanguageVersion.CSharp8)
|
||||
{
|
||||
options.SuppressNullabilityEnforcement = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Given that nullability enforcement can be a compile error we only turn it on for C# >= 8.0. There are
|
||||
// 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.
|
||||
//
|
||||
// Once the project finishes configuration the C# language version will be updated to reflect the effective
|
||||
// language version for the project.
|
||||
options.SuppressNullabilityEnforcement = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,8 @@ namespace Microsoft.AspNetCore.Razor.Tasks
|
|||
|
||||
public string RootNamespace { get; set; }
|
||||
|
||||
public string CSharpLanguageVersion { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Version { get; set; }
|
||||
|
||||
|
|
@ -138,16 +140,24 @@ namespace Microsoft.AspNetCore.Razor.Tasks
|
|||
builder.AppendLine(Configuration[0].GetMetadata(Identity));
|
||||
|
||||
// Added in 3.0
|
||||
if (parsedVersion.Major >= 3 && !string.IsNullOrEmpty(RootNamespace))
|
||||
if (parsedVersion.Major >= 3)
|
||||
{
|
||||
builder.AppendLine("--root-namespace");
|
||||
builder.AppendLine(RootNamespace);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(RootNamespace))
|
||||
{
|
||||
builder.AppendLine("--root-namespace");
|
||||
builder.AppendLine(RootNamespace);
|
||||
}
|
||||
|
||||
// Added in 3.0
|
||||
if (parsedVersion.Major >= 3 && GenerateDeclaration)
|
||||
{
|
||||
builder.AppendLine("--generate-declaration");
|
||||
if (!string.IsNullOrEmpty(CSharpLanguageVersion))
|
||||
{
|
||||
builder.AppendLine("--csharp-language-version");
|
||||
builder.AppendLine(CSharpLanguageVersion);
|
||||
}
|
||||
|
||||
if (GenerateDeclaration)
|
||||
{
|
||||
builder.AppendLine("--generate-declaration");
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < Extensions.Length; i++)
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
PipeName="$(_RazorBuildServerPipeName)"
|
||||
Version="$(RazorLangVersion)"
|
||||
RootNamespace="$(RootNamespace)"
|
||||
CSharpLanguageVersion="$(LangVersion)"
|
||||
Configuration="@(ResolvedRazorConfiguration)"
|
||||
Extensions="@(ResolvedRazorExtension)"
|
||||
Sources="@(RazorGenerateWithTargetPath)"
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
PipeName="$(_RazorBuildServerPipeName)"
|
||||
Version="$(RazorLangVersion)"
|
||||
RootNamespace="$(RootNamespace)"
|
||||
CSharpLanguageVersion="$(LangVersion)"
|
||||
Configuration="@(ResolvedRazorConfiguration)"
|
||||
Extensions="@(ResolvedRazorExtension)"
|
||||
Sources="@(_RazorComponentDeclarationSources)"
|
||||
|
|
|
|||
Loading…
Reference in New Issue