Move FileSystemRazorProject into Razor.Evolution

Add tests
This commit is contained in:
Pranav K 2017-02-24 09:25:12 -08:00
parent c83741f11c
commit 12a502d775
18 changed files with 468 additions and 88 deletions

View File

@ -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
{
/// <summary>
/// A <see cref="RazorProject"/> implementation over the physical file system.
/// </summary>
public class FileSystemRazorProject : RazorProject
{
/// <summary>
/// Initializes a new instance of <see cref="FileSystemRazorProject"/>.
/// </summary>
/// <param name="root">The directory to root the file system at.</param>
public FileSystemRazorProject(string root)
{
if (string.IsNullOrEmpty(root))
{
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(root));
}
Root = root.TrimEnd('/', '\\');
}
/// <summary>
/// The root of the file system.
/// </summary>
public string Root { get; }
/// <inheritdoc />
public override IEnumerable<RazorProjectItem> 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<RazorProjectItem>();
}
return directory
.EnumerateFiles("*.cshtml", SearchOption.AllDirectories)
.Select(file =>
{
var relativePath = file.FullName.Substring(absoluteBasePath.Length).Replace(Path.DirectorySeparatorChar, '/');
return new FileSystemRazorProjectItem(basePath, relativePath, file);
});
}
/// <inheritdoc />
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));
}
}
}

View File

@ -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
{
/// <summary>
/// An implementation of <see cref="RazorProjectItem"/> using <see cref="FileInfo"/>.
/// </summary>
public class FileSystemRazorProjectItem : RazorProjectItem
{
/// <summary>
/// Initializes a new instance of <see cref="FileSystemRazorProjectItem"/>.
/// </summary>
/// <param name="basePath">The base path.</param>
/// <param name="path">The path.</param>
/// <param name="file">The <see cref="FileInfo"/>.</param>
public FileSystemRazorProjectItem(string basePath, string path, FileInfo file)
{
BasePath = basePath;
Path = path;
File = file;
}
/// <summary>
/// Gets the <see cref="FileInfo"/>.
/// </summary>
public FileInfo File { get; }
/// <inheritdoc />
public override string BasePath { get; }
/// <inheritdoc />
public override string Path { get; }
/// <inheritdoc />
public override bool Exists => File.Exists;
/// <inheritdoc />
public override string Filename => File.Name;
/// <inheritdoc />
public override string PhysicalPath => File.FullName;
/// <inheritdoc />
public override Stream Read() => File.OpenRead();
}
}

View File

