diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs index bf3e941f0b..89cf2f120e 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/DefaultRoslynCompilationService.cs @@ -33,7 +33,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal private const string CS0246 = nameof(CS0246); private readonly CSharpCompiler _compiler; - private readonly IFileProvider _fileProvider; private readonly ILogger _logger; private readonly Action _compilationCallback; @@ -42,16 +41,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal /// /// The . /// Accessor to . - /// The . /// The . public DefaultRoslynCompilationService( CSharpCompiler compiler, - IRazorViewEngineFileProviderAccessor fileProviderAccessor, IOptions optionsAccessor, ILoggerFactory loggerFactory) { _compiler = compiler; - _fileProvider = fileProviderAccessor.FileProvider; _compilationCallback = optionsAccessor.Value.CompilationCallback; _logger = loggerFactory.CreateLogger(); } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/Internal/ChunkVisitorTestFactory.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/Internal/ChunkVisitorTestFactory.cs deleted file mode 100644 index b3a3621f61..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/Internal/ChunkVisitorTestFactory.cs +++ /dev/null @@ -1,175 +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.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Razor; -using Microsoft.AspNetCore.Razor.Chunks; -using Microsoft.AspNetCore.Razor.Chunks.Generators; -using Microsoft.AspNetCore.Razor.CodeGenerators; -using Microsoft.AspNetCore.Razor.Compilation.TagHelpers; -using Microsoft.AspNetCore.Razor.TagHelpers; - -namespace Microsoft.AspNetCore.Mvc.Razor.Host -{ - public static class ChunkVisitorTestFactory - { - private static string _testClass = "TestClass"; - private static string _testNamespace = "TestNamespace"; - private static string _testFile = "TestFile"; - - public static CodeGeneratorContext CreateCodeGeneratorContext() - { - var language = new CSharpRazorCodeLanguage(); - var host = new RazorEngineHost(language); - var chunkGeneratorContext = new ChunkGeneratorContext - ( - host, - _testClass, - _testNamespace, - _testFile, - shouldGenerateLinePragmas: false - ); - - var codeGeneratorContext = new CodeGeneratorContext( - chunkGeneratorContext, - errorSink: new ErrorSink()); - return codeGeneratorContext; - } - - public static IList GetTestChunks(bool visitedTagHelperChunks) - { - return new List - { - GetTagHelperChunk("Baz"), - GetNestedViewComponentTagHelperChunk("Foo", visitedTagHelperChunks), - GetViewComponentTagHelperChunk("Bar", visitedTagHelperChunks), - GetIndexerViewComponentTagHelperChunk( - "Bee", - visitedTagHelperChunks, - "System.Collections.Generic.Dictionary>"), - }; - } - - private static TagHelperChunk GetTagHelperChunk(string name) - { - var tagHelperChunk = new TagHelperChunk( - name.ToLowerInvariant(), - TagMode.SelfClosing, - new List(), - new List - { - new TagHelperDescriptor - { - AssemblyName = $"{name}Assembly", - TagName = name.ToLowerInvariant(), - TypeName = $"{name}Type", - } - }); - - return tagHelperChunk; - } - - private static ParentChunk GetNestedViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks) - { - var parentChunk = GetTagHelperChunk("blah"); - var tagHelperChunk = GetViewComponentTagHelperChunk(name, visitedTagHelperChunks); - parentChunk.Children.Add(tagHelperChunk); - return parentChunk; - } - - private static TagHelperChunk GetViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks) - { - var typeName = visitedTagHelperChunks ? $"{_testNamespace}.{_testClass}.{name}Type" : $"{name}Type"; - - var attribute = new TagHelperAttributeDescriptor - { - Name = "attribute", - PropertyName = "Attribute", - TypeName = typeof(string).FullName - }; - - var requiredAttribute = new TagHelperRequiredAttributeDescriptor - { - Name = "Attribute" - }; - - var tagHelperDescriptor = new TagHelperDescriptor - { - AssemblyName = $"{name}Assembly", - TagName = name.ToLowerInvariant(), - TypeName = typeName, - Attributes = new[] - { - attribute - }, - RequiredAttributes = new[] - { - requiredAttribute - } - }; - - tagHelperDescriptor.PropertyBag.Add( - ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, - name); - - var tagHelperChunk = new TagHelperChunk( - $"vc:{name.ToLowerInvariant()}", - TagMode.SelfClosing, - new List(), - new[] - { - tagHelperDescriptor - }); - - return tagHelperChunk; - } - - private static TagHelperChunk GetIndexerViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks, string attributeTypeName) - { - var typeName = visitedTagHelperChunks ? $"{_testNamespace}.{_testClass}.{name}Type" : $"{name}Type"; - - var attribute = new TagHelperAttributeDescriptor - { - Name = "attribute", - PropertyName = "Attribute", - TypeName = attributeTypeName - }; - - var indexerAttribute = new TagHelperAttributeDescriptor - { - Name = attribute.Name + "-", - PropertyName = attribute.PropertyName, - TypeName = attributeTypeName, - IsIndexer = true - }; - - var tagHelperDescriptor = new TagHelperDescriptor - { - AssemblyName = $"{name}Assembly", - TagName = name.ToLowerInvariant(), - TypeName = typeName, - Attributes = new[] - { - attribute, - indexerAttribute - } - }; - - tagHelperDescriptor.PropertyBag.Add( - ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, - name); - - var tagHelperChunk = new TagHelperChunk( - $"vc:{name.ToLowerInvariant()}", - TagMode.SelfClosing, - new List(), - new[] - { - tagHelperDescriptor - }); - - return tagHelperChunk; - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/Internal/TagHelperChunkDecoratorTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/Internal/TagHelperChunkDecoratorTest.cs deleted file mode 100644 index d6edfdd2d9..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/Internal/TagHelperChunkDecoratorTest.cs +++ /dev/null @@ -1,68 +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.Linq; -using Microsoft.AspNetCore.Razor.Chunks; -using Microsoft.AspNetCore.Razor.Parser.SyntaxTree; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.Mvc.Razor.Host.Test -{ - public class TagHelperChunkDecoratorTest - { - #if OLD_RAZOR - [Fact] - public void Accept_CorrectlyDecoratesViewComponentChunks() - { - // Arrange - var codeGeneratorContext = ChunkVisitorTestFactory.CreateCodeGeneratorContext(); - var syntaxTreeNode = new Mock(new SpanBuilder()); - foreach (var chunk in ChunkVisitorTestFactory.GetTestChunks(visitedTagHelperChunks: false)) - { - codeGeneratorContext.ChunkTreeBuilder.AddChunk(chunk, syntaxTreeNode.Object); - } - - var tagHelperChunkDecorator = new TagHelperChunkDecorator(codeGeneratorContext); - var expectedChunks = ChunkVisitorTestFactory.GetTestChunks(visitedTagHelperChunks: true); - - // Act - var resultChunks = codeGeneratorContext.ChunkTreeBuilder.Root.Children; - tagHelperChunkDecorator.Accept(resultChunks); - - // Assert - // Test the normal tag helper chunk, Baz. - Assert.Equal(expectedChunks.Count, resultChunks.Count); - - var expectedTagHelperChunk = (TagHelperChunk)expectedChunks[0]; - var resultTagHelperChunk = Assert.IsType(resultChunks[0]); - - Assert.Equal( - expectedTagHelperChunk.Descriptors.First().TypeName, - Assert.Single(resultTagHelperChunk.Descriptors).TypeName); - - // Test the parent chunk with view component tag helper inside, Foo. - var expectedParentChunk = (ParentChunk)expectedChunks[1]; - var resultParentChunk = Assert.IsType(resultChunks[1]); - Assert.Single(resultParentChunk.Children); - - expectedTagHelperChunk = (TagHelperChunk)expectedParentChunk.Children.First(); - resultTagHelperChunk = (TagHelperChunk)resultParentChunk.Children.First(); - - Assert.Equal(expectedTagHelperChunk.Descriptors.First().TypeName, - resultTagHelperChunk.Descriptors.First().TypeName, - StringComparer.Ordinal); - - // Test the view component tag helper, Bar. - expectedTagHelperChunk = expectedChunks.ElementAt(2) as TagHelperChunk; - resultTagHelperChunk = resultChunks.ElementAt(2) as TagHelperChunk; - Assert.NotNull(resultTagHelperChunk); - - Assert.Equal(expectedTagHelperChunk.Descriptors.First().TypeName, - resultTagHelperChunk.Descriptors.First().TypeName, - StringComparer.Ordinal); - } -#endif - } -} diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperPassTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperPassTest.cs index fe69548cb2..375dde326e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperPassTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Host.Test/ViewComponentTagHelperPassTest.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.Evolution; using Microsoft.AspNetCore.Razor.Evolution.Intermediate; using Microsoft.AspNetCore.Razor.Evolution.Legacy; @@ -38,7 +36,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host TypeName = "System.Int32", Name = "Foo", } - } } }; @@ -86,7 +83,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host Name = "Foo", PropertyName = "Foo", } - } } }; @@ -169,7 +165,6 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore. PropertyName = "Tags", IsIndexer = true, } - } } }; @@ -221,6 +216,99 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore. ", vcthClass.Content); } + [Fact] + public void ViewComponentTagHelperPass_Execute_CreatesViewComponentTagHelper_Nested() + { + // Arrange + var codeDocument = CreateDocument(@" +@addTagHelper *, TestAssembly +

