Remove references to Razor from RazorPageGenerator
This commit is contained in:
parent
3772c7c343
commit
c83741f11c
|
|
@ -19,7 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
NuGet.config = NuGet.config
|
NuGet.config = NuGet.config
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageGenerator", "src\RazorPageGenerator\RazorPageGenerator.csproj", "{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RazorPageGenerator", "src\RazorPageGenerator\RazorPageGenerator.csproj", "{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Evolution", "src\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj", "{932F3C9C-A6C0-40D3-BA50-9309886242FC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Evolution", "src\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj", "{932F3C9C-A6C0-40D3-BA50-9309886242FC}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||||
|
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
{
|
{
|
||||||
|
|
@ -57,6 +58,48 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
return builder;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IRazorEngineBuilder ConfigureClass(
|
||||||
|
this IRazorEngineBuilder builder,
|
||||||
|
Action<RazorCodeDocument, ClassDeclarationIRNode> configureClass)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configureClass == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configureClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder);
|
||||||
|
configurationFeature.ConfigureClass.Add(configureClass);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IRazorEngineBuilder SetNamespace(this IRazorEngineBuilder builder, string namespaceName)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder);
|
||||||
|
configurationFeature.ConfigureNamespace.Add((document, @namespace) => @namespace.Content = namespaceName);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
private static IRazorDirectiveFeature GetDirectiveFeature(IRazorEngineBuilder builder)
|
private static IRazorDirectiveFeature GetDirectiveFeature(IRazorEngineBuilder builder)
|
||||||
{
|
{
|
||||||
var directiveFeature = builder.Features.OfType<IRazorDirectiveFeature>().FirstOrDefault();
|
var directiveFeature = builder.Features.OfType<IRazorDirectiveFeature>().FirstOrDefault();
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
// 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 Microsoft.AspNetCore.Razor;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Razor.CodeGenerators;
|
using Microsoft.AspNetCore.Razor.Evolution;
|
||||||
|
|
||||||
namespace RazorPageGenerator
|
namespace RazorPageGenerator
|
||||||
{
|
{
|
||||||
|
|
@ -23,7 +24,20 @@ namespace RazorPageGenerator
|
||||||
|
|
||||||
var rootNamespace = args[0];
|
var rootNamespace = args[0];
|
||||||
var targetProjectDirectory = Directory.GetCurrentDirectory();
|
var targetProjectDirectory = Directory.GetCurrentDirectory();
|
||||||
|
var razorEngine = RazorEngine.Create(builder =>
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.SetNamespace(rootNamespace)
|
||||||
|
.SetBaseType("Microsoft.Extensions.RazorViews.BaseView")
|
||||||
|
.ConfigureClass((document, @class) =>
|
||||||
|
{
|
||||||
|
@class.Name = Path.GetFileNameWithoutExtension(document.Source.Filename);
|
||||||
|
@class.AccessModifier = "internal";
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Features.Add(new RemovePragamaChecksumFeature());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
|
var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
|
@ -32,8 +46,11 @@ namespace RazorPageGenerator
|
||||||
{
|
{
|
||||||
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 templateEngine = new RazorTemplateEngine(razorEngine, razorProject);
|
||||||
|
|
||||||
var cshtmlFiles = Directory.EnumerateFiles(viewDir, "*.cshtml");
|
|
||||||
|
var cshtmlFiles = razorProject.EnumerateItems("");
|
||||||
|
|
||||||
if (!cshtmlFiles.Any())
|
if (!cshtmlFiles.Any())
|
||||||
{
|
{
|
||||||
|
|
@ -41,10 +58,10 @@ namespace RazorPageGenerator
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var fileName in cshtmlFiles)
|
foreach (var item in cshtmlFiles)
|
||||||
{
|
{
|
||||||
Console.WriteLine(" Generating code file for view {0}...", Path.GetFileName(fileName));
|
Console.WriteLine(" Generating code file for view {0}...", item.Filename);
|
||||||
GenerateCodeFile(fileName, rootNamespace);
|
GenerateCodeFile(templateEngine, item);
|
||||||
Console.WriteLine(" Done!");
|
Console.WriteLine(" Done!");
|
||||||
fileCount++;
|
fileCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -55,66 +72,104 @@ namespace RazorPageGenerator
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateCodeFile(string cshtmlFilePath, string rootNamespace)
|
private static void GenerateCodeFile(RazorTemplateEngine templateEngine, RazorProjectItem projectItem)
|
||||||
{
|
{
|
||||||
var basePath = Path.GetDirectoryName(cshtmlFilePath);
|
var cSharpDocument = templateEngine.GenerateCode(projectItem);
|
||||||
var fileName = Path.GetFileName(cshtmlFilePath);
|
if (cSharpDocument.Diagnostics.Any())
|
||||||
var fileNameNoExtension = Path.GetFileNameWithoutExtension(fileName);
|
{
|
||||||
var codeLang = new CSharpRazorCodeLanguage();
|
var diagnostics = string.Join(Environment.NewLine, cSharpDocument.Diagnostics);
|
||||||
var host = new RazorEngineHost(codeLang);
|
Console.WriteLine($"One or more parse errors encountered. This will not prevent the generator from continuing: {Environment.NewLine}{diagnostics}.");
|
||||||
host.DefaultBaseClass = "Microsoft.Extensions.RazorViews.BaseView";
|
}
|
||||||
host.GeneratedClassContext = new GeneratedClassContext(
|
|
||||||
executeMethodName: GeneratedClassContext.DefaultExecuteMethodName,
|
|
||||||
writeMethodName: GeneratedClassContext.DefaultWriteMethodName,
|
|
||||||
writeLiteralMethodName: GeneratedClassContext.DefaultWriteLiteralMethodName,
|
|
||||||
writeToMethodName: "WriteTo",
|
|
||||||
writeLiteralToMethodName: "WriteLiteralTo",
|
|
||||||
templateTypeName: "HelperResult",
|
|
||||||
defineSectionMethodName: "DefineSection",
|
|
||||||
generatedTagHelperContext: new GeneratedTagHelperContext());
|
|
||||||
var engine = new RazorTemplateEngine(host);
|
|
||||||
|
|
||||||
var cshtmlContent = File.ReadAllText(cshtmlFilePath);
|
var generatedCodeFilePath = Path.ChangeExtension(
|
||||||
cshtmlContent = ProcessFileIncludes(basePath, cshtmlContent);
|
((FileSystemRazorProjectItem)projectItem).FileInfo.FullName,
|
||||||
|
".Designer.cs");
|
||||||
var generatorResults = engine.GenerateCode(
|
File.WriteAllText(generatedCodeFilePath, cSharpDocument.GeneratedCode);
|
||||||
input: new StringReader(cshtmlContent),
|
|
||||||
className: fileNameNoExtension,
|
|
||||||
rootNamespace: Path.GetFileName(rootNamespace),
|
|
||||||
sourceFileName: fileName);
|
|
||||||
|
|
||||||
var generatedCode = generatorResults.GeneratedCode;
|
|
||||||
|
|
||||||
// Make the generated class 'internal' instead of 'public'
|
|
||||||
generatedCode = generatedCode.Replace("public class", "internal class");
|
|
||||||
|
|
||||||
File.WriteAllText(Path.Combine(basePath, string.Format("{0}.Designer.cs", fileNameNoExtension)), generatedCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ProcessFileIncludes(string basePath, string cshtmlContent)
|
private class FileSystemRazorProject : RazorProject
|
||||||
{
|
{
|
||||||
var startMatch = "<%$ include: ";
|
private readonly string _basePath;
|
||||||
var endMatch = " %>";
|
|
||||||
var startIndex = 0;
|
public FileSystemRazorProject(string basePath)
|
||||||
while (startIndex < cshtmlContent.Length)
|
|
||||||
{
|
{
|
||||||
startIndex = cshtmlContent.IndexOf(startMatch, startIndex);
|
_basePath = basePath;
|
||||||
if (startIndex == -1)
|
}
|
||||||
{
|
|
||||||
break;
|
public override IEnumerable<RazorProjectItem> EnumerateItems(string basePath)
|
||||||
}
|
{
|
||||||
var endIndex = cshtmlContent.IndexOf(endMatch, startIndex);
|
return new DirectoryInfo(_basePath)
|
||||||
if (endIndex == -1)
|
.EnumerateFiles("*.cshtml", SearchOption.TopDirectoryOnly)
|
||||||
{
|
.Select(file => GetItem(basePath, file));
|
||||||
throw new InvalidOperationException("Invalid include file format. Usage example: <%$ include: ErrorPage.js %>");
|
}
|
||||||
}
|
|
||||||
var includeFileName = cshtmlContent.Substring(startIndex + startMatch.Length, endIndex - (startIndex + startMatch.Length));
|
public override RazorProjectItem GetItem(string path) => throw new NotSupportedException();
|
||||||
Console.WriteLine(" Inlining file {0}", includeFileName);
|
|
||||||
var includeFileContent = File.ReadAllText(Path.Combine(basePath, includeFileName));
|
private RazorProjectItem GetItem(string basePath, FileInfo file)
|
||||||
cshtmlContent = cshtmlContent.Substring(0, startIndex) + includeFileContent + cshtmlContent.Substring(endIndex + endMatch.Length);
|
{
|
||||||
startIndex = startIndex + includeFileContent.Length;
|
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.
|
||||||
|
public override string PhysicalPath => FileInfo.Name;
|
||||||
|
|
||||||
|
public override bool Exists => true;
|
||||||
|
|
||||||
|
public override Stream Read()
|
||||||
|
{
|
||||||
|
var processedContent = ProcessFileIncludes();
|
||||||
|
return new MemoryStream(Encoding.UTF8.GetBytes(processedContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessFileIncludes()
|
||||||
|
{
|
||||||
|
var basePath = FileInfo.DirectoryName;
|
||||||
|
var cshtmlContent = File.ReadAllText(FileInfo.FullName);
|
||||||
|
|
||||||
|
var startMatch = "<%$ include: ";
|
||||||
|
var endMatch = " %>";
|
||||||
|
var startIndex = 0;
|
||||||
|
while (startIndex < cshtmlContent.Length)
|
||||||
|
{
|
||||||
|
startIndex = cshtmlContent.IndexOf(startMatch, startIndex);
|
||||||
|
if (startIndex == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var endIndex = cshtmlContent.IndexOf(endMatch, startIndex);
|
||||||
|
if (endIndex == -1)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Invalid include file format in {FileInfo.FullName}. Usage example: <%$ include: ErrorPage.js %>");
|
||||||
|
}
|
||||||
|
var includeFileName = cshtmlContent.Substring(startIndex + startMatch.Length, endIndex - (startIndex + startMatch.Length));
|
||||||
|
Console.WriteLine(" Inlining file {0}", includeFileName);
|
||||||
|
var includeFileContent = File.ReadAllText(System.IO.Path.Combine(basePath, includeFileName));
|
||||||
|
cshtmlContent = cshtmlContent.Substring(0, startIndex) + includeFileContent + cshtmlContent.Substring(endIndex + endMatch.Length);
|
||||||
|
startIndex = startIndex + includeFileContent.Length;
|
||||||
|
}
|
||||||
|
return cshtmlContent;
|
||||||
}
|
}
|
||||||
return cshtmlContent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<Import Project="..\..\build\common.props" />
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.Razor\Microsoft.AspNetCore.Razor.csproj" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Razor.Evolution;
|
||||||
|
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||||
|
|
||||||
|
namespace RazorPageGenerator
|
||||||
|
{
|
||||||
|
class RemovePragamaChecksumFeature : RazorIRPassBase, IRazorIROptimizationPass
|
||||||
|
{
|
||||||
|
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||||
|
{
|
||||||
|
var walker = new Walker();
|
||||||
|
walker.Visit(irDocument);
|
||||||
|
|
||||||
|
walker.ChecksumNode.Parent.Children.Remove(walker.ChecksumNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Walker : RazorIRNodeWalker
|
||||||
|
{
|
||||||
|
public ChecksumIRNode ChecksumNode { get; private set; }
|
||||||
|
|
||||||
|
public override void VisitChecksum(ChecksumIRNode node)
|
||||||
|
{
|
||||||
|
ChecksumNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue