Added SourceLocation to inherited chunks \ tag helpers
Updated CompilationResult to support compilation failures from multiple files. Fixes #2321
This commit is contained in:
parent
f878ca5b15
commit
fb451b51e5
|
|
@ -126,22 +126,33 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
|
|||
|
||||
private static CodeTree ParseViewFile(RazorTemplateEngine engine,
|
||||
IFileInfo fileInfo,
|
||||
string viewStartPath)
|
||||
string globalImportPath)
|
||||
{
|
||||
using (var stream = fileInfo.CreateReadStream())
|
||||
{
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
var parseResults = engine.ParseTemplate(streamReader, viewStartPath);
|
||||
var parseResults = engine.ParseTemplate(streamReader, globalImportPath);
|
||||
var className = ParserHelpers.SanitizeClassName(fileInfo.Name);
|
||||
var language = engine.Host.CodeLanguage;
|
||||
var codeGenerator = language.CreateCodeGenerator(className,
|
||||
engine.Host.DefaultNamespace,
|
||||
viewStartPath,
|
||||
globalImportPath,
|
||||
engine.Host);
|
||||
codeGenerator.Visit(parseResults);
|
||||
|
||||
return codeGenerator.Context.CodeTreeBuilder.CodeTree;
|
||||
// Rewrite the location of inherited chunks so they point to the global import file.
|
||||
var codeTree = codeGenerator.Context.CodeTreeBuilder.CodeTree;
|
||||
foreach (var chunk in codeTree.Chunks)
|
||||
{
|
||||
chunk.Start = new SourceLocation(
|
||||
globalImportPath,
|
||||
chunk.Start.AbsoluteIndex,
|
||||
chunk.Start.LineIndex,
|
||||
chunk.Start.CharacterIndex);
|
||||
}
|
||||
|
||||
return codeTree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
var descriptor = new TagHelperDirectiveDescriptor(
|
||||
addTagHelperChunk.LookupText,
|
||||
SourceLocation.Undefined,
|
||||
chunk.Start,
|
||||
TagHelperDirectiveType.AddTagHelper);
|
||||
|
||||
descriptors.Add(descriptor);
|
||||
|
|
@ -89,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
var descriptor = new TagHelperDirectiveDescriptor(
|
||||
removeTagHelperChunk.LookupText,
|
||||
SourceLocation.Undefined,
|
||||
chunk.Start,
|
||||
TagHelperDirectiveType.RemoveTagHelper);
|
||||
|
||||
descriptors.Add(descriptor);
|
||||
|
|
@ -102,7 +102,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
var descriptor = new TagHelperDirectiveDescriptor(
|
||||
tagHelperPrefixDirectiveChunk.Prefix,
|
||||
SourceLocation.Undefined,
|
||||
chunk.Start,
|
||||
TagHelperDirectiveType.TagHelperPrefix);
|
||||
|
||||
descriptors.Add(descriptor);
|
||||
|
|
|
|||
|
|
@ -17,24 +17,24 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
/// <summary>
|
||||
/// Instantiates a new instance of <see cref="CompilationFailedException"/>.
|
||||
/// </summary>
|
||||
/// <param name="compilationFailure">The <see cref="ICompilationFailure"/> instance containing
|
||||
/// <param name="compilationFailures"><see cref="ICompilationFailure"/>s containing
|
||||
/// details of the compilation failure.</param>
|
||||
public CompilationFailedException(
|
||||
[NotNull] ICompilationFailure compilationFailure)
|
||||
: base(FormatMessage(compilationFailure))
|
||||
[NotNull] IEnumerable<ICompilationFailure> compilationFailures)
|
||||
: base(FormatMessage(compilationFailures))
|
||||
{
|
||||
CompilationFailures = new[] { compilationFailure };
|
||||
CompilationFailures = compilationFailures;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ICompilationFailure> CompilationFailures { get; }
|
||||
|
||||
private static string FormatMessage(ICompilationFailure compilationFailure)
|
||||
private static string FormatMessage(IEnumerable<ICompilationFailure> compilationFailures)
|
||||
{
|
||||
return Resources.CompilationFailed + Environment.NewLine +
|
||||
string.Join(
|
||||
Environment.NewLine,
|
||||
compilationFailure.Messages.Select(message => message.FormattedMessage));
|
||||
compilationFailures.SelectMany(f => f.Messages).Select(message => message.FormattedMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Runtime;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
||||
{
|
||||
|
|
@ -31,10 +33,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
public string CompiledContent { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ICompilationFailure"/> produced from parsing or compiling the Razor file.
|
||||
/// Gets the <see cref="ICompilationFailure"/>s produced from parsing or compiling the Razor file.
|
||||
/// </summary>
|
||||
/// <remarks>This property is <c>null</c> when compilation succeeded.</remarks>
|
||||
public ICompilationFailure CompilationFailure { get; private set; }
|
||||
/// <remarks>This property is <c>null</c> when compilation succeeded. An empty sequence
|
||||
/// indicates a failed compilation.</remarks>
|
||||
public IEnumerable<ICompilationFailure> CompilationFailures { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CompilationResult"/>.
|
||||
|
|
@ -43,9 +46,9 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
/// <exception cref="CompilationFailedException">Thrown if compilation failed.</exception>
|
||||
public CompilationResult EnsureSuccessful()
|
||||
{
|
||||
if (CompilationFailure != null)
|
||||
if (CompilationFailures != null)
|
||||
{
|
||||
throw new CompilationFailedException(CompilationFailure);
|
||||
throw new CompilationFailedException(CompilationFailures);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
|
@ -54,14 +57,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
/// <summary>
|
||||
/// Creates a <see cref="CompilationResult"/> for a failed compilation.
|
||||
/// </summary>
|
||||
/// <param name="compilationFailure">The <see cref="ICompilationFailure"/> produced from parsing or
|
||||
/// <param name="compilationFailures"><see cref="ICompilationFailure"/>s produced from parsing or
|
||||
/// compiling the Razor file.</param>
|
||||
/// <returns>A <see cref="CompilationResult"/> instance for a failed compilation.</returns>
|
||||
public static CompilationResult Failed([NotNull] ICompilationFailure compilationFailure)
|
||||
public static CompilationResult Failed([NotNull] IEnumerable<ICompilationFailure> compilationFailures)
|
||||
{
|
||||
return new CompilationResult
|
||||
{
|
||||
CompilationFailure = compilationFailure
|
||||
CompilationFailures = compilationFailures
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.FileProviders;
|
||||
using Microsoft.AspNet.Razor;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
||||
{
|
||||
|
|
@ -16,12 +19,15 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
{
|
||||
private readonly ICompilationService _compilationService;
|
||||
private readonly IMvcRazorHost _razorHost;
|
||||
private readonly IFileProvider _fileProvider;
|
||||
|
||||
public RazorCompilationService(ICompilationService compilationService,
|
||||
IMvcRazorHost razorHost)
|
||||
IMvcRazorHost razorHost,
|
||||
IOptions<RazorViewEngineOptions> viewEngineOptions)
|
||||
{
|
||||
_compilationService = compilationService;
|
||||
_razorHost = razorHost;
|
||||
_fileProvider = viewEngineOptions.Options.FileProvider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -30,39 +36,61 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
GeneratorResults results;
|
||||
using (var inputStream = file.FileInfo.CreateReadStream())
|
||||
{
|
||||
results = _razorHost.GenerateCode(
|
||||
file.RelativePath, inputStream);
|
||||
results = _razorHost.GenerateCode(file.RelativePath, inputStream);
|
||||
}
|
||||
|
||||
if (!results.Success)
|
||||
{
|
||||
var messages = results.ParserErrors
|
||||
.Select(parseError => new RazorCompilationMessage(parseError, file.RelativePath));
|
||||
var failure = new RazorCompilationFailure(
|
||||
file.RelativePath,
|
||||
ReadFileContentsSafely(file.FileInfo),
|
||||
messages);
|
||||
|
||||
return CompilationResult.Failed(failure);
|
||||
return GetCompilationFailedResult(file, results.ParserErrors);
|
||||
}
|
||||
|
||||
return _compilationService.Compile(file, results.GeneratedCode);
|
||||
}
|
||||
|
||||
private static string ReadFileContentsSafely(IFileInfo fileInfo)
|
||||
// Internal for unit testing
|
||||
internal CompilationResult GetCompilationFailedResult(RelativeFileInfo file, IEnumerable<RazorError> errors)
|
||||
{
|
||||
try
|
||||
// If a SourceLocation does not specify a file path, assume it is produced
|
||||
// from parsing the current file.
|
||||
var messageGroups = errors
|
||||
.GroupBy(razorError =>
|
||||
razorError.Location.FilePath ?? file.RelativePath,
|
||||
StringComparer.Ordinal);
|
||||
|
||||
var failures = new List<RazorCompilationFailure>();
|
||||
foreach (var group in messageGroups)
|
||||
{
|
||||
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||
var filePath = group.Key;
|
||||
var fileContent = ReadFileContentsSafely(filePath);
|
||||
var compilationFailure = new RazorCompilationFailure(
|
||||
filePath,
|
||||
fileContent,
|
||||
group.Select(parserError => new RazorCompilationMessage(parserError, filePath)));
|
||||
failures.Add(compilationFailure);
|
||||
}
|
||||
|
||||
return CompilationResult.Failed(failures);
|
||||
}
|
||||
|
||||
private string ReadFileContentsSafely(string relativePath)
|
||||
{
|
||||
var fileInfo = _fileProvider.GetFileInfo(relativePath);
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any failures
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any failures
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis;
|
|||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Compilation;
|
||||
using Microsoft.Framework.Runtime.Roslyn;
|
||||
|
|
@ -34,9 +35,8 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
private readonly IApplicationEnvironment _environment;
|
||||
private readonly IAssemblyLoadContext _loader;
|
||||
private readonly ICompilerOptionsProvider _compilerOptionsProvider;
|
||||
|
||||
private readonly IFileProvider _fileProvider;
|
||||
private readonly Lazy<List<MetadataReference>> _applicationReferences;
|
||||
|
||||
private readonly string _classPrefix;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -50,30 +50,28 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
IAssemblyLoadContextAccessor loaderAccessor,
|
||||
ILibraryManager libraryManager,
|
||||
ICompilerOptionsProvider compilerOptionsProvider,
|
||||
IMvcRazorHost host)
|
||||
IMvcRazorHost host,
|
||||
IOptions<RazorViewEngineOptions> optionsAccessor)
|
||||
{
|
||||
_environment = environment;
|
||||
_loader = loaderAccessor.GetLoadContext(typeof(RoslynCompilationService).GetTypeInfo().Assembly);
|
||||
_libraryManager = libraryManager;
|
||||
_applicationReferences = new Lazy<List<MetadataReference>>(GetApplicationReferences);
|
||||
_compilerOptionsProvider = compilerOptionsProvider;
|
||||
_fileProvider = optionsAccessor.Options.FileProvider;
|
||||
_classPrefix = host.MainClassNamePrefix;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public CompilationResult Compile([NotNull] RelativeFileInfo fileInfo, [NotNull] string compilationContent)
|
||||
{
|
||||
// The path passed to SyntaxTreeGenerator.Generate is used by the compiler to generate symbols (pdb) that
|
||||
// map to the source file. If a file does not exist on a physical file system, PhysicalPath will be null.
|
||||
// This prevents files that exist in a non-physical file system from being debugged.
|
||||
var path = fileInfo.FileInfo.PhysicalPath ?? fileInfo.RelativePath;
|
||||
var assemblyName = Path.GetRandomFileName();
|
||||
var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(compilationContent,
|
||||
path,
|
||||
assemblyName,
|
||||
compilationSettings);
|
||||
var references = _applicationReferences.Value;
|
||||
|
||||
var assemblyName = Path.GetRandomFileName();
|
||||
var compilationOptions = compilationSettings.CompilationOptions
|
||||
.WithOutputKind(OutputKind.DynamicallyLinkedLibrary);
|
||||
|
||||
|
|
@ -99,15 +97,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
|
||||
if (!result.Success)
|
||||
{
|
||||
var failures = result.Diagnostics.Where(IsError);
|
||||
var compilationFailure = new RoslynCompilationFailure(failures)
|
||||
{
|
||||
CompiledContent = compilationContent,
|
||||
SourceFileContent = ReadFileContentsSafely(fileInfo.FileInfo),
|
||||
SourceFilePath = fileInfo.RelativePath
|
||||
};
|
||||
|
||||
return CompilationResult.Failed(compilationFailure);
|
||||
return GetCompilationFailedResult(
|
||||
fileInfo.RelativePath,
|
||||
compilationContent,
|
||||
assemblyName,
|
||||
result.Diagnostics);
|
||||
}
|
||||
|
||||
Assembly assembly;
|
||||
|
|
@ -131,6 +125,56 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
}
|
||||
}
|
||||
|
||||
// Internal for unit testing
|
||||
internal CompilationResult GetCompilationFailedResult(
|
||||
string relativePath,
|
||||
string compilationContent,
|
||||
string assemblyName,
|
||||
IEnumerable<Diagnostic> diagnostics)
|
||||
{
|
||||
var diagnosticGroups = diagnostics
|
||||
.Where(IsError)
|
||||
.GroupBy(diagnostic => GetFilePath(relativePath, diagnostic), StringComparer.Ordinal);
|
||||
|
||||
var failures = new List<ICompilationFailure>();
|
||||
foreach (var group in diagnosticGroups)
|
||||
{
|
||||
var sourceFilePath = group.Key;
|
||||
string sourceFileContent;
|
||||
if (string.Equals(assemblyName, sourceFilePath, StringComparison.Ordinal))
|
||||
{
|
||||
// The error is in the generated code and does not have a mapping line pragma
|
||||
sourceFileContent = compilationContent;
|
||||
sourceFilePath = Resources.GeneratedCodeFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceFileContent = ReadFileContentsSafely(_fileProvider, sourceFilePath);
|
||||
}
|
||||
|
||||
var compilationFailure = new RoslynCompilationFailure(group)
|
||||
{
|
||||
CompiledContent = compilationContent,
|
||||
SourceFileContent = sourceFileContent,
|
||||
SourceFilePath = sourceFilePath
|
||||
};
|
||||
|
||||
failures.Add(compilationFailure);
|
||||
}
|
||||
|
||||
return CompilationResult.Failed(failures);
|
||||
}
|
||||
|
||||
private static string GetFilePath(string relativePath, Diagnostic diagnostic)
|
||||
{
|
||||
if (diagnostic.Location == Location.None)
|
||||
{
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
return diagnostic.Location.GetMappedLineSpan().Path;
|
||||
}
|
||||
|
||||
private List<MetadataReference> GetApplicationReferences()
|
||||
{
|
||||
var references = new List<MetadataReference>();
|
||||
|
|
@ -222,20 +266,25 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
|
||||
}
|
||||
|
||||
private static string ReadFileContentsSafely(IFileInfo fileInfo)
|
||||
private static string ReadFileContentsSafely(IFileProvider fileProvider, string filePath)
|
||||
{
|
||||
try
|
||||
var fileInfo = fileProvider.GetFileInfo(filePath);
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||
try
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any failures
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any failures
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
|||
isEnabledByDefault: true);
|
||||
|
||||
var location = error.Location;
|
||||
if (location == SourceLocation.Undefined)
|
||||
if (location.Equals(SourceLocation.Undefined))
|
||||
{
|
||||
location = SourceLocation.Zero;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,22 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("RazorFileInfoCollection_ResourceCouldNotBeFound"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generated Code
|
||||
/// </summary>
|
||||
internal static string GeneratedCodeFileName
|
||||
{
|
||||
get { return GetString("GeneratedCodeFileName"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generated Code
|
||||
/// </summary>
|
||||
internal static string FormatGeneratedCodeFileName()
|
||||
{
|
||||
return GetString("GeneratedCodeFileName");
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -189,4 +189,7 @@
|
|||
<data name="RazorFileInfoCollection_ResourceCouldNotBeFound" xml:space="preserve">
|
||||
<value>The resource '{0}' specified by '{1}' could not be found.</value>
|
||||
</data>
|
||||
<data name="GeneratedCodeFileName" xml:space="preserve">
|
||||
<value>Generated Code</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -47,5 +47,26 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
Assert.Contains($"/Views/ErrorPageMiddleware/{action}.cshtml", content);
|
||||
Assert.Contains(expected, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CompilationFailuresFromGlobalImportAreListed()
|
||||
{
|
||||
// Arrange
|
||||
var expectedMessage = "The type or namespace name 'NamespaceDoesNotExist' could not be found ("
|
||||
+ "are you missing a using directive or an assembly reference?)";
|
||||
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
|
||||
var client = server.CreateClient();
|
||||
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html");
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/ErrorFromGlobalImport");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
Assert.Contains(@"Views\ErrorFromGlobalImport\_GlobalImport.cshtml", content);
|
||||
Assert.Contains(expectedMessage, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,33 +38,72 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
|
|||
var codeTrees = utility.GetInheritedCodeTrees(@"Views\home\Index.cshtml");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, codeTrees.Count);
|
||||
var viewStartChunks = codeTrees[0].Chunks;
|
||||
Assert.Equal(3, viewStartChunks.Count);
|
||||
Assert.Collection(codeTrees,
|
||||
codeTree =>
|
||||
{
|
||||
var globalImportPath = @"Views\home\_GlobalImport.cshtml";
|
||||
Assert.Collection(codeTree.Chunks,
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<LiteralChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
var usingChunk = Assert.IsType<UsingChunk>(chunk);
|
||||
Assert.Equal("MyNamespace", usingChunk.Namespace);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<LiteralChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
});
|
||||
},
|
||||
codeTree =>
|
||||
{
|
||||
var globalImportPath = @"Views\_GlobalImport.cshtml";
|
||||
Assert.Collection(codeTree.Chunks,
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<LiteralChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
var injectChunk = Assert.IsType<InjectChunk>(chunk);
|
||||
Assert.Equal("MyHelper<TModel>", injectChunk.TypeName);
|
||||
Assert.Equal("Helper", injectChunk.MemberName);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<LiteralChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(chunk);
|
||||
Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
|
||||
Assert.IsType<LiteralChunk>(viewStartChunks[0]);
|
||||
var usingChunk = Assert.IsType<UsingChunk>(viewStartChunks[1]);
|
||||
Assert.Equal("MyNamespace", usingChunk.Namespace);
|
||||
Assert.IsType<LiteralChunk>(viewStartChunks[2]);
|
||||
|
||||
viewStartChunks = codeTrees[1].Chunks;
|
||||
Assert.Equal(7, viewStartChunks.Count);
|
||||
|
||||
Assert.IsType<LiteralChunk>(viewStartChunks[0]);
|
||||
|
||||
var injectChunk = Assert.IsType<InjectChunk>(viewStartChunks[1]);
|
||||
Assert.Equal("MyHelper<TModel>", injectChunk.TypeName);
|
||||
Assert.Equal("Helper", injectChunk.MemberName);
|
||||
|
||||
Assert.IsType<LiteralChunk>(viewStartChunks[2]);
|
||||
|
||||
var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(viewStartChunks[3]);
|
||||
Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName);
|
||||
|
||||
Assert.IsType<LiteralChunk>(viewStartChunks[4]);
|
||||
|
||||
Assert.IsType<StatementChunk>(viewStartChunks[5]);
|
||||
Assert.IsType<LiteralChunk>(viewStartChunks[6]);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<LiteralChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<StatementChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
},
|
||||
chunk =>
|
||||
{
|
||||
Assert.IsType<LiteralChunk>(chunk);
|
||||
Assert.Equal(globalImportPath, chunk.Start.FilePath);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var actual = descriptors[i];
|
||||
|
||||
Assert.Equal(expected.DirectiveText, actual.DirectiveText, StringComparer.Ordinal);
|
||||
Assert.Equal(expected.Location, actual.Location);
|
||||
Assert.Equal(SourceLocation.Zero, actual.Location);
|
||||
Assert.Equal(expected.DirectiveType, actual.DirectiveType);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,15 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
{
|
||||
// Arrange
|
||||
var compilationFailure = Mock.Of<ICompilationFailure>();
|
||||
var result = CompilationResult.Failed(compilationFailure);
|
||||
var failures = new[] { compilationFailure };
|
||||
var result = CompilationResult.Failed(failures);
|
||||
|
||||
// Act and Assert
|
||||
Assert.Null(result.CompiledType);
|
||||
Assert.Same(compilationFailure, result.CompilationFailure);
|
||||
Assert.Same(failures, result.CompilationFailures);
|
||||
var exception = Assert.Throws<CompilationFailedException>(() => result.EnsureSuccessful());
|
||||
Assert.Collection(exception.CompilationFailures,
|
||||
failure => Assert.Same(compilationFailure, failure));
|
||||
var failure = Assert.Single(exception.CompilationFailures);
|
||||
Assert.Same(compilationFailure, failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ using Microsoft.AspNet.Razor;
|
|||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
compiler.Setup(c => c.Compile(relativeFileInfo, It.IsAny<string>()))
|
||||
.Returns(CompilationResult.Successful(typeof(RazorCompilationServiceTest)));
|
||||
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object);
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetOptions());
|
||||
|
||||
// Act
|
||||
razorService.Compile(relativeFileInfo);
|
||||
|
|
@ -68,15 +69,19 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
|
||||
var compiler = new Mock<ICompilationService>(MockBehavior.Strict);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object);
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetOptions());
|
||||
|
||||
// Act
|
||||
var result = razorService.Compile(relativeFileInfo);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompilationFailure);
|
||||
var message = Assert.Single(result.CompilationFailure.Messages);
|
||||
Assert.Equal("some message", message.Message);
|
||||
Assert.NotNull(result.CompilationFailures);
|
||||
Assert.Collection(result.CompilationFailures,
|
||||
failure =>
|
||||
{
|
||||
var message = Assert.Single(failure.Messages);
|
||||
Assert.Equal("some message", message.Message);
|
||||
});
|
||||
host.Verify();
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +110,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
compiler.Setup(c => c.Compile(relativeFileInfo, code))
|
||||
.Returns(compilationResult)
|
||||
.Verifiable();
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object);
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetOptions());
|
||||
|
||||
// Act
|
||||
var result = razorService.Compile(relativeFileInfo);
|
||||
|
|
@ -115,6 +120,86 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
compiler.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCompilationFailedResult_ReturnsCompilationResult_WithGroupedMessages()
|
||||
{
|
||||
// Arrange
|
||||
var viewPath = @"views/index.razor";
|
||||
var globalImportPath = @"views/global.import.cshtml";
|
||||
var host = Mock.Of<IMvcRazorHost>();
|
||||
|
||||
var fileProvider = new TestFileProvider();
|
||||
var file = fileProvider.AddFile(viewPath, "View Content");
|
||||
fileProvider.AddFile(globalImportPath, "Global Import Content");
|
||||
var relativeFileInfo = new RelativeFileInfo(file, viewPath);
|
||||
var razorService = new RazorCompilationService(
|
||||
Mock.Of<ICompilationService>(),
|
||||
Mock.Of<IMvcRazorHost>(),
|
||||
GetOptions(fileProvider));
|
||||
var errors = new[]
|
||||
{
|
||||
new RazorError("message-1", new SourceLocation(1, 2, 17)),
|
||||
new RazorError("message-2", new SourceLocation(viewPath, 1, 4, 6), 7),
|
||||
new RazorError { Message = "message-3" },
|
||||
new RazorError("message-4", new SourceLocation(globalImportPath, 1, 3, 8), 4),
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = razorService.GetCompilationFailedResult(relativeFileInfo, errors);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompilationFailures);
|
||||
Assert.Collection(result.CompilationFailures,
|
||||
failure =>
|
||||
{
|
||||
Assert.Equal(viewPath, failure.SourceFilePath);
|
||||
Assert.Equal("View Content", failure.SourceFileContent);
|
||||
Assert.Collection(failure.Messages,
|
||||
message =>
|
||||
{
|
||||
Assert.Equal(errors[0].Message, message.Message);
|
||||
Assert.Equal(viewPath, message.SourceFilePath);
|
||||
Assert.Equal(3, message.StartLine);
|
||||
Assert.Equal(17, message.StartColumn);
|
||||
Assert.Equal(3, message.EndLine);
|
||||
Assert.Equal(18, message.EndColumn);
|
||||
},
|
||||
message =>
|
||||
{
|
||||
Assert.Equal(errors[1].Message, message.Message);
|
||||
Assert.Equal(viewPath, message.SourceFilePath);
|
||||
Assert.Equal(5, message.StartLine);
|
||||
Assert.Equal(6, message.StartColumn);
|
||||
Assert.Equal(5, message.EndLine);
|
||||
Assert.Equal(13, message.EndColumn);
|
||||
},
|
||||
message =>
|
||||
{
|
||||
Assert.Equal(errors[2].Message, message.Message);
|
||||
Assert.Equal(viewPath, message.SourceFilePath);
|
||||
Assert.Equal(0, message.StartLine);
|
||||
Assert.Equal(-1, message.StartColumn);
|
||||
Assert.Equal(0, message.EndLine);
|
||||
Assert.Equal(0, message.EndColumn);
|
||||
});
|
||||
},
|
||||
failure =>
|
||||
{
|
||||
Assert.Equal(globalImportPath, failure.SourceFilePath);
|
||||
Assert.Equal("Global Import Content", failure.SourceFileContent);
|
||||
Assert.Collection(failure.Messages,
|
||||
message =>
|
||||
{
|
||||
Assert.Equal(errors[3].Message, message.Message);
|
||||
Assert.Equal(globalImportPath, message.SourceFilePath);
|
||||
Assert.Equal(4, message.StartLine);
|
||||
Assert.Equal(8, message.StartColumn);
|
||||
Assert.Equal(4, message.EndLine);
|
||||
Assert.Equal(12, message.EndColumn);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static GeneratorResults GetGeneratorResult()
|
||||
{
|
||||
return new GeneratorResults(
|
||||
|
|
@ -124,5 +209,18 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
new CodeBuilderResult("", new LineMapping[0]),
|
||||
new CodeTree());
|
||||
}
|
||||
|
||||
private static IOptions<RazorViewEngineOptions> GetOptions(IFileProvider fileProvider = null)
|
||||
{
|
||||
var razorViewEngineOptions = new RazorViewEngineOptions
|
||||
{
|
||||
FileProvider = fileProvider ?? new TestFileProvider()
|
||||
};
|
||||
var options = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||
options.SetupGet(o => o.Options)
|
||||
.Returns(razorViewEngineOptions);
|
||||
|
||||
return options.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ using System.IO;
|
|||
using System.Reflection;
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.AspNet.FileProviders;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Compilation;
|
||||
using Moq;
|
||||
|
|
@ -38,7 +41,8 @@ public class MyTestType {}";
|
|||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost.Object);
|
||||
mvcRazorHost.Object,
|
||||
GetOptions());
|
||||
var relativeFileInfo = new RelativeFileInfo(new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
|
|
@ -52,11 +56,14 @@ public class MyTestType {}";
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsCompilationFailureWithRelativePath()
|
||||
public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas()
|
||||
{
|
||||
// Arrange
|
||||
var viewPath = "some-relative-path";
|
||||
var fileContent = "test file content";
|
||||
var content = @"this should fail";
|
||||
var content = $@"
|
||||
#line 1 ""{viewPath}""
|
||||
this should fail";
|
||||
var applicationEnvironment = GetApplicationEnvironment();
|
||||
var accessor = GetLoadContextAccessor();
|
||||
var libraryManager = GetLibraryManager();
|
||||
|
|
@ -67,17 +74,15 @@ public class MyTestType {}";
|
|||
applicationEnvironment.Configuration))
|
||||
.Returns(new CompilerOptions());
|
||||
var mvcRazorHost = Mock.Of<IMvcRazorHost>();
|
||||
var fileProvider = new TestFileProvider();
|
||||
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
|
||||
|
||||
var compilationService = new RoslynCompilationService(applicationEnvironment,
|
||||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost);
|
||||
var fileInfo = new TestFileInfo
|
||||
{
|
||||
Content = fileContent,
|
||||
PhysicalPath = "physical path"
|
||||
};
|
||||
mvcRazorHost,
|
||||
GetOptions(fileProvider));
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
|
||||
|
||||
// Act
|
||||
|
|
@ -86,12 +91,13 @@ public class MyTestType {}";
|
|||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
Assert.Equal(relativeFileInfo.RelativePath, result.CompilationFailure.SourceFilePath);
|
||||
Assert.Equal(fileContent, result.CompilationFailure.SourceFileContent);
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath);
|
||||
Assert.Equal(fileContent, compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsApplicationRelativePath_IfPhyicalPathIsNotSpecified()
|
||||
public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
|
||||
{
|
||||
// Arrange
|
||||
var fileContent = "file content";
|
||||
|
|
@ -111,7 +117,8 @@ public class MyTestType {}";
|
|||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost);
|
||||
mvcRazorHost,
|
||||
GetOptions());
|
||||
var relativeFileInfo = new RelativeFileInfo(new TestFileInfo { Content = fileContent },
|
||||
"some-relative-path");
|
||||
|
||||
|
|
@ -121,15 +128,20 @@ public class MyTestType {}";
|
|||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
Assert.Equal("some-relative-path", result.CompilationFailure.SourceFilePath);
|
||||
Assert.Equal(fileContent, result.CompilationFailure.SourceFileContent);
|
||||
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal("Generated Code", compilationFailure.SourceFilePath);
|
||||
Assert.Equal(content, compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_DoesNotThrow_IfFileCannotBeRead()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"this should fail";
|
||||
var path = "some-relative-path";
|
||||
var content = $@"
|
||||
#line 1 ""{path}""
|
||||
this should fail";
|
||||
var applicationEnvironment = GetApplicationEnvironment();
|
||||
var accessor = GetLoadContextAccessor();
|
||||
var libraryManager = GetLibraryManager();
|
||||
|
|
@ -141,15 +153,20 @@ public class MyTestType {}";
|
|||
.Returns(new CompilerOptions());
|
||||
var mvcRazorHost = Mock.Of<IMvcRazorHost>();
|
||||
|
||||
var mockFileInfo = new Mock<IFileInfo>();
|
||||
mockFileInfo.Setup(f => f.CreateReadStream())
|
||||
.Throws(new Exception());
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(path, mockFileInfo.Object);
|
||||
|
||||
var compilationService = new RoslynCompilationService(applicationEnvironment,
|
||||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost);
|
||||
var mockFileInfo = new Mock<IFileInfo>();
|
||||
mockFileInfo.Setup(f => f.CreateReadStream())
|
||||
.Throws(new Exception());
|
||||
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, "some-relative-path");
|
||||
mvcRazorHost,
|
||||
GetOptions(fileProvider));
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path);
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
|
@ -157,8 +174,9 @@ public class MyTestType {}";
|
|||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
Assert.Equal("some-relative-path", result.CompilationFailure.SourceFilePath);
|
||||
Assert.Null(result.CompilationFailure.SourceFileContent);
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal(path, compilationFailure.SourceFilePath);
|
||||
Assert.Null(compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -189,7 +207,8 @@ public class MyNonCustomDefinedClass {}
|
|||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost.Object);
|
||||
mvcRazorHost.Object,
|
||||
GetOptions());
|
||||
var relativeFileInfo = new RelativeFileInfo(new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
|
|
@ -225,7 +244,8 @@ public class NotRazorPrefixType {}";
|
|||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost.Object);
|
||||
mvcRazorHost.Object,
|
||||
GetOptions());
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
|
@ -238,6 +258,113 @@ public class NotRazorPrefixType {}";
|
|||
Assert.Equal("RazorPrefixType", result.CompiledType.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCompilationFailedResult_ReturnsCompilationResult_WithGroupedMessages()
|
||||
{
|
||||
// Arrange
|
||||
var viewPath = "Views/Home/Index";
|
||||
var generatedCodeFileName = "Generated Code";
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(viewPath, "view-content");
|
||||
var options = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||
options.SetupGet(o => o.Options)
|
||||
.Returns(new RazorViewEngineOptions
|
||||
{
|
||||
FileProvider = fileProvider
|
||||
});
|
||||
var compilationService = new RoslynCompilationService(
|
||||
GetApplicationEnvironment(),
|
||||
GetLoadContextAccessor(),
|
||||
GetLibraryManager(),
|
||||
Mock.Of<ICompilerOptionsProvider>(),
|
||||
Mock.Of<IMvcRazorHost>(),
|
||||
options.Object);
|
||||
|
||||
var assemblyName = "random-assembly-name";
|
||||
|
||||
var diagnostics = new[]
|
||||
{
|
||||
Diagnostic.Create(
|
||||
GetDiagnosticDescriptor("message-1"),
|
||||
Location.Create(
|
||||
viewPath,
|
||||
new TextSpan(10, 5),
|
||||
new LinePositionSpan(new LinePosition(10, 1), new LinePosition(10, 2)))),
|
||||
Diagnostic.Create(
|
||||
GetDiagnosticDescriptor("message-2"),
|
||||
Location.Create(
|
||||
assemblyName,
|
||||
new TextSpan(1, 6),
|
||||
new LinePositionSpan(new LinePosition(1, 2), new LinePosition(3, 4)))),
|
||||
Diagnostic.Create(
|
||||
GetDiagnosticDescriptor("message-3"),
|
||||
Location.Create(
|
||||
viewPath,
|
||||
new TextSpan(40, 50),
|
||||
new LinePositionSpan(new LinePosition(30, 5), new LinePosition(40, 12)))),
|
||||
};
|
||||
|
||||
// Act
|
||||
var compilationResult = compilationService.GetCompilationFailedResult(
|
||||
viewPath,
|
||||
"compilation-content",
|
||||
assemblyName,
|
||||
diagnostics);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(compilationResult.CompilationFailures,
|
||||
failure =>
|
||||
{
|
||||
Assert.Equal(viewPath, failure.SourceFilePath);
|
||||
Assert.Equal("view-content", failure.SourceFileContent);
|
||||
Assert.Collection(failure.Messages,
|
||||
message =>
|
||||
{
|
||||
Assert.Equal("message-1", message.Message);
|
||||
Assert.Equal(viewPath, message.SourceFilePath);
|
||||
Assert.Equal(11, message.StartLine);
|
||||
Assert.Equal(2, message.StartColumn);
|
||||
Assert.Equal(11, message.EndLine);
|
||||
Assert.Equal(3, message.EndColumn);
|
||||
},
|
||||
message =>
|
||||
{
|
||||
Assert.Equal("message-3", message.Message);
|
||||
Assert.Equal(viewPath, message.SourceFilePath);
|
||||
Assert.Equal(31, message.StartLine);
|
||||
Assert.Equal(6, message.StartColumn);
|
||||
Assert.Equal(41, message.EndLine);
|
||||
Assert.Equal(13, message.EndColumn);
|
||||
});
|
||||
},
|
||||
failure =>
|
||||
{
|
||||
Assert.Equal(generatedCodeFileName, failure.SourceFilePath);
|
||||
Assert.Equal("compilation-content", failure.SourceFileContent);
|
||||
Assert.Collection(failure.Messages,
|
||||
message =>
|
||||
{
|
||||
Assert.Equal("message-2", message.Message);
|
||||
Assert.Equal(assemblyName, message.SourceFilePath);
|
||||
Assert.Equal(2, message.StartLine);
|
||||
Assert.Equal(3, message.StartColumn);
|
||||
Assert.Equal(4, message.EndLine);
|
||||
Assert.Equal(5, message.EndColumn);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static DiagnosticDescriptor GetDiagnosticDescriptor(string messageFormat)
|
||||
{
|
||||
return new DiagnosticDescriptor(
|
||||
id: "someid",
|
||||
title: "sometitle",
|
||||
messageFormat: messageFormat,
|
||||
category: "some-category",
|
||||
defaultSeverity: DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true);
|
||||
}
|
||||
|
||||
private static ILibraryManager GetLibraryManager()
|
||||
{
|
||||
var fileReference = new Mock<IMetadataFileReference>();
|
||||
|
|
@ -285,5 +412,18 @@ public class NotRazorPrefixType {}";
|
|||
|
||||
return applicationEnvironment.Object;
|
||||
}
|
||||
|
||||
private static IOptions<RazorViewEngineOptions> GetOptions(IFileProvider fileProvider = null)
|
||||
{
|
||||
var razorViewEngineOptions = new RazorViewEngineOptions
|
||||
{
|
||||
FileProvider = fileProvider ?? new TestFileProvider()
|
||||
};
|
||||
var options = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||
options.SetupGet(o => o.Options)
|
||||
.Returns(razorViewEngineOptions);
|
||||
|
||||
return options.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void AddFile(string path, string contents)
|
||||
public TestFileInfo AddFile(string path, string contents)
|
||||
{
|
||||
var fileInfo = new TestFileInfo
|
||||
{
|
||||
|
|
@ -32,6 +32,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
};
|
||||
|
||||
AddFile(path, fileInfo);
|
||||
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
public void AddFile(string path, IFileInfo contents)
|
||||
|
|
|
|||
|
|
@ -18,5 +18,11 @@ namespace ErrorPageMiddlewareWebSite
|
|||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet("/ErrorFromGlobalImport")]
|
||||
public IActionResult GlobalImportError()
|
||||
{
|
||||
return View("~/Views/ErrorFromGlobalImport/Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<h1>Hello world!</h1>
|
||||
|
|
@ -0,0 +1 @@
|
|||
@using NamespaceDoesNotExist
|
||||
Loading…
Reference in New Issue