diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/FileSystemRazorProject.cs b/src/Microsoft.AspNetCore.Razor.Evolution/FileSystemRazorProject.cs
new file mode 100644
index 0000000000..1d794919b0
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Razor.Evolution/FileSystemRazorProject.cs
@@ -0,0 +1,69 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+
+namespace Microsoft.AspNetCore.Razor.Evolution
+{
+ ///
+ /// A implementation over the physical file system.
+ ///
+ public class FileSystemRazorProject : RazorProject
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The directory to root the file system at.
+ public FileSystemRazorProject(string root)
+ {
+ if (string.IsNullOrEmpty(root))
+ {
+ throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(root));
+ }
+
+ Root = root.TrimEnd('/', '\\');
+ }
+
+ ///
+ /// The root of the file system.
+ ///
+ public string Root { get; }
+
+ ///
+ public override IEnumerable EnumerateItems(string basePath)
+ {
+ EnsureValidPath(basePath);
+
+ Debug.Assert(basePath.StartsWith("/"));
+ var absoluteBasePath = Path.Combine(Root, basePath.Substring(1));
+
+ var directory = new DirectoryInfo(absoluteBasePath);
+ if (!directory.Exists)
+ {
+ return Enumerable.Empty();
+ }
+
+ return directory
+ .EnumerateFiles("*.cshtml", SearchOption.AllDirectories)
+ .Select(file =>
+ {
+ var relativePath = file.FullName.Substring(absoluteBasePath.Length).Replace(Path.DirectorySeparatorChar, '/');
+ return new FileSystemRazorProjectItem(basePath, relativePath, file);
+ });
+ }
+
+ ///
+ public override RazorProjectItem GetItem(string path)
+ {
+ EnsureValidPath(path);
+
+ Debug.Assert(path.StartsWith("/"));
+ var absolutePath = Path.Combine(Root, path.Substring(1));
+ return new FileSystemRazorProjectItem("/", path, new FileInfo(absolutePath));
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/FileSystemRazorProjectItem.cs b/src/Microsoft.AspNetCore.Razor.Evolution/FileSystemRazorProjectItem.cs
new file mode 100644
index 0000000000..9ce8bef44b
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Razor.Evolution/FileSystemRazorProjectItem.cs
@@ -0,0 +1,49 @@
+// 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.IO;
+
+namespace Microsoft.AspNetCore.Razor.Evolution
+{
+ ///
+ /// An implementation of using .
+ ///
+ public class FileSystemRazorProjectItem : RazorProjectItem
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The base path.
+ /// The path.
+ /// The .
+ public FileSystemRazorProjectItem(string basePath, string path, FileInfo file)
+ {
+ BasePath = basePath;
+ Path = path;
+ File = file;
+ }
+
+ ///
+ /// Gets the .
+ ///
+ public FileInfo File { get; }
+
+ ///
+ public override string BasePath { get; }
+
+ ///
+ public override string Path { get; }
+
+ ///
+ public override bool Exists => File.Exists;
+
+ ///
+ public override string Filename => File.Name;
+
+ ///
+ public override string PhysicalPath => File.FullName;
+
+ ///
+ public override Stream Read() => File.OpenRead();
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/RazorEngineBuilderExtensions.cs b/src/Microsoft.AspNetCore.Razor.Evolution/RazorEngineBuilderExtensions.cs
index c7d811488c..f01b5d9f61 100644
--- a/src/Microsoft.AspNetCore.Razor.Evolution/RazorEngineBuilderExtensions.cs
+++ b/src/Microsoft.AspNetCore.Razor.Evolution/RazorEngineBuilderExtensions.cs
@@ -8,8 +8,17 @@ using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
namespace Microsoft.AspNetCore.Razor.Evolution
{
+ ///
+ /// Extension methods to .
+ ///
public static class RazorEngineBuilderExtensions
{
+ ///
+ /// Adds the specified .
+ ///
+ /// The .
+ /// The to add.
+ /// The .
public static IRazorEngineBuilder AddDirective(this IRazorEngineBuilder builder, DirectiveDescriptor directive)
{
if (builder == null)
@@ -28,6 +37,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder;
}
+ ///
+ /// Adds the specified .
+ ///
+ /// The .
+ /// The to add.
+ /// The .
public static IRazorEngineBuilder AddTargetExtension(this IRazorEngineBuilder builder, IRuntimeTargetExtension extension)
{
if (builder == null)
@@ -46,6 +61,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder;
}
+ ///
+ /// Sets the base type for generated types.
+ ///
+ /// The .
+ /// The name of the base type.
+ /// The .
public static IRazorEngineBuilder SetBaseType(this IRazorEngineBuilder builder, string baseType)
{
if (builder == null)
@@ -58,17 +79,13 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder;
}
- public static IRazorEngineBuilder SetClassName(this IRazorEngineBuilder builder, string className)
- {
- if (builder == null)
- {
- throw new ArgumentNullException(nameof(builder));
- }
-
- ConfigureClass(builder, (document, @class) => @class.Name = className);
- return builder;
- }
-
+ ///
+ /// Registers a class configuration delegate that gets invoked during code generation.
+ ///
+ /// The .
+ /// invoked to configure
+ /// during code generation.
+ /// The .
public static IRazorEngineBuilder ConfigureClass(
this IRazorEngineBuilder builder,
Action configureClass)
@@ -88,6 +105,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder;
}
+ ///
+ /// Sets the namespace for generated types.
+ ///
+ /// The .
+ /// The name of the namespace.
+ /// The .
public static IRazorEngineBuilder SetNamespace(this IRazorEngineBuilder builder, string namespaceName)
{
if (builder == null)
diff --git a/src/RazorPageGenerator/Program.cs b/src/RazorPageGenerator/Program.cs
index dbb44c30a2..9680ff590e 100644
--- a/src/RazorPageGenerator/Program.cs
+++ b/src/RazorPageGenerator/Program.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 System.Linq;
using System.Text;
@@ -35,22 +34,21 @@ namespace RazorPageGenerator
@class.AccessModifier = "internal";
});
- builder.Features.Add(new RemovePragamaChecksumFeature());
+ builder.Features.Add(new RemovePragmaChecksumFeature());
});
var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
+ var razorProject = new FileSystemRazorProject(targetProjectDirectory);
+ var templateEngine = new RazorTemplateEngine(razorEngine, razorProject);
var fileCount = 0;
foreach (var viewDir in viewDirectories)
{
Console.WriteLine();
Console.WriteLine(" Generating code files for views in {0}", viewDir);
- var razorProject = new FileSystemRazorProject(viewDir);
- var templateEngine = new RazorTemplateEngine(razorEngine, razorProject);
-
-
- var cshtmlFiles = razorProject.EnumerateItems("");
+ var viewDirPath = viewDir.Substring(targetProjectDirectory.Length).Replace('\\', '/');
+ var cshtmlFiles = razorProject.EnumerateItems(viewDirPath).Cast();
if (!cshtmlFiles.Any())
{
@@ -72,69 +70,37 @@ namespace RazorPageGenerator
Console.WriteLine();
}
- private static void GenerateCodeFile(RazorTemplateEngine templateEngine, RazorProjectItem projectItem)
+ private static void GenerateCodeFile(RazorTemplateEngine templateEngine, FileSystemRazorProjectItem projectItem)
{
- var cSharpDocument = templateEngine.GenerateCode(projectItem);
+ var projectItemWrapper = new FileSystemRazorProjectItemWrapper(projectItem);
+ var cSharpDocument = templateEngine.GenerateCode(projectItemWrapper);
if (cSharpDocument.Diagnostics.Any())
{
var diagnostics = string.Join(Environment.NewLine, cSharpDocument.Diagnostics);
Console.WriteLine($"One or more parse errors encountered. This will not prevent the generator from continuing: {Environment.NewLine}{diagnostics}.");
}
- var generatedCodeFilePath = Path.ChangeExtension(
- ((FileSystemRazorProjectItem)projectItem).FileInfo.FullName,
- ".Designer.cs");
+ var generatedCodeFilePath = Path.ChangeExtension(projectItem.PhysicalPath, ".Designer.cs");
File.WriteAllText(generatedCodeFilePath, cSharpDocument.GeneratedCode);
}
- private class FileSystemRazorProject : RazorProject
+ private class FileSystemRazorProjectItemWrapper : RazorProjectItem
{
- private readonly string _basePath;
+ private readonly FileSystemRazorProjectItem _source;
- public FileSystemRazorProject(string basePath)
+ public FileSystemRazorProjectItemWrapper(FileSystemRazorProjectItem item)
{
- _basePath = basePath;
+ _source = item;
}
- public override IEnumerable EnumerateItems(string basePath)
- {
- return new DirectoryInfo(_basePath)
- .EnumerateFiles("*.cshtml", SearchOption.TopDirectoryOnly)
- .Select(file => GetItem(basePath, file));
- }
+ public override string BasePath => _source.BasePath;
- public override RazorProjectItem GetItem(string path) => throw new NotSupportedException();
-
- private RazorProjectItem GetItem(string basePath, FileInfo file)
- {
- if (!file.Exists)
- {
- throw new FileNotFoundException($"{file.FullName} does not exist.");
- }
-
- return new FileSystemRazorProjectItem(basePath, file);
- }
- }
-
- private class FileSystemRazorProjectItem : RazorProjectItem
- {
- public FileSystemRazorProjectItem(string basePath, FileInfo fileInfo)
- {
- BasePath = basePath;
- Path = fileInfo.Name;
- FileInfo = fileInfo;
- }
-
- public FileInfo FileInfo { get; }
-
- public override string BasePath { get; }
-
- public override string Path { get; }
+ public override string Path => _source.Path;
// Mask the full name since we don't want a developer's local file paths to be commited.
- public override string PhysicalPath => FileInfo.Name;
+ public override string PhysicalPath => _source.Filename;
- public override bool Exists => true;
+ public override bool Exists => _source.Exists;
public override Stream Read()
{
@@ -144,8 +110,8 @@ namespace RazorPageGenerator
private string ProcessFileIncludes()
{
- var basePath = FileInfo.DirectoryName;
- var cshtmlContent = File.ReadAllText(FileInfo.FullName);
+ var basePath = _source.File.DirectoryName;
+ var cshtmlContent = File.ReadAllText(_source.PhysicalPath);
var startMatch = "<%$ include: ";
var endMatch = " %>";
@@ -160,7 +126,7 @@ namespace RazorPageGenerator
var endIndex = cshtmlContent.IndexOf(endMatch, startIndex);
if (endIndex == -1)
{
- throw new InvalidOperationException($"Invalid include file format in {FileInfo.FullName}. Usage example: <%$ include: ErrorPage.js %>");
+ throw new InvalidOperationException($"Invalid include file format in {_source.PhysicalPath}. Usage example: <%$ include: ErrorPage.js %>");
}
var includeFileName = cshtmlContent.Substring(startIndex + startMatch.Length, endIndex - (startIndex + startMatch.Length));
Console.WriteLine(" Inlining file {0}", includeFileName);
diff --git a/src/RazorPageGenerator/RemovePragamaChecksumFeature.cs b/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs
similarity index 89%
rename from src/RazorPageGenerator/RemovePragamaChecksumFeature.cs
rename to src/RazorPageGenerator/RemovePragmaChecksumFeature.cs
index 6ed229693b..bc6386ce25 100644
--- a/src/RazorPageGenerator/RemovePragamaChecksumFeature.cs
+++ b/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs
@@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
namespace RazorPageGenerator
{
- class RemovePragamaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass
+ class RemovePragmaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass
{
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/FileSystemRazorProjectItemTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/FileSystemRazorProjectItemTest.cs
new file mode 100644
index 0000000000..7bb8006fa5
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/FileSystemRazorProjectItemTest.cs
@@ -0,0 +1,58 @@
+// 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.IO;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Razor.Evolution
+{
+ public class FileSystemRazorProjectItemTest
+ {
+ private static string TestFolder { get; } =
+ Path.Combine(TestProject.GetProjectDirectory(), "TestFiles", "FileSystemRazorProject");
+
+ [Fact]
+ public void FileSystemRazorProjectItem_SetsProperties()
+ {
+ // Arrange
+ var fileInfo = new FileInfo(Path.Combine(TestFolder, "Home.cshtml"));
+
+ // Act
+ var projectItem = new FileSystemRazorProjectItem("/Views", "/Home.cshtml", fileInfo);
+
+ // Assert
+ Assert.Equal("/Home.cshtml", projectItem.Path);
+ Assert.Equal("/Views", projectItem.BasePath);
+ Assert.True(projectItem.Exists);
+ Assert.Equal("Home.cshtml", projectItem.Filename);
+ Assert.Equal(fileInfo.FullName, projectItem.PhysicalPath);
+ }
+
+ [Fact]
+ public void Exists_ReturnsFalseWhenFileDoesNotExist()
+ {
+ // Arrange
+ var fileInfo = new FileInfo(Path.Combine(TestFolder, "Views", "FileDoesNotExist.cshtml"));
+
+ // Act
+ var projectItem = new FileSystemRazorProjectItem("/Views", "/FileDoesNotExist.cshtml", fileInfo);
+
+ // Assert
+ Assert.False(projectItem.Exists);
+ }
+
+ [Fact]
+ public void Read_ReturnsReadStream()
+ {
+ // Arrange
+ var fileInfo = new FileInfo(Path.Combine(TestFolder, "Home.cshtml"));
+ var projectItem = new FileSystemRazorProjectItem("/", "/Home.cshtml", fileInfo);
+
+ // Act
+ var stream = projectItem.Read();
+
+ // Assert
+ Assert.Equal("home-content", new StreamReader(stream).ReadToEnd());
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/FileSystemRazorProjectTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/FileSystemRazorProjectTest.cs
new file mode 100644
index 0000000000..d9d21dc1f6
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/FileSystemRazorProjectTest.cs
@@ -0,0 +1,108 @@
+// 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.IO;
+using System.Linq;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Razor.Evolution
+{
+ public class FileSystemRazorProjectTest
+ {
+ private static string TestFolder { get; } =
+ Path.Combine(TestProject.GetProjectDirectory(), "TestFiles", "FileSystemRazorProject");
+
+ [Fact]
+ public void EnumerateItems_DiscoversAllCshtmlFiles()
+ {
+ // Arrange
+ var fileSystemProject = new FileSystemRazorProject(TestFolder);
+
+ // Act
+ var files = fileSystemProject.EnumerateItems("/");
+
+ // Assert
+ Assert.Collection(files.OrderBy(f => f.Path),
+ file =>
+ {
+ Assert.Equal("/Home.cshtml", file.Path);
+ Assert.Equal("/", file.BasePath);
+ },
+ file =>
+ {
+ Assert.Equal("/Views/About/About.cshtml", file.Path);
+ Assert.Equal("/", file.BasePath);
+ },
+ file =>
+ {
+ Assert.Equal("/Views/Home/Index.cshtml", file.Path);
+ Assert.Equal("/", file.BasePath);
+ });
+ }
+
+ [Fact]
+ public void EnumerateItems_DiscoversAllCshtmlFiles_UnderSpecifiedBasePath()
+ {
+ // Arrange
+ var fileSystemProject = new FileSystemRazorProject(TestFolder);
+
+ // Act
+ var files = fileSystemProject.EnumerateItems("/Views");
+
+ // Assert
+ Assert.Collection(files.OrderBy(f => f.Path),
+ file =>
+ {
+ Assert.Equal("/About/About.cshtml", file.Path);
+ Assert.Equal("/Views", file.BasePath);
+ },
+ file =>
+ {
+ Assert.Equal("/Home/Index.cshtml", file.Path);
+ Assert.Equal("/Views", file.BasePath);
+ });
+ }
+
+ [Fact]
+ public void EnumerateItems_ReturnsEmptySequence_WhenBasePathDoesNotExist()
+ {
+ // Arrange
+ var fileSystemProject = new FileSystemRazorProject(TestFolder);
+
+ // Act
+ var files = fileSystemProject.EnumerateItems("/Does-Not-Exist");
+
+ // Assert
+ Assert.Empty(files);
+ }
+
+ [Fact]
+ public void GetItem_ReturnsFileFromDisk()
+ {
+ // Arrange
+ var path = "/Views/About/About.cshtml";
+ var fileSystemProject = new FileSystemRazorProject(TestFolder);
+
+ // Act
+ var file = fileSystemProject.GetItem(path);
+
+ // Assert
+ Assert.True(file.Exists);
+ Assert.Equal(path, file.Path);
+ }
+
+ [Fact]
+ public void GetItem_ReturnsNotFoundResult()
+ {
+ // Arrange
+ var path = "/NotFound.cshtml";
+ var fileSystemProject = new FileSystemRazorProject(TestFolder);
+
+ // Act
+ var file = fileSystemProject.GetItem(path);
+
+ // Assert
+ Assert.False(file.Exists);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/IntegrationTestBase.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/IntegrationTestBase.cs
index cbe8d15193..3b130ae3b3 100644
--- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/IntegrationTestBase.cs
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/IntegrationTestBase.cs
@@ -20,26 +20,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
[IntializeTestFile]
public abstract class IntegrationTestBase
{
- private static readonly string ThisProjectName = typeof(IntializeTestFileAttribute).GetTypeInfo().Assembly.GetName().Name;
-
- private static string FindTestProjectRoot()
- {
-#if NET452
- var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
-#else
- var currentDirectory = new DirectoryInfo(AppContext.BaseDirectory);
-#endif
-
- while (currentDirectory != null &&
- !string.Equals(currentDirectory.Name, ThisProjectName, StringComparison.Ordinal))
- {
- currentDirectory = currentDirectory.Parent;
- }
-
- var normalizedSeparators = currentDirectory.FullName.Replace(Path.DirectorySeparatorChar, '/');
- return currentDirectory.FullName;
- }
-
#if GENERATE_BASELINES
private static readonly bool GenerateBaselines = true;
#else
@@ -50,8 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
private static readonly AsyncLocal _filename = new AsyncLocal();
#endif
- protected static string TestProjectRoot { get; } = FindTestProjectRoot();
-
+ protected static string TestProjectRoot { get; } = TestProject.GetProjectDirectory();
// Used by the test framework to set the 'base' name for test files.
public static string Filename
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs
index fae442ad0e..511506f2a9 100644
--- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorTemplateEngineIntegrationTest.cs
@@ -49,5 +49,63 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
// Assert
AssertCSharpDocumentMatchesBaseline(cSharpDocument);
}
+
+ [Fact]
+ public void GenerateCodeWithConfigureClass()
+ {
+ // Arrange
+ var filePath = Path.Combine(TestProjectRoot, $"{Filename}.cshtml");
+ var content = File.ReadAllText(filePath);
+ var projectItem = new TestRazorProjectItem($"{Filename}.cshtml", "")
+ {
+ Content = content,
+ };
+ var project = new TestRazorProject(new[] { projectItem });
+ var razorEngine = RazorEngine.Create(engine =>
+ {
+ engine.ConfigureClass((document, @class) =>
+ {
+ @class.Name = "MyClass";
+ @class.AccessModifier = "protected internal";
+ });
+
+ engine.ConfigureClass((document, @class) =>
+ {
+ @class.Interfaces = new[] { "global::System.IDisposable" };
+ @class.BaseType = "CustomBaseType";
+ });
+ });
+ var templateEngine = new RazorTemplateEngine(razorEngine, project);
+
+ // Act
+ var cSharpDocument = templateEngine.GenerateCode(projectItem.Path);
+
+ // Assert
+ AssertCSharpDocumentMatchesBaseline(cSharpDocument);
+ }
+
+ [Fact]
+ public void GenerateCodeWithSetNamespace()
+ {
+ // Arrange
+ var filePath = Path.Combine(TestProjectRoot, $"{Filename}.cshtml");
+ var content = File.ReadAllText(filePath);
+ var projectItem = new TestRazorProjectItem($"{Filename}.cshtml", "")
+ {
+ Content = content,
+ };
+ var project = new TestRazorProject(new[] { projectItem });
+ var razorEngine = RazorEngine.Create(engine =>
+ {
+ engine.SetNamespace("MyApp.Razor.Views");
+ });
+ var templateEngine = new RazorTemplateEngine(razorEngine, project);
+
+ // Act
+ var cSharpDocument = templateEngine.GenerateCode(projectItem.Path);
+
+ // Assert
+ AssertCSharpDocumentMatchesBaseline(cSharpDocument);
+ }
}
}
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Home.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Home.cshtml
new file mode 100644
index 0000000000..7c5b3ca2e3
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Home.cshtml
@@ -0,0 +1 @@
+home-content
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/About/About.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/About/About.cshtml
new file mode 100644
index 0000000000..5f282702bb
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/About/About.cshtml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/Home/Index.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/Home/Index.cshtml
new file mode 100644
index 0000000000..5f282702bb
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/Home/Index.cshtml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/Home/Index.txt b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/Home/Index.txt
new file mode 100644
index 0000000000..5f282702bb
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/FileSystemRazorProject/Views/Home/Index.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs
new file mode 100644
index 0000000000..a55823e23f
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs
@@ -0,0 +1,16 @@
+#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "247d02621904d87ab805e437f33c5d03b9a0de91"
+namespace Razor
+{
+ #line hidden
+ using System;
+ using System.Threading.Tasks;
+ protected internal class MyClass : CustomBaseType, global::System.IDisposable
+ {
+ #pragma warning disable 1998
+ public async override global::System.Threading.Tasks.Task ExecuteAsync()
+ {
+ WriteLiteral("Hello world!
");
+ }
+ #pragma warning restore 1998
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml
new file mode 100644
index 0000000000..6df88a66a1
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml
@@ -0,0 +1 @@
+Hello world!
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs
new file mode 100644
index 0000000000..70362197e0
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs
@@ -0,0 +1,16 @@
+#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "247d02621904d87ab805e437f33c5d03b9a0de91"
+namespace MyApp.Razor.Views
+{
+ #line hidden
+ using System;
+ using System.Threading.Tasks;
+ public class Template
+ {
+ #pragma warning disable 1998
+ public async override global::System.Threading.Tasks.Task ExecuteAsync()
+ {
+ WriteLiteral("Hello world!
");
+ }
+ #pragma warning restore 1998
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.cshtml b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.cshtml
new file mode 100644
index 0000000000..6df88a66a1
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.cshtml
@@ -0,0 +1 @@
+Hello world!
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestProject.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestProject.cs
new file mode 100644
index 0000000000..001996a2a8
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestProject.cs
@@ -0,0 +1,32 @@
+// 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.Reflection;
+
+namespace Microsoft.AspNetCore.Razor.Evolution
+{
+ public static class TestProject
+ {
+ private static readonly string ThisProjectName = typeof(TestProject).GetTypeInfo().Assembly.GetName().Name;
+
+ public static string GetProjectDirectory()
+ {
+
+#if NET452
+ var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
+#else
+ var currentDirectory = new DirectoryInfo(AppContext.BaseDirectory);
+#endif
+
+ while (currentDirectory != null &&
+ !string.Equals(currentDirectory.Name, ThisProjectName, StringComparison.Ordinal))
+ {
+ currentDirectory = currentDirectory.Parent;
+ }
+
+ return currentDirectory.FullName;
+ }
+ }
+}