diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CSharpCompiler.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CSharpCompiler.cs index d95de2584b..638c2911ed 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CSharpCompiler.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CSharpCompiler.cs @@ -21,19 +21,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal { private readonly RazorReferenceManager _referenceManager; private readonly IHostingEnvironment _hostingEnvironment; - private readonly DebugInformationFormat _pdbFormat = SymbolsUtility.SupportsFullPdbGeneration() ? - DebugInformationFormat.Pdb : - DebugInformationFormat.PortablePdb; private bool _optionsInitialized; private CSharpParseOptions _parseOptions; private CSharpCompilationOptions _compilationOptions; + private EmitOptions _emitOptions; public CSharpCompiler(RazorReferenceManager manager, IHostingEnvironment hostingEnvironment) { _referenceManager = manager ?? throw new ArgumentNullException(nameof(manager)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); - - EmitOptions = new EmitOptions(debugInformationFormat: _pdbFormat); } public virtual CSharpParseOptions ParseOptions @@ -54,7 +50,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal } } - public EmitOptions EmitOptions { get; } + public virtual EmitOptions EmitOptions + { + get + { + EnsureOptions(); + return _emitOptions; + } + } public SyntaxTree CreateSyntaxTree(SourceText sourceText) { @@ -94,11 +97,47 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal var dependencyContextOptions = GetDependencyContextCompilationOptions(); _parseOptions = GetParseOptions(_hostingEnvironment, dependencyContextOptions); _compilationOptions = GetCompilationOptions(_hostingEnvironment, dependencyContextOptions); + _emitOptions = GetEmitOptions(dependencyContextOptions); _optionsInitialized = true; } } + private EmitOptions GetEmitOptions(DependencyContextCompilationOptions dependencyContextOptions) + { + DebugInformationFormat debugInformationFormat; + if (string.IsNullOrEmpty(dependencyContextOptions.DebugType)) + { + debugInformationFormat = SymbolsUtility.SupportsFullPdbGeneration() ? + DebugInformationFormat.Pdb : + DebugInformationFormat.PortablePdb; + } + else + { + // Based on https://github.com/dotnet/roslyn/blob/1d28ff9ba248b332de3c84d23194a1d7bde07e4d/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs#L624-L640 + switch (dependencyContextOptions.DebugType.ToLower()) + { + case "portable": + debugInformationFormat = DebugInformationFormat.PortablePdb; + break; + case "embedded": + debugInformationFormat = DebugInformationFormat.Embedded; + break; + case "full": + case "pdbonly": + debugInformationFormat = SymbolsUtility.SupportsFullPdbGeneration() ? + DebugInformationFormat.Pdb : + DebugInformationFormat.PortablePdb; + break; + default: + throw new InvalidOperationException(Resources.FormatUnsupportedDebugInformationFormat(dependencyContextOptions.DebugType)); + } + } + + var emitOptions = new EmitOptions(debugInformationFormat: debugInformationFormat); + return emitOptions; + } + private static CSharpCompilationOptions GetCompilationOptions( IHostingEnvironment hostingEnvironment, DependencyContextCompilationOptions dependencyContextOptions) diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs index 3ac504edc8..f82255ab10 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Properties/Resources.Designer.cs @@ -364,6 +364,20 @@ namespace Microsoft.AspNetCore.Mvc.Razor internal static string FormatRazorViewCompiler_ViewPathsDifferOnlyInCase() => GetString("RazorViewCompiler_ViewPathsDifferOnlyInCase"); + /// + /// The debug type specified in the dependency context could be parsed. The debug type value '{0}' is not supported. + /// + internal static string UnsupportedDebugInformationFormat + { + get => GetString("UnsupportedDebugInformationFormat"); + } + + /// + /// The debug type specified in the dependency context could be parsed. The debug type value '{0}' is not supported. + /// + internal static string FormatUnsupportedDebugInformationFormat(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("UnsupportedDebugInformationFormat"), p0); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx b/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx index 777ba9eec7..63deeebd9b 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Resources.resx @@ -194,4 +194,7 @@ The following precompiled view paths differ only in case, which is not supported: - \ No newline at end of file + + The debug type specified in the dependency context could be parsed. The debug type value '{0}' is not supported. + + diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/CSharpCompilerTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/CSharpCompilerTest.cs index c6d9b94dd2..613bab7147 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/CSharpCompilerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/CSharpCompilerTest.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Razor.Compilation; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Text; using Moq; using Xunit; @@ -172,6 +173,36 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal Assert.Equal(LanguageVersion.CSharp7_1, compilationOptions.LanguageVersion); } + + [Theory] + [InlineData("portable", DebugInformationFormat.PortablePdb)] + [InlineData("embedded", DebugInformationFormat.Embedded)] + public void EmitOptions_ReadsDebugTypeFromDependencyContext(string debugType, DebugInformationFormat expected) + { + // Arrange + var dependencyContextOptions = new DependencyContextCompilationOptions( + new[] { "MyDefine" }, + languageVersion: "7.1", + platform: null, + allowUnsafe: true, + warningsAsErrors: null, + optimize: null, + keyFile: null, + delaySign: null, + publicSign: null, + debugType: debugType, + emitEntryPoint: null, + generateXmlDocumentation: null); + var referenceManager = Mock.Of(); + var hostingEnvironment = Mock.Of(); + + var compiler = new TestCSharpCompiler(referenceManager, hostingEnvironment, dependencyContextOptions); + + // Act & Assert + var emitOptions = compiler.EmitOptions; + Assert.Equal(expected, emitOptions.DebugInformationFormat); + } + [Fact] public void Constructor_ConfiguresAllowUnsafe() {