From 133eff3119a5d80df8231a09c73148a4c7941f99 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 9 Feb 2018 17:28:16 -0800 Subject: [PATCH] Move to RazorProjectEngine. - Instead of using Razor/Mvc TemplateEngine use `RazorProjectEngine`. This involved changing several locations (each of which used `RazorTemplateEngine` in an entirely different way) to use the RazorProjectEngine's two Process methods. - Changed an unused public API `VisualStudioRazorParser.TemplateEngine` to `VisualStudioRazorParser.RazorProjectEngine`. - Ported the remainder of `RazorEngineBuilder`'s extension methods over to `RazorProjectEngineBuilder`. These were used in tests and our `RazorGenerate` tool. - Added a few test helper methods/classes to enable simple testing of the `RazorProjectEngine`. - Resolved several test hacks that were working around little discrepancies each of the `RazorTemplateEngine` APIs. - Changed the template engine factory service to be a project engine factory service. --- .../CodeGenerationBenchmark.cs | 30 ++--- .../Properties/AssemblyInfo.cs | 1 + .../RazorProjectEngineBuilderExtensions.cs | 127 ++++++++++++++++++ .../CompositeRazorProjectFileSystem.cs | 15 ++- .../GenerateCommand.cs | 32 ++--- ...cs => RazorProjectEngineFactoryService.cs} | 4 +- .../BackgroundParser.cs | 49 ++++--- .../DefaultImportDocumentManager.cs | 33 +++-- .../DefaultImportDocumentManagerFactory.cs | 4 +- ... => DefaultProjectEngineFactoryService.cs} | 26 ++-- ...aultProjectEngineFactoryServiceFactory.cs} | 6 +- .../DefaultVisualStudioRazorParser.cs | 20 +-- .../DefaultVisualStudioRazorParserFactory.cs | 12 +- ...ltVisualStudioRazorParserFactoryFactory.cs | 4 +- .../TextSnapshotProjectItem.cs | 65 +++++++++ .../TextSnapshotSourceDocument.cs | 79 ----------- .../VisualStudioRazorParser.cs | 2 +- src/RazorPageGenerator/Program.cs | 36 ++--- .../RazorProjectEngineBuilderExtensions.cs | 70 ++++++++++ .../Language/TestRazorProjectFileSystem.cs | 5 +- .../Properties/AssemblyInfo.cs | 2 + ...ultImportDocumentManagerIntegrationTest.cs | 6 +- .../DefaultImportDocumentManagerTest.cs | 4 +- ...DefaultProjectEngineFactoryServiceTest.cs} | 25 ++-- ...tVisualStudioRazorParserIntegrationTest.cs | 24 ++-- .../DefaultVisualStudioRazorParserTest.cs | 22 +-- .../RazorSyntaxTreePartialParserTest.cs | 50 +++---- .../RazorPageGeneratorTest.cs | 5 +- 28 files changed, 471 insertions(+), 287 deletions(-) rename src/Microsoft.CodeAnalysis.Razor.Workspaces/{RazorTemplateEngineFactoryService.cs => RazorProjectEngineFactoryService.cs} (61%) rename src/Microsoft.VisualStudio.Editor.Razor/{DefaultTemplateEngineFactoryService.cs => DefaultProjectEngineFactoryService.cs} (77%) rename src/Microsoft.VisualStudio.Editor.Razor/{DefaultTemplateEngineFactoryServiceFactory.cs => DefaultProjectEngineFactoryServiceFactory.cs} (60%) create mode 100644 src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotProjectItem.cs delete mode 100644 src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs create mode 100644 test/Microsoft.AspNetCore.Razor.Test.Common/Language/RazorProjectEngineBuilderExtensions.cs rename test/Microsoft.VisualStudio.Editor.Razor.Test/{DefaultTemplateEngineFactoryServiceTest.cs => DefaultProjectEngineFactoryServiceTest.cs} (89%) diff --git a/benchmarks/Microsoft.AspNetCore.Razor.Performance/CodeGenerationBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Razor.Performance/CodeGenerationBenchmark.cs index b4320782e6..c35e1db42f 100644 --- a/benchmarks/Microsoft.AspNetCore.Razor.Performance/CodeGenerationBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Razor.Performance/CodeGenerationBenchmark.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.IO; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Mvc.Razor.Extensions; @@ -21,33 +20,22 @@ namespace Microsoft.AspNetCore.Razor.Performance } var root = current; - - var engine = RazorEngine.Create(b => { RazorExtensions.Register(b); }); - var fileSystem = RazorProjectFileSystem.Create(root.FullName); + + ProjectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, b => RazorExtensions.Register(b)); ; - DesignTimeTemplateEngine = new MvcRazorTemplateEngine(RazorEngine.CreateDesignTime(b => { RazorExtensions.Register(b); }), fileSystem); - RuntimeTemplateEngine = new MvcRazorTemplateEngine(RazorEngine.Create(b => { RazorExtensions.Register(b); }), fileSystem); - - var codeDocument = RuntimeTemplateEngine.CreateCodeDocument(Path.Combine(root.FullName, "MSN.cshtml")); - - Imports = codeDocument.Imports; - MSN = codeDocument.Source; + MSN = fileSystem.GetItem(Path.Combine(root.FullName, "MSN.cshtml")); } - public RazorTemplateEngine DesignTimeTemplateEngine { get; } + public RazorProjectEngine ProjectEngine { get; } - public RazorTemplateEngine RuntimeTemplateEngine { get; } - - public IReadOnlyList Imports { get; } - - public RazorSourceDocument MSN { get; } + public RazorProjectItem MSN { get; } [Benchmark(Description = "Razor Design Time Code Generation of MSN.com")] public void CodeGeneration_DesignTime_LargeStaticFile() { - var codeDocument = RazorCodeDocument.Create(MSN, Imports); - var generated = DesignTimeTemplateEngine.GenerateCode(codeDocument); + var codeDocument = ProjectEngine.ProcessDesignTime(MSN); + var generated = codeDocument.GetCSharpDocument(); if (generated.Diagnostics.Count != 0) { @@ -58,8 +46,8 @@ namespace Microsoft.AspNetCore.Razor.Performance [Benchmark(Description = "Razor Runtime Code Generation of MSN.com")] public void CodeGeneration_Runtime_LargeStaticFile() { - var codeDocument = RazorCodeDocument.Create(MSN, Imports); - var generated = RuntimeTemplateEngine.GenerateCode(codeDocument); + var codeDocument = ProjectEngine.Process(MSN); + var generated = codeDocument.GetCSharpDocument(); if (generated.Diagnostics.Count != 0) { diff --git a/src/Microsoft.AspNetCore.Razor.Language/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Razor.Language/Properties/AssemblyInfo.cs index 02e2547355..7214d8baca 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Properties/AssemblyInfo.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.GenerateTool, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorProjectEngineBuilderExtensions.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorProjectEngineBuilderExtensions.cs index 6d14b838eb..4c3fe12cc7 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorProjectEngineBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorProjectEngineBuilderExtensions.cs @@ -2,13 +2,77 @@ // 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 Microsoft.AspNetCore.Razor.Language.CodeGeneration; +using Microsoft.AspNetCore.Razor.Language.Intermediate; namespace Microsoft.AspNetCore.Razor.Language { public static class RazorProjectEngineBuilderExtensions { + /// + /// Registers a class configuration delegate that gets invoked during code generation. + /// + /// The . + /// invoked to configure + /// during code generation. + /// The . + public static RazorProjectEngineBuilder ConfigureClass( + this RazorProjectEngineBuilder builder, + Action configureClass) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configureClass == null) + { + throw new ArgumentNullException(nameof(configureClass)); + } + + var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder); + configurationFeature.ConfigureClass.Add(configureClass); + return builder; + } + + /// + /// Sets the base type for generated types. + /// + /// The . + /// The name of the base type. + /// The . + public static RazorProjectEngineBuilder SetBaseType(this RazorProjectEngineBuilder builder, string baseType) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder); + configurationFeature.ConfigureClass.Add((document, @class) => @class.BaseType = baseType); + return builder; + } + + /// + /// Sets the namespace for generated types. + /// + /// The . + /// The name of the namespace. + /// The . + public static RazorProjectEngineBuilder SetNamespace(this RazorProjectEngineBuilder builder, string namespaceName) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder); + configurationFeature.ConfigureNamespace.Add((document, @namespace) => @namespace.Content = namespaceName); + return builder; + } + public static void SetImportFeature(this RazorProjectEngineBuilder builder, IImportProjectFeature feature) { if (builder == null) @@ -79,6 +143,27 @@ namespace Microsoft.AspNetCore.Razor.Language return builder; } + /// + /// Adds the provided documents as imports to all documents processed + /// by the . + /// + /// The . + /// The collection of imports. + /// The . + public static RazorProjectEngineBuilder AddDefaultImports(this RazorProjectEngineBuilder builder, params RazorSourceDocument[] imports) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + var existingImportFeature = builder.Features.OfType().First(); + var testImportFeature = new AdditionalImportsProjectFeature(existingImportFeature, imports); + builder.SetImportFeature(testImportFeature); + + return builder; + } + private static IRazorDirectiveFeature GetDirectiveFeature(RazorProjectEngineBuilder builder) { var directiveFeature = builder.Features.OfType().FirstOrDefault(); @@ -102,5 +187,47 @@ namespace Microsoft.AspNetCore.Razor.Language return targetExtensionFeature; } + + private static DefaultDocumentClassifierPassFeature GetDefaultDocumentClassifierPassFeature(RazorProjectEngineBuilder builder) + { + var configurationFeature = builder.Features.OfType().FirstOrDefault(); + if (configurationFeature == null) + { + configurationFeature = new DefaultDocumentClassifierPassFeature(); + builder.Features.Add(configurationFeature); + } + + return configurationFeature; + } + + private class AdditionalImportsProjectFeature : RazorProjectEngineFeatureBase, IImportProjectFeature + { + private readonly IImportProjectFeature _existingImportFeature; + private readonly RazorSourceDocument[] _imports; + + public override RazorProjectEngine ProjectEngine + { + get => base.ProjectEngine; + set + { + _existingImportFeature.ProjectEngine = value; + base.ProjectEngine = value; + } + } + + public AdditionalImportsProjectFeature(IImportProjectFeature existingImportFeature, params RazorSourceDocument[] imports) + { + _existingImportFeature = existingImportFeature; + _imports = imports; + } + + public IReadOnlyList GetImports(RazorProjectItem projectItem) + { + var imports = _existingImportFeature.GetImports(projectItem).ToList(); + imports.AddRange(_imports); + + return imports; + } + } } } diff --git a/src/Microsoft.AspNetCore.Razor.Tools/CompositeRazorProjectFileSystem.cs b/src/Microsoft.AspNetCore.Razor.Tools/CompositeRazorProjectFileSystem.cs index 5102cf056b..63fad347ee 100644 --- a/src/Microsoft.AspNetCore.Razor.Tools/CompositeRazorProjectFileSystem.cs +++ b/src/Microsoft.AspNetCore.Razor.Tools/CompositeRazorProjectFileSystem.cs @@ -3,24 +3,25 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.AspNetCore.Razor.Language; namespace Microsoft.AspNetCore.Razor.Tools { internal class CompositeRazorProjectFileSystem : RazorProjectFileSystem { - public CompositeRazorProjectFileSystem(IReadOnlyList projects) + public CompositeRazorProjectFileSystem(IReadOnlyList fileSystems) { - Projects = projects ?? throw new ArgumentNullException(nameof(projects)); + FileSystems = fileSystems ?? throw new ArgumentNullException(nameof(fileSystems)); } - public IReadOnlyList Projects { get; } + public IReadOnlyList FileSystems { get; } public override IEnumerable EnumerateItems(string basePath) { - foreach (var project in Projects) + foreach (var fileSystem in FileSystems) { - foreach (var result in project.EnumerateItems(basePath)) + foreach (var result in fileSystem.EnumerateItems(basePath)) { yield return result; } @@ -30,9 +31,9 @@ namespace Microsoft.AspNetCore.Razor.Tools public override RazorProjectItem GetItem(string path) { RazorProjectItem razorProjectItem = null; - foreach (var project in Projects) + foreach (var fileSystem in FileSystems) { - razorProjectItem = project.GetItem(path); + razorProjectItem = fileSystem.GetItem(path); if (razorProjectItem != null && razorProjectItem.Exists) { return razorProjectItem; diff --git a/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs b/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs index fc0a876940..0981cc1a03 100644 --- a/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs +++ b/src/Microsoft.AspNetCore.Razor.Tools/GenerateCommand.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Razor.Extensions; @@ -90,26 +91,20 @@ namespace Microsoft.AspNetCore.Razor.Tools tagHelperManifest = Path.Combine(projectDirectory, tagHelperManifest); var tagHelpers = GetTagHelpers(tagHelperManifest); - - var engine = RazorEngine.Create(b => + var inputItems = GetInputItems(projectDirectory, sources, outputs, relativePaths); + var compositeFileSystem = new CompositeRazorProjectFileSystem(new[] + { + GetVirtualRazorProjectSystem(inputItems), + RazorProjectFileSystem.Create(projectDirectory), + }); + var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, compositeFileSystem, b => { RazorExtensions.Register(b); b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, }); }); - - var inputItems = GetInputItems(projectDirectory, sources, outputs, relativePaths); - var compositeProject = new CompositeRazorProjectFileSystem( - new[] - { - GetVirtualRazorProjectSystem(inputItems), - RazorProjectFileSystem.Create(projectDirectory), - }); - - var templateEngine = new MvcRazorTemplateEngine(engine, compositeProject); - - var results = GenerateCode(templateEngine, inputItems); + var results = GenerateCode(projectEngine, inputItems); var success = true; @@ -180,14 +175,15 @@ namespace Microsoft.AspNetCore.Razor.Tools return items; } - private OutputItem[] GenerateCode(RazorTemplateEngine templateEngine, SourceItem[] inputs) + private OutputItem[] GenerateCode(RazorProjectEngine projectEngine, SourceItem[] inputs) { var outputs = new OutputItem[inputs.Length]; - Parallel.For(0, outputs.Length, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, i => + Parallel.For(0, outputs.Length, new ParallelOptions() { MaxDegreeOfParallelism = Debugger.IsAttached ? 1 : 4 }, i => { var inputItem = inputs[i]; - - var csharpDocument = templateEngine.GenerateCode(inputItem.FilePath); + var projectItem = projectEngine.FileSystem.GetItem(inputItem.FilePath); + var codeDocument = projectEngine.Process(projectItem); + var csharpDocument = codeDocument.GetCSharpDocument(); outputs[i] = new OutputItem(inputItem, csharpDocument); }); diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs b/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorProjectEngineFactoryService.cs similarity index 61% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs rename to src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorProjectEngineFactoryService.cs index 26ff5b803a..0388de4671 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorTemplateEngineFactoryService.cs +++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorProjectEngineFactoryService.cs @@ -7,8 +7,8 @@ using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Razor { - internal abstract class RazorTemplateEngineFactoryService : ILanguageService + internal abstract class RazorProjectEngineFactoryService : ILanguageService { - public abstract RazorTemplateEngine Create(string projectPath, Action configure); + public abstract RazorProjectEngine Create(string projectPath, Action configure); } } \ No newline at end of file diff --git a/src/Microsoft.VisualStudio.Editor.Razor/BackgroundParser.cs b/src/Microsoft.VisualStudio.Editor.Razor/BackgroundParser.cs index 887a98dab0..9a7cabb8e1 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/BackgroundParser.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/BackgroundParser.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; using System.Threading; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Legacy; @@ -18,10 +19,10 @@ namespace Microsoft.VisualStudio.Editor.Razor private MainThreadState _main; private BackgroundThread _bg; - public BackgroundParser(RazorTemplateEngine templateEngine, string filePath) + public BackgroundParser(RazorProjectEngine projectEngine, string filePath, string projectDirectory) { _main = new MainThreadState(filePath); - _bg = new BackgroundThread(_main, templateEngine, filePath); + _bg = new BackgroundThread(_main, projectEngine, filePath, projectDirectory); _main.ResultsReady += (sender, args) => OnResultsReady(args); } @@ -233,22 +234,25 @@ namespace Microsoft.VisualStudio.Editor.Razor private class BackgroundThread : ThreadStateBase { + private readonly string _filePath; + private readonly string _relativeFilePath; + private readonly string _projectDirectory; private MainThreadState _main; private Thread _backgroundThread; private CancellationToken _shutdownToken; - private RazorTemplateEngine _templateEngine; - private string _filePath; + private RazorProjectEngine _projectEngine; private RazorSyntaxTree _currentSyntaxTree; private IList _previouslyDiscarded = new List(); - public BackgroundThread(MainThreadState main, RazorTemplateEngine templateEngine, string fileName) + public BackgroundThread(MainThreadState main, RazorProjectEngine projectEngine, string filePath, string projectDirectory) { // Run on MAIN thread! _main = main; _shutdownToken = _main.CancelToken; - _templateEngine = templateEngine; - _filePath = fileName; - + _projectEngine = projectEngine; + _filePath = filePath; + _relativeFilePath = GetNormalizedRelativeFilePath(filePath, projectDirectory); + _projectDirectory = projectDirectory; _backgroundThread = new Thread(WorkerLoop); SetThreadId(_backgroundThread.ManagedThreadId); } @@ -262,8 +266,6 @@ namespace Microsoft.VisualStudio.Editor.Razor // **** BACKGROUND THREAD **** private void WorkerLoop() { - var fileNameOnly = Path.GetFileName(_filePath); - try { EnsureOnThread(); @@ -347,14 +349,31 @@ namespace Microsoft.VisualStudio.Editor.Razor { EnsureOnThread(); - var sourceDocument = new TextSnapshotSourceDocument(snapshot, _filePath); - var imports = _templateEngine.GetImports(_filePath); + var projectItem = new TextSnapshotProjectItem(snapshot, _projectDirectory, _relativeFilePath, _filePath); + var codeDocument = _projectEngine.ProcessDesignTime(projectItem); - var codeDocument = RazorCodeDocument.Create(sourceDocument, imports); - - _templateEngine.GenerateCode(codeDocument); return codeDocument; } + + private string GetNormalizedRelativeFilePath(string filePath, string projectDirectory) + { + if (filePath.StartsWith(projectDirectory, StringComparison.OrdinalIgnoreCase)) + { + filePath = filePath.Substring(projectDirectory.Length); + } + + if (filePath.Length > 1) + { + filePath = filePath.Replace('\\', '/'); + + if (filePath[0] != '/') + { + filePath = "/" + filePath; + } + } + + return filePath; + } } private class WorkParcel diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManager.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManager.cs index 36f600a59a..0783713d7c 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManager.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManager.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor; @@ -15,7 +16,7 @@ namespace Microsoft.VisualStudio.Editor.Razor private readonly FileChangeTrackerFactory _fileChangeTrackerFactory; private readonly ForegroundDispatcher _foregroundDispatcher; private readonly ErrorReporter _errorReporter; - private readonly RazorTemplateEngineFactoryService _templateEngineFactoryService; + private readonly RazorProjectEngineFactoryService _projectEngineFactoryService; private readonly Dictionary _importTrackerCache; public override event EventHandler Changed; @@ -24,7 +25,7 @@ namespace Microsoft.VisualStudio.Editor.Razor ForegroundDispatcher foregroundDispatcher, ErrorReporter errorReporter, FileChangeTrackerFactory fileChangeTrackerFactory, - RazorTemplateEngineFactoryService templateEngineFactoryService) + RazorProjectEngineFactoryService projectEngineFactoryService) { if (foregroundDispatcher == null) { @@ -41,15 +42,15 @@ namespace Microsoft.VisualStudio.Editor.Razor throw new ArgumentNullException(nameof(fileChangeTrackerFactory)); } - if (templateEngineFactoryService == null) + if (projectEngineFactoryService == null) { - throw new ArgumentNullException(nameof(templateEngineFactoryService)); + throw new ArgumentNullException(nameof(projectEngineFactoryService)); } _foregroundDispatcher = foregroundDispatcher; _errorReporter = errorReporter; _fileChangeTrackerFactory = fileChangeTrackerFactory; - _templateEngineFactoryService = templateEngineFactoryService; + _projectEngineFactoryService = projectEngineFactoryService; _importTrackerCache = new Dictionary(StringComparer.OrdinalIgnoreCase); } @@ -115,10 +116,26 @@ namespace Microsoft.VisualStudio.Editor.Razor private IEnumerable GetImportItems(VisualStudioDocumentTracker tracker) { var projectDirectory = Path.GetDirectoryName(tracker.ProjectPath); - var templateEngine = _templateEngineFactoryService.Create(projectDirectory, _ => { }); - var imports = templateEngine.GetImportItems(tracker.FilePath); + var projectEngine = _projectEngineFactoryService.Create(projectDirectory, _ => { }); + var trackerItem = projectEngine.FileSystem.GetItem(tracker.FilePath); + var importFeature = projectEngine.ProjectFeatures.OfType().FirstOrDefault(); - return imports; + // There should always be an import feature unless someone has misconfigured their RazorProjectEngine. + // In that case once we attempt to parse the Razor file we'll explode and give the a user a decent + // error message; for now, lets just be extra protective and assume 0 imports to not give a bad error. + var imports = importFeature?.GetImports(trackerItem) ?? Enumerable.Empty(); + var physicalImports = imports.Where(import => import.FilePath != null); + + // Now that we have non-dynamic imports we need to get their RazorProjectItem equivalents so we have their + // physical file paths (according to the FileSystem). + var projectItems = new List(); + foreach (var physicalImport in physicalImports) + { + var projectItem = projectEngine.FileSystem.GetItem(physicalImport.FilePath); + projectItems.Add(projectItem); + } + + return projectItems; } private void OnChanged(ImportTracker importTracker, FileChangeKind changeKind) diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManagerFactory.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManagerFactory.cs index 480374c4f8..47efa8b96c 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManagerFactory.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultImportDocumentManagerFactory.cs @@ -35,13 +35,13 @@ namespace Microsoft.VisualStudio.Editor.Razor var errorReporter = languageServices.WorkspaceServices.GetRequiredService(); var fileChangeTrackerFactory = languageServices.GetRequiredService(); - var templateEngineFactoryService = languageServices.GetRequiredService(); + var projectEngineFactoryService = languageServices.GetRequiredService(); return new DefaultImportDocumentManager( _foregroundDispatcher, errorReporter, fileChangeTrackerFactory, - templateEngineFactoryService); + projectEngineFactoryService); } } } diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultProjectEngineFactoryService.cs similarity index 77% rename from src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs rename to src/Microsoft.VisualStudio.Editor.Razor/DefaultProjectEngineFactoryService.cs index f4f7c8b608..5d1373729c 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultProjectEngineFactoryService.cs @@ -12,7 +12,7 @@ using MvcLatest = Microsoft.AspNetCore.Mvc.Razor.Extensions; namespace Microsoft.VisualStudio.Editor.Razor { - internal class DefaultTemplateEngineFactoryService : RazorTemplateEngineFactoryService + internal class DefaultProjectEngineFactoryService : RazorProjectEngineFactoryService { private readonly static MvcExtensibilityConfiguration DefaultConfiguration = new MvcExtensibilityConfiguration( RazorLanguageVersion.Version_2_0, @@ -22,7 +22,7 @@ namespace Microsoft.VisualStudio.Editor.Razor private readonly ProjectSnapshotManager _projectManager; - public DefaultTemplateEngineFactoryService(ProjectSnapshotManager projectManager) + public DefaultProjectEngineFactoryService(ProjectSnapshotManager projectManager) { if (projectManager == null) { @@ -32,7 +32,7 @@ namespace Microsoft.VisualStudio.Editor.Razor _projectManager = projectManager; } - public override RazorTemplateEngine Create(string projectPath, Action configure) + public override RazorProjectEngine Create(string projectPath, Action configure) { if (projectPath == null) { @@ -43,12 +43,14 @@ namespace Microsoft.VisualStudio.Editor.Razor var project = FindProject(projectPath); var configuration = (project?.Configuration as MvcExtensibilityConfiguration) ?? DefaultConfiguration; var razorLanguageVersion = configuration.LanguageVersion; - var razorConfiguration = new RazorConfiguration(razorLanguageVersion, "unnamed", Array.Empty()); - RazorEngine engine; + var razorConfiguration = new RazorConfiguration(razorLanguageVersion, "unnamed", Array.Empty()); + var fileSystem = RazorProjectFileSystem.Create(projectPath); + + RazorProjectEngine projectEngine; if (razorLanguageVersion.Major == 1) { - engine = RazorEngine.CreateCore(razorConfiguration, true, b => + projectEngine = RazorProjectEngine.Create(razorConfiguration, fileSystem, b => { configure?.Invoke(b); @@ -59,24 +61,18 @@ namespace Microsoft.VisualStudio.Editor.Razor Mvc1_X.RazorExtensions.RegisterViewComponentTagHelpers(b); } }); - - var templateEngine = new Mvc1_X.MvcRazorTemplateEngine(engine, RazorProjectFileSystem.Create(projectPath)); - templateEngine.Options.ImportsFileName = "_ViewImports.cshtml"; - return templateEngine; } else { - engine = RazorEngine.CreateCore(razorConfiguration, true, b => + projectEngine = RazorProjectEngine.Create(razorConfiguration, fileSystem, b => { configure?.Invoke(b); MvcLatest.RazorExtensions.Register(b); }); - - var templateEngine = new MvcLatest.MvcRazorTemplateEngine(engine, RazorProjectFileSystem.Create(projectPath)); - templateEngine.Options.ImportsFileName = "_ViewImports.cshtml"; - return templateEngine; } + + return projectEngine; } private ProjectSnapshot FindProject(string directory) diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryServiceFactory.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultProjectEngineFactoryServiceFactory.cs similarity index 60% rename from src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryServiceFactory.cs rename to src/Microsoft.VisualStudio.Editor.Razor/DefaultProjectEngineFactoryServiceFactory.cs index f95df76c08..babed97a5c 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryServiceFactory.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultProjectEngineFactoryServiceFactory.cs @@ -8,12 +8,12 @@ using Microsoft.CodeAnalysis.Razor.ProjectSystem; namespace Microsoft.VisualStudio.Editor.Razor { - [ExportLanguageServiceFactory(typeof(RazorTemplateEngineFactoryService), RazorLanguage.Name, ServiceLayer.Default)] - internal class DefaultTemplateEngineFactoryServiceFactory : ILanguageServiceFactory + [ExportLanguageServiceFactory(typeof(RazorProjectEngineFactoryService), RazorLanguage.Name, ServiceLayer.Default)] + internal class DefaultProjectEngineFactoryServiceFactory : ILanguageServiceFactory { public ILanguageService CreateLanguageService(HostLanguageServices languageServices) { - return new DefaultTemplateEngineFactoryService(languageServices.GetRequiredService()); + return new DefaultProjectEngineFactoryService(languageServices.GetRequiredService()); } } } \ No newline at end of file diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs index 053b980e86..7225f0dd8e 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs @@ -31,9 +31,9 @@ namespace Microsoft.VisualStudio.Editor.Razor private readonly VisualStudioCompletionBroker _completionBroker; private readonly VisualStudioDocumentTracker _documentTracker; private readonly ForegroundDispatcher _dispatcher; - private readonly RazorTemplateEngineFactoryService _templateEngineFactory; + private readonly RazorProjectEngineFactoryService _projectEngineFactory; private readonly ErrorReporter _errorReporter; - private RazorTemplateEngine _templateEngine; + private RazorProjectEngine _projectEngine; private RazorCodeDocument _codeDocument; private ITextSnapshot _snapshot; private bool _disposed; @@ -47,7 +47,7 @@ namespace Microsoft.VisualStudio.Editor.Razor public DefaultVisualStudioRazorParser( ForegroundDispatcher dispatcher, VisualStudioDocumentTracker documentTracker, - RazorTemplateEngineFactoryService templateEngineFactory, + RazorProjectEngineFactoryService projectEngineFactory, ErrorReporter errorReporter, VisualStudioCompletionBroker completionBroker) { @@ -61,9 +61,9 @@ namespace Microsoft.VisualStudio.Editor.Razor throw new ArgumentNullException(nameof(documentTracker)); } - if (templateEngineFactory == null) + if (projectEngineFactory == null) { - throw new ArgumentNullException(nameof(templateEngineFactory)); + throw new ArgumentNullException(nameof(projectEngineFactory)); } if (errorReporter == null) @@ -77,7 +77,7 @@ namespace Microsoft.VisualStudio.Editor.Razor } _dispatcher = dispatcher; - _templateEngineFactory = templateEngineFactory; + _projectEngineFactory = projectEngineFactory; _errorReporter = errorReporter; _completionBroker = completionBroker; _documentTracker = documentTracker; @@ -85,7 +85,7 @@ namespace Microsoft.VisualStudio.Editor.Razor _documentTracker.ContextChanged += DocumentTracker_ContextChanged; } - public override RazorTemplateEngine TemplateEngine => _templateEngine; + public override RazorProjectEngine ProjectEngine => _projectEngine; public override string FilePath => _documentTracker.FilePath; @@ -170,8 +170,8 @@ namespace Microsoft.VisualStudio.Editor.Razor _dispatcher.AssertForegroundThread(); var projectDirectory = Path.GetDirectoryName(_documentTracker.ProjectPath); - _templateEngine = _templateEngineFactory.Create(projectDirectory, ConfigureTemplateEngine); - _parser = new BackgroundParser(TemplateEngine, FilePath); + _projectEngine = _projectEngineFactory.Create(projectDirectory, ConfigureProjectEngine); + _parser = new BackgroundParser(ProjectEngine, FilePath, projectDirectory); _parser.ResultsReady += OnResultsReady; _parser.Start(); @@ -383,7 +383,7 @@ namespace Microsoft.VisualStudio.Editor.Razor DocumentStructureChanged?.Invoke(this, args); } - private void ConfigureTemplateEngine(IRazorEngineBuilder builder) + private void ConfigureProjectEngine(RazorProjectEngineBuilder builder) { builder.Features.Add(new VisualStudioParserOptionsFeature(_documentTracker.EditorSettings)); builder.Features.Add(new VisualStudioTagHelperFeature(_documentTracker.TagHelpers)); diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs index 9e9ea12135..5318ede596 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.VisualStudio.Editor.Razor internal class DefaultVisualStudioRazorParserFactory : VisualStudioRazorParserFactory { private readonly ForegroundDispatcher _dispatcher; - private readonly RazorTemplateEngineFactoryService _templateEngineFactoryService; + private readonly RazorProjectEngineFactoryService _projectEngineFactoryService; private readonly VisualStudioCompletionBroker _completionBroker; private readonly ErrorReporter _errorReporter; @@ -17,7 +17,7 @@ namespace Microsoft.VisualStudio.Editor.Razor ForegroundDispatcher dispatcher, ErrorReporter errorReporter, VisualStudioCompletionBroker completionBroker, - RazorTemplateEngineFactoryService templateEngineFactoryService) + RazorProjectEngineFactoryService projectEngineFactoryService) { if (dispatcher == null) { @@ -34,15 +34,15 @@ namespace Microsoft.VisualStudio.Editor.Razor throw new ArgumentNullException(nameof(completionBroker)); } - if (templateEngineFactoryService == null) + if (projectEngineFactoryService == null) { - throw new ArgumentNullException(nameof(templateEngineFactoryService)); + throw new ArgumentNullException(nameof(projectEngineFactoryService)); } _dispatcher = dispatcher; _errorReporter = errorReporter; _completionBroker = completionBroker; - _templateEngineFactoryService = templateEngineFactoryService; + _projectEngineFactoryService = projectEngineFactoryService; } public override VisualStudioRazorParser Create(VisualStudioDocumentTracker documentTracker) @@ -57,7 +57,7 @@ namespace Microsoft.VisualStudio.Editor.Razor var parser = new DefaultVisualStudioRazorParser( _dispatcher, documentTracker, - _templateEngineFactoryService, + _projectEngineFactoryService, _errorReporter, _completionBroker); return parser; diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs index d1f2d94cdc..38cfe5f189 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs @@ -35,13 +35,13 @@ namespace Microsoft.VisualStudio.Editor.Razor var workspaceServices = languageServices.WorkspaceServices; var errorReporter = workspaceServices.GetRequiredService(); var completionBroker = languageServices.GetRequiredService(); - var templateEngineFactoryService = languageServices.GetRequiredService(); + var projectEngineFactoryService = languageServices.GetRequiredService(); return new DefaultVisualStudioRazorParserFactory( _foregroundDispatcher, errorReporter, completionBroker, - templateEngineFactoryService); + projectEngineFactoryService); } } } \ No newline at end of file diff --git a/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotProjectItem.cs b/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotProjectItem.cs new file mode 100644 index 0000000000..4a605fd4a4 --- /dev/null +++ b/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotProjectItem.cs @@ -0,0 +1,65 @@ +// 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.IO; +using System.Text; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.VisualStudio.Text; + +namespace Microsoft.VisualStudio.Editor.Razor +{ + internal class TextSnapshotProjectItem : RazorProjectItem + { + private readonly ITextSnapshot _snapshot; + + public TextSnapshotProjectItem(ITextSnapshot snapshot, string projectDirectory, string relativeFilePath, string filePath) + { + if (snapshot == null) + { + throw new ArgumentNullException(nameof(snapshot)); + } + + if (string.IsNullOrEmpty(projectDirectory)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(projectDirectory)); + } + + if (string.IsNullOrEmpty(relativeFilePath)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(relativeFilePath)); + } + + if (string.IsNullOrEmpty(filePath)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(filePath)); + } + + _snapshot = snapshot; + BasePath = projectDirectory; + FilePath = relativeFilePath; + PhysicalPath = filePath; + } + + public override string BasePath { get; } + + public override string FilePath { get; } + + public override string PhysicalPath { get; } + + public override bool Exists => true; + + public override Stream Read() + { + var charArray = _snapshot.ToCharArray(0, _snapshot.Length); + + // We can assume UTF8 because the call path that reads from RazorProjectItem => SourceDocument + // can't determine the encoding and always assumes Encoding.UTF8. This is something that we might + // want to revisit in the future. + var bytes = Encoding.UTF8.GetBytes(charArray); + var memoryStream = new MemoryStream(bytes); + return memoryStream; + } + } + +} diff --git a/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs b/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs deleted file mode 100644 index ffe6c2f212..0000000000 --- a/src/Microsoft.VisualStudio.Editor.Razor/TextSnapshotSourceDocument.cs +++ /dev/null @@ -1,79 +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.AspNetCore.Razor.Language; -using Microsoft.VisualStudio.Text; - -namespace Microsoft.VisualStudio.Editor.Razor -{ - internal class TextSnapshotSourceDocument : RazorSourceDocument - { - private readonly ITextSnapshot _buffer; - private readonly RazorSourceLineCollection _lines; - - public TextSnapshotSourceDocument(ITextSnapshot snapshot, string filePath) - { - if (snapshot == null) - { - throw new ArgumentNullException(nameof(snapshot)); - } - - if (filePath == null) - { - throw new ArgumentNullException(nameof(filePath)); - } - - _buffer = snapshot; - FilePath = filePath; - - _lines = new DefaultRazorSourceLineCollection(this); - } - - public override char this[int position] => _buffer[position]; - - public override Encoding Encoding => Encoding.UTF8; - - public override int Length => _buffer.Length; - - public override RazorSourceLineCollection Lines => _lines; - - public override string FilePath { get; } - - public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) - { - if (destination == null) - { - throw new ArgumentNullException(nameof(destination)); - } - - if (sourceIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(sourceIndex)); - } - - if (destinationIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(destinationIndex)); - } - - if (count < 0 || count > Length - sourceIndex || count > destination.Length - destinationIndex) - { - throw new ArgumentOutOfRangeException(nameof(count)); - } - - if (count == 0) - { - return; - } - - for (var i = 0; i < count; i++) - { - destination[destinationIndex + i] = this[sourceIndex + i]; - } - } - - public override byte[] GetChecksum() => throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioRazorParser.cs b/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioRazorParser.cs index e8dd96cf90..41810db7c9 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioRazorParser.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioRazorParser.cs @@ -11,7 +11,7 @@ namespace Microsoft.VisualStudio.Editor.Razor { public abstract event EventHandler DocumentStructureChanged; - public abstract RazorTemplateEngine TemplateEngine { get; } + public abstract RazorProjectEngine ProjectEngine { get; } public abstract string FilePath { get; } diff --git a/src/RazorPageGenerator/Program.cs b/src/RazorPageGenerator/Program.cs index aecb2344dc..4646463889 100644 --- a/src/RazorPageGenerator/Program.cs +++ b/src/RazorPageGenerator/Program.cs @@ -31,8 +31,8 @@ Examples: var rootNamespace = args[0]; var targetProjectDirectory = args.Length > 1 ? args[1] : Directory.GetCurrentDirectory(); - var razorEngine = CreateRazorEngine(rootNamespace); - var results = MainCore(razorEngine, targetProjectDirectory); + var projectEngine = CreateProjectEngine(rootNamespace, targetProjectDirectory); + var results = MainCore(projectEngine, targetProjectDirectory); foreach (var result in results) { @@ -45,9 +45,10 @@ Examples: return 0; } - public static RazorEngine CreateRazorEngine(string rootNamespace, Action configure = null) + public static RazorProjectEngine CreateProjectEngine(string rootNamespace, string targetProjectDirectory, Action configure = null) { - var razorEngine = RazorEngine.Create(builder => + var fileSystem = RazorProjectFileSystem.Create(targetProjectDirectory); + var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder => { builder .SetNamespace(rootNamespace) @@ -66,20 +67,18 @@ Examples: { configure(builder); } - }); - return razorEngine; - } - public static IList MainCore(RazorEngine razorEngine, string targetProjectDirectory) - { - var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories); - var razorProject = RazorProjectFileSystem.Create(targetProjectDirectory); - var templateEngine = new RazorTemplateEngine(razorEngine, razorProject); - templateEngine.Options.DefaultImports = RazorSourceDocument.Create(@" + builder.AddDefaultImports(RazorSourceDocument.Create(@" @using System @using System.Threading.Tasks -", fileName: null); +", fileName: null)); + }); + return projectEngine; + } + public static IList MainCore(RazorProjectEngine projectEngine, string targetProjectDirectory) + { + var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories); var fileCount = 0; var results = new List(); @@ -88,7 +87,7 @@ Examples: Console.WriteLine(); Console.WriteLine(" Generating code files for views in {0}", viewDir); var viewDirPath = viewDir.Substring(targetProjectDirectory.Length).Replace('\\', '/'); - var cshtmlFiles = razorProject.EnumerateItems(viewDirPath); + var cshtmlFiles = projectEngine.FileSystem.EnumerateItems(viewDirPath); if (!cshtmlFiles.Any()) { @@ -99,7 +98,7 @@ Examples: foreach (var item in cshtmlFiles) { Console.WriteLine(" Generating code file for view {0}...", item.FileName); - results.Add(GenerateCodeFile(templateEngine, item)); + results.Add(GenerateCodeFile(projectEngine, item)); Console.WriteLine(" Done!"); fileCount++; } @@ -108,10 +107,11 @@ Examples: return results; } - private static RazorPageGeneratorResult GenerateCodeFile(RazorTemplateEngine templateEngine, RazorProjectItem projectItem) + private static RazorPageGeneratorResult GenerateCodeFile(RazorProjectEngine projectEngine, RazorProjectItem projectItem) { var projectItemWrapper = new FileSystemRazorProjectItemWrapper(projectItem); - var cSharpDocument = templateEngine.GenerateCode(projectItemWrapper); + var codeDocument = projectEngine.Process(projectItemWrapper); + var cSharpDocument = codeDocument.GetCSharpDocument(); if (cSharpDocument.Diagnostics.Any()) { var diagnostics = string.Join(Environment.NewLine, cSharpDocument.Diagnostics); diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/RazorProjectEngineBuilderExtensions.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/RazorProjectEngineBuilderExtensions.cs new file mode 100644 index 0000000000..bcea84e918 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/RazorProjectEngineBuilderExtensions.cs @@ -0,0 +1,70 @@ +// 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.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language.IntegrationTests; +using Microsoft.AspNetCore.Razor.Language.Intermediate; + +namespace Microsoft.AspNetCore.Razor.Language +{ + public static class RazorProjectEngineBuilderExtensions + { + public static RazorProjectEngineBuilder AddTagHelpers(this RazorProjectEngineBuilder builder, params TagHelperDescriptor[] tagHelpers) + { + return AddTagHelpers(builder, (IEnumerable)tagHelpers); + } + + public static RazorProjectEngineBuilder AddTagHelpers(this RazorProjectEngineBuilder builder, IEnumerable tagHelpers) + { + var feature = (TestTagHelperFeature)builder.Features.OfType().FirstOrDefault(); + if (feature == null) + { + feature = new TestTagHelperFeature(); + builder.Features.Add(feature); + } + + feature.TagHelpers.AddRange(tagHelpers); + return builder; + } + + public static RazorProjectEngineBuilder ConfigureDocumentClassifier(this RazorProjectEngineBuilder builder) + { + var feature = builder.Features.OfType().FirstOrDefault(); + if (feature == null) + { + feature = new DefaultDocumentClassifierPassFeature(); + builder.Features.Add(feature); + } + + feature.ConfigureNamespace.Clear(); + feature.ConfigureClass.Clear(); + feature.ConfigureMethod.Clear(); + + feature.ConfigureNamespace.Add((RazorCodeDocument codeDocument, NamespaceDeclarationIntermediateNode node) => + { + node.Content = "Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles"; + }); + + feature.ConfigureClass.Add((RazorCodeDocument codeDocument, ClassDeclarationIntermediateNode node) => + { + node.ClassName = IntegrationTestBase.FileName.Replace('/', '_'); + node.Modifiers.Clear(); + node.Modifiers.Add("public"); + }); + + feature.ConfigureMethod.Add((RazorCodeDocument codeDocument, MethodDeclarationIntermediateNode node) => + { + node.Modifiers.Clear(); + node.Modifiers.Add("public"); + node.Modifiers.Add("async"); + node.MethodName = "ExecuteAsync"; + node.ReturnType = typeof(Task).FullName; + }); + + return builder; + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectFileSystem.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectFileSystem.cs index 08528b1014..39ff443eb5 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectFileSystem.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Language/TestRazorProjectFileSystem.cs @@ -4,11 +4,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace Microsoft.AspNetCore.Razor.Language { - public class TestRazorProjectFileSystem : RazorProjectFileSystem + internal class TestRazorProjectFileSystem : DefaultRazorProjectFileSystem { public static RazorProjectFileSystem Empty = new TestRazorProjectFileSystem(); @@ -19,7 +18,7 @@ namespace Microsoft.AspNetCore.Razor.Language { } - public TestRazorProjectFileSystem(IList items) + public TestRazorProjectFileSystem(IList items) : base("/") { _lookup = items.ToDictionary(item => item.FilePath); } diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Properties/AssemblyInfo.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Properties/AssemblyInfo.cs index 3a2cadef34..576c4e4e44 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Properties/AssemblyInfo.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Language.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerIntegrationTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerIntegrationTest.cs index 18d890faac..5494ba8a4a 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerIntegrationTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerIntegrationTest.cs @@ -21,7 +21,7 @@ namespace Microsoft.VisualStudio.Editor.Razor var testImportsPath = "C:\\path\\to\\project\\_ViewImports.cshtml"; var tracker = Mock.Of(t => t.FilePath == filePath && t.ProjectPath == projectPath); var anotherTracker = Mock.Of(t => t.FilePath == anotherFilePath && t.ProjectPath == projectPath); - var templateEngineFactoryService = GetTemplateEngineFactoryService(); + var templateEngineFactoryService = GetProjectEngineFactoryService(); var fileChangeTracker = new Mock(); fileChangeTracker.Setup(f => f.FilePath).Returns(testImportsPath); var fileChangeTrackerFactory = new Mock(); @@ -58,12 +58,12 @@ namespace Microsoft.VisualStudio.Editor.Razor Assert.True(called); } - private RazorTemplateEngineFactoryService GetTemplateEngineFactoryService() + private RazorProjectEngineFactoryService GetProjectEngineFactoryService() { var projectManager = new Mock(); projectManager.Setup(p => p.Projects).Returns(Array.Empty()); - var service = new DefaultTemplateEngineFactoryService(projectManager.Object); + var service = new DefaultProjectEngineFactoryService(projectManager.Object); return service; } } diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerTest.cs index 856461052f..c32bbd0af3 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultImportDocumentManagerTest.cs @@ -137,12 +137,12 @@ namespace Microsoft.VisualStudio.Editor.Razor manager.OnUnsubscribed(tracker); } - private RazorTemplateEngineFactoryService GetTemplateEngineFactoryService() + private RazorProjectEngineFactoryService GetTemplateEngineFactoryService() { var projectManager = new Mock(); projectManager.Setup(p => p.Projects).Returns(Array.Empty()); - var service = new DefaultTemplateEngineFactoryService(projectManager.Object); + var service = new DefaultProjectEngineFactoryService(projectManager.Object); return service; } } diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTemplateEngineFactoryServiceTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectEngineFactoryServiceTest.cs similarity index 89% rename from test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTemplateEngineFactoryServiceTest.cs rename to test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectEngineFactoryServiceTest.cs index 5e83b06042..a9ef8baba3 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTemplateEngineFactoryServiceTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectEngineFactoryServiceTest.cs @@ -14,9 +14,9 @@ using MvcLatest = Microsoft.AspNetCore.Mvc.Razor.Extensions; namespace Microsoft.VisualStudio.Editor.Razor { - public class DefaultTemplateEngineFactoryServiceTest + public class DefaultProjectEngineFactoryServiceTest { - public DefaultTemplateEngineFactoryServiceTest() + public DefaultProjectEngineFactoryServiceTest() { Project project = null; @@ -35,7 +35,7 @@ namespace Microsoft.VisualStudio.Editor.Razor public Workspace Workspace { get; } [Fact] - public void Create_CreatesDesignTimeTemplateEngine_ForLatest() + public void Create_CreatesTemplateEngine_ForLatest() { // Arrange var projectManager = new TestProjectSnapshotManager(Workspace); @@ -49,13 +49,12 @@ namespace Microsoft.VisualStudio.Editor.Razor new ProjectExtensibilityAssembly(new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version("2.0.0.0")))), }); - var factoryService = new DefaultTemplateEngineFactoryService(projectManager); + var factoryService = new DefaultProjectEngineFactoryService(projectManager); // Act var engine = factoryService.Create("/TestPath/SomePath/", b => { b.Features.Add(new MyCoolNewFeature()); - Assert.True(b.DesignTime); }); // Assert @@ -65,7 +64,7 @@ namespace Microsoft.VisualStudio.Editor.Razor } [Fact] - public void Create_CreatesDesignTimeTemplateEngine_ForVersion1_1() + public void Create_CreatesTemplateEngine_ForVersion1_1() { // Arrange var projectManager = new TestProjectSnapshotManager(Workspace); @@ -79,13 +78,12 @@ namespace Microsoft.VisualStudio.Editor.Razor new ProjectExtensibilityAssembly(new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version("1.1.3.0")))), }); - var factoryService = new DefaultTemplateEngineFactoryService(projectManager); + var factoryService = new DefaultProjectEngineFactoryService(projectManager); // Act var engine = factoryService.Create("/TestPath/SomePath/", b => { b.Features.Add(new MyCoolNewFeature()); - Assert.True(b.DesignTime); }); // Assert @@ -109,7 +107,7 @@ namespace Microsoft.VisualStudio.Editor.Razor new ProjectExtensibilityAssembly(new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version("1.0.0.0")))), }); - var factoryService = new DefaultTemplateEngineFactoryService(projectManager); + var factoryService = new DefaultProjectEngineFactoryService(projectManager); // Act var engine = factoryService.Create("/TestPath/SomePath/", b => @@ -138,13 +136,12 @@ namespace Microsoft.VisualStudio.Editor.Razor new ProjectExtensibilityAssembly(new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version("3.0.0.0")))), }); - var factoryService = new DefaultTemplateEngineFactoryService(projectManager); + var factoryService = new DefaultProjectEngineFactoryService(projectManager); // Act var engine = factoryService.Create("/TestPath/SomePath/", b => { b.Features.Add(new MyCoolNewFeature()); - Assert.True(b.DesignTime); }); // Assert @@ -159,13 +156,12 @@ namespace Microsoft.VisualStudio.Editor.Razor // Arrange var projectManager = new TestProjectSnapshotManager(Workspace); - var factoryService = new DefaultTemplateEngineFactoryService(projectManager); + var factoryService = new DefaultProjectEngineFactoryService(projectManager); // Act var engine = factoryService.Create("/TestPath/DifferentPath/", b => { b.Features.Add(new MyCoolNewFeature()); - Assert.True(b.DesignTime); }); // Assert @@ -181,13 +177,12 @@ namespace Microsoft.VisualStudio.Editor.Razor var projectManager = new TestProjectSnapshotManager(Workspace); projectManager.ProjectAdded(Project); - var factoryService = new DefaultTemplateEngineFactoryService(projectManager); + var factoryService = new DefaultProjectEngineFactoryService(projectManager); // Act var engine = factoryService.Create("/TestPath/DifferentPath/", b => { b.Features.Add(new MyCoolNewFeature()); - Assert.True(b.DesignTime); }); // Assert diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs index 9b38140366..6f4c0086cd 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Threading; @@ -525,34 +524,27 @@ namespace Microsoft.VisualStudio.Editor.Razor return new TestParserManager(parser); } - private static RazorTemplateEngineFactoryService CreateTemplateEngineFactory( + private static RazorProjectEngineFactoryService CreateTemplateEngineFactory( string path = TestLinePragmaFileName, IEnumerable tagHelpers = null) { - var engine = RazorEngine.CreateDesignTime(builder => + var fileSystem = new TestRazorProjectFileSystem(); + var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder => { RazorExtensions.Register(builder); + builder.AddDefaultImports(RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml")); + if (tagHelpers != null) { builder.AddTagHelpers(tagHelpers); } }); - // GetImports on RazorTemplateEngine will at least check that the item exists, so we need to pretend - // that it does. - var items = new List(); - items.Add(new TestRazorProjectItem(path)); + var projectEngineFactoryService = Mock.Of( + service => service.Create(It.IsAny(), It.IsAny>()) == projectEngine); - var project = new TestRazorProjectFileSystem(items); - - var templateEngine = new RazorTemplateEngine(engine, project); - templateEngine.Options.DefaultImports = RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml"); - - var templateEngineFactory = Mock.Of( - service => service.Create(It.IsAny(), It.IsAny>()) == templateEngine); - - return templateEngineFactory; + return projectEngineFactoryService; } private async Task RunTypeKeywordTestAsync(string keyword) diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs index 38075b0460..8747324211 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs @@ -32,7 +32,7 @@ namespace Microsoft.VisualStudio.Editor.Razor var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of()); parser.Dispose(); @@ -48,7 +48,7 @@ namespace Microsoft.VisualStudio.Editor.Razor var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of()); parser.Dispose(); @@ -64,7 +64,7 @@ namespace Microsoft.VisualStudio.Editor.Razor var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of()); parser.Dispose(); @@ -80,7 +80,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of())) { @@ -108,7 +108,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, documentTracker, - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of())) { @@ -139,7 +139,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of()) { @@ -169,7 +169,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of()) { @@ -198,7 +198,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of())) { @@ -222,7 +222,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, documentTracker, - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of())) { @@ -242,7 +242,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(isSupportedProject: true), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of())) { @@ -261,7 +261,7 @@ namespace Microsoft.VisualStudio.Editor.Razor using (var parser = new DefaultVisualStudioRazorParser( Dispatcher, CreateDocumentTracker(isSupportedProject: false), - Mock.Of(), + Mock.Of(), new DefaultErrorReporter(), Mock.Of())) { diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/RazorSyntaxTreePartialParserTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/RazorSyntaxTreePartialParserTest.cs index 074fa0e1be..529e0126e8 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/RazorSyntaxTreePartialParserTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/RazorSyntaxTreePartialParserTest.cs @@ -3,14 +3,12 @@ using System; using System.Collections.Generic; -using System.Linq; using Microsoft.AspNetCore.Mvc.Razor.Extensions; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.VisualStudio.Test; using Microsoft.VisualStudio.Text; using Xunit; -using Span = Microsoft.AspNetCore.Razor.Language.Legacy.Span; namespace Microsoft.VisualStudio.Editor.Razor { @@ -44,12 +42,13 @@ namespace Microsoft.VisualStudio.Editor.Razor { builder.Build() }; - var templateEngine = CreateTemplateEngine(tagHelpers: descriptors); - var document = TestRazorCodeDocument.Create( - TestRazorSourceDocument.Create(edit.OldSnapshot.GetText()), - new[] { templateEngine.Options.DefaultImports }); - templateEngine.Engine.Process(document); - var syntaxTree = document.GetSyntaxTree(); + var projectEngine = CreateProjectEngine(tagHelpers: descriptors); + var projectItem = new TestRazorProjectItem("Index.cshtml") + { + Content = edit.OldSnapshot.GetText() + }; + var codeDocument = projectEngine.Process(projectItem); + var syntaxTree = codeDocument.GetSyntaxTree(); var parser = new RazorSyntaxTreePartialParser(syntaxTree); // Act @@ -115,12 +114,13 @@ namespace Microsoft.VisualStudio.Editor.Razor attribute.SetPropertyName("StringAttribute"); }); var descriptors = new[] { builder.Build() }; - var templateEngine = CreateTemplateEngine(tagHelpers: descriptors); - var document = TestRazorCodeDocument.Create( - TestRazorSourceDocument.Create(edit.OldSnapshot.GetText()), - new[] { templateEngine.Options.DefaultImports }); - templateEngine.Engine.Process(document); - var syntaxTree = document.GetSyntaxTree(); + var projectEngine = CreateProjectEngine(tagHelpers: descriptors); + var sourceDocument = new TestRazorProjectItem("Index.cshtml") + { + Content = edit.OldSnapshot.GetText() + }; + var codeDocument = projectEngine.Process(sourceDocument); + var syntaxTree = codeDocument.GetSyntaxTree(); var parser = new RazorSyntaxTreePartialParser(syntaxTree); // Act @@ -548,7 +548,7 @@ namespace Microsoft.VisualStudio.Editor.Razor private void RunPartialParseRejectionTest(TestEdit edit, PartialParseResultInternal additionalFlags = 0) { - var templateEngine = CreateTemplateEngine(); + var templateEngine = CreateProjectEngine(); var document = TestRazorCodeDocument.Create(edit.OldSnapshot.GetText()); templateEngine.Engine.Process(document); var syntaxTree = document.GetSyntaxTree(); @@ -560,7 +560,7 @@ namespace Microsoft.VisualStudio.Editor.Razor private static void RunPartialParseTest(TestEdit edit, Block expectedTree, PartialParseResultInternal additionalFlags = 0) { - var templateEngine = CreateTemplateEngine(); + var templateEngine = CreateProjectEngine(); var document = TestRazorCodeDocument.Create(edit.OldSnapshot.GetText()); templateEngine.Engine.Process(document); var syntaxTree = document.GetSyntaxTree(); @@ -580,30 +580,24 @@ namespace Microsoft.VisualStudio.Editor.Razor return new TestEdit(sourceChange, oldSnapshot, changedSnapshot); } - private static RazorTemplateEngine CreateTemplateEngine( + private static RazorProjectEngine CreateProjectEngine( string path = "C:\\This\\Path\\Is\\Just\\For\\Line\\Pragmas.cshtml", IEnumerable tagHelpers = null) { - var engine = RazorEngine.CreateDesignTime(builder => + var fileSystem = new TestRazorProjectFileSystem(); + var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder => { RazorExtensions.Register(builder); + builder.AddDefaultImports(RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml")); + if (tagHelpers != null) { builder.AddTagHelpers(tagHelpers); } }); - // GetImports on RazorTemplateEngine will at least check that the item exists, so we need to pretend - // that it does. - var items = new List(); - items.Add(new TestRazorProjectItem(path)); - - var project = new TestRazorProjectFileSystem(items); - - var templateEngine = new RazorTemplateEngine(engine, project); - templateEngine.Options.DefaultImports = RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml"); - return templateEngine; + return projectEngine; } } } diff --git a/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs b/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs index 81465d9541..613df16b0c 100644 --- a/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs +++ b/test/RazorPageGenerator.Test/RazorPageGeneratorTest.cs @@ -35,9 +35,10 @@ namespace RazorPageGenerator.Test { // Arrange var projectDirectory = TestProject.GetProjectDirectory(GetType()); - var razorEngine = Program.CreateRazorEngine("Microsoft.AspNetCore.TestGenerated"); + var projectEngine = Program.CreateProjectEngine("Microsoft.AspNetCore.TestGenerated", projectDirectory); + // Act - var results = Program.MainCore(razorEngine, projectDirectory); + var results = Program.MainCore(projectEngine, projectDirectory); // Assert Assert.Collection(results,