From 83faaebdb65037bf248fd9184cd41bbd1b713ce5 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 14 Apr 2017 16:34:49 -0700 Subject: [PATCH] Upgrade Roslyn dependency to 2.0.0. - Added C# 7 unit and functional test to validate features work end-to-end. #6149 --- build/dependencies.props | 2 +- .../RazorViewEngineOptions.cs | 2 +- .../BasicTests.cs | 24 +++++++++++++ .../BasicWebSite.Home.CSharp7View.html | 19 ++++++++++ .../DefaultRoslynCompilationServiceTest.cs | 36 +++++++++++++++++-- ...yContextRazorViewEngineOptionsSetupTest.cs | 2 +- .../Controllers/HomeController.cs | 13 +++++++ .../Views/Home/CSharp7View.cshtml | 24 +++++++++++++ 8 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/BasicWebSite.Home.CSharp7View.html create mode 100644 test/WebSites/BasicWebSite/Views/Home/CSharp7View.cshtml diff --git a/build/dependencies.props b/build/dependencies.props index ca7f57c3de..914e6010c3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,7 +8,7 @@ 1.0.1 4.7.1 1.6.1 - 1.3.0 + 2.0.0 2.0.0-* 15.0.0 5.2.2 diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs index 674d81b8aa..5ea398ce5f 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// public class RazorViewEngineOptions { - private CSharpParseOptions _parseOptions = new CSharpParseOptions(LanguageVersion.CSharp6); + private CSharpParseOptions _parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7); private CSharpCompilationOptions _compilationOptions = new CSharpCompilationOptions(CodeAnalysis.OutputKind.DynamicallyLinkedLibrary); private Action _compilationCallback = c => { }; diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/BasicTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/BasicTests.cs index 010ba08631..b6bd2c39a7 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/BasicTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/BasicTests.cs @@ -30,6 +30,30 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public HttpClient Client { get; } + [Fact] + public async Task CanRender_CSharp7Views() + { + // Arrange + var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8"); + var outputFile = "compiler/resources/BasicWebSite.Home.CSharp7View.html"; + var expectedContent = + await ResourceFile.ReadResourceAsync(_resourcesAssembly, outputFile, sourceFile: false); + + // Act + var response = await Client.GetAsync("Home/CSharp7View"); + var responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(expectedMediaType, response.Content.Headers.ContentType); + +#if GENERATE_BASELINES + ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); +#else + Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true); +#endif + } + [Fact] public async Task CanRender_ViewComponentWithArgumentsFromController() { diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/BasicWebSite.Home.CSharp7View.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/BasicWebSite.Home.CSharp7View.html new file mode 100644 index 0000000000..a2a29ca6c5 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/BasicWebSite.Home.CSharp7View.html @@ -0,0 +1,19 @@ + +

+ John Doe's favorite number is + + +(double) 6.02214085774747E+23 +

+

+ John Smith's favorite number is + + +(long) 100000000000 +

+

+ Someone Nice's favorite number is + + +(decimal) 1.6180339887498948482045868344 +

diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs index 1e72b1b92c..ae218dafef 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DefaultRoslynCompilationServiceTest.cs @@ -2,9 +2,7 @@ // 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.Language; @@ -19,6 +17,38 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal { public class DefaultRoslynCompilationServiceTest { + [Fact] + public void Compile_SucceedsForCSharp7() + { + // Arrange + var content = @" +public class MyTestType +{ + private string _name; + + public string Name + { + get => _name; + set => _name = value ?? throw new System.ArgumentNullException(nameof(value)); + } +}"; + var compilationService = GetRoslynCompilationService(); + + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("Hello world", "test.cshtml")); + + var csharpDocument = new RazorCSharpDocument() + { + GeneratedCode = content + }; + + // Act + var result = compilationService.Compile(codeDocument, csharpDocument); + + // Assert + Assert.Equal("MyTestType", result.CompiledType.Name); + Assert.Null(result.CompilationFailures); + } + [Fact] public void Compile_ReturnsCompilationResult() { @@ -219,7 +249,7 @@ public class MyNonCustomDefinedClass {} RoslynCompilationContext usedCompilation = null; var options = GetOptions(c => usedCompilation = c); var compilationService = GetRoslynCompilationService(options: options); - + var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.Create("Hello world", "some-relative-path")); var csharpDocument = new RazorCSharpDocument() diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DependencyContextRazorViewEngineOptionsSetupTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DependencyContextRazorViewEngineOptionsSetupTest.cs index d2a4d3ca1f..de3d7956c1 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DependencyContextRazorViewEngineOptionsSetupTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/DependencyContextRazorViewEngineOptionsSetupTest.cs @@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal }); Assert.Empty(parseOptions.PreprocessorSymbolNames); - Assert.Equal(LanguageVersion.CSharp6, parseOptions.LanguageVersion); + Assert.Equal(LanguageVersion.CSharp7, parseOptions.LanguageVersion); } [Fact] diff --git a/test/WebSites/BasicWebSite/Controllers/HomeController.cs b/test/WebSites/BasicWebSite/Controllers/HomeController.cs index 48e1aa850c..c6554d7c76 100644 --- a/test/WebSites/BasicWebSite/Controllers/HomeController.cs +++ b/test/WebSites/BasicWebSite/Controllers/HomeController.cs @@ -1,6 +1,7 @@ // 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.Threading.Tasks; using BasicWebSite.Models; using Microsoft.AspNetCore.Http; @@ -16,6 +17,18 @@ namespace BasicWebSite.Controllers return View(); } + public IActionResult CSharp7View() + { + var people = new List<(string FirstName, string LastName, object FavoriteNumber)>() + { + ("John", "Doe", 6.022_140_857_747_474e23), + ("John", "Smith", 100_000_000_000), + ("Someone", "Nice", (decimal)1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M), + }; + + return View(people); + } + // Keep the return type as object to ensure that we don't // wrap IActionResult instances into ObjectResults. public object PlainView() diff --git a/test/WebSites/BasicWebSite/Views/Home/CSharp7View.cshtml b/test/WebSites/BasicWebSite/Views/Home/CSharp7View.cshtml new file mode 100644 index 0000000000..e2518ae708 --- /dev/null +++ b/test/WebSites/BasicWebSite/Views/Home/CSharp7View.cshtml @@ -0,0 +1,24 @@ +@model IEnumerable<(string FirstName, string LastName, object FavoriteNumber)> + + @foreach (var person in Model) + { +

+ @person.FirstName @person.LastName's favorite number is + + + @switch (person.FavoriteNumber) + { + case double doubleVal: + (double) @doubleVal + break; + case long longVal: + (long) @longVal + break; + case decimal longVal: + (decimal) @longVal + break; + + } + +

+ } \ No newline at end of file