Adopt more of Razor Exensibility
Removes some workarounds and uses Razor extensibility in a few more places. _ViewImports now works in VS
This commit is contained in:
parent
39c5aee9a1
commit
57a04fb178
|
|
@ -93,9 +93,9 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.RazorCompilation
|
||||||
// name and any public members. Don't need to actually emit all the RenderTreeBuilder
|
// name and any public members. Don't need to actually emit all the RenderTreeBuilder
|
||||||
// invocations.
|
// invocations.
|
||||||
|
|
||||||
var engine = new BlazorRazorEngine();
|
var engine = RazorEngine.Create(b => BlazorExtensionInitializer.Register(b));
|
||||||
var blazorTemplateEngine = new BlazorTemplateEngine(
|
var blazorTemplateEngine = new BlazorTemplateEngine(
|
||||||
engine.Engine,
|
engine,
|
||||||
RazorProjectFileSystem.Create(inputRootPath));
|
RazorProjectFileSystem.Create(inputRootPath));
|
||||||
var codeDoc = blazorTemplateEngine.CreateCodeDocument(
|
var codeDoc = blazorTemplateEngine.CreateCodeDocument(
|
||||||
new BlazorProjectItem(inputRootPath, inputFilePath, inputFileContents));
|
new BlazorProjectItem(inputRootPath, inputFilePath, inputFileContents));
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,14 @@
|
||||||
<None Remove="tools\**" />
|
<None Remove="tools\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- This is a newer version than is in the shared framework, so copy it -->
|
||||||
|
<Content Include="..\Microsoft.AspNetCore.Blazor.Razor.Extensions\bin\$(Configuration)\netstandard2.0\Microsoft.AspNetCore.Razor.Language.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.Blazor.Browser.JS\Microsoft.AspNetCore.Blazor.Browser.JS.csproj" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.Blazor.Browser.JS\Microsoft.AspNetCore.Blazor.Browser.JS.csproj" />
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.Blazor.Mono\Microsoft.AspNetCore.Blazor.Mono.csproj" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.Blazor.Mono\Microsoft.AspNetCore.Blazor.Mono.csproj" />
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
|
{
|
||||||
|
// Constants for method names used in code-generation
|
||||||
|
// Keep these in sync with the actual definitions
|
||||||
|
internal static class BlazorApi
|
||||||
|
{
|
||||||
|
public static class BlazorComponent
|
||||||
|
{
|
||||||
|
public static readonly string FullTypeName = "Microsoft.AspNetCore.Blazor.Components.BlazorComponent";
|
||||||
|
|
||||||
|
public static readonly string BuildRenderTree = nameof(BuildRenderTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RenderFragment
|
||||||
|
{
|
||||||
|
public static readonly string FullTypeName = "Microsoft.AspNetCore.Blazor.RenderFragment";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RenderTreeBuilder
|
||||||
|
{
|
||||||
|
public static readonly string FullTypeName = "Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder";
|
||||||
|
|
||||||
|
public static readonly string OpenElement = nameof(OpenElement);
|
||||||
|
|
||||||
|
public static readonly string CloseElement = nameof(CloseElement);
|
||||||
|
|
||||||
|
public static readonly string OpenComponent = nameof(OpenComponent);
|
||||||
|
|
||||||
|
public static readonly string CloseComponent = nameof(CloseElement);
|
||||||
|
|
||||||
|
public static readonly string AddContent = nameof(AddContent);
|
||||||
|
|
||||||
|
public static readonly string AddAttribute = nameof(AddAttribute);
|
||||||
|
|
||||||
|
public static readonly string Clear = nameof(Clear);
|
||||||
|
|
||||||
|
public static readonly string GetFrames = nameof(GetFrames);
|
||||||
|
|
||||||
|
public static readonly string ChildContent = nameof(ChildContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BindMethods
|
||||||
|
{
|
||||||
|
public static readonly string GetValue = "Microsoft.AspNetCore.Blazor.Components.BindMethods.GetValue";
|
||||||
|
|
||||||
|
public static readonly string SetValue = "Microsoft.AspNetCore.Blazor.Components.BindMethods.SetValue";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
|
|
@ -11,11 +13,47 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class BlazorCodeTarget : CodeTarget
|
internal class BlazorCodeTarget : CodeTarget
|
||||||
{
|
{
|
||||||
|
private readonly RazorCodeGenerationOptions _options;
|
||||||
|
|
||||||
|
public BlazorCodeTarget(RazorCodeGenerationOptions options, IEnumerable<ICodeTargetExtension> extensions)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
Extensions = extensions.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICodeTargetExtension[] Extensions { get; }
|
||||||
|
|
||||||
public override IntermediateNodeWriter CreateNodeWriter()
|
public override IntermediateNodeWriter CreateNodeWriter()
|
||||||
=> new BlazorIntermediateNodeWriter();
|
{
|
||||||
|
return _options.DesignTime ? (IntermediateNodeWriter)new DesignTimeNodeWriter() : new BlazorIntermediateNodeWriter();
|
||||||
|
}
|
||||||
|
|
||||||
public override TExtension GetExtension<TExtension>() => null;
|
public override TExtension GetExtension<TExtension>()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < Extensions.Length; i++)
|
||||||
|
{
|
||||||
|
var match = Extensions[i] as TExtension;
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool HasExtension<TExtension>() => false;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasExtension<TExtension>()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < Extensions.Length; i++)
|
||||||
|
{
|
||||||
|
var match = Extensions[i] as TExtension;
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// 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.AspNetCore.Blazor.Razor
|
|
||||||
{
|
|
||||||
internal static class BlazorComponent
|
|
||||||
{
|
|
||||||
public static readonly string FullTypeName = "Microsoft.AspNetCore.Blazor.Components.BlazorComponent";
|
|
||||||
|
|
||||||
public static readonly string BuildRenderTree = nameof(BuildRenderTree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
|
{
|
||||||
|
public static class BlazorConfiguration
|
||||||
|
{
|
||||||
|
public static readonly RazorConfiguration Default = new RazorConfiguration(
|
||||||
|
RazorLanguageVersion.Version_2_1,
|
||||||
|
"Blazor-0.1",
|
||||||
|
Array.Empty<RazorExtension>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
|
{
|
||||||
|
public class BlazorExtensionInitializer : RazorExtensionInitializer
|
||||||
|
{
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionsDirective.Register(builder);
|
||||||
|
InjectDirective.Register(builder);
|
||||||
|
InheritsDirective.Register(builder);
|
||||||
|
TemporaryLayoutPass.Register(builder);
|
||||||
|
TemporaryImplementsPass.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Remove(builder.Features.OfType<IImportProjectFeature>().Single());
|
||||||
|
builder.Features.Add(new BlazorImportProjectFeature());
|
||||||
|
|
||||||
|
builder.Features.Add(new ConfigureBlazorCodeGenerationOptions());
|
||||||
|
|
||||||
|
builder.Features.Add(new ComponentDocumentClassifierPass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is temporarily used to initialize a RazorEngine by the build tools until we get the features
|
||||||
|
// we need into the RazorProjectEngine (namespace).
|
||||||
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionsDirective.Register(builder);
|
||||||
|
InjectDirective.Register(builder);
|
||||||
|
InheritsDirective.Register(builder);
|
||||||
|
TemporaryLayoutPass.Register(builder);
|
||||||
|
TemporaryImplementsPass.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new ConfigureBlazorCodeGenerationOptions());
|
||||||
|
|
||||||
|
builder.Features.Add(new ComponentDocumentClassifierPass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
Register(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConfigureBlazorCodeGenerationOptions : IConfigureRazorCodeGenerationOptionsFeature
|
||||||
|
{
|
||||||
|
public int Order => 0;
|
||||||
|
|
||||||
|
public RazorEngine Engine { get; set; }
|
||||||
|
|
||||||
|
public void Configure(RazorCodeGenerationOptionsBuilder options)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
// These metadata attributes require a reference to the Razor.Runtime package which we don't
|
||||||
|
// otherwise need.
|
||||||
|
options.SuppressMetadataAttributes = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
// 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;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
|
{
|
||||||
|
internal class BlazorImportProjectFeature : IImportProjectFeature
|
||||||
|
{
|
||||||
|
private const string ImportsFileName = "_ViewImports.cshtml";
|
||||||
|
|
||||||
|
public RazorProjectItem DefaultImports => VirtualProjectItem.Instance;
|
||||||
|
|
||||||
|
public RazorProjectEngine ProjectEngine { get; set; }
|
||||||
|
|
||||||
|
public IReadOnlyList<RazorProjectItem> GetImports(RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
if (projectItem == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
var imports = new List<RazorProjectItem>()
|
||||||
|
{
|
||||||
|
VirtualProjectItem.Instance,
|
||||||
|
};
|
||||||
|
|
||||||
|
// We add hierarchical imports second so any default directive imports can be overridden.
|
||||||
|
imports.AddRange(GetHierarchicalImports(ProjectEngine.FileSystem, projectItem));
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary API until we fully convert to RazorProjectEngine
|
||||||
|
public IEnumerable<RazorProjectItem> GetHierarchicalImports(RazorProject project, RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
// We want items in descending order. FindHierarchicalItems returns items in ascending order.
|
||||||
|
return project.FindHierarchicalItems(projectItem.FilePath, ImportsFileName).Reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VirtualProjectItem : RazorProjectItem
|
||||||
|
{
|
||||||
|
private readonly byte[] _defaultImportBytes;
|
||||||
|
|
||||||
|
private VirtualProjectItem()
|
||||||
|
{
|
||||||
|
var preamble = Encoding.UTF8.GetPreamble();
|
||||||
|
var content = @"
|
||||||
|
@using System
|
||||||
|
@using System.Collections.Generic
|
||||||
|
@using System.Linq
|
||||||
|
@using System.Threading.Tasks
|
||||||
|
";
|
||||||
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
|
_defaultImportBytes = new byte[preamble.Length + contentBytes.Length];
|
||||||
|
preamble.CopyTo(_defaultImportBytes, 0);
|
||||||
|
contentBytes.CopyTo(_defaultImportBytes, preamble.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BasePath => null;
|
||||||
|
|
||||||
|
public override string FilePath => null;
|
||||||
|
|
||||||
|
public override string PhysicalPath => null;
|
||||||
|
|
||||||
|
public override bool Exists => true;
|
||||||
|
|
||||||
|
public static VirtualProjectItem Instance { get; } = new VirtualProjectItem();
|
||||||
|
|
||||||
|
public override Stream Read() => new MemoryStream(_defaultImportBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -126,7 +126,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
// text to display
|
// text to display
|
||||||
_scopeStack.IncrementCurrentScopeChildCount(context);
|
_scopeStack.IncrementCurrentScopeChildCount(context);
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(RenderTreeBuilder.AddContent)}")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.AddContent)}")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteParameterSeparator();
|
.WriteParameterSeparator();
|
||||||
|
|
||||||
|
|
@ -216,7 +216,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
// Text node
|
// Text node
|
||||||
_scopeStack.IncrementCurrentScopeChildCount(context);
|
_scopeStack.IncrementCurrentScopeChildCount(context);
|
||||||
codeWriter
|
codeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(RenderTreeBuilder.AddContent)}")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.AddContent)}")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteParameterSeparator()
|
.WriteParameterSeparator()
|
||||||
.WriteStringLiteral(nextToken.Data)
|
.WriteStringLiteral(nextToken.Data)
|
||||||
|
|
@ -237,14 +237,14 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
if (isComponent)
|
if (isComponent)
|
||||||
{
|
{
|
||||||
codeWriter
|
codeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(RenderTreeBuilder.OpenComponent)}<{componentTypeName}>")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.OpenComponent)}<{componentTypeName}>")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
codeWriter
|
codeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(RenderTreeBuilder.OpenElement)}")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.OpenElement)}")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteParameterSeparator()
|
.WriteParameterSeparator()
|
||||||
.WriteStringLiteral(nextTag.Data)
|
.WriteStringLiteral(nextTag.Data)
|
||||||
|
|
@ -294,8 +294,8 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
isComponent: isComponent,
|
isComponent: isComponent,
|
||||||
source: CalculateSourcePosition(node.Source, nextToken.Position));
|
source: CalculateSourcePosition(node.Source, nextToken.Position));
|
||||||
var closeMethodName = isComponent
|
var closeMethodName = isComponent
|
||||||
? nameof(RenderTreeBuilder.CloseComponent)
|
? nameof(BlazorApi.RenderTreeBuilder.CloseComponent)
|
||||||
: nameof(RenderTreeBuilder.CloseElement);
|
: nameof(BlazorApi.RenderTreeBuilder.CloseElement);
|
||||||
codeWriter
|
codeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{closeMethodName}")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{closeMethodName}")
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
|
|
@ -334,7 +334,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
WriteAttribute(context.CodeWriter, "value", new IntermediateToken
|
WriteAttribute(context.CodeWriter, "value", new IntermediateToken
|
||||||
{
|
{
|
||||||
Kind = TokenKind.CSharp,
|
Kind = TokenKind.CSharp,
|
||||||
Content = $"{RenderTreeBuilder.BindMethodsGetValue}({valueParams})"
|
Content = $"{BlazorApi.BindMethods.GetValue}({valueParams})"
|
||||||
});
|
});
|
||||||
|
|
||||||
// [2] @onchange(BindSetValue(parsed => { X = parsed; }, X, Y, Z, ...))
|
// [2] @onchange(BindSetValue(parsed => { X = parsed; }, X, Y, Z, ...))
|
||||||
|
|
@ -350,7 +350,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
AttributeValue = new IntermediateToken
|
AttributeValue = new IntermediateToken
|
||||||
{
|
{
|
||||||
Kind = TokenKind.CSharp,
|
Kind = TokenKind.CSharp,
|
||||||
Content = $"onchange({RenderTreeBuilder.BindMethodsSetValue}({parsedArgsJoined}))"
|
Content = $"onchange({BlazorApi.BindMethods.SetValue}({parsedArgsJoined}))"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
WriteElementAttributeToken(context, tag, onChangeAttributeToken);
|
WriteElementAttributeToken(context, tag, onChangeAttributeToken);
|
||||||
|
|
@ -360,7 +360,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
// For any other attribute token (e.g., @onclick(...)), treat it as an expression
|
// For any other attribute token (e.g., @onclick(...)), treat it as an expression
|
||||||
// that will evaluate as an attribute frame
|
// that will evaluate as an attribute frame
|
||||||
context.CodeWriter
|
context.CodeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(RenderTreeBuilder.AddAttribute)}")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.AddAttribute)}")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteParameterSeparator()
|
.WriteParameterSeparator()
|
||||||
.Write(token.AttributeValue.Content)
|
.Write(token.AttributeValue.Content)
|
||||||
|
|
@ -439,7 +439,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
public void BeginWriteAttribute(CodeWriter codeWriter, string key)
|
public void BeginWriteAttribute(CodeWriter codeWriter, string key)
|
||||||
{
|
{
|
||||||
codeWriter
|
codeWriter
|
||||||
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(RenderTreeBuilder.AddAttribute)}")
|
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.AddAttribute)}")
|
||||||
.Write((_sourceSequence++).ToString())
|
.Write((_sourceSequence++).ToString())
|
||||||
.WriteParameterSeparator()
|
.WriteParameterSeparator()
|
||||||
.WriteStringLiteral(key)
|
.WriteStringLiteral(key)
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
// 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 Microsoft.AspNetCore.Razor.Language;
|
|
||||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
|
||||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
|
||||||
{
|
|
||||||
/// <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();
|
|
||||||
ConvertToBlazorPrimaryMethod(documentNode);
|
|
||||||
var csharpDoc = writer.WriteDocument(codeDocument, documentNode);
|
|
||||||
codeDocument.SetCSharpDocument(csharpDoc);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConvertToBlazorPrimaryMethod(DocumentIntermediateNode documentNode)
|
|
||||||
{
|
|
||||||
// Replaces the default "ExecuteAsync" method with Blazor's "BuildRenderTree".
|
|
||||||
// Note that DefaultDocumentWriter's VisitMethodDeclaration is hardcoded to
|
|
||||||
// emit methods with no parameters, so there's no way of setting the parameters
|
|
||||||
// from here. We inject the parameter later in RazorCompiler.
|
|
||||||
var primaryMethod = documentNode.FindPrimaryMethod();
|
|
||||||
primaryMethod.ReturnType = "void";
|
|
||||||
primaryMethod.MethodName = BlazorComponent.BuildRenderTree;
|
|
||||||
primaryMethod.Modifiers.Clear();
|
|
||||||
primaryMethod.Modifiers.Add("protected");
|
|
||||||
primaryMethod.Modifiers.Add("override");
|
|
||||||
|
|
||||||
var line = new CSharpCodeIntermediateNode();
|
|
||||||
line.Children.Add(new IntermediateToken
|
|
||||||
{
|
|
||||||
Kind = TokenKind.CSharp,
|
|
||||||
Content = $"base.{primaryMethod.MethodName}(builder);" + Environment.NewLine
|
|
||||||
});
|
|
||||||
primaryMethod.Children.Insert(0, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
// 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.Linq;
|
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
|
||||||
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps <see cref="RazorEngine"/>, configuring it to compile Blazor components.
|
|
||||||
/// </summary>
|
|
||||||
public class BlazorRazorEngine
|
|
||||||
{
|
|
||||||
private readonly RazorEngine _engine;
|
|
||||||
private readonly RazorCodeGenerationOptions _codegenOptions;
|
|
||||||
|
|
||||||
public RazorEngine Engine => _engine;
|
|
||||||
|
|
||||||
public BlazorRazorEngine()
|
|
||||||
{
|
|
||||||
_codegenOptions = RazorCodeGenerationOptions.CreateDefault();
|
|
||||||
|
|
||||||
_engine = RazorEngine.Create(configure =>
|
|
||||||
{
|
|
||||||
FunctionsDirective.Register(configure);
|
|
||||||
InheritsDirective.Register(configure);
|
|
||||||
InjectDirective.Register(configure);
|
|
||||||
TemporaryLayoutPass.Register(configure);
|
|
||||||
TemporaryImplementsPass.Register(configure);
|
|
||||||
|
|
||||||
configure.SetBaseType(BlazorComponent.FullTypeName);
|
|
||||||
|
|
||||||
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];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
{
|
{
|
||||||
|
|
@ -12,11 +13,26 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BlazorTemplateEngine : RazorTemplateEngine
|
public class BlazorTemplateEngine : RazorTemplateEngine
|
||||||
{
|
{
|
||||||
|
// We need to implement and register this feature for tooling support to work. Subclassing TemplateEngine
|
||||||
|
// doesn't work inside visual studio.
|
||||||
|
private readonly BlazorImportProjectFeature _feature;
|
||||||
|
|
||||||
public BlazorTemplateEngine(RazorEngine engine, RazorProject project)
|
public BlazorTemplateEngine(RazorEngine engine, RazorProject project)
|
||||||
: base(engine, project)
|
: base(engine, project)
|
||||||
{
|
{
|
||||||
Options.ImportsFileName = "_ViewImports.cshtml";
|
_feature = new BlazorImportProjectFeature();
|
||||||
Options.DefaultImports = GetDefaultImports();
|
|
||||||
|
Options.DefaultImports = RazorSourceDocument.ReadFrom(_feature.DefaultImports);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<RazorProjectItem> GetImportItems(RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
if (projectItem == null)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentNullException(nameof(projectItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _feature.GetHierarchicalImports(Project, projectItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RazorSourceDocument GetDefaultImports()
|
private static RazorSourceDocument GetDefaultImports()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
// 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;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
|
{
|
||||||
|
internal class ComponentDocumentClassifierPass : DocumentClassifierPassBase, IRazorDocumentClassifierPass
|
||||||
|
{
|
||||||
|
protected override string DocumentKind => "Blazor.Component-0.1";
|
||||||
|
|
||||||
|
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
// Treat everything as a component by default if Blazor is part of the configuration.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDocumentStructureCreated(
|
||||||
|
RazorCodeDocument codeDocument,
|
||||||
|
NamespaceDeclarationIntermediateNode @namespace,
|
||||||
|
ClassDeclarationIntermediateNode @class,
|
||||||
|
MethodDeclarationIntermediateNode method)
|
||||||
|
{
|
||||||
|
@namespace.Content = (string)codeDocument.Items[BlazorCodeDocItems.Namespace];
|
||||||
|
if (@namespace.Content == null)
|
||||||
|
{
|
||||||
|
@namespace.Content = "Blazor";
|
||||||
|
}
|
||||||
|
|
||||||
|
@class.BaseType = BlazorApi.BlazorComponent.FullTypeName;
|
||||||
|
@class.ClassName = (string)codeDocument.Items[BlazorCodeDocItems.ClassName];
|
||||||
|
if (@class.ClassName == null)
|
||||||
|
{
|
||||||
|
@class.ClassName = codeDocument.Source.FilePath == null ? null : Path.GetFileNameWithoutExtension(codeDocument.Source.FilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@class.ClassName == null)
|
||||||
|
{
|
||||||
|
@class.ClassName = "__BlazorComponent";
|
||||||
|
}
|
||||||
|
|
||||||
|
@class.Modifiers.Clear();
|
||||||
|
@class.Modifiers.Add("public");
|
||||||
|
|
||||||
|
method.ReturnType = "void";
|
||||||
|
method.MethodName = BlazorApi.BlazorComponent.BuildRenderTree;
|
||||||
|
method.Modifiers.Clear();
|
||||||
|
method.Modifiers.Add("protected");
|
||||||
|
method.Modifiers.Add("override");
|
||||||
|
|
||||||
|
method.Parameters.Clear();
|
||||||
|
method.Parameters.Add(new MethodParameter()
|
||||||
|
{
|
||||||
|
ParameterName = "builder",
|
||||||
|
TypeName = BlazorApi.RenderTreeBuilder.FullTypeName,
|
||||||
|
});
|
||||||
|
|
||||||
|
// We need to call the 'base' method as the first statement.
|
||||||
|
var callBase = new CSharpCodeIntermediateNode();
|
||||||
|
callBase.Children.Add(new IntermediateToken
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = $"base.{BlazorApi.BlazorComponent.BuildRenderTree}(builder);" + Environment.NewLine
|
||||||
|
});
|
||||||
|
method.Children.Insert(0, callBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Workaround
|
||||||
|
// This is a workaround for the fact that the base class doesn't provide good support
|
||||||
|
// for replacing the IntermediateNodeWriter when building the code target.
|
||||||
|
void IRazorDocumentClassifierPass.Execute(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
base.Execute(codeDocument, documentNode);
|
||||||
|
documentNode.Target = new BlazorCodeTarget(documentNode.Options, _targetExtensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
base.OnInitialized();
|
||||||
|
|
||||||
|
var feature = Engine.Features.OfType<IRazorTargetExtensionFeature>();
|
||||||
|
_targetExtensions = feature.FirstOrDefault()?.TargetExtensions.ToArray() ?? EmptyExtensionArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ICodeTargetExtension[] EmptyExtensionArray = new ICodeTargetExtension[0];
|
||||||
|
private ICodeTargetExtension[] _targetExtensions;
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,12 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
builder.Description = "Inject a service from the application's service container into a property.";
|
builder.Description = "Inject a service from the application's service container into a property.";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
}
|
||||||
|
|
||||||
public static void Register(IRazorEngineBuilder builder)
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
{
|
{
|
||||||
builder.AddDirective(Directive);
|
builder.AddDirective(Directive);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>
|
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>
|
||||||
<RootNamespace>Microsoft.AspNetCore.Blazor.Razor</RootNamespace>
|
<RootNamespace>Microsoft.AspNetCore.Blazor.Razor</RootNamespace>
|
||||||
|
|
||||||
|
<!-- Copy package references to output, needed so the build project can find them -->
|
||||||
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
// 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.Blazor.Razor;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
[assembly: ProvideRazorExtensionInitializer("Blazor-0.1", typeof(BlazorExtensionInitializer))]
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
// 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.AspNetCore.Blazor.Razor
|
|
||||||
{
|
|
||||||
// Constants for method names used in code-generation
|
|
||||||
// Keep these in sync with the actual RenderTreeBuilder definitions
|
|
||||||
internal static class RenderTreeBuilder
|
|
||||||
{
|
|
||||||
public static readonly string OpenElement = nameof(OpenElement);
|
|
||||||
|
|
||||||
public static readonly string CloseElement = nameof(CloseElement);
|
|
||||||
|
|
||||||
public static readonly string OpenComponent = nameof(OpenComponent);
|
|
||||||
|
|
||||||
public static readonly string CloseComponent = nameof(CloseElement);
|
|
||||||
|
|
||||||
public static readonly string AddContent = nameof(AddContent);
|
|
||||||
|
|
||||||
public static readonly string AddAttribute = nameof(AddAttribute);
|
|
||||||
|
|
||||||
public static readonly string Clear = nameof(Clear);
|
|
||||||
|
|
||||||
public static readonly string GetFrames = nameof(GetFrames);
|
|
||||||
|
|
||||||
public static readonly string ChildContent = nameof(ChildContent);
|
|
||||||
|
|
||||||
public static readonly string BindMethodsGetValue = "Microsoft.AspNetCore.Blazor.Components.BindMethods.GetValue";
|
|
||||||
|
|
||||||
public static readonly string BindMethodsSetValue = "Microsoft.AspNetCore.Blazor.Components.BindMethods.SetValue";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,8 +15,6 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class ScopeStack
|
internal class ScopeStack
|
||||||
{
|
{
|
||||||
private const string _renderFragmentTypeName = "Microsoft.AspNetCore.Blazor.RenderFragment";
|
|
||||||
|
|
||||||
private readonly Stack<ScopeEntry> _stack = new Stack<ScopeEntry>();
|
private readonly Stack<ScopeEntry> _stack = new Stack<ScopeEntry>();
|
||||||
private int _builderVarNumber = 1;
|
private int _builderVarNumber = 1;
|
||||||
|
|
||||||
|
|
@ -72,9 +70,9 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
// When we're about to insert the first child into a component,
|
// When we're about to insert the first child into a component,
|
||||||
// it's time to open a new lambda
|
// it's time to open a new lambda
|
||||||
var blazorNodeWriter = (BlazorIntermediateNodeWriter)context.NodeWriter;
|
var blazorNodeWriter = (BlazorIntermediateNodeWriter)context.NodeWriter;
|
||||||
blazorNodeWriter.BeginWriteAttribute(context.CodeWriter, RenderTreeBuilder.ChildContent);
|
blazorNodeWriter.BeginWriteAttribute(context.CodeWriter, BlazorApi.RenderTreeBuilder.ChildContent);
|
||||||
OffsetBuilderVarNumber(1);
|
OffsetBuilderVarNumber(1);
|
||||||
context.CodeWriter.Write($"({_renderFragmentTypeName})(");
|
context.CodeWriter.Write($"({BlazorApi.RenderFragment.FullTypeName})(");
|
||||||
currentScope.LambdaScope = context.CodeWriter.BuildLambda(BuilderVarName);
|
currentScope.LambdaScope = context.CodeWriter.BuildLambda(BuilderVarName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,14 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
// Captures: MyApp.Namespace.ISomeType<T1, T2>
|
// Captures: MyApp.Namespace.ISomeType<T1, T2>
|
||||||
private const string ImplementsTokenPattern = @"\s*Implements\s*<(.+)\>\s*\(\s*\)\s*";
|
private const string ImplementsTokenPattern = @"\s*Implements\s*<(.+)\>\s*\(\s*\)\s*";
|
||||||
|
|
||||||
public static void Register(IRazorEngineBuilder configuration)
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
{
|
{
|
||||||
configuration.Features.Add(new TemporaryImplementsPass());
|
builder.Features.Add(new TemporaryImplementsPass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Features.Add(new TemporaryImplementsPass());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TemporaryImplementsPass() : base(ImplementsTokenPattern)
|
private TemporaryImplementsPass() : base(ImplementsTokenPattern)
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,14 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
||||||
private const string LayoutAttributeTypeName
|
private const string LayoutAttributeTypeName
|
||||||
= "Microsoft.AspNetCore.Blazor.Layouts.LayoutAttribute";
|
= "Microsoft.AspNetCore.Blazor.Layouts.LayoutAttribute";
|
||||||
|
|
||||||
public static void Register(IRazorEngineBuilder configuration)
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
{
|
{
|
||||||
configuration.Features.Add(new TemporaryLayoutPass());
|
builder.Features.Add(new TemporaryLayoutPass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Features.Add(new TemporaryLayoutPass());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TemporaryLayoutPass() : base(LayoutTokenPattern)
|
private TemporaryLayoutPass() : base(LayoutTokenPattern)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
||||||
// IMPORTANT
|
// IMPORTANT
|
||||||
//
|
//
|
||||||
// Many of these names are used in code generation. Keep these in sync with the code generation code
|
// Many of these names are used in code generation. Keep these in sync with the code generation code
|
||||||
// See: src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorComponent.cs
|
// See: src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorApi.cs
|
||||||
|
|
||||||
// Most of the developer-facing component lifecycle concepts are encapsulated in this
|
// Most of the developer-facing component lifecycle concepts are encapsulated in this
|
||||||
// base class. The core Blazor rendering system doesn't know about them (it only knows
|
// base class. The core Blazor rendering system doesn't know about them (it only knows
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
// IMPORTANT
|
// IMPORTANT
|
||||||
//
|
//
|
||||||
// Many of these names are used in code generation. Keep these in sync with the code generation code
|
// Many of these names are used in code generation. Keep these in sync with the code generation code
|
||||||
// See: src/Microsoft.AspNetCore.Blazor.Razor.Extensions/RenderTreeBuilder.cs
|
// See: src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorApi.cs
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides methods for building a collection of <see cref="RenderTreeFrame"/> entries.
|
/// Provides methods for building a collection of <see cref="RenderTreeFrame"/> entries.
|
||||||
|
|
|
||||||
|
|
@ -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 System;
|
||||||
|
using Microsoft.AspNetCore.Blazor.Razor;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
|
|
||||||
|
namespace Microsoft.VisualStudio.LanguageServices.Blazor
|
||||||
|
{
|
||||||
|
[ExportCustomProjectEngineFactory("Blazor-0.1", SupportsSerialization = false)]
|
||||||
|
internal class BlazorProjectEngineFactory : IProjectEngineFactory
|
||||||
|
{
|
||||||
|
public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure)
|
||||||
|
{
|
||||||
|
return RazorProjectEngine.Create(configuration, fileSystem, b =>
|
||||||
|
{
|
||||||
|
configure?.Invoke(b);
|
||||||
|
new BlazorExtensionInitializer().Initialize(b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue