* Moving DNX dependencies to test only
* Updating Mvc tests to use dotnet test to run on dnxcore50
This commit is contained in:
parent
c259f82615
commit
80b6996701
|
|
@ -58,14 +58,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
// To enable unit testing
|
||||
internal static void AddMvcCoreServices(IServiceCollection services)
|
||||
{
|
||||
//
|
||||
// RuntimeServices
|
||||
//
|
||||
if (DnxPlatformServices.Default?.LibraryManager != null)
|
||||
{
|
||||
services.TryAddSingleton(DnxPlatformServices.Default.LibraryManager);
|
||||
}
|
||||
|
||||
//
|
||||
// Options
|
||||
//
|
||||
|
|
@ -78,14 +70,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
// Action Discovery
|
||||
//
|
||||
// These are consumed only when creating action descriptors, then they can be de-allocated
|
||||
if (DnxPlatformServices.Default?.LibraryManager != null)
|
||||
{
|
||||
services.TryAddTransient<IAssemblyProvider, DefaultAssemblyProvider>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.TryAddTransient<IAssemblyProvider, DependencyContextAssemblyProvider>();
|
||||
}
|
||||
services.TryAddTransient<IAssemblyProvider, DefaultAssemblyProvider>();
|
||||
|
||||
services.TryAddTransient<IControllerTypeProvider, DefaultControllerTypeProvider>();
|
||||
services.TryAddEnumerable(
|
||||
|
|
|
|||
|
|
@ -6,17 +6,27 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IAssemblyProvider"/> that uses <see cref="DependencyContext"/> to discover assemblies that may
|
||||
/// contain Mvc specific types such as controllers, and view components.
|
||||
/// </summary>
|
||||
public class DefaultAssemblyProvider : IAssemblyProvider
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly DependencyContext _dependencyContext;
|
||||
|
||||
public DefaultAssemblyProvider(ILibraryManager libraryManager)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DefaultAssemblyProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="environment">The <see cref="IApplicationEnvironment"/>.</param>
|
||||
public DefaultAssemblyProvider(IApplicationEnvironment environment)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName));
|
||||
_dependencyContext = DependencyContext.Load(applicationAssembly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -49,8 +59,9 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
{
|
||||
get
|
||||
{
|
||||
return GetCandidateLibraries().SelectMany(l => l.Assemblies)
|
||||
.Select(Load);
|
||||
return GetCandidateLibraries()
|
||||
.SelectMany(l => l.Assemblies)
|
||||
.Select(Load);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,29 +71,25 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
/// while ignoring MVC assemblies.
|
||||
/// </summary>
|
||||
/// <returns>A set of <see cref="Library"/>.</returns>
|
||||
protected virtual IEnumerable<Library> GetCandidateLibraries()
|
||||
protected virtual IEnumerable<RuntimeLibrary> GetCandidateLibraries()
|
||||
{
|
||||
if (ReferenceAssemblies == null)
|
||||
{
|
||||
return Enumerable.Empty<Library>();
|
||||
return Enumerable.Empty<RuntimeLibrary>();
|
||||
}
|
||||
|
||||
// GetReferencingLibraries returns the transitive closure of referencing assemblies
|
||||
// for a given assembly.
|
||||
return ReferenceAssemblies.SelectMany(_libraryManager.GetReferencingLibraries)
|
||||
.Distinct()
|
||||
.Where(IsCandidateLibrary);
|
||||
return DependencyContext.Default.RuntimeLibraries.Where(IsCandidateLibrary);
|
||||
}
|
||||
|
||||
private static Assembly Load(AssemblyName assemblyName)
|
||||
private static Assembly Load(RuntimeAssembly assembly)
|
||||
{
|
||||
return Assembly.Load(assemblyName);
|
||||
return Assembly.Load(assembly.Name);
|
||||
}
|
||||
|
||||
private bool IsCandidateLibrary(Library library)
|
||||
private bool IsCandidateLibrary(RuntimeLibrary library)
|
||||
{
|
||||
Debug.Assert(ReferenceAssemblies != null);
|
||||
return !ReferenceAssemblies.Contains(library.Name);
|
||||
return library.Dependencies.Any(dependency => ReferenceAssemblies.Contains(dependency.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IAssemblyProvider"/> that uses <see cref="DependencyContext"/> to discover assemblies that may
|
||||
/// contain Mvc specific types such as controllers, and view components.
|
||||
/// </summary>
|
||||
public class DependencyContextAssemblyProvider : IAssemblyProvider
|
||||
{
|
||||
private readonly DependencyContext _dependencyContext;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DependencyContextAssemblyProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="environment">The <see cref="IApplicationEnvironment"/>.</param>
|
||||
public DependencyContextAssemblyProvider(IApplicationEnvironment environment)
|
||||
{
|
||||
var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName));
|
||||
_dependencyContext = DependencyContext.Load(applicationAssembly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the set of assembly names that are used as root for discovery of
|
||||
/// MVC controllers, view components and views.
|
||||
/// </summary>
|
||||
// DefaultControllerTypeProvider uses CandidateAssemblies to determine if the base type of a POCO controller
|
||||
// lives in an assembly that references MVC. CandidateAssemblies excludes all assemblies from the
|
||||
// ReferenceAssemblies set. Consequently adding WebApiCompatShim to this set would cause the ApiController to
|
||||
// fail this test.
|
||||
protected virtual HashSet<string> ReferenceAssemblies { get; } = new HashSet<string>(StringComparer.Ordinal)
|
||||
{
|
||||
"Microsoft.AspNetCore.Mvc",
|
||||
"Microsoft.AspNetCore.Mvc.Abstractions",
|
||||
"Microsoft.AspNetCore.Mvc.ApiExplorer",
|
||||
"Microsoft.AspNetCore.Mvc.Core",
|
||||
"Microsoft.AspNetCore.Mvc.Cors",
|
||||
"Microsoft.AspNetCore.Mvc.DataAnnotations",
|
||||
"Microsoft.AspNetCore.Mvc.Formatters.Json",
|
||||
"Microsoft.AspNetCore.Mvc.Formatters.Xml",
|
||||
"Microsoft.AspNetCore.Mvc.Localization",
|
||||
"Microsoft.AspNetCore.Mvc.Razor",
|
||||
"Microsoft.AspNetCore.Mvc.Razor.Host",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers",
|
||||
"Microsoft.AspNetCore.Mvc.ViewFeatures"
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Assembly> CandidateAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetCandidateLibraries()
|
||||
.SelectMany(l => l.Assemblies)
|
||||
.Select(Load);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of libraries that references the assemblies in <see cref="ReferenceAssemblies"/>.
|
||||
/// By default it returns all assemblies that reference any of the primary MVC assemblies
|
||||
/// while ignoring MVC assemblies.
|
||||
/// </summary>
|
||||
/// <returns>A set of <see cref="Library"/>.</returns>
|
||||
protected virtual IEnumerable<RuntimeLibrary> GetCandidateLibraries()
|
||||
{
|
||||
if (ReferenceAssemblies == null)
|
||||
{
|
||||
return Enumerable.Empty<RuntimeLibrary>();
|
||||
}
|
||||
|
||||
return DependencyContext.Default.RuntimeLibraries.Where(IsCandidateLibrary);
|
||||
}
|
||||
|
||||
private static Assembly Load(RuntimeAssembly assembly)
|
||||
{
|
||||
return Assembly.Load(assembly.Name);
|
||||
}
|
||||
|
||||
private bool IsCandidateLibrary(RuntimeLibrary library)
|
||||
{
|
||||
Debug.Assert(ReferenceAssemblies != null);
|
||||
return library.Dependencies.Any(dependency => ReferenceAssemblies.Contains(dependency.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
|
||||
"Microsoft.Extensions.PlatformAbstractions.Dnx": "1.0.0-*",
|
||||
"Microsoft.Extensions.DependencyModel": "1.0.0-*",
|
||||
"Microsoft.Extensions.ClosedGenericMatcher.Sources": {
|
||||
"version": "1.0.0-*",
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
"Microsoft.Extensions.PropertyHelper.Sources": {
|
||||
"version": "1.0.0-*",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
|
|
@ -12,7 +10,6 @@ using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
|||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
|
@ -94,30 +91,22 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
// Internal for testing.
|
||||
internal static void AddRazorViewEngineServices(IServiceCollection services)
|
||||
{
|
||||
var compilationServicesAvailible = CompilationServices.Default != null;
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<
|
||||
IConfigureOptions<RazorViewEngineOptions>,
|
||||
DependencyContextRazorViewEngineOptionsSetup>());
|
||||
|
||||
if (compilationServicesAvailible)
|
||||
{
|
||||
services.TryAddSingleton(CompilationServices.Default.LibraryExporter);
|
||||
|
||||
// This caches compilation related details that are valid across the lifetime of the application.
|
||||
services.TryAddSingleton<ICompilationService, DefaultRoslynCompilationService>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<RazorViewEngineOptions>, DependencyContextRazorViewEngineOptionsSetup>());
|
||||
|
||||
// This caches compilation related details that are valid across the lifetime of the application.
|
||||
services.TryAddSingleton<ICompilationService, DependencyContextCompilationService>();
|
||||
}
|
||||
// This caches compilation related details that are valid across the lifetime of the application.
|
||||
services.TryAddSingleton<ICompilationService, DefaultRoslynCompilationService>();
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcRazorMvcViewOptionsSetup>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>());
|
||||
|
||||
services.TryAddSingleton<IRazorViewEngineFileProviderAccessor, DefaultRazorViewEngineFileProviderAccessor>();
|
||||
services.TryAddSingleton<
|
||||
IRazorViewEngineFileProviderAccessor,
|
||||
DefaultRazorViewEngineFileProviderAccessor>();
|
||||
|
||||
services.TryAddSingleton<IRazorViewEngine, RazorViewEngine>();
|
||||
|
||||
|
|
@ -144,11 +133,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
// Consumed by the Cache tag helper to cache results across the lifetime of the application.
|
||||
services.TryAddSingleton<IMemoryCache, MemoryCache>();
|
||||
|
||||
if (DnxPlatformServices.Default?.AssemblyLoadContextAccessor != null)
|
||||
{
|
||||
services.TryAddSingleton(DnxPlatformServices.Default.AssemblyLoadContextAccessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
// 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 Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="ICompilerOptionsProvider"/>.
|
||||
/// </summary>
|
||||
public static class CompilationOptionsProviderExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses the <see cref="ICompilerOptions"/> for the current executing application and returns a
|
||||
/// <see cref="CompilationSettings"/> used for Roslyn compilation.
|
||||
/// </summary>
|
||||
/// <param name="compilerOptionsProvider">
|
||||
/// A <see cref="ICompilerOptionsProvider"/> that reads compiler options.
|
||||
/// </param>
|
||||
/// <param name="applicationEnvironment">
|
||||
/// The <see cref="IApplicationEnvironment"/> for the executing application.
|
||||
/// </param>
|
||||
/// <param name="configuration">
|
||||
/// The configuration name to use for compilation.
|
||||
/// </param>
|
||||
/// <returns>The <see cref="CompilationSettings"/> for the current application.</returns>
|
||||
public static CompilationSettings GetCompilationSettings(
|
||||
this ICompilerOptionsProvider compilerOptionsProvider,
|
||||
IApplicationEnvironment applicationEnvironment,
|
||||
string configuration)
|
||||
{
|
||||
if (compilerOptionsProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(compilerOptionsProvider));
|
||||
}
|
||||
|
||||
if (applicationEnvironment == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(applicationEnvironment));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(configuration))
|
||||
{
|
||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(configuration));
|
||||
}
|
||||
|
||||
return compilerOptionsProvider.GetCompilerOptions(
|
||||
applicationEnvironment.ApplicationName,
|
||||
applicationEnvironment.RuntimeFramework,
|
||||
configuration)
|
||||
.ToCompilationSettings(applicationEnvironment.RuntimeFramework, applicationEnvironment.ApplicationBasePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,25 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.PortableExecutable;
|
||||
#if DOTNET5_6
|
||||
using System.Runtime.Loader;
|
||||
#endif
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
|
@ -15,107 +28,293 @@ using Microsoft.Extensions.PlatformAbstractions;
|
|||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A type that uses Roslyn to compile C# content and <see cref="ILibraryExporter"/> to find out references.
|
||||
/// A type that uses Roslyn to compile C# content.
|
||||
/// </summary>
|
||||
public class DefaultRoslynCompilationService : RoslynCompilationService
|
||||
public class DefaultRoslynCompilationService : ICompilationService
|
||||
{
|
||||
private readonly Lazy<bool> _supportsPdbGeneration = new Lazy<bool>(SymbolsUtility.SupportsSymbolsGeneration);
|
||||
private readonly ConcurrentDictionary<string, AssemblyMetadata> _metadataFileCache =
|
||||
new ConcurrentDictionary<string, AssemblyMetadata>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly IApplicationEnvironment _environment;
|
||||
private readonly ILibraryExporter _libraryExporter;
|
||||
private readonly IFileProvider _fileProvider;
|
||||
private readonly Lazy<List<MetadataReference>> _applicationReferences;
|
||||
private readonly string _classPrefix;
|
||||
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
||||
private readonly CSharpParseOptions _parseOptions;
|
||||
private readonly CSharpCompilationOptions _compilationOptions;
|
||||
private readonly ILogger _logger;
|
||||
private readonly DependencyContext _dependencyContext;
|
||||
|
||||
#if DOTNET5_6
|
||||
private readonly RazorLoadContext _razorLoadContext;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="environment">The environment for the executing application.</param>
|
||||
/// <param name="libraryExporter">The library manager that provides export and reference information.</param>
|
||||
/// <param name="host">The <see cref="IMvcRazorHost"/> that was used to generate the code.</param>
|
||||
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
||||
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public DefaultRoslynCompilationService(IApplicationEnvironment environment,
|
||||
ILibraryExporter libraryExporter,
|
||||
public DefaultRoslynCompilationService(
|
||||
IApplicationEnvironment environment,
|
||||
IMvcRazorHost host,
|
||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
|
||||
ILoggerFactory loggerFactory)
|
||||
: base(environment, host, optionsAccessor, fileProviderAccessor, loggerFactory)
|
||||
{
|
||||
_environment = environment;
|
||||
_libraryExporter = libraryExporter;
|
||||
_applicationReferences = new Lazy<List<MetadataReference>>(GetApplicationReferences);
|
||||
_fileProvider = fileProviderAccessor.FileProvider;
|
||||
_classPrefix = host.MainClassNamePrefix;
|
||||
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
||||
_parseOptions = optionsAccessor.Value.ParseOptions;
|
||||
_compilationOptions = optionsAccessor.Value.CompilationOptions;
|
||||
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
||||
|
||||
#if DOTNET5_6
|
||||
_razorLoadContext = new RazorLoadContext();
|
||||
#endif
|
||||
|
||||
var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName));
|
||||
_dependencyContext = DependencyContext.Load(applicationAssembly);
|
||||
}
|
||||
|
||||
protected override List<MetadataReference> GetApplicationReferences()
|
||||
/// <inheritdoc />
|
||||
public CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent)
|
||||
{
|
||||
var references = new List<MetadataReference>();
|
||||
|
||||
// Get the MetadataReference for the executing application. If it's a Roslyn reference,
|
||||
// we can copy the references created when compiling the application to the Razor page being compiled.
|
||||
// This avoids performing expensive calls to MetadataReference.CreateFromImage.
|
||||
var libraryExport = _libraryExporter.GetExport(_environment.ApplicationName);
|
||||
if (libraryExport?.MetadataReferences != null && libraryExport.MetadataReferences.Count > 0)
|
||||
if (fileInfo == null)
|
||||
{
|
||||
Debug.Assert(libraryExport.MetadataReferences.Count == 1,
|
||||
"Expected 1 MetadataReferences, found " + libraryExport.MetadataReferences.Count);
|
||||
var roslynReference = libraryExport.MetadataReferences[0] as IRoslynMetadataReference;
|
||||
var compilationReference = roslynReference?.MetadataReference as CompilationReference;
|
||||
if (compilationReference != null)
|
||||
{
|
||||
references.AddRange(compilationReference.Compilation.References);
|
||||
references.Add(roslynReference.MetadataReference);
|
||||
return references;
|
||||
}
|
||||
throw new ArgumentNullException(nameof(fileInfo));
|
||||
}
|
||||
|
||||
var export = _libraryExporter.GetAllExports(_environment.ApplicationName);
|
||||
if (export != null)
|
||||
if (compilationContent == null)
|
||||
{
|
||||
foreach (var metadataReference in export.MetadataReferences)
|
||||
{
|
||||
// Taken from https://github.com/aspnet/KRuntime/blob/757ba9bfdf80bd6277e715d6375969a7f44370ee/src/...
|
||||
// Microsoft.Extensions.Runtime.Roslyn/RoslynCompiler.cs#L164
|
||||
// We don't want to take a dependency on the Roslyn bit directly since it pulls in more dependencies
|
||||
// than the view engine needs (Microsoft.Extensions.Runtime) for example
|
||||
references.Add(ConvertMetadataReference(metadataReference));
|
||||
}
|
||||
throw new ArgumentNullException(nameof(compilationContent));
|
||||
}
|
||||
|
||||
return references;
|
||||
_logger.GeneratedCodeToAssemblyCompilationStart(fileInfo.RelativePath);
|
||||
|
||||
var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;
|
||||
|
||||
var assemblyName = Path.GetRandomFileName();
|
||||
|
||||
var sourceText = SourceText.From(compilationContent, Encoding.UTF8);
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(
|
||||
sourceText,
|
||||
path: assemblyName,
|
||||
options: _parseOptions);
|
||||
|
||||
var references = _applicationReferences.Value;
|
||||
|
||||
var compilation = CSharpCompilation.Create(
|
||||
assemblyName,
|
||||
options: _compilationOptions,
|
||||
syntaxTrees: new[] { syntaxTree },
|
||||
references: references);
|
||||
|
||||
compilation = Rewrite(compilation);
|
||||
|
||||
var compilationContext = new RoslynCompilationContext(compilation);
|
||||
_compilationCallback(compilationContext);
|
||||
compilation = compilationContext.Compilation;
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var pdb = new MemoryStream())
|
||||
{
|
||||
EmitResult result;
|
||||
|
||||
if (_supportsPdbGeneration.Value)
|
||||
{
|
||||
result = compilation.Emit(ms, pdbStream: pdb);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = compilation.Emit(ms);
|
||||
}
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
return GetCompilationFailedResult(
|
||||
fileInfo.RelativePath,
|
||||
compilationContent,
|
||||
assemblyName,
|
||||
result.Diagnostics);
|
||||
}
|
||||
|
||||
Assembly assembly;
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
if (_supportsPdbGeneration.Value)
|
||||
{
|
||||
pdb.Seek(0, SeekOrigin.Begin);
|
||||
assembly = LoadStream(ms, pdb);
|
||||
}
|
||||
else
|
||||
{
|
||||
assembly = LoadStream(ms, assemblySymbols: null);
|
||||
}
|
||||
|
||||
var type = assembly
|
||||
.GetExportedTypes()
|
||||
.First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));
|
||||
|
||||
_logger.GeneratedCodeToAssemblyCompilationEnd(fileInfo.RelativePath, startTimestamp);
|
||||
|
||||
return new CompilationResult(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MetadataReference ConvertMetadataReference(IMetadataReference metadataReference)
|
||||
private Assembly LoadStream(MemoryStream ms, MemoryStream assemblySymbols)
|
||||
{
|
||||
var roslynReference = metadataReference as IRoslynMetadataReference;
|
||||
#if NET451
|
||||
return Assembly.Load(ms.ToArray(), assemblySymbols?.ToArray());
|
||||
#else
|
||||
return _razorLoadContext.Load(ms, assemblySymbols);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (roslynReference != null)
|
||||
private CSharpCompilation Rewrite(CSharpCompilation compilation)
|
||||
{
|
||||
var rewrittenTrees = new List<SyntaxTree>();
|
||||
foreach (var tree in compilation.SyntaxTrees)
|
||||
{
|
||||
return roslynReference.MetadataReference;
|
||||
var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
|
||||
var rewriter = new ExpressionRewriter(semanticModel);
|
||||
|
||||
var rewrittenTree = tree.WithRootAndOptions(rewriter.Visit(tree.GetRoot()), tree.Options);
|
||||
rewrittenTrees.Add(rewrittenTree);
|
||||
}
|
||||
|
||||
var embeddedReference = metadataReference as IMetadataEmbeddedReference;
|
||||
return compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(rewrittenTrees);
|
||||
}
|
||||
|
||||
if (embeddedReference != null)
|
||||
private 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<CompilationFailure>();
|
||||
foreach (var group in diagnosticGroups)
|
||||
{
|
||||
return MetadataReference.CreateFromImage(embeddedReference.Contents);
|
||||
}
|
||||
|
||||
var fileMetadataReference = metadataReference as IMetadataFileReference;
|
||||
|
||||
if (fileMetadataReference != null)
|
||||
{
|
||||
return CreateMetadataFileReference(fileMetadataReference.Path);
|
||||
}
|
||||
|
||||
var projectReference = metadataReference as IMetadataProjectReference;
|
||||
if (projectReference != null)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
var sourceFilePath = group.Key;
|
||||
string sourceFileContent;
|
||||
if (string.Equals(assemblyName, sourceFilePath, StringComparison.Ordinal))
|
||||
{
|
||||
projectReference.EmitReferenceAssembly(ms);
|
||||
// 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);
|
||||
}
|
||||
|
||||
return MetadataReference.CreateFromImage(ms.ToArray());
|
||||
var compilationFailure = new CompilationFailure(
|
||||
sourceFilePath,
|
||||
sourceFileContent,
|
||||
compilationContent,
|
||||
group.Select(GetDiagnosticMessage));
|
||||
|
||||
failures.Add(compilationFailure);
|
||||
}
|
||||
|
||||
return new CompilationResult(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()
|
||||
{
|
||||
return _dependencyContext.CompileLibraries
|
||||
.SelectMany(library => library.ResolveReferencePaths())
|
||||
.Select(CreateMetadataFileReference)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private MetadataReference CreateMetadataFileReference(string path)
|
||||
{
|
||||
var metadata = _metadataFileCache.GetOrAdd(path, _ =>
|
||||
{
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
|
||||
return AssemblyMetadata.Create(moduleMetadata);
|
||||
}
|
||||
});
|
||||
|
||||
return metadata.GetReference(filePath: path);
|
||||
}
|
||||
|
||||
private static bool IsError(Diagnostic diagnostic)
|
||||
{
|
||||
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
|
||||
}
|
||||
|
||||
private static string ReadFileContentsSafely(IFileProvider fileProvider, string filePath)
|
||||
{
|
||||
var fileInfo = fileProvider.GetFileInfo(filePath);
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any failures
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DiagnosticMessage GetDiagnosticMessage(Diagnostic diagnostic)
|
||||
{
|
||||
var mappedLineSpan = diagnostic.Location.GetMappedLineSpan();
|
||||
return new DiagnosticMessage(
|
||||
diagnostic.GetMessage(),
|
||||
CSharpDiagnosticFormatter.Instance.Format(diagnostic),
|
||||
mappedLineSpan.Path,
|
||||
mappedLineSpan.StartLinePosition.Line + 1,
|
||||
mappedLineSpan.StartLinePosition.Character + 1,
|
||||
mappedLineSpan.EndLinePosition.Line + 1,
|
||||
mappedLineSpan.EndLinePosition.Character + 1);
|
||||
}
|
||||
|
||||
#if DOTNET5_6
|
||||
private class RazorLoadContext : AssemblyLoadContext
|
||||
{
|
||||
protected override Assembly Load(AssemblyName assemblyName)
|
||||
{
|
||||
return Default.LoadFromAssemblyName(assemblyName);
|
||||
}
|
||||
|
||||
public Assembly Load(Stream assembly, Stream assemblySymbols)
|
||||
{
|
||||
return LoadFromStream(assembly, assemblySymbols);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A type that uses Roslyn to compile C# content and <see cref="DependencyContext"/> to locate references.
|
||||
/// </summary>
|
||||
public class DependencyContextCompilationService : RoslynCompilationService
|
||||
{
|
||||
private readonly DependencyContext _dependencyContext;
|
||||
|
||||
/// <summary>
|
||||
/// Initalizes a new instance of the <see cref="DependencyContextCompilationService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="environment">The environment for the executing application.</param>
|
||||
/// <param name="host">The <see cref="IMvcRazorHost"/> that was used to generate the code.</param>
|
||||
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
||||
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public DependencyContextCompilationService(
|
||||
IApplicationEnvironment environment,
|
||||
IMvcRazorHost host,
|
||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
|
||||
ILoggerFactory loggerFactory)
|
||||
: base(environment, host, optionsAccessor, fileProviderAccessor, loggerFactory)
|
||||
{
|
||||
var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName));
|
||||
_dependencyContext = DependencyContext.Load(applicationAssembly);
|
||||
}
|
||||
|
||||
protected override List<MetadataReference> GetApplicationReferences()
|
||||
{
|
||||
return _dependencyContext.CompileLibraries
|
||||
.SelectMany(library => library.ResolveReferencePaths())
|
||||
.Select(CreateMetadataFileReference)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
// 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.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.PortableExecutable;
|
||||
#if DOTNET5_6
|
||||
using System.Runtime.Loader;
|
||||
#endif
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A type that uses Roslyn to compile C# content.
|
||||
/// </summary>
|
||||
public abstract class RoslynCompilationService : ICompilationService
|
||||
{
|
||||
private readonly Lazy<bool> _supportsPdbGeneration = new Lazy<bool>(SymbolsUtility.SupportsSymbolsGeneration);
|
||||
private readonly ConcurrentDictionary<string, AssemblyMetadata> _metadataFileCache =
|
||||
new ConcurrentDictionary<string, AssemblyMetadata>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly IApplicationEnvironment _environment;
|
||||
private readonly IFileProvider _fileProvider;
|
||||
private readonly Lazy<List<MetadataReference>> _applicationReferences;
|
||||
private readonly string _classPrefix;
|
||||
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
||||
private readonly CSharpParseOptions _parseOptions;
|
||||
private readonly CSharpCompilationOptions _compilationOptions;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#if DOTNET5_6
|
||||
private readonly RazorLoadContext _razorLoadContext;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initalizes a new instance of the <see cref="RoslynCompilationService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="environment">The environment for the executing application.</param>
|
||||
/// <param name="host">The <see cref="IMvcRazorHost"/> that was used to generate the code.</param>
|
||||
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
||||
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public RoslynCompilationService(
|
||||
IApplicationEnvironment environment,
|
||||
IMvcRazorHost host,
|
||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_environment = environment;
|
||||
_applicationReferences = new Lazy<List<MetadataReference>>(GetApplicationReferences);
|
||||
_fileProvider = fileProviderAccessor.FileProvider;
|
||||
_classPrefix = host.MainClassNamePrefix;
|
||||
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
||||
_parseOptions = optionsAccessor.Value.ParseOptions;
|
||||
_compilationOptions = optionsAccessor.Value.CompilationOptions;
|
||||
_logger = loggerFactory.CreateLogger<RoslynCompilationService>();
|
||||
|
||||
#if DOTNET5_6
|
||||
_razorLoadContext = new RazorLoadContext();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent)
|
||||
{
|
||||
if (fileInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileInfo));
|
||||
}
|
||||
|
||||
if (compilationContent == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(compilationContent));
|
||||
}
|
||||
|
||||
_logger.GeneratedCodeToAssemblyCompilationStart(fileInfo.RelativePath);
|
||||
|
||||
var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;
|
||||
|
||||
var assemblyName = Path.GetRandomFileName();
|
||||
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(
|
||||
compilationContent,
|
||||
assemblyName,
|
||||
_parseOptions);
|
||||
|
||||
var references = _applicationReferences.Value;
|
||||
|
||||
var compilation = CSharpCompilation.Create(
|
||||
assemblyName,
|
||||
options: _compilationOptions,
|
||||
syntaxTrees: new[] { syntaxTree },
|
||||
references: references);
|
||||
|
||||
compilation = Rewrite(compilation);
|
||||
|
||||
var compilationContext = new RoslynCompilationContext(compilation);
|
||||
_compilationCallback(compilationContext);
|
||||
compilation = compilationContext.Compilation;
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var pdb = new MemoryStream())
|
||||
{
|
||||
EmitResult result;
|
||||
|
||||
if (_supportsPdbGeneration.Value)
|
||||
{
|
||||
result = compilation.Emit(ms, pdbStream: pdb);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = compilation.Emit(ms);
|
||||
}
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
return GetCompilationFailedResult(
|
||||
fileInfo.RelativePath,
|
||||
compilationContent,
|
||||
assemblyName,
|
||||
result.Diagnostics);
|
||||
}
|
||||
|
||||
Assembly assembly;
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
if (_supportsPdbGeneration.Value)
|
||||
{
|
||||
pdb.Seek(0, SeekOrigin.Begin);
|
||||
assembly = LoadStream(ms, pdb);
|
||||
}
|
||||
else
|
||||
{
|
||||
assembly = LoadStream(ms, assemblySymbols: null);
|
||||
}
|
||||
|
||||
var type = assembly
|
||||
.GetExportedTypes()
|
||||
.First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));
|
||||
|
||||
_logger.GeneratedCodeToAssemblyCompilationEnd(fileInfo.RelativePath, startTimestamp);
|
||||
|
||||
return new CompilationResult(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Assembly LoadStream(MemoryStream ms, MemoryStream assemblySymbols)
|
||||
{
|
||||
#if NET451
|
||||
return Assembly.Load(ms.ToArray(), assemblySymbols?.ToArray());
|
||||
#else
|
||||
return _razorLoadContext.Load(ms, assemblySymbols);
|
||||
#endif
|
||||
}
|
||||
|
||||
private CSharpCompilation Rewrite(CSharpCompilation compilation)
|
||||
{
|
||||
var rewrittenTrees = new List<SyntaxTree>();
|
||||
foreach (var tree in compilation.SyntaxTrees)
|
||||
{
|
||||
var semanticModel = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
|
||||
var rewriter = new ExpressionRewriter(semanticModel);
|
||||
|
||||
var rewrittenTree = tree.WithRootAndOptions(rewriter.Visit(tree.GetRoot()), tree.Options);
|
||||
rewrittenTrees.Add(rewrittenTree);
|
||||
}
|
||||
|
||||
return compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(rewrittenTrees);
|
||||
}
|
||||
|
||||
// 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<CompilationFailure>();
|
||||
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 CompilationFailure(
|
||||
sourceFilePath,
|
||||
sourceFileContent,
|
||||
compilationContent,
|
||||
group.Select(diagnostic => GetDiagnosticMessage(diagnostic, _environment.RuntimeFramework)));
|
||||
|
||||
failures.Add(compilationFailure);
|
||||
}
|
||||
|
||||
return new CompilationResult(failures);
|
||||
}
|
||||
|
||||
private static string GetFilePath(string relativePath, Diagnostic diagnostic)
|
||||
{
|
||||
if (diagnostic.Location == Location.None)
|
||||
{
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
return diagnostic.Location.GetMappedLineSpan().Path;
|
||||
}
|
||||
|
||||
protected abstract List<MetadataReference> GetApplicationReferences();
|
||||
|
||||
protected MetadataReference CreateMetadataFileReference(string path)
|
||||
{
|
||||
var metadata = _metadataFileCache.GetOrAdd(path, _ =>
|
||||
{
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
|
||||
return AssemblyMetadata.Create(moduleMetadata);
|
||||
}
|
||||
});
|
||||
|
||||
return metadata.GetReference(filePath: path);
|
||||
}
|
||||
|
||||
private static bool IsError(Diagnostic diagnostic)
|
||||
{
|
||||
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
|
||||
}
|
||||
|
||||
private static string ReadFileContentsSafely(IFileProvider fileProvider, string filePath)
|
||||
{
|
||||
var fileInfo = fileProvider.GetFileInfo(filePath);
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any failures
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DiagnosticMessage GetDiagnosticMessage(Diagnostic diagnostic, FrameworkName targetFramework)
|
||||
{
|
||||
var mappedLineSpan = diagnostic.Location.GetMappedLineSpan();
|
||||
return new DiagnosticMessage(
|
||||
diagnostic.GetMessage(),
|
||||
RoslynDiagnosticFormatter.Format(diagnostic, targetFramework),
|
||||
mappedLineSpan.Path,
|
||||
mappedLineSpan.StartLinePosition.Line + 1,
|
||||
mappedLineSpan.StartLinePosition.Character + 1,
|
||||
mappedLineSpan.EndLinePosition.Line + 1,
|
||||
mappedLineSpan.EndLinePosition.Character + 1);
|
||||
}
|
||||
|
||||
#if DOTNET5_6
|
||||
private class RazorLoadContext : AssemblyLoadContext
|
||||
{
|
||||
protected override Assembly Load(AssemblyName assemblyName)
|
||||
{
|
||||
return Default.LoadFromAssemblyName(assemblyName);
|
||||
}
|
||||
|
||||
public Assembly Load(Stream assembly, Stream assemblySymbols)
|
||||
{
|
||||
return LoadFromStream(assembly, assemblySymbols);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// 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.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
public static class SyntaxTreeGenerator
|
||||
{
|
||||
public static SyntaxTree Generate(
|
||||
string text,
|
||||
string path,
|
||||
CompilationSettings compilationSettings)
|
||||
{
|
||||
if (compilationSettings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(compilationSettings));
|
||||
}
|
||||
|
||||
return Generate(text, path, GetParseOptions(compilationSettings));
|
||||
}
|
||||
|
||||
public static SyntaxTree Generate(
|
||||
string text,
|
||||
string path,
|
||||
CSharpParseOptions parseOptions)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
if (parseOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parseOptions));
|
||||
}
|
||||
|
||||
var sourceText = SourceText.From(text, Encoding.UTF8);
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(sourceText,
|
||||
path: path,
|
||||
options: parseOptions);
|
||||
|
||||
return syntaxTree;
|
||||
}
|
||||
|
||||
public static CSharpParseOptions GetParseOptions(CompilationSettings compilationSettings)
|
||||
{
|
||||
return new CSharpParseOptions(
|
||||
languageVersion: compilationSettings.LanguageVersion,
|
||||
preprocessorSymbols: compilationSettings.Defines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.Razor.Host": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Mvc.ViewFeatures": "1.0.0-*",
|
||||
"Microsoft.CodeAnalysis.CSharp": "1.1.0-rc1-*",
|
||||
"Microsoft.Extensions.FileProviders.Composite": "1.0.0-*",
|
||||
"Microsoft.Extensions.HashCodeCombiner.Sources": {
|
||||
"version": "1.0.0-*",
|
||||
|
|
@ -24,10 +25,7 @@
|
|||
"Microsoft.Extensions.PropertyHelper.Sources": {
|
||||
"version": "1.0.0-*",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.Dnx.Compilation.CSharp.Common": "1.0.0-*",
|
||||
"Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@
|
|||
"Microsoft.Extensions.PropertyHelper.Sources": {
|
||||
"version": "1.0.0-*",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -23,13 +30,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -28,13 +35,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#if DNXCORE50
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
||||
{
|
||||
public class DefaultAssemblyProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public void CandidateAssemblies_IgnoresMvcAssemblies()
|
||||
{
|
||||
// Arrange
|
||||
var manager = new Mock<ILibraryManager>();
|
||||
manager.Setup(f => f.GetReferencingLibraries(It.IsAny<string>()))
|
||||
.Returns(new[]
|
||||
{
|
||||
new Library("Microsoft.AspNetCore.Mvc.Core"),
|
||||
new Library("Microsoft.AspNetCore.Mvc"),
|
||||
new Library("Microsoft.AspNetCore.Mvc.Abstractions"),
|
||||
new Library("SomeRandomAssembly"),
|
||||
})
|
||||
.Verifiable();
|
||||
var provider = new TestAssemblyProvider(manager.Object);
|
||||
|
||||
// Act
|
||||
var candidates = provider.GetCandidateLibraries();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { "SomeRandomAssembly" }, candidates.Select(a => a.Name));
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CandidateAssemblies_ReturnsLibrariesReferencingAnyMvcAssembly()
|
||||
{
|
||||
// Arrange
|
||||
var manager = new Mock<ILibraryManager>();
|
||||
manager.Setup(f => f.GetReferencingLibraries(It.IsAny<string>()))
|
||||
.Returns(Enumerable.Empty<Library>());
|
||||
manager.Setup(f => f.GetReferencingLibraries("Microsoft.AspNetCore.Mvc.Core"))
|
||||
.Returns(new[] { new Library("Foo") });
|
||||
manager.Setup(f => f.GetReferencingLibraries("Microsoft.AspNetCore.Mvc.Abstractions"))
|
||||
.Returns(new[] { new Library("Bar") });
|
||||
manager.Setup(f => f.GetReferencingLibraries("Microsoft.AspNetCore.Mvc"))
|
||||
.Returns(new[] { new Library("Baz") });
|
||||
var provider = new TestAssemblyProvider(manager.Object);
|
||||
|
||||
// Act
|
||||
var candidates = provider.GetCandidateLibraries();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { "Baz", "Bar", "Foo" }, candidates.Select(a => a.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CandidateAssemblies_ReturnsLibrariesReferencingDefaultAssemblies()
|
||||
{
|
||||
// Arrange
|
||||
var defaultProvider = new TestAssemblyProvider(CreateLibraryManager());
|
||||
|
||||
// Act
|
||||
var defaultProviderCandidates = defaultProvider.GetCandidateLibraries();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { "Baz" }, defaultProviderCandidates.Select(a => a.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CandidateAssemblies_ReturnsLibrariesReferencingOverriddenAssemblies()
|
||||
{
|
||||
// Arrange
|
||||
var overriddenProvider = new OverriddenAssemblyProvider(CreateLibraryManager());
|
||||
|
||||
// Act
|
||||
var overriddenProviderCandidates = overriddenProvider.GetCandidateLibraries();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { "Foo", "Bar" }, overriddenProviderCandidates.Select(a => a.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CandidateAssemblies_ReturnsEmptySequenceWhenReferenceAssembliesIsNull()
|
||||
{
|
||||
// Arrange
|
||||
var nullProvider = new NullAssemblyProvider(CreateLibraryManager());
|
||||
|
||||
// Act
|
||||
var nullProviderCandidates = nullProvider.GetCandidateLibraries();
|
||||
|
||||
// Assert
|
||||
Assert.Empty(nullProviderCandidates.Select(a => a.Name));
|
||||
}
|
||||
|
||||
// This test verifies DefaultAssemblyProvider.ReferenceAssemblies reflects the actual loadable assemblies
|
||||
// of the libraries that Microsoft.AspNetCore.Mvc dependes on.
|
||||
// If we add or remove dependencies, this test should be changed together.
|
||||
[Fact]
|
||||
public void ReferenceAssemblies_ReturnsLoadableReferenceAssemblies()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new MvcAssembliesTestingProvider();
|
||||
var expected = provider.LoadableReferenceAssemblies.OrderBy(p => p, StringComparer.Ordinal);
|
||||
|
||||
// Act
|
||||
var referenceAssemblies = provider.ReferenceAssemblies.OrderBy(p => p, StringComparer.Ordinal);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, referenceAssemblies);
|
||||
}
|
||||
|
||||
private static ILibraryManager CreateLibraryManager()
|
||||
{
|
||||
var manager = new Mock<ILibraryManager>();
|
||||
manager.Setup(f => f.GetReferencingLibraries(It.IsAny<string>()))
|
||||
.Returns(Enumerable.Empty<Library>());
|
||||
manager.Setup(f => f.GetReferencingLibraries("Microsoft.AspNetCore.Mvc.Core"))
|
||||
.Returns(new[] { new Library("Baz") });
|
||||
manager.Setup(f => f.GetReferencingLibraries("MyAssembly"))
|
||||
.Returns(new[] { new Library("Foo") });
|
||||
manager.Setup(f => f.GetReferencingLibraries("AnotherAssembly"))
|
||||
.Returns(new[] { new Library("Bar") });
|
||||
return manager.Object;
|
||||
}
|
||||
|
||||
private class TestAssemblyProvider : DefaultAssemblyProvider
|
||||
{
|
||||
public new IEnumerable<Library> GetCandidateLibraries()
|
||||
{
|
||||
return base.GetCandidateLibraries();
|
||||
}
|
||||
|
||||
public TestAssemblyProvider(ILibraryManager libraryManager) : base(libraryManager)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class OverriddenAssemblyProvider : TestAssemblyProvider
|
||||
{
|
||||
protected override HashSet<string> ReferenceAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
return new HashSet<string>
|
||||
{
|
||||
"MyAssembly",
|
||||
"AnotherAssembly"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public OverriddenAssemblyProvider(ILibraryManager libraryManager) : base(libraryManager)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class NullAssemblyProvider : TestAssemblyProvider
|
||||
{
|
||||
protected override HashSet<string> ReferenceAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public NullAssemblyProvider(ILibraryManager libraryManager) : base(libraryManager)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MvcAssembliesTestingProvider : DefaultAssemblyProvider
|
||||
{
|
||||
private static readonly ILibraryManager _libraryManager = GetLibraryManager();
|
||||
private static readonly string _mvcName = "Microsoft.AspNetCore.Mvc";
|
||||
|
||||
public MvcAssembliesTestingProvider() : base(_libraryManager)
|
||||
{ }
|
||||
|
||||
public HashSet<string> LoadableReferenceAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
var dependencies = new HashSet<string>() { _mvcName };
|
||||
GetAllDependencies(_mvcName, dependencies);
|
||||
|
||||
return new HashSet<string>(
|
||||
SelectMvcAssemblies(
|
||||
GetAssemblies(dependencies)));
|
||||
}
|
||||
}
|
||||
|
||||
public new HashSet<string> ReferenceAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.ReferenceAssemblies;
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetAllDependencies(string libraryName, HashSet<string> dependencies)
|
||||
{
|
||||
var directDependencies = _libraryManager.GetLibrary(libraryName).Dependencies;
|
||||
|
||||
if (directDependencies != null)
|
||||
{
|
||||
foreach (var dependency in directDependencies)
|
||||
{
|
||||
GetAllDependencies(dependency, dependencies);
|
||||
dependencies.Add(dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<string> SelectMvcAssemblies(IEnumerable<string> assemblies)
|
||||
{
|
||||
var exceptionalAssebmlies = new string[]
|
||||
{
|
||||
"Microsoft.AspNetCore.Mvc.WebApiCompatShim",
|
||||
};
|
||||
|
||||
var mvcAssemblies = assemblies
|
||||
.Distinct()
|
||||
.Where(n => n.StartsWith(_mvcName))
|
||||
.Except(exceptionalAssebmlies)
|
||||
.ToList();
|
||||
|
||||
// The following assemblies are not reachable from Microsoft.AspNetCore.Mvc
|
||||
mvcAssemblies.Add("Microsoft.AspNetCore.Mvc.TagHelpers");
|
||||
mvcAssemblies.Add("Microsoft.AspNetCore.Mvc.Formatters.Xml");
|
||||
|
||||
return mvcAssemblies;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetAssemblies(IEnumerable<string> libraries)
|
||||
{
|
||||
return libraries
|
||||
.Select(n => _libraryManager.GetLibrary(n))
|
||||
.SelectMany(n => n.Assemblies)
|
||||
.Distinct()
|
||||
.Select(n => n.Name);
|
||||
}
|
||||
|
||||
private static ILibraryManager GetLibraryManager()
|
||||
{
|
||||
return DnxPlatformServices.Default.LibraryManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -27,6 +27,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -37,13 +44,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -30,13 +37,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -30,13 +37,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -30,13 +37,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -29,13 +36,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
// 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.
|
||||
|
||||
#if DNX451
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A type that uses Roslyn to compile C# content and <see cref="ILibraryExporter"/> to find out references.
|
||||
/// </summary>
|
||||
public class DnxRoslynCompilationService : ICompilationService
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, AssemblyMetadata> _metadataFileCache =
|
||||
new ConcurrentDictionary<string, AssemblyMetadata>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly IApplicationEnvironment _environment;
|
||||
private readonly ILibraryExporter _libraryExporter;
|
||||
private readonly RazorViewEngineOptions _options;
|
||||
private readonly Lazy<List<MetadataReference>> _applicationReferences;
|
||||
|
||||
/// <summary>
|
||||
/// Initalizes a new instance of the <see cref="DnxRoslynCompilationService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="environment">The environment for the executing application.</param>
|
||||
/// <param name="libraryExporter">The library manager that provides export and reference information.</param>
|
||||
/// <param name="host">The <see cref="IMvcRazorHost"/> that was used to generate the code.</param>
|
||||
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
||||
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public DnxRoslynCompilationService(IApplicationEnvironment environment,
|
||||
ILibraryExporter libraryExporter,
|
||||
IMvcRazorHost host,
|
||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor)
|
||||
{
|
||||
_environment = environment;
|
||||
_libraryExporter = libraryExporter;
|
||||
_options = optionsAccessor.Value;
|
||||
_applicationReferences = new Lazy<List<MetadataReference>>(GetApplicationReferences);
|
||||
}
|
||||
|
||||
public CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent)
|
||||
{
|
||||
var assemblyName = Path.GetRandomFileName();
|
||||
|
||||
var sourceText = SourceText.From(compilationContent, Encoding.UTF8);
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(
|
||||
sourceText,
|
||||
path: assemblyName,
|
||||
options: _options.ParseOptions);
|
||||
|
||||
var references = _applicationReferences.Value;
|
||||
|
||||
var compilation = CSharpCompilation.Create(
|
||||
assemblyName,
|
||||
options: _options.CompilationOptions,
|
||||
syntaxTrees: new[] { syntaxTree },
|
||||
references: references);
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var pdb = new MemoryStream())
|
||||
{
|
||||
var result = compilation.Emit(ms);
|
||||
if (!result.Success)
|
||||
{
|
||||
return GetCompilationFailedResult(
|
||||
fileInfo.RelativePath,
|
||||
compilationContent,
|
||||
assemblyName,
|
||||
result.Diagnostics);
|
||||
}
|
||||
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var assembly = LoadStream(ms, assemblySymbols: null);
|
||||
|
||||
var type = assembly
|
||||
.GetExportedTypes()[0];
|
||||
|
||||
return new CompilationResult(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal CompilationResult GetCompilationFailedResult(
|
||||
string relativePath,
|
||||
string compilationContent,
|
||||
string assemblyName,
|
||||
IEnumerable<Diagnostic> diagnostics)
|
||||
{
|
||||
var diagnosticGroups = diagnostics
|
||||
.Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)
|
||||
.GroupBy(diagnostic => diagnostic.Location.GetMappedLineSpan().Path, StringComparer.Ordinal);
|
||||
|
||||
var failures = new List<Diagnostics.CompilationFailure>();
|
||||
foreach (var group in diagnosticGroups)
|
||||
{
|
||||
var sourceFilePath = group.Key;
|
||||
|
||||
var compilationFailure = new Diagnostics.CompilationFailure(
|
||||
sourceFilePath,
|
||||
string.Empty,
|
||||
compilationContent,
|
||||
group.Select(GetDiagnosticMessage));
|
||||
|
||||
failures.Add(compilationFailure);
|
||||
}
|
||||
|
||||
return new CompilationResult(failures);
|
||||
}
|
||||
|
||||
private static Diagnostics.DiagnosticMessage GetDiagnosticMessage(Diagnostic diagnostic)
|
||||
{
|
||||
var mappedLineSpan = diagnostic.Location.GetMappedLineSpan();
|
||||
return new Diagnostics.DiagnosticMessage(
|
||||
diagnostic.GetMessage(),
|
||||
CSharpDiagnosticFormatter.Instance.Format(diagnostic),
|
||||
mappedLineSpan.Path,
|
||||
mappedLineSpan.StartLinePosition.Line + 1,
|
||||
mappedLineSpan.StartLinePosition.Character + 1,
|
||||
mappedLineSpan.EndLinePosition.Line + 1,
|
||||
mappedLineSpan.EndLinePosition.Character + 1);
|
||||
}
|
||||
|
||||
private Assembly LoadStream(MemoryStream ms, MemoryStream assemblySymbols)
|
||||
{
|
||||
return Assembly.Load(ms.ToArray(), assemblySymbols?.ToArray());
|
||||
}
|
||||
|
||||
private List<MetadataReference> GetApplicationReferences()
|
||||
{
|
||||
var references = new List<MetadataReference>();
|
||||
|
||||
// Get the MetadataReference for the executing application. If it's a Roslyn reference,
|
||||
// we can copy the references created when compiling the application to the Razor page being compiled.
|
||||
// This avoids performing expensive calls to MetadataReference.CreateFromImage.
|
||||
var libraryExport = _libraryExporter.GetExport(_environment.ApplicationName);
|
||||
if (libraryExport?.MetadataReferences != null && libraryExport.MetadataReferences.Count > 0)
|
||||
{
|
||||
Debug.Assert(libraryExport.MetadataReferences.Count == 1,
|
||||
"Expected 1 MetadataReferences, found " + libraryExport.MetadataReferences.Count);
|
||||
var roslynReference = libraryExport.MetadataReferences[0] as IRoslynMetadataReference;
|
||||
var compilationReference = roslynReference?.MetadataReference as CompilationReference;
|
||||
if (compilationReference != null)
|
||||
{
|
||||
references.AddRange(compilationReference.Compilation.References);
|
||||
references.Add(roslynReference.MetadataReference);
|
||||
return references;
|
||||
}
|
||||
}
|
||||
|
||||
var export = _libraryExporter.GetAllExports(_environment.ApplicationName);
|
||||
if (export != null)
|
||||
{
|
||||
foreach (var metadataReference in export.MetadataReferences)
|
||||
{
|
||||
// Taken from https://github.com/aspnet/KRuntime/blob/757ba9bfdf80bd6277e715d6375969a7f44370ee/src/...
|
||||
// Microsoft.Extensions.Runtime.Roslyn/RoslynCompiler.cs#L164
|
||||
// We don't want to take a dependency on the Roslyn bit directly since it pulls in more dependencies
|
||||
// than the view engine needs (Microsoft.Extensions.Runtime) for example
|
||||
references.Add(ConvertMetadataReference(metadataReference));
|
||||
}
|
||||
}
|
||||
|
||||
return references;
|
||||
}
|
||||
|
||||
private MetadataReference ConvertMetadataReference(IMetadataReference metadataReference)
|
||||
{
|
||||
var roslynReference = metadataReference as IRoslynMetadataReference;
|
||||
|
||||
if (roslynReference != null)
|
||||
{
|
||||
return roslynReference.MetadataReference;
|
||||
}
|
||||
|
||||
var embeddedReference = metadataReference as IMetadataEmbeddedReference;
|
||||
|
||||
if (embeddedReference != null)
|
||||
{
|
||||
return MetadataReference.CreateFromImage(embeddedReference.Contents);
|
||||
}
|
||||
|
||||
var fileMetadataReference = metadataReference as IMetadataFileReference;
|
||||
|
||||
if (fileMetadataReference != null)
|
||||
{
|
||||
return CreateMetadataFileReference(fileMetadataReference.Path);
|
||||
}
|
||||
|
||||
var projectReference = metadataReference as IMetadataProjectReference;
|
||||
if (projectReference != null)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
projectReference.EmitReferenceAssembly(ms);
|
||||
|
||||
return MetadataReference.CreateFromImage(ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
private MetadataReference CreateMetadataFileReference(string path)
|
||||
{
|
||||
var metadata = _metadataFileCache.GetOrAdd(path, _ =>
|
||||
{
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
|
||||
return AssemblyMetadata.Create(moduleMetadata);
|
||||
}
|
||||
});
|
||||
|
||||
return metadata.GetReference(filePath: path);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -6,7 +6,11 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
public class MvcSampleFixture<TStartup> : MvcTestFixture<TStartup>
|
||||
{
|
||||
public MvcSampleFixture()
|
||||
#if DNXCORE50
|
||||
:base("../../../../../../samples/")
|
||||
#else
|
||||
: base("../../../../samples/")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,13 @@ using System.Net.Http;
|
|||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
#if DNX451
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
#endif
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
|
|
@ -19,7 +24,11 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
private readonly TestServer _server;
|
||||
|
||||
public MvcTestFixture()
|
||||
#if DNXCORE50
|
||||
: this("../../../../../Websites/")
|
||||
#else
|
||||
: this("../../../Websites/")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -61,11 +70,14 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
var applicationName = startupAssembly.GetName().Name;
|
||||
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
#if DNXCORE50 || DNX451
|
||||
#if DNX451
|
||||
services.AddSingleton(CompilationServices.Default.LibraryExporter);
|
||||
services.AddSingleton<ICompilationService, DnxRoslynCompilationService>();
|
||||
|
||||
var libraryManager = DnxPlatformServices.Default.LibraryManager;
|
||||
var library = libraryManager.GetLibrary(applicationName);
|
||||
var applicationRoot = Path.GetDirectoryName(library.Path);
|
||||
#else
|
||||
var applicationRoot = Path.GetDirectoryName(library.Path);
|
||||
#else
|
||||
var applicationRoot = Path.GetFullPath(Path.Combine(
|
||||
applicationEnvironment.ApplicationBasePath,
|
||||
relativePath,
|
||||
|
|
|
|||
|
|
@ -57,18 +57,22 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
},
|
||||
"net451": { },
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
"Microsoft.Dnx.Compilation.CSharp.Common": "1.0.0-*",
|
||||
"Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
},
|
||||
"imports": "portable-net451+win8"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Microsoft.Dnx.Compilation.CSharp.Common": "1.0.0-*",
|
||||
"Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
},
|
||||
"net451": { }
|
||||
},
|
||||
"exclude": [
|
||||
"wwwroot",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -29,13 +36,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -28,13 +35,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,13 @@
|
|||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -35,13 +42,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
|
|
|
|||
|
|
@ -1,393 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#if DNXCORE50
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
public class DefaultRoslynCompilationServiceTest
|
||||
{
|
||||
private const string ConfigurationName = "Release";
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsCompilationResult()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"
|
||||
public class MyTestType {}";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns(string.Empty);
|
||||
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost.Object,
|
||||
GetOptions(),
|
||||
GetFileProviderAccessor(),
|
||||
NullLoggerFactory.Instance);
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("MyTestType", result.CompiledType.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas()
|
||||
{
|
||||
// Arrange
|
||||
var viewPath = "some-relative-path";
|
||||
var fileContent = "test file content";
|
||||
var content = $@"
|
||||
#line 1 ""{viewPath}""
|
||||
this should fail";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
var mvcRazorHost = Mock.Of<IMvcRazorHost>();
|
||||
var fileProvider = new TestFileProvider();
|
||||
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
|
||||
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost,
|
||||
GetOptions(),
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath);
|
||||
Assert.Equal(fileContent, compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
|
||||
{
|
||||
// Arrange
|
||||
var fileContent = "file content";
|
||||
var content = @"this should fail";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
var mvcRazorHost = Mock.Of<IMvcRazorHost>();
|
||||
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost,
|
||||
GetOptions(),
|
||||
GetFileProviderAccessor(),
|
||||
NullLoggerFactory.Instance);
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { Content = fileContent },
|
||||
"some-relative-path");
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
|
||||
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 path = "some-relative-path";
|
||||
var content = $@"
|
||||
#line 1 ""{path}""
|
||||
this should fail";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
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 DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost,
|
||||
GetOptions(),
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path);
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal(path, compilationFailure.SourceFilePath);
|
||||
Assert.Null(compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"
|
||||
#if MY_CUSTOM_DEFINE
|
||||
public class MyCustomDefinedClass {}
|
||||
#else
|
||||
public class MyNonCustomDefinedClass {}
|
||||
#endif
|
||||
";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns("My");
|
||||
|
||||
var options = GetOptions();
|
||||
options.Value.ParseOptions = options.Value.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
|
||||
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost.Object,
|
||||
options,
|
||||
GetFileProviderAccessor(),
|
||||
NullLoggerFactory.Instance);
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompiledType);
|
||||
Assert.Equal("MyCustomDefinedClass", result.CompiledType.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsSingleTypeThatStartsWithMainClassNamePrefix()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"
|
||||
public class RazorPrefixType {}
|
||||
public class NotRazorPrefixType {}";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns("RazorPrefix");
|
||||
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost.Object,
|
||||
GetOptions(),
|
||||
GetFileProviderAccessor(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompiledType);
|
||||
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 RazorViewEngineOptions();
|
||||
options.FileProviders.Add(fileProvider);
|
||||
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||
optionsAccessor.SetupGet(o => o.Value)
|
||||
.Returns(options);
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
PlatformServices.Default.Application,
|
||||
CompilationServices.Default.LibraryExporter,
|
||||
Mock.Of<IMvcRazorHost>(),
|
||||
optionsAccessor.Object,
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_RunsCallback()
|
||||
{
|
||||
var content = "public class MyTestType {}";
|
||||
var applicationEnvironment = PlatformServices.Default.Application;
|
||||
var libraryExporter = CompilationServices.Default.LibraryExporter;
|
||||
RoslynCompilationContext usedCompilation = null;
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns(string.Empty);
|
||||
|
||||
var compilationService = new DefaultRoslynCompilationService(
|
||||
applicationEnvironment,
|
||||
libraryExporter,
|
||||
mvcRazorHost.Object,
|
||||
GetOptions(callback: c => usedCompilation = c),
|
||||
GetFileProviderAccessor(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
Assert.NotNull(usedCompilation);
|
||||
Assert.NotNull(usedCompilation.Compilation);
|
||||
Assert.Equal(1, usedCompilation.Compilation.SyntaxTrees.Length);
|
||||
}
|
||||
|
||||
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 IOptions<RazorViewEngineOptions> GetOptions(Action<RoslynCompilationContext> callback = null)
|
||||
{
|
||||
var razorViewEngineOptions = new RazorViewEngineOptions
|
||||
{
|
||||
CompilationCallback = callback ?? (c => { }),
|
||||
};
|
||||
var options = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||
options
|
||||
.SetupGet(o => o.Value)
|
||||
.Returns(razorViewEngineOptions);
|
||||
|
||||
return options.Object;
|
||||
}
|
||||
|
||||
private IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
|
||||
{
|
||||
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
|
||||
options.SetupGet(o => o.FileProvider)
|
||||
.Returns(fileProvider ?? new TestFileProvider());
|
||||
|
||||
return options.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -8,9 +8,6 @@ using System.Reflection;
|
|||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
|
|
@ -567,28 +564,13 @@ public class Person
|
|||
|
||||
private IEnumerable<MetadataReference> GetReferences()
|
||||
{
|
||||
var libraryExporter = CompilationServices.Default?.LibraryExporter;
|
||||
if (libraryExporter == null)
|
||||
var types = new[]
|
||||
{
|
||||
var types = new[]
|
||||
{
|
||||
typeof(System.Linq.Expressions.Expression),
|
||||
typeof(string),
|
||||
};
|
||||
typeof(System.Linq.Expressions.Expression),
|
||||
typeof(string),
|
||||
};
|
||||
|
||||
return types.Select(t => MetadataReference.CreateFromFile(t.GetTypeInfo().Assembly.Location));
|
||||
}
|
||||
|
||||
var environment = PlatformServices.Default.Application;
|
||||
var references = new List<MetadataReference>();
|
||||
|
||||
var libraryExports = libraryExporter.GetAllExports(environment.ApplicationName);
|
||||
foreach (var export in libraryExports.MetadataReferences)
|
||||
{
|
||||
references.Add(export.ConvertMetadataReference(MetadataReferenceExtensions.CreateAssemblyMetadata));
|
||||
}
|
||||
|
||||
return references;
|
||||
return types.Select(t => MetadataReference.CreateFromFile(t.GetTypeInfo().Assembly.Location));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -43,13 +50,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
|
|
|
|||
|
|
@ -21,6 +21,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -31,13 +38,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -17,7 +17,6 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -34,7 +33,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public void Setup_SetsUpViewEngines()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = GetOptions<MvcViewOptions>(AddDnxServices);
|
||||
var options = GetOptions<MvcViewOptions>(AddViewEngineOptionsServices);
|
||||
|
||||
// Assert
|
||||
var viewEngine = Assert.Single(options.ViewEngines);
|
||||
|
|
@ -119,7 +118,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public void Setup_SetsUpClientModelValidatorProviders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = GetOptions<MvcViewOptions>(AddDnxServices);
|
||||
var options = GetOptions<MvcViewOptions>(AddViewEngineOptionsServices);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(options.ClientModelValidatorProviders,
|
||||
|
|
@ -236,6 +235,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddMvc();
|
||||
serviceCollection.AddTransient<ILoggerFactory, LoggerFactory>();
|
||||
|
||||
if (action != null)
|
||||
{
|
||||
action(serviceCollection);
|
||||
|
|
@ -245,14 +245,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
return serviceProvider;
|
||||
}
|
||||
|
||||
private static void AddDnxServices(IServiceCollection serviceCollection)
|
||||
private static void AddViewEngineOptionsServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton(Mock.Of<ILibraryManager>());
|
||||
serviceCollection.AddSingleton(Mock.Of<ILibraryExporter>());
|
||||
serviceCollection.AddSingleton(Mock.Of<ICompilerOptionsProvider>());
|
||||
serviceCollection.AddSingleton(Mock.Of<IHostingEnvironment>());
|
||||
var applicationEnvironment = new Mock<IApplicationEnvironment>();
|
||||
|
||||
applicationEnvironment.SetupGet(e => e.ApplicationName)
|
||||
.Returns(typeof(MvcOptionsSetupTest).GetTypeInfo().Assembly.GetName().Name);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
|||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Cors;
|
||||
using Microsoft.AspNetCore.Mvc.Cors.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.DataAnnotations.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
|
@ -21,7 +20,6 @@ using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
|||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.CompilationAbstractions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -139,24 +137,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
get
|
||||
{
|
||||
Type[] razorViewEngineOptionsRegistrations;
|
||||
if (CompilationServices.Default == null)
|
||||
{
|
||||
razorViewEngineOptionsRegistrations = new[]
|
||||
{
|
||||
typeof(RazorViewEngineOptionsSetup),
|
||||
typeof(DependencyContextRazorViewEngineOptionsSetup)
|
||||
};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
razorViewEngineOptionsRegistrations = new[]
|
||||
{
|
||||
typeof(RazorViewEngineOptionsSetup)
|
||||
};
|
||||
}
|
||||
|
||||
return new Dictionary<Type, Type[]>()
|
||||
{
|
||||
{
|
||||
|
|
@ -186,7 +166,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
},
|
||||
{
|
||||
typeof(IConfigureOptions<RazorViewEngineOptions>),
|
||||
razorViewEngineOptionsRegistrations
|
||||
new[]
|
||||
{
|
||||
typeof(RazorViewEngineOptionsSetup),
|
||||
typeof(DependencyContextRazorViewEngineOptionsSetup)
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(IActionConstraintProvider),
|
||||
|
|
|
|||
|
|
@ -7,13 +7,21 @@
|
|||
"Microsoft.AspNetCore.Mvc.Formatters.Xml": "1.0.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging": "1.0.0-*",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||
"xunit": "2.1.0"
|
||||
},
|
||||
"testRunner": "xunit",
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -22,15 +30,7 @@
|
|||
},
|
||||
"net451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
"xunit": "2.1.0"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
@ -36,13 +43,6 @@
|
|||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,18 +16,18 @@
|
|||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"dotnet-test-xunit": "1.0.0-dev-*"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"imports": "portable-net451+win8",
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ namespace RazorWebSite
|
|||
{
|
||||
public string ExecuteOperation()
|
||||
{
|
||||
#if NET451
|
||||
#if NET451 || DNX451
|
||||
return "This method is running from NET451";
|
||||
#elif DNXCORE50
|
||||
return "This method is running from DNXCORE50";
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace RazorWebSite
|
|||
.AddRazorOptions(options =>
|
||||
{
|
||||
options.ViewLocationExpanders.Add(new NonMainPageViewLocationExpander());
|
||||
#if DNXCORE50
|
||||
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("DNXCORE50", "DNXCORE50_CUSTOM_DEFINE");
|
||||
#if NET451
|
||||
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("DNX451", "NET451_CUSTOM_DEFINE");
|
||||
#endif
|
||||
})
|
||||
.AddViewOptions(options =>
|
||||
|
|
|
|||
Loading…
Reference in New Issue