"); + + var tagHelpers = new[] + { + new TagHelperDescriptor() + { + AssemblyName = "TestAssembly", + TypeName = "PTestTagHelper", + TagName = "p", + Attributes = new TagHelperAttributeDescriptor[] + { + new TagHelperAttributeDescriptor() + { + TypeName = "System.Int32", + Name = "Foo", + } + } + }, + new TagHelperDescriptor() + { + AssemblyName = "TestAssembly", + TypeName = "TestTagHelper", + TagName = "tagcloud", + Attributes = new TagHelperAttributeDescriptor[] + { + new TagHelperAttributeDescriptor() + { + TypeName = "System.Int32", + Name = "Foo", + PropertyName = "Foo", + } + } + } + }; + + tagHelpers[1].PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "TagCloud"); + + var engine = CreateEngine(tagHelpers); + var pass = new ViewComponentTagHelperPass() + { + Engine = engine, + }; + + var irDocument = CreateIRDocument(engine, codeDocument); + + var expectedTagHelperName = "PTestTagHelper"; + var expectedVCTHName = "AspNetCore.Generated_test.__Generated__TagCloudViewComponentTagHelper"; + + // Act + pass.Execute(codeDocument, irDocument); + + // Assert + var outerTagHelper = FindTagHelperNode(irDocument); + Assert.Equal(expectedTagHelperName, Assert.IsType(outerTagHelper.Children[1]).TagHelperTypeName); + Assert.Equal(expectedTagHelperName, Assert.IsType(outerTagHelper.Children[2]).TagHelperTypeName); + + var vcth = FindTagHelperNode(outerTagHelper.Children[0]); + Assert.Equal(expectedVCTHName, Assert.IsType(vcth.Children[1]).TagHelperTypeName); + Assert.Equal(expectedVCTHName, Assert.IsType(vcth.Children[2]).TagHelperTypeName); + + + var @class = FindClassNode(irDocument); + Assert.Equal(3, @class.Children.Count); + + var vcthClass = Assert.IsType(@class.Children[2]); + Assert.Equal(@"[Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(""tagcloud"")] +public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper +{ + private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper _helper = null; + public __Generated__TagCloudViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper) + { + _helper = helper; + } + [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; } + public System.Int32 Foo { get; set; } + public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output) + { + (_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext); + var content = await _helper.InvokeAsync(""TagCloud"", new { Foo }); + output.TagName = null; + output.Content.SetHtmlContent(content); + } +} +", vcthClass.Content); + } + private RazorCodeDocument CreateDocument(string content) { using (var stream = new MemoryStream()) diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs index 30cf4c92ad..3afa05e69b 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs @@ -2,12 +2,14 @@ // 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.Reflection; +using System.Text; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Razor.Compilation; +using Microsoft.AspNetCore.Razor.Evolution; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; -using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging.Testing; using Microsoft.Extensions.Options; using Moq; @@ -17,7 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal { public class DefaultRoslynCompilationServiceTest { -#if OLD_RAZOR [Fact] public void Compile_ReturnsCompilationResult() { @@ -26,12 +27,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal public class MyTestType {}"; var compilationService = GetRoslynCompilationService(); - var relativeFileInfo = new RelativeFileInfo( - new TestFileInfo { PhysicalPath = "SomePath" }, - "some-relative-path"); + + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "test.cshtml")); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); // Assert Assert.Equal("MyTestType", result.CompiledType.Name); @@ -46,20 +51,23 @@ public class MyTestType {}"; var content = $@" #line 1 ""{viewPath}"" this should fail"; - var fileProvider = new TestFileProvider(); - var fileInfo = fileProvider.AddFile(viewPath, fileContent); - var compilationService = GetRoslynCompilationService(fileProvider: fileProvider); - var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path"); + var compilationService = GetRoslynCompilationService(); + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(fileContent), viewPath)); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); // Assert Assert.IsType(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); - Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath); + Assert.Equal(viewPath, compilationFailure.SourceFilePath); Assert.Equal(fileContent, compilationFailure.SourceFileContent); } @@ -67,16 +75,20 @@ this should fail"; public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable() { // Arrange + var viewPath = "some-relative-path"; var fileContent = "file content"; var content = "this should fail"; var compilationService = GetRoslynCompilationService(); - var relativeFileInfo = new RelativeFileInfo( - new TestFileInfo { Content = fileContent }, - "some-relative-path"); + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(fileContent), viewPath)); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); // Assert Assert.IsType(result); @@ -87,39 +99,11 @@ this should fail"; 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 mockFileInfo = new Mock(); - mockFileInfo.Setup(f => f.CreateReadStream()) - .Throws(new Exception()); - var fileProvider = new TestFileProvider(); - fileProvider.AddFile(path, mockFileInfo.Object); - - var compilationService = GetRoslynCompilationService(fileProvider: fileProvider); - 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 viewPath = "some-relative-path"; var content = @" #if MY_CUSTOM_DEFINE public class MyCustomDefinedClass {} @@ -130,12 +114,15 @@ public class MyNonCustomDefinedClass {} var options = GetOptions(); options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE"); var compilationService = GetRoslynCompilationService(options: options); - var relativeFileInfo = new RelativeFileInfo( - new TestFileInfo { PhysicalPath = "SomePath" }, - "some-relative-path"); + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), viewPath)); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); // Assert Assert.NotNull(result.CompiledType); @@ -148,11 +135,8 @@ public class MyNonCustomDefinedClass {} // 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 compilationService = GetRoslynCompilationService(options: options, fileProvider: fileProvider); + var compilationService = GetRoslynCompilationService(); + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent("view-content"), viewPath)); var assemblyName = "random-assembly-name"; var diagnostics = new[] @@ -179,7 +163,7 @@ public class MyNonCustomDefinedClass {} // Act var compilationResult = compilationService.GetCompilationFailedResult( - viewPath, + codeDocument, "compilation-content", assemblyName, diagnostics); @@ -235,13 +219,16 @@ public class MyNonCustomDefinedClass {} RoslynCompilationContext usedCompilation = null; var options = GetOptions(c => usedCompilation = c); var compilationService = GetRoslynCompilationService(options: options); + + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path")); - var relativeFileInfo = new RelativeFileInfo( - new TestFileInfo { PhysicalPath = "SomePath" }, - "some-relative-path"); + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); Assert.NotNull(usedCompilation); Assert.Single(usedCompilation.Compilation.SyntaxTrees); @@ -257,12 +244,15 @@ public class MyNonCustomDefinedClass {} }); var content = "public class MyTestType {}"; var compilationService = GetRoslynCompilationService(options: options); - var relativeFileInfo = new RelativeFileInfo( - new TestFileInfo { PhysicalPath = "SomePath" }, - "some-relative-path.cshtml"); + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path.cshtml")); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); // Assert Assert.Single(result.CompilationFailures); @@ -284,12 +274,15 @@ public class MyNonCustomDefinedClass {} var applicationPartManager = new ApplicationPartManager(); var compilationService = GetRoslynCompilationService(applicationPartManager, options); - var relativeFileInfo = new RelativeFileInfo( - new TestFileInfo { PhysicalPath = "SomePath" }, - "some-relative-path.cshtml"); + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path.cshtml")); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; // Act - var result = compilationService.Compile(relativeFileInfo, content); + var result = compilationService.Compile(codeDocument, csharpDocument); // Assert Assert.Null(result.CompilationFailures); @@ -315,15 +308,6 @@ public class MyNonCustomDefinedClass {} }; } - private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null) - { - var options = new Mock(); - options.SetupGet(o => o.FileProvider) - .Returns(fileProvider ?? new TestFileProvider()); - - return options.Object; - } - private static IOptions GetAccessor(RazorViewEngineOptions options) { var optionsAccessor = new Mock>(); @@ -343,8 +327,7 @@ public class MyNonCustomDefinedClass {} private static DefaultRoslynCompilationService GetRoslynCompilationService( ApplicationPartManager partManager = null, - RazorViewEngineOptions options = null, - IFileProvider fileProvider = null) + RazorViewEngineOptions options = null) { partManager = partManager ?? GetApplicationPartManager(); options = options ?? GetOptions(); @@ -354,10 +337,22 @@ public class MyNonCustomDefinedClass {} return new DefaultRoslynCompilationService( compiler, - GetFileProviderAccessor(fileProvider), optionsAccessor, NullLoggerFactory.Instance); } -#endif + + private static MemoryStream CreateStreamContent(string content = "Hello, World!", Encoding encoding = null) + { + var stream = new MemoryStream(); + encoding = encoding ?? Encoding.UTF8; + using (var writer = new StreamWriter(stream, encoding, bufferSize: 1024, leaveOpen: true)) + { + writer.Write(content); + } + + stream.Seek(0L, SeekOrigin.Begin); + + return stream; + } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorCompilationServiceTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorCompilationServiceTest.cs index 957c3c8dd5..a0a0f734a5 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorCompilationServiceTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorCompilationServiceTest.cs @@ -1,17 +1,13 @@ // 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.Collections.Generic; using System.IO; -using System.Linq; using Microsoft.AspNetCore.Mvc.Razor.Compilation; -using Microsoft.AspNetCore.Razor; -using Microsoft.AspNetCore.Razor.Chunks; -using Microsoft.AspNetCore.Razor.CodeGenerators; -using Microsoft.AspNetCore.Razor.Compilation.TagHelpers; -using Microsoft.AspNetCore.Razor.Parser.SyntaxTree; +using Microsoft.AspNetCore.Razor.Evolution; +using Microsoft.AspNetCore.Razor.Evolution.Legacy; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging.Testing; -using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -19,61 +15,82 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal { public class RazorCompilationServiceTest { -#if OLD_RAZOR - [Theory] - [InlineData(@"src\work\myapp", @"src\work\myapp\Views\index\home.cshtml")] - [InlineData(@"src\work\myapp\", @"src\work\myapp\Views\index\home.cshtml")] - public void CompileCalculatesRootRelativePath(string appPath, string viewPath) + [Fact] + public void CompileCalculatesRootRelativePath() { // Arrange - var host = new Mock(); - host.Setup(h => h.GenerateCode(@"Views\index\home.cshtml", It.IsAny())) - .Returns(GetGeneratorResult()) - .Verifiable(); + var viewPath = @"src\work\myapp\Views\index\home.cshtml"; + var relativePath = @"Views\index\home.cshtml"; var fileInfo = new Mock(); fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath); - fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null); - - var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml"); + fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 })); + var fileProvider = new TestFileProvider(); + fileProvider.AddFile(relativePath, fileInfo.Object); + var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath); var compiler = new Mock(); - compiler.Setup(c => c.Compile(relativeFileInfo, It.IsAny())) + compiler.Setup(c => c.Compile(It.IsAny(), It.IsAny())) .Returns(new CompilationResult(typeof(RazorCompilationServiceTest))); - var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance); + var engine = new Mock(); + engine.Setup(e => e.Process(It.IsAny())) + .Callback(document => + { + document.SetCSharpDocument(new RazorCSharpDocument() + { + Diagnostics = new List() + }); + + Assert.Equal(viewPath, document.Source.Filename); // Assert if source file name is the root relative path + }).Verifiable(); + + var razorService = new RazorCompilationService( + compiler.Object, + engine.Object, + new DefaultRazorProject(fileProvider), + GetFileProviderAccessor(fileProvider), + NullLoggerFactory.Instance); // Act razorService.Compile(relativeFileInfo); // Assert - host.Verify(); + engine.Verify(); } [Fact] public void Compile_ReturnsFailedResultIfParseFails() { // Arrange - var errorSink = new ErrorSink(); - errorSink.OnError(new RazorError("some message", 1, 1, 1, 1)); - var generatorResult = new GeneratorResults( - new Block(new BlockBuilder { Type = BlockType.Comment }), - Enumerable.Empty(), - errorSink, - new CodeGeneratorResult("", new LineMapping[0]), - new ChunkTree()); - var host = new Mock(); - host.Setup(h => h.GenerateCode(It.IsAny(), It.IsAny())) - .Returns(generatorResult) - .Verifiable(); - + var relativePath = @"Views\index\home.cshtml"; var fileInfo = new Mock(); - fileInfo.Setup(f => f.CreateReadStream()) - .Returns(Stream.Null); + fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 })); + var fileProvider = new TestFileProvider(); + fileProvider.AddFile(relativePath, fileInfo.Object); + var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath); var compiler = new Mock(MockBehavior.Strict); - var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml"); - var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance); + + var engine = new Mock(); + engine.Setup(e => e.Process(It.IsAny())) + .Callback(document => + { + document.SetCSharpDocument(new RazorCSharpDocument() + { + Diagnostics = new List() + { + new RazorError("some message", 1, 1, 1, 1) + } + }); + }).Verifiable(); + + var razorService = new RazorCompilationService( + compiler.Object, + engine.Object, + new DefaultRazorProject(fileProvider), + GetFileProviderAccessor(fileProvider), + NullLoggerFactory.Instance); // Act var result = razorService.Compile(relativeFileInfo); @@ -86,35 +103,41 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal var message = Assert.Single(failure.Messages); Assert.Equal("some message", message.Message); }); - host.Verify(); + engine.Verify(); } [Fact] public void Compile_ReturnsResultFromCompilationServiceIfParseSucceeds() { - // Arrange - var code = "compiled-content"; - var generatorResult = new GeneratorResults( - new Block(new BlockBuilder { Type = BlockType.Comment }), - Enumerable.Empty(), - new ErrorSink(), - new CodeGeneratorResult(code, new LineMapping[0]), - new ChunkTree()); - var host = new Mock(); - host.Setup(h => h.GenerateCode(It.IsAny(), It.IsAny())) - .Returns(generatorResult); - + var relativePath = @"Views\index\home.cshtml"; var fileInfo = new Mock(); - fileInfo.Setup(f => f.CreateReadStream()) - .Returns(Stream.Null); - var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml"); + fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 })); + var fileProvider = new TestFileProvider(); + fileProvider.AddFile(relativePath, fileInfo.Object); + var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath); var compilationResult = new CompilationResult(typeof(object)); var compiler = new Mock(); - compiler.Setup(c => c.Compile(relativeFileInfo, code)) + compiler.Setup(c => c.Compile(It.IsAny(), It.IsAny())) .Returns(compilationResult) .Verifiable(); - var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance); + + var engine = new Mock(); + engine.Setup(e => e.Process(It.IsAny())) + .Callback(document => + { + document.SetCSharpDocument(new RazorCSharpDocument() + { + Diagnostics = new List() + }); + }); + + var razorService = new RazorCompilationService( + compiler.Object, + engine.Object, + new DefaultRazorProject(fileProvider), + GetFileProviderAccessor(fileProvider), + NullLoggerFactory.Instance); // Act var result = razorService.Compile(relativeFileInfo); @@ -130,7 +153,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal // Arrange var viewPath = @"views/index.razor"; var viewImportsPath = @"views/global.import.cshtml"; - var host = Mock.Of(); var fileProvider = new TestFileProvider(); var file = fileProvider.AddFile(viewPath, "View Content"); @@ -138,7 +160,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal var relativeFileInfo = new RelativeFileInfo(file, viewPath); var razorService = new RazorCompilationService( Mock.Of(), - Mock.Of(), + Mock.Of(), + new DefaultRazorProject(fileProvider), GetFileProviderAccessor(fileProvider), NullLoggerFactory.Instance); var errors = new[] @@ -205,16 +228,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal }); } - private static GeneratorResults GetGeneratorResult() - { - return new GeneratorResults( - new Block(new BlockBuilder { Type = BlockType.Comment }), - Enumerable.Empty(), - new ErrorSink(), - new CodeGeneratorResult("", new LineMapping[0]), - new ChunkTree()); - } - private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null) { var options = new Mock(); @@ -223,7 +236,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal return options.Object; } - -#endif } }