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)
|
if (node.Source.HasValue)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.WriteLine(RazorInjectAttribute)
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
|
||||||
|
|
||||||
if (node.Source.HasValue)
|
if (node.Source.HasValue)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.WriteLine(RazorInjectAttribute)
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
|
||||||
if (node.Source.HasValue)
|
if (node.Source.HasValue)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.WriteLine(RazorInjectAttribute)
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
|
|
||||||
|
|
@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
return new CSharpCodeWritingScope(writer);
|
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))
|
if (string.IsNullOrEmpty(span?.FilePath))
|
||||||
{
|
{
|
||||||
|
|
@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
return NullDisposable.Default;
|
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)
|
private static void WriteVerbatimStringLiteral(CodeWriter writer, string literal)
|
||||||
|
|
@ -596,9 +596,13 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
private class LinePragmaWriter : IDisposable
|
private class LinePragmaWriter : IDisposable
|
||||||
{
|
{
|
||||||
private readonly CodeWriter _writer;
|
private readonly CodeWriter _writer;
|
||||||
|
private readonly RazorCodeGenerationOptions _codeGenerationOptions;
|
||||||
private readonly int _startIndent;
|
private readonly int _startIndent;
|
||||||
|
|
||||||
public LinePragmaWriter(CodeWriter writer, SourceSpan span)
|
public LinePragmaWriter(
|
||||||
|
CodeWriter writer,
|
||||||
|
SourceSpan span,
|
||||||
|
RazorCodeGenerationOptions codeGenerationOptions)
|
||||||
{
|
{
|
||||||
if (writer == null)
|
if (writer == null)
|
||||||
{
|
{
|
||||||
|
|
@ -606,8 +610,15 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer = writer;
|
_writer = writer;
|
||||||
|
_codeGenerationOptions = codeGenerationOptions;
|
||||||
_startIndent = _writer.CurrentIndent;
|
_startIndent = _writer.CurrentIndent;
|
||||||
_writer.CurrentIndent = 0;
|
_writer.CurrentIndent = 0;
|
||||||
|
|
||||||
|
if (!_codeGenerationOptions.SuppressNullabilityEnforcement)
|
||||||
|
{
|
||||||
|
_writer.WriteLine("#nullable restore");
|
||||||
|
}
|
||||||
|
|
||||||
WriteLineNumberDirective(writer, span);
|
WriteLineNumberDirective(writer, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -630,6 +641,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
.WriteLine("#line default")
|
.WriteLine("#line default")
|
||||||
.WriteLine("#line hidden");
|
.WriteLine("#line hidden");
|
||||||
|
|
||||||
|
if (!_codeGenerationOptions.SuppressNullabilityEnforcement)
|
||||||
|
{
|
||||||
|
_writer.WriteLine("#nullable disable");
|
||||||
|
}
|
||||||
|
|
||||||
_writer.CurrentIndent = _startIndent;
|
_writer.CurrentIndent = _startIndent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
{
|
{
|
||||||
if (node.Source.HasValue)
|
if (node.Source.HasValue)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
context.AddSourceMappingFor(node);
|
context.AddSourceMappingFor(node);
|
||||||
context.CodeWriter.WriteUsing(node.Content);
|
context.CodeWriter.WriteUsing(node.Content);
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
if (node.Source != null)
|
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;
|
var offset = DesignTimeDirectivePass.DesignTimeVariable.Length + " = ".Length;
|
||||||
context.CodeWriter.WritePadding(offset, node.Source, context);
|
context.CodeWriter.WritePadding(offset, node.Source, context);
|
||||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
IDisposable linePragmaScope = null;
|
IDisposable linePragmaScope = null;
|
||||||
if (node.Source != 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);
|
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
var firstChild = node.Children[0];
|
var firstChild = node.Children[0];
|
||||||
if (firstChild.Source != null)
|
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;
|
var offset = DesignTimeDirectivePass.DesignTimeVariable.Length + " = ".Length;
|
||||||
context.CodeWriter.WritePadding(offset, firstChild.Source, context);
|
context.CodeWriter.WritePadding(offset, firstChild.Source, context);
|
||||||
|
|
@ -210,7 +210,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
{
|
{
|
||||||
if (!isWhitespaceStatement)
|
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);
|
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
{
|
{
|
||||||
if (node.Source.HasValue)
|
if (node.Source.HasValue)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter.WriteUsing(node.Content);
|
context.CodeWriter.WriteUsing(node.Content);
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
IDisposable linePragmaScope = null;
|
IDisposable linePragmaScope = null;
|
||||||
if (node.Source != 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);
|
context.CodeWriter.WritePadding(WriteCSharpExpressionMethod.Length + 1, node.Source, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
IDisposable linePragmaScope = null;
|
IDisposable linePragmaScope = null;
|
||||||
if (node.Source != 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);
|
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)
|
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;
|
var prefixLocation = node.Source.Value.AbsoluteIndex;
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
|
|
@ -266,7 +266,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
{
|
{
|
||||||
if (!isWhitespaceStatement)
|
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);
|
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||||
|
|
||||||
if (node.Source.HasValue)
|
if (node.Source.HasValue)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
context.AddSourceMappingFor(node);
|
context.AddSourceMappingFor(node);
|
||||||
context.CodeWriter.WriteUsing(node.Content);
|
context.CodeWriter.WriteUsing(node.Content);
|
||||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||||
|
|
||||||
if (node.Source != null)
|
if (node.Source != null)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
|
||||||
{
|
{
|
||||||
var offset = DesignTimeVariable.Length + " = ".Length;
|
var offset = DesignTimeVariable.Length + " = ".Length;
|
||||||
context.CodeWriter.WritePadding(offset, node.Source, context);
|
context.CodeWriter.WritePadding(offset, node.Source, context);
|
||||||
|
|
@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||||
{
|
{
|
||||||
if (!isWhitespaceStatement)
|
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);
|
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||||
|
|
@ -247,7 +247,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||||
var firstChild = node.Children[0];
|
var firstChild = node.Children[0];
|
||||||
if (firstChild.Source != null)
|
if (firstChild.Source != null)
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(firstChild.Source.Value))
|
using (context.CodeWriter.BuildLinePragma(firstChild.Source.Value, context))
|
||||||
{
|
{
|
||||||
var offset = DesignTimeVariable.Length + " = ".Length;
|
var offset = DesignTimeVariable.Length + " = ".Length;
|
||||||
context.CodeWriter.WritePadding(offset, firstChild.Source, context);
|
context.CodeWriter.WritePadding(offset, firstChild.Source, context);
|
||||||
|
|
@ -835,7 +835,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (context.CodeWriter.BuildLinePragma(token.Source))
|
using (context.CodeWriter.BuildLinePragma(token.Source, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
context.CodeWriter.WritePadding(0, token.Source.Value, context);
|
||||||
context.AddSourceMappingFor(token);
|
context.AddSourceMappingFor(token);
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||||
IDisposable linePragmaScope = null;
|
IDisposable linePragmaScope = null;
|
||||||
if (node.Source != 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);
|
context.CodeWriter.WritePadding(0, node.Source.Value, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
string rootNamespace,
|
string rootNamespace,
|
||||||
bool suppressChecksum,
|
bool suppressChecksum,
|
||||||
bool supressMetadataAttributes,
|
bool supressMetadataAttributes,
|
||||||
bool suppressPrimaryMethodBody)
|
bool suppressPrimaryMethodBody,
|
||||||
|
bool suppressNullabilityEnforcement)
|
||||||
{
|
{
|
||||||
IndentWithTabs = indentWithTabs;
|
IndentWithTabs = indentWithTabs;
|
||||||
IndentSize = indentSize;
|
IndentSize = indentSize;
|
||||||
|
|
@ -21,6 +22,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
SuppressChecksum = suppressChecksum;
|
SuppressChecksum = suppressChecksum;
|
||||||
SuppressMetadataAttributes = supressMetadataAttributes;
|
SuppressMetadataAttributes = supressMetadataAttributes;
|
||||||
SuppressPrimaryMethodBody = suppressPrimaryMethodBody;
|
SuppressPrimaryMethodBody = suppressPrimaryMethodBody;
|
||||||
|
SuppressNullabilityEnforcement = suppressNullabilityEnforcement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool DesignTime { get; }
|
public override bool DesignTime { get; }
|
||||||
|
|
@ -32,5 +34,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
public override string RootNamespace { get; }
|
public override string RootNamespace { get; }
|
||||||
|
|
||||||
public override bool SuppressChecksum { 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 SuppressChecksum { get; set; }
|
||||||
|
|
||||||
|
public override bool SuppressNullabilityEnforcement { get; set; }
|
||||||
|
|
||||||
public override RazorCodeGenerationOptions Build()
|
public override RazorCodeGenerationOptions Build()
|
||||||
{
|
{
|
||||||
return new DefaultRazorCodeGenerationOptions(
|
return new DefaultRazorCodeGenerationOptions(
|
||||||
|
|
@ -46,7 +48,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
RootNamespace,
|
RootNamespace,
|
||||||
SuppressChecksum,
|
SuppressChecksum,
|
||||||
SuppressMetadataAttributes,
|
SuppressMetadataAttributes,
|
||||||
SuppressPrimaryMethodBody);
|
SuppressPrimaryMethodBody,
|
||||||
|
SuppressNullabilityEnforcement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetDesignTime(bool designTime)
|
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 firstMappedChild = node.Children.FirstOrDefault(child => child.Source != null) as IntermediateNode;
|
||||||
var valueStart = firstMappedChild?.Source;
|
var valueStart = firstMappedChild?.Source;
|
||||||
|
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
var accessor = GetPropertyAccessor(node);
|
var accessor = GetPropertyAccessor(node);
|
||||||
var assignmentPrefixLength = accessor.Length + " = ".Length;
|
var assignmentPrefixLength = accessor.Length + " = ".Length;
|
||||||
|
|
@ -422,7 +422,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter.WriteStartAssignment(GetPropertyAccessor(node));
|
context.CodeWriter.WriteStartAssignment(GetPropertyAccessor(node));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// {node.Content} __typeHelper = default({node.Content});
|
// {node.Content} __typeHelper = default({node.Content});
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
context.AddSourceMappingFor(node);
|
context.AddSourceMappingFor(node);
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// global::System.Object {node.content} = null;
|
// global::System.Object {node.content} = null;
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.Write("global::")
|
.Write("global::")
|
||||||
|
|
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// global::System.Object __typeHelper = nameof({node.Content});
|
// global::System.Object __typeHelper = nameof({node.Content});
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.Write("global::")
|
.Write("global::")
|
||||||
|
|
@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
case DirectiveTokenKind.String:
|
case DirectiveTokenKind.String:
|
||||||
|
|
||||||
// global::System.Object __typeHelper = "{node.Content}";
|
// global::System.Object __typeHelper = "{node.Content}";
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.Write("global::")
|
.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
|
// 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
|
// a previously non-existent line pragma from being added and destroying the context in which
|
||||||
// the completion session was started.
|
// the completion session was started.
|
||||||
using (context.CodeWriter.BuildLinePragma(node.Source))
|
using (context.CodeWriter.BuildLinePragma(node.Source, context))
|
||||||
{
|
{
|
||||||
context.AddSourceMappingFor(node);
|
context.AddSourceMappingFor(node);
|
||||||
context.CodeWriter.Write(" ");
|
context.CodeWriter.Write(" ");
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
suppressChecksum: false,
|
suppressChecksum: false,
|
||||||
rootNamespace: null,
|
rootNamespace: null,
|
||||||
supressMetadataAttributes: false,
|
supressMetadataAttributes: false,
|
||||||
suppressPrimaryMethodBody: false);
|
suppressPrimaryMethodBody: false,
|
||||||
|
suppressNullabilityEnforcement: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RazorCodeGenerationOptions CreateDesignTimeDefault()
|
public static RazorCodeGenerationOptions CreateDesignTimeDefault()
|
||||||
|
|
@ -28,7 +29,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
rootNamespace: null,
|
rootNamespace: null,
|
||||||
suppressChecksum: false,
|
suppressChecksum: false,
|
||||||
supressMetadataAttributes: true,
|
supressMetadataAttributes: true,
|
||||||
suppressPrimaryMethodBody: false);
|
suppressPrimaryMethodBody: false,
|
||||||
|
suppressNullabilityEnforcement: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RazorCodeGenerationOptions Create(Action<RazorCodeGenerationOptionsBuilder> configure)
|
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.
|
/// Gets or sets a value that determines if an empty body is generated for the primary method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool SuppressPrimaryMethodBody { get; protected set; }
|
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>
|
/// </summary>
|
||||||
public virtual bool SuppressPrimaryMethodBody { get; set; }
|
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 abstract RazorCodeGenerationOptions Build();
|
||||||
|
|
||||||
public virtual void SetDesignTime(bool designTime)
|
public virtual void SetDesignTime(bool designTime)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.Razor;
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
using Microsoft.Extensions.CommandLineUtils;
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
||||||
|
|
@ -30,6 +31,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
||||||
ExtensionNames = Option("-n", "extension name", CommandOptionType.MultipleValue);
|
ExtensionNames = Option("-n", "extension name", CommandOptionType.MultipleValue);
|
||||||
ExtensionFilePaths = Option("-e", "extension file path", CommandOptionType.MultipleValue);
|
ExtensionFilePaths = Option("-e", "extension file path", CommandOptionType.MultipleValue);
|
||||||
RootNamespace = Option("--root-namespace", "root namespace for generated code", CommandOptionType.SingleValue);
|
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);
|
GenerateDeclaration = Option("--generate-declaration", "Generate declaration", CommandOptionType.NoValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +57,8 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
||||||
|
|
||||||
public CommandOption RootNamespace { get; }
|
public CommandOption RootNamespace { get; }
|
||||||
|
|
||||||
|
public CommandOption CSharpLanguageVersion { get; }
|
||||||
|
|
||||||
public CommandOption GenerateDeclaration { get; }
|
public CommandOption GenerateDeclaration { get; }
|
||||||
|
|
||||||
protected override Task<int> ExecuteCoreAsync()
|
protected override Task<int> ExecuteCoreAsync()
|
||||||
|
|
@ -170,6 +174,22 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
||||||
RazorProjectFileSystem.Create(projectDirectory),
|
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 =>
|
var engine = RazorProjectEngine.Create(configuration, compositeFileSystem, b =>
|
||||||
{
|
{
|
||||||
b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, });
|
b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, });
|
||||||
|
|
@ -184,12 +204,12 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
||||||
{
|
{
|
||||||
b.SetRootNamespace(RootNamespace.Value());
|
b.SetRootNamespace(RootNamespace.Value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.SetCSharpLanguageVersion(csharpLanguageVersion);
|
||||||
});
|
});
|
||||||
|
|
||||||
var results = GenerateCode(engine, sourceItems);
|
var results = GenerateCode(engine, sourceItems);
|
||||||
|
|
||||||
var success = true;
|
|
||||||
|
|
||||||
foreach (var result in results)
|
foreach (var result in results)
|
||||||
{
|
{
|
||||||
var errorCount = result.CSharpDocument.Diagnostics.Count;
|
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 RootNamespace { get; set; }
|
||||||
|
|
||||||
|
public string CSharpLanguageVersion { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
|
@ -138,16 +140,24 @@ namespace Microsoft.AspNetCore.Razor.Tasks
|
||||||
builder.AppendLine(Configuration[0].GetMetadata(Identity));
|
builder.AppendLine(Configuration[0].GetMetadata(Identity));
|
||||||
|
|
||||||
// Added in 3.0
|
// Added in 3.0
|
||||||
if (parsedVersion.Major >= 3 && !string.IsNullOrEmpty(RootNamespace))
|
if (parsedVersion.Major >= 3)
|
||||||
{
|
{
|
||||||
builder.AppendLine("--root-namespace");
|
if (!string.IsNullOrEmpty(RootNamespace))
|
||||||
builder.AppendLine(RootNamespace);
|
{
|
||||||
}
|
builder.AppendLine("--root-namespace");
|
||||||
|
builder.AppendLine(RootNamespace);
|
||||||
|
}
|
||||||
|
|
||||||
// Added in 3.0
|
if (!string.IsNullOrEmpty(CSharpLanguageVersion))
|
||||||
if (parsedVersion.Major >= 3 && GenerateDeclaration)
|
{
|
||||||
{
|
builder.AppendLine("--csharp-language-version");
|
||||||
builder.AppendLine("--generate-declaration");
|
builder.AppendLine(CSharpLanguageVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GenerateDeclaration)
|
||||||
|
{
|
||||||
|
builder.AppendLine("--generate-declaration");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < Extensions.Length; i++)
|
for (var i = 0; i < Extensions.Length; i++)
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
PipeName="$(_RazorBuildServerPipeName)"
|
PipeName="$(_RazorBuildServerPipeName)"
|
||||||
Version="$(RazorLangVersion)"
|
Version="$(RazorLangVersion)"
|
||||||
RootNamespace="$(RootNamespace)"
|
RootNamespace="$(RootNamespace)"
|
||||||
|
CSharpLanguageVersion="$(LangVersion)"
|
||||||
Configuration="@(ResolvedRazorConfiguration)"
|
Configuration="@(ResolvedRazorConfiguration)"
|
||||||
Extensions="@(ResolvedRazorExtension)"
|
Extensions="@(ResolvedRazorExtension)"
|
||||||
Sources="@(RazorGenerateWithTargetPath)"
|
Sources="@(RazorGenerateWithTargetPath)"
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
||||||
PipeName="$(_RazorBuildServerPipeName)"
|
PipeName="$(_RazorBuildServerPipeName)"
|
||||||
Version="$(RazorLangVersion)"
|
Version="$(RazorLangVersion)"
|
||||||
RootNamespace="$(RootNamespace)"
|
RootNamespace="$(RootNamespace)"
|
||||||
|
CSharpLanguageVersion="$(LangVersion)"
|
||||||
Configuration="@(ResolvedRazorConfiguration)"
|
Configuration="@(ResolvedRazorConfiguration)"
|
||||||
Extensions="@(ResolvedRazorExtension)"
|
Extensions="@(ResolvedRazorExtension)"
|
||||||
Sources="@(_RazorComponentDeclarationSources)"
|
Sources="@(_RazorComponentDeclarationSources)"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue