Begin emitting C# classes for Razor components
This commit is contained in:
parent
3f522ab216
commit
5b3f05bdc1
|
|
@ -1,30 +1,91 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides facilities for transforming Razor files into Blazor component classes.
|
||||
/// </summary>
|
||||
public class RazorCompiler
|
||||
{
|
||||
public ICollection<RazorCompilerDiagnostic> CompileFiles(IEnumerable<string> inputPaths, string outputNamespace, TextWriter resultOutput, TextWriter verboseOutput)
|
||||
{
|
||||
var diagnostics = new List<RazorCompilerDiagnostic>();
|
||||
// TODO: Relax this to allow for whatever C# allows
|
||||
private static Regex ClassNameRegex
|
||||
= new Regex("^[a-z][a-z0-9_]*$", RegexOptions.IgnoreCase);
|
||||
|
||||
foreach (var inputFilePath in inputPaths)
|
||||
/// <summary>
|
||||
/// Writes C# source code representing Blazor components defined by Razor files.
|
||||
/// </summary>
|
||||
/// <param name="inputPaths">Paths to the input files.</param>
|
||||
/// <param name="outputNamespace">The namespace for the generated classes.</param>
|
||||
/// <param name="resultOutput">A <see cref="TextWriter"/> to which C# source code will be written.</param>
|
||||
/// <param name="verboseOutput">If not null, additional information will be written to this <see cref="TextWriter"/>.</param>
|
||||
/// <returns>A collection of <see cref="RazorCompilerDiagnostic"/> instances representing any warnings or errors that were encountered.</returns>
|
||||
public ICollection<RazorCompilerDiagnostic> CompileFiles(IEnumerable<string> inputPaths, string outputNamespace, TextWriter resultOutput, TextWriter verboseOutput)
|
||||
=> inputPaths.SelectMany(
|
||||
path => CompileSingleFile(path, outputNamespace, resultOutput, verboseOutput)).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Writes C# source code representing a Blazor component defined by a Razor file.
|
||||
/// </summary>
|
||||
/// <param name="inputPaths">The path to the input file.</param>
|
||||
/// <param name="outputNamespace">The namespace for the generated class.</param>
|
||||
/// <param name="resultOutput">A <see cref="TextWriter"/> to which C# source code will be written.</param>
|
||||
/// <param name="verboseOutput">If not null, additional information will be written to this <see cref="TextWriter"/>.</param>
|
||||
/// <returns>An enumerable of <see cref="RazorCompilerDiagnostic"/> instances representing any warnings or errors that were encountered.</returns>
|
||||
public IEnumerable<RazorCompilerDiagnostic> CompileSingleFile(string inputFilePath, string outputNamespace, TextWriter resultOutput, TextWriter verboseOutput)
|
||||
{
|
||||
if (resultOutput == null)
|
||||
{
|
||||
verboseOutput?.WriteLine($"Compiling {inputFilePath}...");
|
||||
resultOutput.WriteLine($"// TODO: Compile {inputFilePath}");
|
||||
diagnostics.Add(new RazorCompilerDiagnostic(
|
||||
RazorCompilerDiagnostic.DiagnosticType.Warning,
|
||||
inputFilePath,
|
||||
1,
|
||||
1,
|
||||
"Compiler not implemented"));
|
||||
throw new ArgumentNullException(nameof(resultOutput));
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
try
|
||||
{
|
||||
verboseOutput?.WriteLine($"Compiling {inputFilePath}...");
|
||||
var className = GetClassName(inputFilePath);
|
||||
|
||||
resultOutput.WriteLine($"namespace {outputNamespace} {{");
|
||||
resultOutput.WriteLine($"public class {className}");
|
||||
resultOutput.WriteLine("{");
|
||||
resultOutput.WriteLine("}");
|
||||
resultOutput.WriteLine("}");
|
||||
resultOutput.WriteLine();
|
||||
|
||||
return Enumerable.Empty<RazorCompilerDiagnostic>();
|
||||
}
|
||||
catch (RazorCompilerException ex)
|
||||
{
|
||||
return new[] { ex.ToDiagnostic(inputFilePath) };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new RazorCompilerDiagnostic(
|
||||
RazorCompilerDiagnostic.DiagnosticType.Error,
|
||||
inputFilePath,
|
||||
1,
|
||||
1,
|
||||
$"Unexpected exception: {ex.Message}{Environment.NewLine}{ex.StackTrace}")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetClassName(string inputFilePath)
|
||||
{
|
||||
var basename = Path.GetFileNameWithoutExtension(inputFilePath);
|
||||
if (!ClassNameRegex.IsMatch(basename))
|
||||
{
|
||||
throw new RazorCompilerException($"Invalid name '{basename}'. The name must be valid for a C# class name.");
|
||||
}
|
||||
|
||||
return basename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.Blazor.Build.Core.RazorCompilation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a fatal error during the transformation of a Blazor component from
|
||||
/// Razor source code to C# source code.
|
||||
/// </summary>
|
||||
internal class RazorCompilerException : Exception
|
||||
{
|
||||
public RazorCompilerException(string message): base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public RazorCompilerDiagnostic ToDiagnostic(string sourceFilePath)
|
||||
=> new RazorCompilerDiagnostic(
|
||||
RazorCompilerDiagnostic.DiagnosticType.Error,
|
||||
sourceFilePath,
|
||||
line: 1, // Later it might be necessary to take line/col constructor args, but not needed yet
|
||||
column: 1,
|
||||
message: Message);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,4 @@
|
|||
<Project>
|
||||
|
||||
<!-- Temporarily, the Razor 'compile' process just produces a set of empty classes. This is to
|
||||
show it's possible to codegen the classes both during regular builds and at design time so
|
||||
that the Razor components can be referenced with intellisense from .cs files. -->
|
||||
|
||||
<Project>
|
||||
<Target Name="BlazorCompileRazorComponents" BeforeTargets="CoreCompile">
|
||||
<PropertyGroup>
|
||||
<BlazorComponentsNamespace>BlazorComponents</BlazorComponentsNamespace>
|
||||
|
|
|
|||
Loading…
Reference in New Issue