Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Commit

Permalink
Add support for base path in FindHiearchicalItems
Browse files Browse the repository at this point in the history
Required for aspnet/Mvc#5915
  • Loading branch information
pranavkm committed Mar 13, 2017
1 parent 7d43bfc commit 7f303f9
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/Microsoft.AspNetCore.Razor.Evolution/RazorProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,27 @@ public abstract class RazorProject
/// e.g.
/// /Views/Home/View.cshtml -> [ /Views/Home/FileName.cshtml, /Views/FileName.cshtml, /FileName.cshtml ]
/// </remarks>
public virtual IEnumerable<RazorProjectItem> FindHierarchicalItems(string path, string fileName)
public IEnumerable<RazorProjectItem> FindHierarchicalItems(string path, string fileName)
{
return FindHierarchicalItems(basePath: "/", path: path, fileName: fileName);
}

/// <summary>
/// Gets the sequence of files named <paramref name="fileName"/> that are applicable to the specified path.
/// </summary>
/// <param name="basePath">The base path.</param>
/// <param name="path">The path of a project item.</param>
/// <param name="fileName">The file name to seek.</param>
/// <returns>A sequence of applicable <see cref="RazorProjectItem"/> instances.</returns>
/// <remarks>
/// This method returns paths starting from the directory of <paramref name="path"/> and
/// traverses to the <paramref name="basePath"/>.
/// e.g.
/// (/Views, /Views/Home/View.cshtml) -> [ /Views/Home/FileName.cshtml, /Views/FileName.cshtml ]
/// </remarks>
public virtual IEnumerable<RazorProjectItem> FindHierarchicalItems(string basePath, string path, string fileName)
{
EnsureValidPath(basePath);
EnsureValidPath(path);
if (string.IsNullOrEmpty(fileName))
{
Expand All @@ -53,6 +72,11 @@ public virtual IEnumerable<RazorProjectItem> FindHierarchicalItems(string path,
yield break;
}

if (!path.StartsWith(basePath, StringComparison.OrdinalIgnoreCase))
{
yield break;
}

StringBuilder builder;
var fileNameIndex = path.LastIndexOf('/');
var length = path.Length;
Expand All @@ -69,8 +93,9 @@ public virtual IEnumerable<RazorProjectItem> FindHierarchicalItems(string path,
builder = new StringBuilder(path);
}

var maxDepth = 255;
var index = length;
while (index > 0 && (index = path.LastIndexOf('/', index - 1)) != -1)
while (maxDepth-- > 0 && index > basePath.Length && (index = path.LastIndexOf('/', index - 1)) != -1)
{
builder.Length = index + 1;
builder.Append(fileName);
Expand Down
121 changes: 121 additions & 0 deletions test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorProjectTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,127 @@ public void FindHierarchicalItems_IncludesNonExistentFiles()
});
}

[Theory]
[InlineData("/Areas")]
[InlineData("/Areas/")]
public void FindHierarchicalItems_WithBasePath(string basePath)
{
// Arrange
var path = "/Areas/MyArea/Views/Home/Test.cshtml";
var items = new Dictionary<string, RazorProjectItem>
{
{ "/Areas/MyArea/File.cshtml", CreateProjectItem("/Areas/MyArea/File.cshtml") },
{ "/File.cshtml", CreateProjectItem("/File.cshtml") },
};
var project = new TestRazorProject(items);

// Act
var result = project.FindHierarchicalItems(basePath, path, "File.cshtml");

// Assert
Assert.Collection(
result,
item =>
{
Assert.Equal("/Areas/MyArea/Views/Home/File.cshtml", item.Path);
Assert.False(item.Exists);
},
item =>
{
Assert.Equal("/Areas/MyArea/Views/File.cshtml", item.Path);
Assert.False(item.Exists);
},
item =>
{
Assert.Equal("/Areas/MyArea/File.cshtml", item.Path);
Assert.True(item.Exists);
},
item =>
{
Assert.Equal("/Areas/File.cshtml", item.Path);
Assert.False(item.Exists);
});
}

[Theory]
[InlineData("/Areas/MyArea/Views")]
[InlineData("/Areas/MyArea/Views/")]
public void FindHierarchicalItems_WithNestedBasePath(string basePath)
{
// Arrange
var path = "/Areas/MyArea/Views/Home/Test.cshtml";
var items = new Dictionary<string, RazorProjectItem>
{
{ "/Areas/MyArea/File.cshtml", CreateProjectItem("/Areas/MyArea/File.cshtml") },
{ "/File.cshtml", CreateProjectItem("/File.cshtml") },
};
var project = new TestRazorProject(items);

// Act
var result = project.FindHierarchicalItems(basePath, path, "File.cshtml");

// Assert
Assert.Collection(
result,
item =>
{
Assert.Equal("/Areas/MyArea/Views/Home/File.cshtml", item.Path);
Assert.False(item.Exists);
},
item =>
{
Assert.Equal("/Areas/MyArea/Views/File.cshtml", item.Path);
Assert.False(item.Exists);
});
}

[Theory]
[InlineData("/Areas/MyArea/Views/Home")]
[InlineData("/Areas/MyArea/Views/Home/")]
public void FindHierarchicalItems_WithFileAtBasePath(string basePath)
{
// Arrange
var path = "/Areas/MyArea/Views/Home/Test.cshtml";
var items = new Dictionary<string, RazorProjectItem>
{
{ "/Areas/MyArea/File.cshtml", CreateProjectItem("/Areas/MyArea/File.cshtml") },
{ "/File.cshtml", CreateProjectItem("/File.cshtml") },
};
var project = new TestRazorProject(items);

// Act
var result = project.FindHierarchicalItems(basePath, path, "File.cshtml");

// Assert
Assert.Collection(
result,
item =>
{
Assert.Equal("/Areas/MyArea/Views/Home/File.cshtml", item.Path);
Assert.False(item.Exists);
});
}

[Fact]
public void FindHierarchicalItems_ReturnsEmptySequenceIfPathIsNotASubPathOfBasePath()
{
// Arrange
var basePath = "/Pages";
var path = "/Areas/MyArea/Views/Home/Test.cshtml";
var items = new Dictionary<string, RazorProjectItem>
{
{ "/Areas/MyArea/File.cshtml", CreateProjectItem("/Areas/MyArea/File.cshtml") },
{ "/File.cshtml", CreateProjectItem("/File.cshtml") },
};
var project = new TestRazorProject(items);

// Act
var result = project.FindHierarchicalItems(basePath, path, "File.cshtml");

// Assert
Assert.Empty(result);
}

private RazorProjectItem CreateProjectItem(string path)
{
var projectItem = new Mock<RazorProjectItem>();
Expand Down

0 comments on commit 7f303f9

Please sign in to comment.