зеркало из https://github.com/dotnet/razor.git
Added view component tag helper updates. (#823)
Added view component tag helper updates. aspnet/mvc#1051
This commit is contained in:
Родитель
8d7c51bd60
Коммит
489c0d9046
|
@ -703,6 +703,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
/// Converts from pascal/camel case to lower kebab-case.
|
/// Converts from pascal/camel case to lower kebab-case.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <example>
|
/// <example>
|
||||||
|
/// <code>
|
||||||
/// SomeThing => some-thing
|
/// SomeThing => some-thing
|
||||||
/// capsONInside => caps-on-inside
|
/// capsONInside => caps-on-inside
|
||||||
/// CAPSOnOUTSIDE => caps-on-outside
|
/// CAPSOnOUTSIDE => caps-on-outside
|
||||||
|
@ -710,8 +711,9 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
/// One1Two2Three3 => one1-two2-three3
|
/// One1Two2Three3 => one1-two2-three3
|
||||||
/// ONE1TWO2THREE3 => one1two2three3
|
/// ONE1TWO2THREE3 => one1two2three3
|
||||||
/// First_Second_ThirdHi => first_second_third-hi
|
/// First_Second_ThirdHi => first_second_third-hi
|
||||||
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
private static string ToHtmlCase(string name)
|
public static string ToHtmlCase(string name)
|
||||||
{
|
{
|
||||||
return HtmlCaseRegex.Replace(name, HtmlCaseRegexReplacement).ToLowerInvariant();
|
return HtmlCaseRegex.Replace(name, HtmlCaseRegexReplacement).ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkTree Tree { get { return Context.ChunkTreeBuilder.Root; } }
|
protected ChunkTree Tree { get { return Context.ChunkTreeBuilder.Root; } }
|
||||||
public RazorEngineHost Host { get { return Context.Host; } }
|
public RazorEngineHost Host { get { return Context.Host; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -82,12 +82,23 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators
|
||||||
csharpCodeVisitor.Accept(Tree.Children);
|
csharpCodeVisitor.Accept(Tree.Children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BuildAfterExecuteContent(writer, Tree.Children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CodeGeneratorResult(writer.GenerateCode(), writer.LineMappingManager.Mappings);
|
return new CodeGeneratorResult(writer.GenerateCode(), writer.LineMappingManager.Mappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an entry point to append code (after execute content) to a generated Razor class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="CSharpCodeWriter"/> to receive the additional content.</param>
|
||||||
|
/// <param name="chunks">The list of <see cref="Chunk"/>s for the generated program.</param>
|
||||||
|
protected virtual void BuildAfterExecuteContent(CSharpCodeWriter writer, IList<Chunk> chunks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual CSharpCodeVisitor CreateCSharpCodeVisitor(
|
protected virtual CSharpCodeVisitor CreateCSharpCodeVisitor(
|
||||||
CSharpCodeWriter writer,
|
CSharpCodeWriter writer,
|
||||||
CodeGeneratorContext context)
|
CodeGeneratorContext context)
|
||||||
|
|
|
@ -319,6 +319,17 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators
|
||||||
.WriteEndMethodInvocation(endLine);
|
.WriteEndMethodInvocation(endLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CSharpCodeWriter WriteAutoPropertyDeclaration(string accessibility, string typeName, string name)
|
||||||
|
{
|
||||||
|
return Write(accessibility)
|
||||||
|
.Write(" ")
|
||||||
|
.Write(typeName)
|
||||||
|
.Write(" ")
|
||||||
|
.Write(name)
|
||||||
|
.Write(" { get; set; }")
|
||||||
|
.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
public CSharpDisableWarningScope BuildDisableWarningScope(int warning)
|
public CSharpDisableWarningScope BuildDisableWarningScope(int warning)
|
||||||
{
|
{
|
||||||
return new CSharpDisableWarningScope(this, warning);
|
return new CSharpDisableWarningScope(this, warning);
|
||||||
|
|
|
@ -2172,6 +2172,35 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
TagHelperAttributeDescriptorComparer.Default);
|
TagHelperAttributeDescriptorComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TheoryData HtmlConversionData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<string, string>
|
||||||
|
{
|
||||||
|
{ "SomeThing", "some-thing" },
|
||||||
|
{ "someOtherThing", "some-other-thing" },
|
||||||
|
{ "capsONInside", "caps-on-inside" },
|
||||||
|
{ "CAPSOnOUTSIDE", "caps-on-outside" },
|
||||||
|
{ "ALLCAPS", "allcaps" },
|
||||||
|
{ "One1Two2Three3", "one1-two2-three3" },
|
||||||
|
{ "ONE1TWO2THREE3", "one1two2three3" },
|
||||||
|
{ "First_Second_ThirdHi", "first_second_third-hi" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(HtmlConversionData))]
|
||||||
|
public void ToHtmlCase_ReturnsExpectedConversions(string input, string expectedOutput)
|
||||||
|
{
|
||||||
|
// Arrange, Act
|
||||||
|
var output = TagHelperDescriptorFactory.ToHtmlCase(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(output, expectedOutput);
|
||||||
|
}
|
||||||
|
|
||||||
// TagHelperDesignTimeDescriptors are not created in CoreCLR.
|
// TagHelperDesignTimeDescriptors are not created in CoreCLR.
|
||||||
#if !NETCOREAPP1_0
|
#if !NETCOREAPP1_0
|
||||||
public static TheoryData OutputElementHintData
|
public static TheoryData OutputElementHintData
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
#if GENERATE_BASELINES
|
#if GENERATE_BASELINES
|
||||||
using System;
|
using System;
|
||||||
#endif
|
#endif
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.Chunks;
|
||||||
|
using Microsoft.AspNetCore.Razor.Chunks.Generators;
|
||||||
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNetCore.Razor.Test.CodeGenerators;
|
using Microsoft.AspNetCore.Razor.Test.CodeGenerators;
|
||||||
using Microsoft.AspNetCore.Razor.Test.Utils;
|
using Microsoft.AspNetCore.Razor.Test.Utils;
|
||||||
|
@ -14,9 +18,15 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators
|
||||||
{
|
{
|
||||||
public class CSharpCodeGeneratorTest
|
public class CSharpCodeGeneratorTest
|
||||||
{
|
{
|
||||||
|
#if GENERATE_BASELINES
|
||||||
|
private static readonly string _baselinePathStart = "test/Microsoft.AspNetCore.Razor.Test";
|
||||||
|
#endif
|
||||||
|
private static readonly string _testOutputDirectory = "TestFiles/CodeGenerator/Output/CSharpCodeGenerator";
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ChunkTreeWithUsings()
|
public void ChunkTreeWithUsings()
|
||||||
{
|
{
|
||||||
|
// Arrange
|
||||||
var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
|
var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
|
||||||
var language = new CSharpRazorCodeLanguage();
|
var language = new CSharpRazorCodeLanguage();
|
||||||
var host = new CodeGenTestHost(language);
|
var host = new CodeGenTestHost(language);
|
||||||
|
@ -30,7 +40,9 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators
|
||||||
codeGeneratorContext.ChunkTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
codeGeneratorContext.ChunkTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
||||||
codeGeneratorContext.ChunkTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
codeGeneratorContext.ChunkTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
||||||
var codeGenerator = new CodeGenTestCodeGenerator(codeGeneratorContext);
|
var codeGenerator = new CodeGenTestCodeGenerator(codeGeneratorContext);
|
||||||
var testFile = TestFile.Create("TestFiles/CodeGenerator/Output/CSharpCodeGenerator.cs");
|
|
||||||
|
var path = $"{_testOutputDirectory}/ChunkTreeWithUsings.cs";
|
||||||
|
var testFile = TestFile.Create(path);
|
||||||
|
|
||||||
string expectedOutput;
|
string expectedOutput;
|
||||||
#if GENERATE_BASELINES
|
#if GENERATE_BASELINES
|
||||||
|
@ -54,14 +66,151 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators
|
||||||
// Update baseline files if files do not already match.
|
// Update baseline files if files do not already match.
|
||||||
if (!string.Equals(expectedOutput, result.Code, StringComparison.Ordinal))
|
if (!string.Equals(expectedOutput, result.Code, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
BaselineWriter.WriteBaseline(
|
var baselinePath = $"{_baselinePathStart}/{_testOutputDirectory}/ChunkTreeWithUsings.cs";
|
||||||
@"test\Microsoft.AspNetCore.Razor.Test\TestFiles\CodeGenerator\Output\CSharpCodeGenerator.cs",
|
BaselineWriter.WriteBaseline( baselinePath, result.Code);
|
||||||
result.Code);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Assert.Equal(expectedOutput, result.Code);
|
Assert.Equal(expectedOutput, result.Code);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public static TheoryData ModifyOutputData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var addFileName = "AddGenerateChunkTest.cs";
|
||||||
|
var addGenerator = new AddGenerateTestCodeGenerator(CreateContext());
|
||||||
|
var addResult = CreateCodeGeneratorResult(addFileName);
|
||||||
|
|
||||||
|
var clearFileName = "ClearGenerateChunkTest.cs";
|
||||||
|
var clearGenerator = new ClearGenerateTestCodeGenerator(CreateContext());
|
||||||
|
var clearResult = CreateCodeGeneratorResult(clearFileName);
|
||||||
|
|
||||||
|
var defaultFileName = "DefaultGenerateChunkTest.cs";
|
||||||
|
var defaultGenerator = new CSharpCodeGenerator(CreateContext());
|
||||||
|
var defaultResult = CreateCodeGeneratorResult(defaultFileName);
|
||||||
|
|
||||||
|
var commentFileName = "BuildAfterExecuteContentTest.cs";
|
||||||
|
var commentGenerator = new BuildAfterExecuteContentTestCodeGenerator(CreateContext());
|
||||||
|
var commentResult = CreateCodeGeneratorResult(commentFileName);
|
||||||
|
|
||||||
|
return new TheoryData<CSharpCodeGenerator, CodeGeneratorResult, string>
|
||||||
|
{
|
||||||
|
{addGenerator, addResult, addFileName},
|
||||||
|
{clearGenerator, clearResult, clearFileName },
|
||||||
|
{defaultGenerator, defaultResult, defaultFileName },
|
||||||
|
{commentGenerator, commentResult, commentFileName }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ModifyOutputData))]
|
||||||
|
public void BuildAfterExecuteContent_ModifyChunks_ModifyOutput(
|
||||||
|
CSharpCodeGenerator generator,
|
||||||
|
CodeGeneratorResult expectedResult,
|
||||||
|
string fileName)
|
||||||
|
{
|
||||||
|
// Arrange, Act
|
||||||
|
var result = generator.Generate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
#if GENERATE_BASELINES
|
||||||
|
// Update baseline files if files do not already match.
|
||||||
|
if (!string.Equals(expectedResult.Code, result.Code, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var baselinePath = $"{_baselinePathStart}/{_testOutputDirectory}/{fileName}";
|
||||||
|
BaselineWriter.WriteBaseline( baselinePath, result.Code);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Assert.Equal(result.Code, expectedResult.Code);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static CodeGeneratorResult CreateCodeGeneratorResult(string fileName)
|
||||||
|
{
|
||||||
|
var path = $"{_testOutputDirectory}/{fileName}";
|
||||||
|
var file = TestFile.Create(path);
|
||||||
|
string code;
|
||||||
|
|
||||||
|
#if GENERATE_BASELINES
|
||||||
|
if (file.Exists())
|
||||||
|
{
|
||||||
|
code = file.ReadAllText();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
code = null;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
code = file.ReadAllText();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var result = new CodeGeneratorResult(code, new List<LineMapping>());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a context with two literal chunks.
|
||||||
|
private static CodeGeneratorContext CreateContext()
|
||||||
|
{
|
||||||
|
var language = new CSharpRazorCodeLanguage();
|
||||||
|
var host = new CodeGenTestHost(language);
|
||||||
|
|
||||||
|
var codeGeneratorContext = new CodeGeneratorContext(
|
||||||
|
new ChunkGeneratorContext(
|
||||||
|
host,
|
||||||
|
host.DefaultClassName,
|
||||||
|
host.DefaultNamespace,
|
||||||
|
"",
|
||||||
|
shouldGenerateLinePragmas: false),
|
||||||
|
new ErrorSink());
|
||||||
|
|
||||||
|
codeGeneratorContext.ChunkTreeBuilder = new ChunkTreeBuilder();
|
||||||
|
var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
|
||||||
|
codeGeneratorContext.ChunkTreeBuilder.AddLiteralChunk("hello", syntaxTreeNode.Object);
|
||||||
|
codeGeneratorContext.ChunkTreeBuilder.AddStatementChunk("// asdf", syntaxTreeNode.Object);
|
||||||
|
codeGeneratorContext.ChunkTreeBuilder.AddLiteralChunk("world", syntaxTreeNode.Object);
|
||||||
|
return codeGeneratorContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BuildAfterExecuteContentTestCodeGenerator : CSharpCodeGenerator
|
||||||
|
{
|
||||||
|
public BuildAfterExecuteContentTestCodeGenerator(CodeGeneratorContext context) : base(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BuildAfterExecuteContent(CSharpCodeWriter writer, IList<Chunk> chunks)
|
||||||
|
{
|
||||||
|
writer.WriteLine("// test add content.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AddGenerateTestCodeGenerator : CSharpCodeGenerator
|
||||||
|
{
|
||||||
|
public AddGenerateTestCodeGenerator(CodeGeneratorContext context) : base(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override CodeGeneratorResult Generate()
|
||||||
|
{
|
||||||
|
var firstChunk = Tree.Children.First();
|
||||||
|
Tree.Children.Add(firstChunk);
|
||||||
|
return base.Generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClearGenerateTestCodeGenerator : CSharpCodeGenerator
|
||||||
|
{
|
||||||
|
public ClearGenerateTestCodeGenerator(CodeGeneratorContext context) : base(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override CodeGeneratorResult Generate()
|
||||||
|
{
|
||||||
|
Tree.Children.Clear();
|
||||||
|
return base.Generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
namespace Razor
|
||||||
|
{
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class __CompiledTemplate
|
||||||
|
{
|
||||||
|
#line hidden
|
||||||
|
public __CompiledTemplate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
WriteLiteral("hello");
|
||||||
|
#line 1 ""
|
||||||
|
// asdf
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
WriteLiteral("world");
|
||||||
|
WriteLiteral("hello");
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
namespace Razor
|
||||||
|
{
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class __CompiledTemplate
|
||||||
|
{
|
||||||
|
#line hidden
|
||||||
|
public __CompiledTemplate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
WriteLiteral("hello");
|
||||||
|
#line 1 ""
|
||||||
|
// asdf
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
WriteLiteral("world");
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
// test add content.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Razor
|
||||||
|
{
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class __CompiledTemplate
|
||||||
|
{
|
||||||
|
#line hidden
|
||||||
|
public __CompiledTemplate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
namespace Razor
|
||||||
|
{
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class __CompiledTemplate
|
||||||
|
{
|
||||||
|
#line hidden
|
||||||
|
public __CompiledTemplate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
WriteLiteral("hello");
|
||||||
|
#line 1 ""
|
||||||
|
// asdf
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
WriteLiteral("world");
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче