Update to use Razor parser to parse page directive

This commit is contained in:
Pranav K 2017-05-31 11:59:14 -07:00
parent 17a74a4c2d
commit 20c04d099e
2 changed files with 49 additions and 58 deletions

View File

@ -3,12 +3,29 @@
using System; using System;
using System.IO; using System.IO;
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{ {
public static class PageDirectiveFeature public static class PageDirectiveFeature
{ {
private static readonly RazorEngine PageDirectiveEngine = RazorEngine.Create(builder =>
{
for (var i = builder.Phases.Count - 1; i >= 0; i--)
{
var phase = builder.Phases[i];
builder.Phases.RemoveAt(i);
if (phase is IRazorDocumentClassifierPhase)
{
break;
}
}
RazorExtensions.Register(builder);
builder.Features.Add(new PageDirectiveParserOptionsFeature());
});
public static bool TryGetPageDirective(RazorProjectItem projectItem, out string template) public static bool TryGetPageDirective(RazorProjectItem projectItem, out string template)
{ {
if (projectItem == null) if (projectItem == null)
@ -16,7 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
throw new ArgumentNullException(nameof(projectItem)); throw new ArgumentNullException(nameof(projectItem));
} }
return TryGetPageDirective(projectItem.Read, out template); var sourceDocument = RazorSourceDocument.ReadFrom(projectItem);
return TryGetPageDirective(sourceDocument, out template);
} }
public static bool TryGetPageDirective(Func<Stream> streamFactory, out string template) public static bool TryGetPageDirective(Func<Stream> streamFactory, out string template)
@ -26,38 +44,36 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
throw new ArgumentNullException(nameof(streamFactory)); throw new ArgumentNullException(nameof(streamFactory));
} }
const string PageDirective = "@page"; using (var stream = streamFactory())
string content;
using (var streamReader = new StreamReader(streamFactory()))
{ {
do var sourceDocument = RazorSourceDocument.ReadFrom(stream, fileName: "Parse.cshtml");
{ return TryGetPageDirective(sourceDocument, out template);
content = streamReader.ReadLine(); }
}
} while (content != null && string.IsNullOrWhiteSpace(content)); private static bool TryGetPageDirective(RazorSourceDocument sourceDocument, out string template)
content = content?.Trim(); {
var codeDocument = RazorCodeDocument.Create(sourceDocument);
PageDirectiveEngine.Process(codeDocument);
if (PageDirective.TryGetPageDirective(codeDocument.GetIRDocument(), out var pageDirective))
{
template = pageDirective.RouteTemplate;
return true;
} }
if (content == null || !content.StartsWith(PageDirective, StringComparison.Ordinal)) template = null;
{ return false;
template = null; }
return false;
}
template = content.Substring(PageDirective.Length, content.Length - PageDirective.Length).TrimStart(); private class PageDirectiveParserOptionsFeature : RazorEngineFeatureBase, IRazorParserOptionsFeature
{
public int Order { get; }
if (template.StartsWith("\"") && template.EndsWith("\"")) public void Configure(RazorParserOptionsBuilder options)
{ {
template = template.Substring(1, template.Length - 2); options.ParseOnlyLeadingDirectives = true;
} }
// If it's not in quotes it's not our template
else
{
template = string.Empty;
}
return true;
} }
} }
} }

View File

@ -48,18 +48,6 @@ The rest of the thing");
Assert.Null(template); Assert.Null(template);
} }
[Fact]
public void TryGetPageDirective_MultipleQuotes()
{
// Arrange
string template;
var projectItem = new TestRazorProjectItem(@"@page """"template""""");
// Act & Assert
Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Equal(@"""template""", template);
}
[Theory] [Theory]
[InlineData(@"""Some/Path/{value}")] [InlineData(@"""Some/Path/{value}")]
[InlineData(@"Some/Path/{value}""")] [InlineData(@"Some/Path/{value}""")]
@ -71,10 +59,9 @@ The rest of the thing");
// Act & Assert // Act & Assert
Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template)); Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Equal(string.Empty, template); Assert.Null(template);
} }
[Fact] [Fact]
public void TryGetPageDirective_NoQuotesAroundPath_IsNotTemplate() public void TryGetPageDirective_NoQuotesAroundPath_IsNotTemplate()
{ {
@ -84,7 +71,7 @@ The rest of the thing");
// Act & Assert // Act & Assert
Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template)); Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Equal(string.Empty, template); Assert.Null(template);
} }
[Fact] [Fact]
@ -126,7 +113,7 @@ The rest of the thing");
Assert.Equal("Some/Path/{value}", template); Assert.Equal("Some/Path/{value}", template);
} }
[Fact(Skip = "Re-evaluate this scenario after we use Razor to parse this stuff")] [Fact]
public void TryGetPageDirective_JunkBeforeNewline() public void TryGetPageDirective_JunkBeforeNewline()
{ {
// Arrange // Arrange
@ -136,7 +123,7 @@ a new line");
// Act & Assert // Act & Assert
Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template)); Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Empty(template); Assert.Equal("Some/Path/{value}", template);
} }
[Fact] [Fact]
@ -148,7 +135,7 @@ a new line");
// Act & Assert // Act & Assert
Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template)); Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Empty(template); Assert.Null(template);
} }
[Fact] [Fact]
@ -161,7 +148,7 @@ Non-path things");
// Act & Assert // Act & Assert
Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template)); Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Empty(template); Assert.Null(template);
} }
[Fact] [Fact]
@ -236,21 +223,9 @@ Nobody will use it");
} }
} }
public override string Path public override string Path => "Test.cshtml";
{
get
{
throw new NotImplementedException();
}
}
public override string PhysicalPath public override string PhysicalPath => null;
{
get
{
throw new NotImplementedException();
}
}
public override Stream Read() public override Stream Read()
{ {