From 764b1e64b86433312d7a3bc7b018e221358a2a88 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 13 Aug 2014 12:16:27 -0700 Subject: [PATCH] RoslynCompilationService should set the generated code when compilation is successful Fixes #895 --- .../Compilation/CompilationResult.cs | 17 +++-- .../Compilation/RoslynCompilationService.cs | 2 +- .../Compilation/UncachedCompilationResult.cs | 34 ++++++++++ .../Compilation/CompilerCacheTest.cs | 62 +++++++++++++++++++ 4 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 src/Microsoft.AspNet.Mvc.Razor/Compilation/UncachedCompilationResult.cs create mode 100644 test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/CompilerCacheTest.cs diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationResult.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationResult.cs index 7c520db3ad..04e628161f 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationResult.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationResult.cs @@ -15,7 +15,10 @@ namespace Microsoft.AspNet.Mvc.Razor { private Type _type; - private CompilationResult() + /// + /// Creates a new instance of . + /// + protected CompilationResult() { } @@ -40,12 +43,12 @@ namespace Microsoft.AspNet.Mvc.Razor public IEnumerable Messages { get; private set; } /// - /// Gets the generated C# content that was compiled. + /// Gets (or sets in derived types) the generated C# content that was compiled. /// - public string CompiledContent { get; private set; } + public string CompiledContent { get; protected set; } /// - /// Gets the type produced as a result of compilation. + /// Gets (or sets in derived types) the type produced as a result of compilation. /// /// An error occured during compilation. public Type CompiledType @@ -59,6 +62,10 @@ namespace Microsoft.AspNet.Mvc.Razor return _type; } + protected set + { + _type = value; + } } private IFileInfo File { get; set; } @@ -91,7 +98,7 @@ namespace Microsoft.AspNet.Mvc.Razor { return new CompilationResult { - _type = type + CompiledType = type }; } diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs index 2658f8ad52..29b0594bb2 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs @@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation var type = assembly.GetExportedTypes() .First(); - return CompilationResult.Successful(type); + return UncachedCompilationResult.Successful(type, compilationContent); } } } diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/UncachedCompilationResult.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/UncachedCompilationResult.cs new file mode 100644 index 0000000000..7c4799b7ed --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/UncachedCompilationResult.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNet.Mvc.Razor +{ + /// + /// Represents the result of compilation that does not come from the . + /// + public class UncachedCompilationResult : CompilationResult + { + private UncachedCompilationResult() + { + } + + /// + /// Creates a that represents a success in compilation. + /// + /// The compiled type. + /// The generated C# content that was compiled. + /// An instance that indicates a successful + /// compilation. + public static UncachedCompilationResult Successful([NotNull] Type type, + [NotNull] string compiledContent) + { + return new UncachedCompilationResult + { + CompiledType = type, + CompiledContent = compiledContent, + }; + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/CompilerCacheTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/CompilerCacheTest.cs new file mode 100644 index 0000000000..13a02efabe --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/Compilation/CompilerCacheTest.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.FileSystems; +using Moq; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Razor.Test +{ + public class CompilerCacheTest + { + [Fact] + public void GetOrAdd_ReturnsCompilationResultFromFactory() + { + // Arrange + var cache = new CompilerCache(); + var fileInfo = Mock.Of(); + var type = GetType(); + var expected = UncachedCompilationResult.Successful(type, "hello world"); + + // Act + var actual = cache.GetOrAdd(fileInfo, () => expected); + + // Assert + Assert.Same(expected, actual); + Assert.Equal("hello world", actual.CompiledContent); + Assert.Same(type, actual.CompiledType); + } + + [Fact] + public void GetOrAdd_DoesNotCacheCompiledContent_OnCallsAfterInitial() + { + // Arrange + var lastModified = DateTime.UtcNow; + var cache = new CompilerCache(); + var fileInfo = new Mock(); + fileInfo.SetupGet(f => f.PhysicalPath) + .Returns("test"); + fileInfo.SetupGet(f => f.LastModified) + .Returns(lastModified); + var type = GetType(); + var uncachedResult = UncachedCompilationResult.Successful(type, "hello world"); + + // Act + cache.GetOrAdd(fileInfo.Object, () => uncachedResult); + var actual1 = cache.GetOrAdd(fileInfo.Object, () => uncachedResult); + var actual2 = cache.GetOrAdd(fileInfo.Object, () => uncachedResult); + + // Assert + Assert.NotSame(uncachedResult, actual1); + Assert.NotSame(uncachedResult, actual2); + var result = Assert.IsType(actual1); + Assert.Null(actual1.CompiledContent); + Assert.Same(type, actual1.CompiledType); + + result = Assert.IsType(actual2); + Assert.Null(actual2.CompiledContent); + Assert.Same(type, actual2.CompiledType); + } + } +} \ No newline at end of file