// 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.Text;
namespace Microsoft.AspNetCore.Razor.Evolution
{
///
/// An abstraction for working with a project containing Razor files.
///
public abstract class RazorProject
{
///
/// Gets a sequence of under the specific path in the project.
///
/// The base path.
/// The sequence of .
public abstract IEnumerable EnumerateItems(string basePath);
///
/// Gets a for the specified path.
///
/// The path.
/// The .
public abstract RazorProjectItem GetItem(string path);
///
/// Gets the sequence of files named that are applicable to the specified path.
///
/// The path of a project item.
/// The file name to seek.
/// A sequence of applicable instances.
///
/// This method returns paths starting from the directory of and
/// traverses to the project root.
/// e.g.
/// /Views/Home/View.cshtml -> [ /Views/Home/FileName.cshtml, /Views/FileName.cshtml, /FileName.cshtml ]
///
public virtual IEnumerable FindHierarchicalItems(string path, string fileName)
{
EnsureValidPath(path);
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(fileName));
}
Debug.Assert(!string.IsNullOrEmpty(path));
if (path.Length == 1)
{
yield break;
}
StringBuilder builder;
var fileNameIndex = path.LastIndexOf('/');
var length = path.Length;
Debug.Assert(fileNameIndex != -1);
if (string.Compare(path, fileNameIndex + 1, fileName, 0, fileName.Length) == 0)
{
// If the specified path is for the file hierarchy being constructed, then the first file that applies
// to it is in a parent directory.
builder = new StringBuilder(path, 0, fileNameIndex, fileNameIndex + fileName.Length);
length = fileNameIndex;
}
else
{
builder = new StringBuilder(path);
}
var index = length;
while (index > 0 && (index = path.LastIndexOf('/', index - 1)) != -1)
{
builder.Length = index + 1;
builder.Append(fileName);
var itemPath = builder.ToString();
yield return GetItem(itemPath);
}
}
///
/// Performs validation for paths passed to methods of .
///
/// The path to validate.
protected virtual void EnsureValidPath(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(path));
}
if (path[0] != '/')
{
throw new ArgumentException(Resources.RazorProject_PathMustStartWithForwardSlash, nameof(path));
}
}
}
}