RazorCompilationService should throw a meaningful error when a user produces an application without `preserveCompilationContext`
Fixes #4202
This commit is contained in:
parent
bf1fc7dab3
commit
c03aabbff5
|
|
@ -85,7 +85,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD1_5
|
||||||
_razorLoadContext = new RazorLoadContext();
|
_razorLoadContext = new RazorLoadContext();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -144,6 +143,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
|
|
||||||
if (!result.Success)
|
if (!result.Success)
|
||||||
{
|
{
|
||||||
|
if (!compilation.References.Any() && !_applicationReferences.Value.Any())
|
||||||
|
{
|
||||||
|
// DependencyModel had no references specified and the user did not use the
|
||||||
|
// CompilationCallback to add extra references. It is likely that the user did not specify
|
||||||
|
// preserveCompilationContext in the app's project.json.
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
Resources.FormatCompilation_DependencyContextIsNotSpecified(
|
||||||
|
fileInfo.RelativePath,
|
||||||
|
"project.json",
|
||||||
|
"preserveCompilationContext"));
|
||||||
|
}
|
||||||
|
|
||||||
return GetCompilationFailedResult(
|
return GetCompilationFailedResult(
|
||||||
fileInfo.RelativePath,
|
fileInfo.RelativePath,
|
||||||
compilationContent,
|
compilationContent,
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("LayoutHasCircularReference"), p0, p1);
|
return string.Format(CultureInfo.CurrentCulture, GetString("LayoutHasCircularReference"), p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string Compilation_DependencyContextIsNotSpecified
|
||||||
|
{
|
||||||
|
get { return GetString("Compilation_DependencyContextIsNotSpecified"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatCompilation_DependencyContextIsNotSpecified(object p0, object p1, object p2)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("Compilation_DependencyContextIsNotSpecified"), p0, p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetString(string name, params string[] formatterNames)
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
{
|
{
|
||||||
var value = _resourceManager.GetString(name);
|
var value = _resourceManager.GetString(name);
|
||||||
|
|
|
||||||
|
|
@ -203,4 +203,7 @@
|
||||||
<data name="LayoutHasCircularReference" xml:space="preserve">
|
<data name="LayoutHasCircularReference" xml:space="preserve">
|
||||||
<value>A circular layout reference was detected when rendering '{0}'. The layout page '{1}' has already been rendered.</value>
|
<value>A circular layout reference was detected when rendering '{0}'. The layout page '{1}' has already been rendered.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Compilation_DependencyContextIsNotSpecified" xml:space="preserve">
|
||||||
|
<value>The Razor page '{0}' failed to compile. Ensure that your application's {1} sets the '{2}' compilation property.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -256,6 +256,7 @@ public class MyNonCustomDefinedClass {}
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Compile_RunsCallback()
|
public void Compile_RunsCallback()
|
||||||
{
|
{
|
||||||
|
// Arrange
|
||||||
var content = "public class MyTestType {}";
|
var content = "public class MyTestType {}";
|
||||||
RoslynCompilationContext usedCompilation = null;
|
RoslynCompilationContext usedCompilation = null;
|
||||||
|
|
||||||
|
|
@ -276,6 +277,117 @@ public class MyNonCustomDefinedClass {}
|
||||||
Assert.Single(usedCompilation.Compilation.SyntaxTrees);
|
Assert.Single(usedCompilation.Compilation.SyntaxTrees);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compile_ThrowsIfDependencyContextIsNullAndTheApplicationFailsToCompileWithNoReferences()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "public class MyTestType {}";
|
||||||
|
var compilationService = new DefaultRoslynCompilationService(
|
||||||
|
dependencyContext: null,
|
||||||
|
viewEngineOptions: GetOptions(),
|
||||||
|
fileProviderAccessor: GetFileProviderAccessor(),
|
||||||
|
loggerFactory: NullLoggerFactory.Instance);
|
||||||
|
|
||||||
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
"some-relative-path.cshtml");
|
||||||
|
|
||||||
|
var expected = "The Razor page 'some-relative-path.cshtml' failed to compile. Ensure that your "
|
||||||
|
+ "application's project.json sets the 'preserveCompilationContext' compilation property.";
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||||
|
compilationService.Compile(relativeFileInfo, content));
|
||||||
|
Assert.Equal(expected, ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compile_ThrowsIfDependencyContextReturnsNoReferencesAndTheApplicationFailsToCompile()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var content = "public class MyTestType {}";
|
||||||
|
var dependencyContext = new DependencyContext(
|
||||||
|
target: null,
|
||||||
|
runtime: null,
|
||||||
|
compilationOptions: Extensions.DependencyModel.CompilationOptions.Default,
|
||||||
|
compileLibraries: new CompilationLibrary[0],
|
||||||
|
runtimeLibraries: new RuntimeLibrary[0]);
|
||||||
|
var compilationService = new DefaultRoslynCompilationService(
|
||||||
|
dependencyContext: dependencyContext,
|
||||||
|
viewEngineOptions: GetOptions(),
|
||||||
|
fileProviderAccessor: GetFileProviderAccessor(),
|
||||||
|
loggerFactory: NullLoggerFactory.Instance);
|
||||||
|
|
||||||
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
"some-relative-path.cshtml");
|
||||||
|
|
||||||
|
var expected = "The Razor page 'some-relative-path.cshtml' failed to compile. Ensure that your "
|
||||||
|
+ "application's project.json sets the 'preserveCompilationContext' compilation property.";
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||||
|
compilationService.Compile(relativeFileInfo, content));
|
||||||
|
Assert.Equal(expected, ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compile_DoesNotThrowIfReferencesWereClearedInCallback()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = GetOptions(context =>
|
||||||
|
{
|
||||||
|
context.Compilation = context.Compilation.RemoveAllReferences();
|
||||||
|
});
|
||||||
|
var content = "public class MyTestType {}";
|
||||||
|
var compilationService = new DefaultRoslynCompilationService(
|
||||||
|
dependencyContext: GetDependencyContext(),
|
||||||
|
viewEngineOptions: options,
|
||||||
|
fileProviderAccessor: GetFileProviderAccessor(),
|
||||||
|
loggerFactory: NullLoggerFactory.Instance);
|
||||||
|
|
||||||
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
"some-relative-path.cshtml");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = compilationService.Compile(relativeFileInfo, content);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Single(result.CompilationFailures);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compile_SucceedsIfReferencesAreAddedInCallback()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = GetOptions(context =>
|
||||||
|
{
|
||||||
|
var assemblyLocation = typeof(object).GetTypeInfo().Assembly.Location;
|
||||||
|
|
||||||
|
context.Compilation = context
|
||||||
|
.Compilation
|
||||||
|
.AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
|
||||||
|
});
|
||||||
|
var content = "public class MyTestType {}";
|
||||||
|
var compilationService = new DefaultRoslynCompilationService(
|
||||||
|
dependencyContext: null,
|
||||||
|
viewEngineOptions: options,
|
||||||
|
fileProviderAccessor: GetFileProviderAccessor(),
|
||||||
|
loggerFactory: NullLoggerFactory.Instance);
|
||||||
|
|
||||||
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
"some-relative-path.cshtml");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = compilationService.Compile(relativeFileInfo, content);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(result.CompilationFailures);
|
||||||
|
Assert.NotNull(result.CompiledType);
|
||||||
|
}
|
||||||
|
|
||||||
private static DiagnosticDescriptor GetDiagnosticDescriptor(string messageFormat)
|
private static DiagnosticDescriptor GetDiagnosticDescriptor(string messageFormat)
|
||||||
{
|
{
|
||||||
return new DiagnosticDescriptor(
|
return new DiagnosticDescriptor(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue