diff --git a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index 03e1190a81..9f01cd034c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -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(); - } - else - { - services.TryAddTransient(); - } + services.TryAddTransient(); services.TryAddTransient(); services.TryAddEnumerable( diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DefaultAssemblyProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DefaultAssemblyProvider.cs index a022dadf4c..12cc4dc0d9 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DefaultAssemblyProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DefaultAssemblyProvider.cs @@ -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 { + /// + /// An that uses to discover assemblies that may + /// contain Mvc specific types such as controllers, and view components. + /// public class DefaultAssemblyProvider : IAssemblyProvider { - private readonly ILibraryManager _libraryManager; + private readonly DependencyContext _dependencyContext; - public DefaultAssemblyProvider(ILibraryManager libraryManager) + /// + /// Initializes a new instance of . + /// + /// The . + public DefaultAssemblyProvider(IApplicationEnvironment environment) { - _libraryManager = libraryManager; + var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName)); + _dependencyContext = DependencyContext.Load(applicationAssembly); } /// @@ -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. /// /// A set of . - protected virtual IEnumerable GetCandidateLibraries() + protected virtual IEnumerable GetCandidateLibraries() { if (ReferenceAssemblies == null) { - return Enumerable.Empty(); + return Enumerable.Empty(); } - // 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)); } } -} +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DependencyContextAssemblyProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DependencyContextAssemblyProvider.cs deleted file mode 100644 index 3c9e099441..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DependencyContextAssemblyProvider.cs +++ /dev/null @@ -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 -{ - /// - /// An that uses to discover assemblies that may - /// contain Mvc specific types such as controllers, and view components. - /// - public class DependencyContextAssemblyProvider : IAssemblyProvider - { - private readonly DependencyContext _dependencyContext; - - /// - /// Initializes a new instance of . - /// - /// The . - public DependencyContextAssemblyProvider(IApplicationEnvironment environment) - { - var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName)); - _dependencyContext = DependencyContext.Load(applicationAssembly); - } - - /// - /// Gets the set of assembly names that are used as root for discovery of - /// MVC controllers, view components and views. - /// - // 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 ReferenceAssemblies { get; } = new HashSet(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" - }; - - /// - public IEnumerable CandidateAssemblies - { - get - { - return GetCandidateLibraries() - .SelectMany(l => l.Assemblies) - .Select(Load); - } - } - - /// - /// Returns a list of libraries that references the assemblies in . - /// By default it returns all assemblies that reference any of the primary MVC assemblies - /// while ignoring MVC assemblies. - /// - /// A set of . - protected virtual IEnumerable GetCandidateLibraries() - { - if (ReferenceAssemblies == null) - { - return Enumerable.Empty(); - } - - 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)); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/project.json b/src/Microsoft.AspNetCore.Mvc.Core/project.json index f379682261..5db836e30e 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/project.json +++ b/src/Microsoft.AspNetCore.Mvc.Core/project.json @@ -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-*", diff --git a/src/Microsoft.AspNetCore.Mvc.Localization/project.json b/src/Microsoft.AspNetCore.Mvc.Localization/project.json index 99fd3ee394..d6ed7266bb 100644 --- a/src/Microsoft.AspNetCore.Mvc.Localization/project.json +++ b/src/Microsoft.AspNetCore.Mvc.Localization/project.json @@ -13,8 +13,7 @@ "Microsoft.Extensions.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" - }, - "Microsoft.NETCore.Platforms": "1.0.1-*" + } }, "frameworks": { "net451": {}, diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs index 49042ae384..da4abb7dd4 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs @@ -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, + DependencyContextRazorViewEngineOptionsSetup>()); - if (compilationServicesAvailible) - { - services.TryAddSingleton(CompilationServices.Default.LibraryExporter); - - // This caches compilation related details that are valid across the lifetime of the application. - services.TryAddSingleton(); - } - else - { - services.TryAddEnumerable( - ServiceDescriptor.Transient, DependencyContextRazorViewEngineOptionsSetup>()); - - // This caches compilation related details that are valid across the lifetime of the application. - services.TryAddSingleton(); - } + // This caches compilation related details that are valid across the lifetime of the application. + services.TryAddSingleton(); services.TryAddEnumerable( ServiceDescriptor.Transient, MvcRazorMvcViewOptionsSetup>()); services.TryAddEnumerable( ServiceDescriptor.Transient, RazorViewEngineOptionsSetup>()); - services.TryAddSingleton(); + services.TryAddSingleton< + IRazorViewEngineFileProviderAccessor, + DefaultRazorViewEngineFileProviderAccessor>(); services.TryAddSingleton(); @@ -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(); - - if (DnxPlatformServices.Default?.AssemblyLoadContextAccessor != null) - { - services.TryAddSingleton(DnxPlatformServices.Default.AssemblyLoadContextAccessor); - } } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CompilationOptionsProviderExtension.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CompilationOptionsProviderExtension.cs deleted file mode 100644 index 5a6448d640..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/CompilationOptionsProviderExtension.cs +++ /dev/null @@ -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 -{ - /// - /// Extension methods for . - /// - public static class CompilationOptionsProviderExtension - { - /// - /// Parses the for the current executing application and returns a - /// used for Roslyn compilation. - /// - /// - /// A that reads compiler options. - /// - /// - /// The for the executing application. - /// - /// - /// The configuration name to use for compilation. - /// - /// The for the current application. - 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); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs index 430f1e9c0e..ea82220310 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs @@ -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 { /// - /// A type that uses Roslyn to compile C# content and to find out references. + /// A type that uses Roslyn to compile C# content. /// - public class DefaultRoslynCompilationService : RoslynCompilationService + public class DefaultRoslynCompilationService : ICompilationService { + private readonly Lazy _supportsPdbGeneration = new Lazy(SymbolsUtility.SupportsSymbolsGeneration); + private readonly ConcurrentDictionary _metadataFileCache = + new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly IApplicationEnvironment _environment; - private readonly ILibraryExporter _libraryExporter; + private readonly IFileProvider _fileProvider; + private readonly Lazy> _applicationReferences; + private readonly string _classPrefix; + private readonly Action _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 /// /// Initalizes a new instance of the class. /// /// The environment for the executing application. - /// The library manager that provides export and reference information. /// The that was used to generate the code. /// Accessor to . /// The . /// The . - public DefaultRoslynCompilationService(IApplicationEnvironment environment, - ILibraryExporter libraryExporter, + public DefaultRoslynCompilationService( + IApplicationEnvironment environment, IMvcRazorHost host, IOptions optionsAccessor, IRazorViewEngineFileProviderAccessor fileProviderAccessor, ILoggerFactory loggerFactory) - : base(environment, host, optionsAccessor, fileProviderAccessor, loggerFactory) { _environment = environment; - _libraryExporter = libraryExporter; + _applicationReferences = new Lazy>(GetApplicationReferences); + _fileProvider = fileProviderAccessor.FileProvider; + _classPrefix = host.MainClassNamePrefix; + _compilationCallback = optionsAccessor.Value.CompilationCallback; + _parseOptions = optionsAccessor.Value.ParseOptions; + _compilationOptions = optionsAccessor.Value.CompilationOptions; + _logger = loggerFactory.CreateLogger(); + +#if DOTNET5_6 + _razorLoadContext = new RazorLoadContext(); +#endif + + var applicationAssembly = Assembly.Load(new AssemblyName(environment.ApplicationName)); + _dependencyContext = DependencyContext.Load(applicationAssembly); } - protected override List GetApplicationReferences() + /// + public CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent) { - var references = new List(); - - // 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(); + 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 diagnostics) + { + var diagnosticGroups = diagnostics + .Where(IsError) + .GroupBy(diagnostic => GetFilePath(relativePath, diagnostic), StringComparer.Ordinal); + + var failures = new List(); + 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 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 } -} \ No newline at end of file +} diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DependencyContextCompilationService.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DependencyContextCompilationService.cs deleted file mode 100644 index 76da719a8b..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DependencyContextCompilationService.cs +++ /dev/null @@ -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 -{ - /// - /// A type that uses Roslyn to compile C# content and to locate references. - /// - public class DependencyContextCompilationService : RoslynCompilationService - { - private readonly DependencyContext _dependencyContext; - - /// - /// Initalizes a new instance of the class. - /// - /// The environment for the executing application. - /// The that was used to generate the code. - /// Accessor to . - /// The . - /// The . - public DependencyContextCompilationService( - IApplicationEnvironment environment, - IMvcRazorHost host, - IOptions 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 GetApplicationReferences() - { - return _dependencyContext.CompileLibraries - .SelectMany(library => library.ResolveReferencePaths()) - .Select(CreateMetadataFileReference) - .ToList(); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RoslynCompilationService.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RoslynCompilationService.cs deleted file mode 100644 index 47cbf66eff..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RoslynCompilationService.cs +++ /dev/null @@ -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 -{ - /// - /// A type that uses Roslyn to compile C# content. - /// - public abstract class RoslynCompilationService : ICompilationService - { - private readonly Lazy _supportsPdbGeneration = new Lazy(SymbolsUtility.SupportsSymbolsGeneration); - private readonly ConcurrentDictionary _metadataFileCache = - new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - - private readonly IApplicationEnvironment _environment; - private readonly IFileProvider _fileProvider; - private readonly Lazy> _applicationReferences; - private readonly string _classPrefix; - private readonly Action _compilationCallback; - private readonly CSharpParseOptions _parseOptions; - private readonly CSharpCompilationOptions _compilationOptions; - private readonly ILogger _logger; - -#if DOTNET5_6 - private readonly RazorLoadContext _razorLoadContext; -#endif - - /// - /// Initalizes a new instance of the class. - /// - /// The environment for the executing application. - /// The that was used to generate the code. - /// Accessor to . - /// The . - /// The . - public RoslynCompilationService( - IApplicationEnvironment environment, - IMvcRazorHost host, - IOptions optionsAccessor, - IRazorViewEngineFileProviderAccessor fileProviderAccessor, - ILoggerFactory loggerFactory) - { - _environment = environment; - _applicationReferences = new Lazy>(GetApplicationReferences); - _fileProvider = fileProviderAccessor.FileProvider; - _classPrefix = host.MainClassNamePrefix; - _compilationCallback = optionsAccessor.Value.CompilationCallback; - _parseOptions = optionsAccessor.Value.ParseOptions; - _compilationOptions = optionsAccessor.Value.CompilationOptions; - _logger = loggerFactory.CreateLogger(); - -#if DOTNET5_6 - _razorLoadContext = new RazorLoadContext(); -#endif - } - - /// - 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(); - 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 diagnostics) - { - var diagnosticGroups = diagnostics - .Where(IsError) - .GroupBy(diagnostic => GetFilePath(relativePath, diagnostic), StringComparer.Ordinal); - - var failures = new List(); - 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 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 - } -} diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/SyntaxTreeGenerator.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/SyntaxTreeGenerator.cs deleted file mode 100644 index 778b0e0ace..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/SyntaxTreeGenerator.cs +++ /dev/null @@ -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); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/project.json b/src/Microsoft.AspNetCore.Mvc.Razor/project.json index f0045c9991..e2c2e6ea7d 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/project.json +++ b/src/Microsoft.AspNetCore.Mvc.Razor/project.json @@ -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": { diff --git a/src/Microsoft.AspNetCore.Mvc/project.json b/src/Microsoft.AspNetCore.Mvc/project.json index e944eb3214..fb7f01786a 100644 --- a/src/Microsoft.AspNetCore.Mvc/project.json +++ b/src/Microsoft.AspNetCore.Mvc/project.json @@ -22,8 +22,7 @@ "Microsoft.Extensions.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" - }, - "Microsoft.NETCore.Platforms": "1.0.1-*" + } }, "frameworks": { "net451": {}, diff --git a/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/project.json index 6dc60aa02b..1c5583b5d3 100644 --- a/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/project.json b/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/project.json index f29b158c99..60ec35a11e 100644 --- a/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/DefaultAssemblyProviderTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/DefaultAssemblyProviderTests.cs deleted file mode 100644 index 129bc816c3..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/DefaultAssemblyProviderTests.cs +++ /dev/null @@ -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(); - manager.Setup(f => f.GetReferencingLibraries(It.IsAny())) - .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(); - } - - [Fact] - public void CandidateAssemblies_ReturnsLibrariesReferencingAnyMvcAssembly() - { - // Arrange - var manager = new Mock(); - manager.Setup(f => f.GetReferencingLibraries(It.IsAny())) - .Returns(Enumerable.Empty()); - 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(); - manager.Setup(f => f.GetReferencingLibraries(It.IsAny())) - .Returns(Enumerable.Empty()); - 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 GetCandidateLibraries() - { - return base.GetCandidateLibraries(); - } - - public TestAssemblyProvider(ILibraryManager libraryManager) : base(libraryManager) - { - } - } - - private class OverriddenAssemblyProvider : TestAssemblyProvider - { - protected override HashSet ReferenceAssemblies - { - get - { - return new HashSet - { - "MyAssembly", - "AnotherAssembly" - }; - } - } - - public OverriddenAssemblyProvider(ILibraryManager libraryManager) : base(libraryManager) - { - } - } - - private class NullAssemblyProvider : TestAssemblyProvider - { - protected override HashSet 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 LoadableReferenceAssemblies - { - get - { - var dependencies = new HashSet() { _mvcName }; - GetAllDependencies(_mvcName, dependencies); - - return new HashSet( - SelectMvcAssemblies( - GetAssemblies(dependencies))); - } - } - - public new HashSet ReferenceAssemblies - { - get - { - return base.ReferenceAssemblies; - } - } - - private static void GetAllDependencies(string libraryName, HashSet dependencies) - { - var directDependencies = _libraryManager.GetLibrary(libraryName).Dependencies; - - if (directDependencies != null) - { - foreach (var dependency in directDependencies) - { - GetAllDependencies(dependency, dependencies); - dependencies.Add(dependency); - } - } - } - - private static IEnumerable SelectMvcAssemblies(IEnumerable 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 GetAssemblies(IEnumerable 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 \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Core.Test/project.json index 7de05538f6..b27deadebc 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Cors.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Cors.Test/project.json index 27b7985b46..9c0b3bfb19 100644 --- a/test/Microsoft.AspNetCore.Mvc.Cors.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Cors.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/project.json b/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/project.json index e6f5f5b5d4..7fb3beeba7 100644 --- a/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/project.json index 27b7985b46..9c0b3bfb19 100644 --- a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/project.json index e061478f4b..88c47ed209 100644 --- a/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/DnxRoslynCompilationService.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/DnxRoslynCompilationService.cs new file mode 100644 index 0000000000..cd3f48ddc2 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/DnxRoslynCompilationService.cs @@ -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 +{ + /// + /// A type that uses Roslyn to compile C# content and to find out references. + /// + public class DnxRoslynCompilationService : ICompilationService + { + private readonly ConcurrentDictionary _metadataFileCache = + new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + + private readonly IApplicationEnvironment _environment; + private readonly ILibraryExporter _libraryExporter; + private readonly RazorViewEngineOptions _options; + private readonly Lazy> _applicationReferences; + + /// + /// Initalizes a new instance of the class. + /// + /// The environment for the executing application. + /// The library manager that provides export and reference information. + /// The that was used to generate the code. + /// Accessor to . + /// The . + /// The . + public DnxRoslynCompilationService(IApplicationEnvironment environment, + ILibraryExporter libraryExporter, + IMvcRazorHost host, + IOptions optionsAccessor, + IRazorViewEngineFileProviderAccessor fileProviderAccessor) + { + _environment = environment; + _libraryExporter = libraryExporter; + _options = optionsAccessor.Value; + _applicationReferences = new Lazy>(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 diagnostics) + { + var diagnosticGroups = diagnostics + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error) + .GroupBy(diagnostic => diagnostic.Location.GetMappedLineSpan().Path, StringComparer.Ordinal); + + var failures = new List(); + 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 GetApplicationReferences() + { + var references = new List(); + + // 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 \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcSampleFixture.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcSampleFixture.cs index 54aeff56ad..415ed5d8c9 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcSampleFixture.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcSampleFixture.cs @@ -6,7 +6,11 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public class MvcSampleFixture : MvcTestFixture { public MvcSampleFixture() +#if DNXCORE50 + :base("../../../../../../samples/") +#else : base("../../../../samples/") +#endif { } } diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcTestFixture.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcTestFixture.cs index a4805030c0..aeba9f443d 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcTestFixture.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/MvcTestFixture.cs @@ -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(); + 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, diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json index 4e8e93290e..19b5a6e630 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json @@ -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", diff --git a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/project.json b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/project.json index 6e8f94a4ca..b540c7e6ff 100644 --- a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/project.json +++ b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Localization.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Localization.Test/project.json index bff5355904..322a120290 100644 --- a/test/Microsoft.AspNetCore.Mvc.Localization.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Localization.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/project.json index 593a74ac8d..b243747d0a 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/project.json @@ -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": [ diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs deleted file mode 100644 index 190c39ff4e..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs +++ /dev/null @@ -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(); - 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(); - 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(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(); - - 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(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(); - - var mockFileInfo = new Mock(); - 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(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(); - 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(); - 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>(); - optionsAccessor.SetupGet(o => o.Value) - .Returns(options); - var compilationService = new DefaultRoslynCompilationService( - PlatformServices.Default.Application, - CompilationServices.Default.LibraryExporter, - Mock.Of(), - 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(); - 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 GetOptions(Action callback = null) - { - var razorViewEngineOptions = new RazorViewEngineOptions - { - CompilationCallback = callback ?? (c => { }), - }; - var options = new Mock>(); - options - .SetupGet(o => o.Value) - .Returns(razorViewEngineOptions); - - return options.Object; - } - - private IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null) - { - var options = new Mock(); - options.SetupGet(o => o.FileProvider) - .Returns(fileProvider ?? new TestFileProvider()); - - return options.Object; - } - } -} -#endif \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/ExpressionRewriterTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/ExpressionRewriterTest.cs index 578de54d61..9e55373f62 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/ExpressionRewriterTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/ExpressionRewriterTest.cs @@ -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 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(); - - 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)); } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Razor.Test/project.json index f7a12e247f..f52936f1e7 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/project.json @@ -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": [ diff --git a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/project.json b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/project.json index 2051f0d105..2de94cef2d 100644 --- a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/project.json @@ -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": [ diff --git a/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs index 4fd05807a5..77d0e72e89 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs @@ -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(AddDnxServices); + var options = GetOptions(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(AddDnxServices); + var options = GetOptions(AddViewEngineOptionsServices); // Assert Assert.Collection(options.ClientModelValidatorProviders, @@ -236,6 +235,7 @@ namespace Microsoft.AspNetCore.Mvc var serviceCollection = new ServiceCollection(); serviceCollection.AddMvc(); serviceCollection.AddTransient(); + 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()); - serviceCollection.AddSingleton(Mock.Of()); - serviceCollection.AddSingleton(Mock.Of()); serviceCollection.AddSingleton(Mock.Of()); var applicationEnvironment = new Mock(); - applicationEnvironment.SetupGet(e => e.ApplicationName) .Returns(typeof(MvcOptionsSetupTest).GetTypeInfo().Assembly.GetName().Name); diff --git a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs index 93454ca6d2..d7ae2a0a57 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs @@ -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() { { @@ -186,7 +166,11 @@ namespace Microsoft.AspNetCore.Mvc }, { typeof(IConfigureOptions), - razorViewEngineOptionsRegistrations + new[] + { + typeof(RazorViewEngineOptionsSetup), + typeof(DependencyContextRazorViewEngineOptionsSetup) + } }, { typeof(IActionConstraintProvider), diff --git a/test/Microsoft.AspNetCore.Mvc.Test/project.json b/test/Microsoft.AspNetCore.Mvc.Test/project.json index a49f9acea4..9d0bea763f 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.Test/project.json @@ -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" } } } diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/project.json b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/project.json index 0b2ee74ff2..180624b784 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/project.json +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/project.json b/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/project.json index c609edbcd0..1492cfb745 100644 --- a/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/project.json +++ b/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/project.json @@ -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-*" - } } } } \ No newline at end of file diff --git a/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs b/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs index 0662a17354..d11b5362fa 100644 --- a/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs +++ b/test/WebSites/RazorWebSite/Services/FrameworkSpecificHelper.cs @@ -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"; diff --git a/test/WebSites/RazorWebSite/Startup.cs b/test/WebSites/RazorWebSite/Startup.cs index 7d275862e6..fea427a65e 100644 --- a/test/WebSites/RazorWebSite/Startup.cs +++ b/test/WebSites/RazorWebSite/Startup.cs @@ -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 =>