Begin integrating with real Razor compiler
This commit is contained in:
parent
a03cb48c7a
commit
3ccdc1d16f
|
|
@ -1,3 +1,2 @@
|
|||
@inherits Microsoft.Blazor.Components.BlazorComponent
|
||||
<h1>Hello, world!</h1>
|
||||
<h1>Hello, world!</h1>
|
||||
Hello from the Razor component.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
||||
{
|
||||
internal static class BlazorCodeDocItems
|
||||
{
|
||||
public static object ClassName = new object();
|
||||
public static object Namespace = new object();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
||||
{
|
||||
/// <summary>
|
||||
/// Directs a <see cref="DocumentWriter"/> to use <see cref="BlazorIntermediateNodeWriter"/>.
|
||||
/// </summary>
|
||||
internal class BlazorCodeTarget : CodeTarget
|
||||
{
|
||||
public override IntermediateNodeWriter CreateNodeWriter()
|
||||
=> new BlazorIntermediateNodeWriter();
|
||||
|
||||
public override TExtension GetExtension<TExtension>()
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public override bool HasExtension<TExtension>()
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates the C# code corresponding to Razor source document contents.
|
||||
/// </summary>
|
||||
internal class BlazorIntermediateNodeWriter : IntermediateNodeWriter
|
||||
{
|
||||
public override void BeginWriterScope(CodeRenderingContext context, string writer)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(BeginWriterScope));
|
||||
}
|
||||
|
||||
public override void EndWriterScope(CodeRenderingContext context)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(EndWriterScope));
|
||||
}
|
||||
|
||||
public override void WriteCSharpCode(CodeRenderingContext context, CSharpCodeIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteCSharpCode));
|
||||
}
|
||||
|
||||
public override void WriteCSharpCodeAttributeValue(CodeRenderingContext context, CSharpCodeAttributeValueIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteCSharpCodeAttributeValue));
|
||||
}
|
||||
|
||||
public override void WriteCSharpExpression(CodeRenderingContext context, CSharpExpressionIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteCSharpExpression));
|
||||
}
|
||||
|
||||
public override void WriteCSharpExpressionAttributeValue(CodeRenderingContext context, CSharpExpressionAttributeValueIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteCSharpExpressionAttributeValue));
|
||||
}
|
||||
|
||||
public override void WriteHtmlAttribute(CodeRenderingContext context, HtmlAttributeIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteHtmlAttribute));
|
||||
}
|
||||
|
||||
public override void WriteHtmlAttributeValue(CodeRenderingContext context, HtmlAttributeValueIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteHtmlAttributeValue));
|
||||
}
|
||||
|
||||
public override void WriteHtmlContent(CodeRenderingContext context, HtmlContentIntermediateNode node)
|
||||
{
|
||||
context.CodeWriter.Write("/* HTML content */");
|
||||
}
|
||||
|
||||
public override void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node)
|
||||
{
|
||||
throw new System.NotImplementedException(nameof(WriteUsingDirective));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="RazorEngine"/> phase that builds the C# document corresponding to
|
||||
/// a <see cref="RazorCodeDocument"/> for a Blazor component.
|
||||
/// </summary>
|
||||
internal class BlazorLoweringPhase : IRazorCSharpLoweringPhase
|
||||
{
|
||||
private readonly RazorCodeGenerationOptions _codegenOptions;
|
||||
|
||||
public BlazorLoweringPhase(RazorCodeGenerationOptions codegenOptions)
|
||||
{
|
||||
_codegenOptions = codegenOptions
|
||||
?? throw new ArgumentNullException(nameof(codegenOptions));
|
||||
}
|
||||
|
||||
public RazorEngine Engine { get; set; }
|
||||
|
||||
public void Execute(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var writer = BlazorComponentDocumentWriter.Create(_codegenOptions);
|
||||
var documentNode = codeDocument.GetDocumentIntermediateNode();
|
||||
var csharpDoc = writer.WriteDocument(codeDocument, documentNode);
|
||||
codeDocument.SetCSharpDocument(csharpDoc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates <see cref="DocumentWriter"/> instances that are configured to use
|
||||
/// <see cref="BlazorCodeTarget"/>.
|
||||
/// </summary>
|
||||
private class BlazorComponentDocumentWriter : DocumentWriter
|
||||
{
|
||||
public static DocumentWriter Create(RazorCodeGenerationOptions options)
|
||||
=> Instance.Create(new BlazorCodeTarget(), options);
|
||||
|
||||
private static BlazorComponentDocumentWriter Instance
|
||||
= new BlazorComponentDocumentWriter();
|
||||
|
||||
public override RazorCSharpDocument WriteDocument(
|
||||
RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.Blazor.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps <see cref="RazorEngine"/>, configuring it to compile Blazor components.
|
||||
/// </summary>
|
||||
internal class BlazorRazorEngine
|
||||
{
|
||||
private readonly RazorEngine _engine;
|
||||
private readonly RazorCodeGenerationOptions _codegenOptions;
|
||||
|
||||
public BlazorRazorEngine()
|
||||
{
|
||||
_codegenOptions = RazorCodeGenerationOptions.CreateDefault();
|
||||
|
||||
_engine = RazorEngine.Create(configure =>
|
||||
{
|
||||
configure.SetBaseType(typeof(BlazorComponent).FullName);
|
||||
|
||||
configure.Phases.Remove(
|
||||
configure.Phases.OfType<IRazorCSharpLoweringPhase>().Single());
|
||||
configure.Phases.Add(new BlazorLoweringPhase(_codegenOptions));
|
||||
|
||||
configure.ConfigureClass((codeDoc, classNode) =>
|
||||
{
|
||||
configure.SetNamespace((string)codeDoc.Items[BlazorCodeDocItems.Namespace]);
|
||||
classNode.ClassName = (string)codeDoc.Items[BlazorCodeDocItems.ClassName];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void Process(RazorCodeDocument document)
|
||||
=> _engine.Process(document);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.Blazor.Build.Core.RazorCompilation.Engine;
|
||||
using Microsoft.Blazor.Components;
|
||||
using Microsoft.Blazor.RenderTree;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
@ -35,7 +39,7 @@ namespace Microsoft.Blazor.Build.Core.RazorCompilation
|
|||
TextWriter verboseOutput)
|
||||
=> inputPaths.SelectMany(path =>
|
||||
{
|
||||
using (var reader = File.OpenText(path))
|
||||
using (var reader = File.OpenRead(path))
|
||||
{
|
||||
return CompileSingleFile(inputRootPath, path, reader, baseNamespace, resultOutput, verboseOutput);
|
||||
}
|
||||
|
|
@ -53,14 +57,14 @@ namespace Microsoft.Blazor.Build.Core.RazorCompilation
|
|||
public IEnumerable<RazorCompilerDiagnostic> CompileSingleFile(
|
||||
string inputRootPath,
|
||||
string inputFilePath,
|
||||
TextReader inputFileReader,
|
||||
Stream inputFileContents,
|
||||
string baseNamespace,
|
||||
TextWriter resultOutput,
|
||||
TextWriter verboseOutput)
|
||||
{
|
||||
if (inputFileReader == null)
|
||||
if (inputFileContents == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(inputFileReader));
|
||||
throw new ArgumentNullException(nameof(inputFileContents));
|
||||
}
|
||||
|
||||
if (resultOutput == null)
|
||||
|
|
@ -86,12 +90,20 @@ namespace Microsoft.Blazor.Build.Core.RazorCompilation
|
|||
? baseNamespace
|
||||
: $"{baseNamespace}.{itemNamespace}";
|
||||
|
||||
resultOutput.WriteLine($"namespace {combinedNamespace} {{");
|
||||
resultOutput.WriteLine($"public class {itemClassName}");
|
||||
resultOutput.WriteLine("{");
|
||||
resultOutput.WriteLine("}");
|
||||
resultOutput.WriteLine("}");
|
||||
resultOutput.WriteLine();
|
||||
var engine = new BlazorRazorEngine();
|
||||
|
||||
var sourceDoc = RazorSourceDocument.ReadFrom(inputFileContents, inputFilePath);
|
||||
var codeDoc = RazorCodeDocument.Create(sourceDoc);
|
||||
codeDoc.Items[BlazorCodeDocItems.Namespace] = combinedNamespace;
|
||||
codeDoc.Items[BlazorCodeDocItems.ClassName] = itemClassName;
|
||||
engine.Process(codeDoc);
|
||||
var csharpDocument = codeDoc.GetCSharpDocument();
|
||||
var generatedCode = csharpDocument.GeneratedCode;
|
||||
generatedCode = generatedCode.Replace(
|
||||
"public async override global::System.Threading.Tasks.Task ExecuteAsync()",
|
||||
$"public override void {nameof(BlazorComponent.BuildRenderTree)}({typeof(RenderTreeBuilder).FullName} builder)");
|
||||
|
||||
resultOutput.WriteLine(generatedCode);
|
||||
|
||||
return Enumerable.Empty<RazorCompilerDiagnostic>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Blazor.Browser.JS\Microsoft.Blazor.Browser.JS.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Blazor.Mono\Microsoft.Blazor.Mono.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Blazor\Microsoft.Blazor.csproj" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="2.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Composite" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="2.0.0" />
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Blazor.Build.Core.RazorCompilation;
|
||||
using Microsoft.Blazor.Components;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using System;
|
||||
|
|
@ -95,10 +96,17 @@ namespace Microsoft.Blazor.Build.Test
|
|||
{
|
||||
CSharpSyntaxTree.ParseText(csharpResult.Code)
|
||||
};
|
||||
var references = new[]
|
||||
var referenceAssembliesContainingTypes = new[]
|
||||
{
|
||||
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)
|
||||
typeof(System.Runtime.AssemblyTargetedPatchBandAttribute), // System.Runtime
|
||||
typeof(BlazorComponent)
|
||||
};
|
||||
var references = referenceAssembliesContainingTypes
|
||||
.SelectMany(type => type.Assembly.GetReferencedAssemblies().Concat(new[] { type.Assembly.GetName() }))
|
||||
.Distinct()
|
||||
.Select(Assembly.Load)
|
||||
.Select(assembly => MetadataReference.CreateFromFile(assembly.Location))
|
||||
.ToList();
|
||||
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
|
||||
var assemblyName = "TestAssembly" + Guid.NewGuid().ToString("N");
|
||||
var compilation = CSharpCompilation.Create(assemblyName,
|
||||
|
|
@ -126,12 +134,12 @@ namespace Microsoft.Blazor.Build.Test
|
|||
using (var resultWriter = new StreamWriter(resultStream))
|
||||
using (var verboseLogStream = new MemoryStream())
|
||||
using (var verboseWriter = new StreamWriter(verboseLogStream))
|
||||
using (var inputReader = new StringReader(cshtmlContent))
|
||||
using (var inputContents = new MemoryStream(Encoding.UTF8.GetBytes(cshtmlContent)))
|
||||
{
|
||||
var diagnostics = new RazorCompiler().CompileSingleFile(
|
||||
cshtmlRootPath,
|
||||
cshtmlRelativePath,
|
||||
inputReader,
|
||||
inputContents,
|
||||
outputNamespace,
|
||||
resultWriter,
|
||||
verboseWriter);
|
||||
|
|
|
|||
Loading…
Reference in New Issue