@ -8,8 +8,17 @@ using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
namespace Microsoft.AspNetCore.Razor.Evolution namespace Microsoft.AspNetCore.Razor.Evolution
{ {
/// <summary>
/// Extension methods to <see cref="IRazorEngineBuilder" />.
/// </summary>
public static class RazorEngineBuilderExtensions public static class RazorEngineBuilderExtensions
{ {
/// <summary>
/// Adds the specified <see cref="DirectiveDescriptor"/>.
/// </summary>
/// <param name="builder">The <see cref="IRazorEngineBuilder"/>.</param>
/// <param name="directive">The <see cref="DirectiveDescriptor"/> to add.</param>
/// <returns>The <see cref="IRazorEngineBuilder"/>.</returns>
public static IRazorEngineBuilder AddDirective(this IRazorEngineBuilder builder, DirectiveDescriptor directive) public static IRazorEngineBuilder AddDirective(this IRazorEngineBuilder builder, DirectiveDescriptor directive)
{ {
if (builder == null) if (builder == null)
@ -28,6 +37,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder; return builder;
} }
/// <summary>
/// Adds the specified <see cref="IRuntimeTargetExtension"/>.
/// </summary>
/// <param name="builder">The <see cref="IRazorEngineBuilder"/>.</param>
/// <param name="extension">The <see cref="IRuntimeTargetExtension"/> to add.</param>
/// <returns>The <see cref="IRazorEngineBuilder"/>.</returns>
public static IRazorEngineBuilder AddTargetExtension(this IRazorEngineBuilder builder, IRuntimeTargetExtension extension) public static IRazorEngineBuilder AddTargetExtension(this IRazorEngineBuilder builder, IRuntimeTargetExtension extension)
{ {
if (builder == null) if (builder == null)
@ -46,6 +61,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder; return builder;
} }
/// <summary>
/// Sets the base type for generated types.
/// </summary>
/// <param name="builder">The <see cref="IRazorEngineBuilder"/>.</param>
/// <param name="baseType">The name of the base type.</param>
/// <returns>The <see cref="IRazorEngineBuilder"/>.</returns>
public static IRazorEngineBuilder SetBaseType(this IRazorEngineBuilder builder, string baseType) public static IRazorEngineBuilder SetBaseType(this IRazorEngineBuilder builder, string baseType)
{ {
if (builder == null) if (builder == null)
@ -58,17 +79,13 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder; return builder;
} }
public static IRazorEngineBuilder SetClassName(this IRazorEngineBuilder builder, string className) /// <summary>
{ /// Registers a class configuration delegate that gets invoked during code generation.
if (builder == null) /// </summary>
{ /// <param name="builder">The <see cref="IRazorEngineBuilder"/>.</param>
throw new ArgumentNullException(nameof(builder)); /// <param name="configureClass"><see cref="Action"/> invoked to configure
} /// <see cref="ClassDeclarationIRNode"/> during code generation.</param>
/// <returns>The <see cref="IRazorEngineBuilder"/>.</returns>
ConfigureClass(builder, (document, @class) => @class.Name = className);
return builder;
}
public static IRazorEngineBuilder ConfigureClass( public static IRazorEngineBuilder ConfigureClass(
this IRazorEngineBuilder builder, this IRazorEngineBuilder builder,
Action<RazorCodeDocument, ClassDeclarationIRNode> configureClass) Action<RazorCodeDocument, ClassDeclarationIRNode> configureClass)
@ -88,6 +105,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
return builder; return builder;
} }
/// <summary>
/// Sets the namespace for generated types.
/// </summary>
/// <param name="builder">The <see cref="IRazorEngineBuilder"/>.</param>
/// <param name="namespaceName">The name of the namespace.</param>
/// <returns>The <see cref="IRazorEngineBuilder"/>.</returns>
public static IRazorEngineBuilder SetNamespace(this IRazorEngineBuilder builder, string namespaceName) public static IRazorEngineBuilder SetNamespace(this IRazorEngineBuilder builder, string namespaceName)
{ {
if (builder == null) if (builder == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -35,22 +34,21 @@ namespace RazorPageGenerator
@class.AccessModifier = "internal"; @class.AccessModifier = "internal";
}); });
builder.Features.Add(new RemovePragamaChecksumFeature()); builder.Features.Add(new RemovePragmaChecksumFeature());
}); });
var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories); var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
var razorProject = new FileSystemRazorProject(targetProjectDirectory);
var templateEngine = new RazorTemplateEngine(razorEngine, razorProject);
var fileCount = 0; var fileCount = 0;
foreach (var viewDir in viewDirectories) foreach (var viewDir in viewDirectories)
{ {
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(" Generating code files for views in {0}", viewDir); Console.WriteLine(" Generating code files for views in {0}", viewDir);
var razorProject = new FileSystemRazorProject(viewDir); var viewDirPath = viewDir.Substring(targetProjectDirectory.Length).Replace('\\', '/');
var templateEngine = new RazorTemplateEngine(razorEngine, razorProject); var cshtmlFiles = razorProject.EnumerateItems(viewDirPath).Cast<FileSystemRazorProjectItem>();
var cshtmlFiles = razorProject.EnumerateItems("");
if (!cshtmlFiles.Any()) if (!cshtmlFiles.Any())
{ {
@ -72,69 +70,37 @@ namespace RazorPageGenerator
Console.WriteLine(); 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()) if (cSharpDocument.Diagnostics.Any())
{ {
var diagnostics = string.Join(Environment.NewLine, cSharpDocument.Diagnostics); 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}."); Console.WriteLine($"One or more parse errors encountered. This will not prevent the generator from continuing: {Environment.NewLine}{diagnostics}.");
} }
var generatedCodeFilePath = Path.ChangeExtension( var generatedCodeFilePath = Path.ChangeExtension(projectItem.PhysicalPath, ".Designer.cs");
((FileSystemRazorProjectItem)projectItem).FileInfo.FullName,
".Designer.cs");
File.WriteAllText(generatedCodeFilePath, cSharpDocument.GeneratedCode); 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<RazorProjectItem> EnumerateItems(string basePath) public override string BasePath => _source.BasePath;
{
return new DirectoryInfo(_basePath)
.EnumerateFiles("*.cshtml", SearchOption.TopDirectoryOnly)
.Select(file => GetItem(basePath, file));
}
public override RazorProjectItem GetItem(string path) => throw new NotSupportedException(); public override string Path => _source.Path;
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; }
// Mask the full name since we don't want a developer's local file paths to be commited. // 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() public override Stream Read()
{ {
@ -144,8 +110,8 @@ namespace RazorPageGenerator
private string ProcessFileIncludes() private string ProcessFileIncludes()
{ {
var basePath = FileInfo.DirectoryName; var basePath = _source.File.DirectoryName;
var cshtmlContent = File.ReadAllText(FileInfo.FullName); var cshtmlContent = File.ReadAllText(_source.PhysicalPath);
var startMatch = "<%$ include: "; var startMatch = "<%$ include: ";
var endMatch = " %>"; var endMatch = " %>";
@ -160,7 +126,7 @@ namespace RazorPageGenerator
var endIndex = cshtmlContent.IndexOf(endMatch, startIndex); var endIndex = cshtmlContent.IndexOf(endMatch, startIndex);
if (endIndex == -1) 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)); var includeFileName = cshtmlContent.Substring(startIndex + startMatch.Length, endIndex - (startIndex + startMatch.Length));
Console.WriteLine(" Inlining file {0}", includeFileName); Console.WriteLine(" Inlining file {0}", includeFileName);

View File

@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
namespace RazorPageGenerator namespace RazorPageGenerator
{ {
class RemovePragamaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass class RemovePragmaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass
{ {
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument) public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{ {

View File

@ -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());
}
}
}

View File

@ -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);
}
}
}

View File

@ -20,26 +20,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
[IntializeTestFile] [IntializeTestFile]
public abstract class IntegrationTestBase 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 #if GENERATE_BASELINES
private static readonly bool GenerateBaselines = true; private static readonly bool GenerateBaselines = true;
#else #else
@ -50,8 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
private static readonly AsyncLocal<string> _filename = new AsyncLocal<string>(); private static readonly AsyncLocal<string> _filename = new AsyncLocal<string>();
#endif #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. // Used by the test framework to set the 'base' name for test files.
public static string Filename public static string Filename

View File

@ -49,5 +49,63 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
// Assert // Assert
AssertCSharpDocumentMatchesBaseline(cSharpDocument); 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);
}
} }
} }

View File

@ -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("<h1>Hello world!</h1>");
}
#pragma warning restore 1998
}
}

View File

@ -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("<h1>Hello world!</h1>");
}
#pragma warning restore 1998
}
}

View File

@ -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;
}
}
}