Skip to content
代码片段 群组 项目
未验证 提交 e48fff6f 编辑于 作者: Brennan's avatar Brennan 提交者: GitHub
浏览文件

[automated] Merge branch 'release/6.0-rc2' => 'release/6.0' (#36948)

No related branches found
No related tags found
无相关合并请求
显示
189 个添加17 个删除
......@@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Razor.Language
bool suppressPrimaryMethodBody,
bool suppressNullabilityEnforcement,
bool omitMinimizedComponentAttributeValues,
bool supportLocalizedComponentNames,
bool useEnhancedLinePragma)
{
IndentWithTabs = indentWithTabs;
......@@ -26,6 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Language
SuppressPrimaryMethodBody = suppressPrimaryMethodBody;
SuppressNullabilityEnforcement = suppressNullabilityEnforcement;
OmitMinimizedComponentAttributeValues = omitMinimizedComponentAttributeValues;
SupportLocalizedComponentNames = supportLocalizedComponentNames;
UseEnhancedLinePragma = useEnhancedLinePragma;
}
......
......@@ -41,6 +41,8 @@ namespace Microsoft.AspNetCore.Razor.Language
public override bool OmitMinimizedComponentAttributeValues { get; set; }
public override bool SupportLocalizedComponentNames { get; set; }
public override bool UseEnhancedLinePragma { get; set; }
public override RazorCodeGenerationOptions Build()
......@@ -55,6 +57,7 @@ namespace Microsoft.AspNetCore.Razor.Language
SuppressPrimaryMethodBody,
SuppressNullabilityEnforcement,
OmitMinimizedComponentAttributeValues,
SupportLocalizedComponentNames,
UseEnhancedLinePragma)
{
SuppressMetadataSourceChecksumAttributes = SuppressMetadataSourceChecksumAttributes,
......
......@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Components;
using Microsoft.AspNetCore.Razor.Language.Extensions;
......@@ -1200,10 +1201,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
// We only want this error during the second phase of the two phase compilation.
var startTagName = node.StartTag.GetTagNameWithOptionalBang();
if (startTagName != null && startTagName.Length > 0 && char.IsUpper(startTagName, 0))
if (!string.IsNullOrEmpty(startTagName) && LooksLikeAComponentName(_document, startTagName))
{
// A markup element that starts with an uppercase character.
// It is most likely intended to be a component. Add a warning.
element.Diagnostics.Add(
ComponentDiagnosticFactory.Create_UnexpectedMarkupElement(startTagName, BuildSourceSpanFromNode(node.StartTag)));
}
......@@ -1214,6 +1213,24 @@ namespace Microsoft.AspNetCore.Razor.Language
base.VisitMarkupElement(node);
_builder.Pop();
static bool LooksLikeAComponentName(DocumentIntermediateNode document, string startTagName)
{
var category = char.GetUnicodeCategory(startTagName, 0);
// A markup element which starts with an uppercase character is likely a component.
//
// In certain cultures, characters are not explicitly Uppercase/Lowercase, hence we must check
// the specific UnicodeCategory to see if we may still be able to treat it as a component.
//
// The goal here is to avoid clashing with any future standard-HTML elements.
//
// To avoid a breaking change, the support of localized component names (without explicit
// Uppercase classification) is behind a `SupportLocalizedComponentNames` feature flag.
return category is UnicodeCategory.UppercaseLetter ||
(document.Options.SupportLocalizedComponentNames &&
(category is UnicodeCategory.TitlecaseLetter || category is UnicodeCategory.OtherLetter));
}
}
public override void VisitMarkupStartTag(MarkupStartTagSyntax node)
......
......@@ -33,3 +33,8 @@ Microsoft.AspNetCore.Razor.Language.SourceSpan.EndCharacterIndex.get -> int
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptionsBuilder.UseEnhancedLinePragma.get -> bool
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptionsBuilder.UseEnhancedLinePragma.set -> void
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptions.UseEnhancedLinePragma.get -> bool
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptionsBuilder.SupportLocalizedComponentNames.get -> bool
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptionsBuilder.SupportLocalizedComponentNames.set -> void
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptions.SupportLocalizedComponentNames.get -> bool
virtual Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptions.SupportLocalizedComponentNames.set -> void
~static Microsoft.AspNetCore.Razor.Language.RazorProjectEngineBuilderExtensions.SetSupportLocalizedComponentNames(this Microsoft.AspNetCore.Razor.Language.RazorProjectEngineBuilder builder) -> Microsoft.AspNetCore.Razor.Language.RazorProjectEngineBuilder
......@@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Razor.Language
suppressPrimaryMethodBody: false,
suppressNullabilityEnforcement: false,
omitMinimizedComponentAttributeValues: false,
supportLocalizedComponentNames: false,
useEnhancedLinePragma: true);
}
......@@ -34,6 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Language
suppressPrimaryMethodBody: false,
suppressNullabilityEnforcement: false,
omitMinimizedComponentAttributeValues: false,
supportLocalizedComponentNames: false,
useEnhancedLinePragma: true);
}
......@@ -133,6 +135,14 @@ namespace Microsoft.AspNetCore.Razor.Language
/// </summary>
public virtual bool OmitMinimizedComponentAttributeValues { get; }
/// <summary>
/// Gets a value that determines if localized component names are to be supported.
/// </summary>
public virtual bool SupportLocalizedComponentNames { get; set; }
/// <summary>
/// Gets a value that determines if enhanced line pragmas are to be utilized.
/// </summary>
public virtual bool UseEnhancedLinePragma { get; }
}
}
......@@ -73,6 +73,14 @@ namespace Microsoft.AspNetCore.Razor.Language
/// </summary>
public virtual bool OmitMinimizedComponentAttributeValues { get; set; }
/// <summary>
/// Gets or sets a value that determines if localized component names are to be supported.
/// </summary>
public virtual bool SupportLocalizedComponentNames { get; set; }
/// <summary>
/// Gets a value that determines if enhanced line pragmas are to be utilized.
/// </summary>
public virtual bool UseEnhancedLinePragma { get; set; }
public abstract RazorCodeGenerationOptions Build();
......
......@@ -92,6 +92,22 @@ namespace Microsoft.AspNetCore.Razor.Language
return builder;
}
/// <summary>
/// Sets the SupportLocalizedComponentNames property to make localized component name diagnostics available.
/// </summary>
/// <param name="builder">The <see cref="RazorProjectEngineBuilder"/>.</param>
/// <returns>The <see cref="RazorProjectEngineBuilder"/>.</returns>
public static RazorProjectEngineBuilder SetSupportLocalizedComponentNames(this RazorProjectEngineBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Features.Add(new SetSupportLocalizedComponentNamesFeature());
return builder;
}
public static void SetImportFeature(this RazorProjectEngineBuilder builder, IImportProjectFeature feature)
{
if (builder == null)
......@@ -302,6 +318,21 @@ namespace Microsoft.AspNetCore.Razor.Language
}
}
private class SetSupportLocalizedComponentNamesFeature : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature
{
public int Order { get; set; }
public void Configure(RazorCodeGenerationOptionsBuilder options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.SupportLocalizedComponentNames = true;
}
}
private class ConfigureRootNamespaceFeature : IConfigureRazorCodeGenerationOptionsFeature
{
private readonly string _rootNamespace;
......
......@@ -115,8 +115,10 @@ Some Content
diagnostic.GetMessage(CultureInfo.CurrentCulture));
}
[Fact]
public void ChildContent_ExplicitChildContent_UnrecogizedElement_ProducesDiagnostic()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void ChildContent_ExplicitChildContent_UnrecogizedElement_ProducesDiagnostic(bool supportLocalizedComponentNames)
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
......@@ -127,7 +129,7 @@ Some Content
<ChildContent>
</ChildContent>
<UnrecognizedChildContent></UnrecognizedChildContent>
</RenderChildContent>");
</RenderChildContent>", supportLocalizedComponentNames: supportLocalizedComponentNames);
// Assert
Assert.Collection(
......@@ -136,6 +138,47 @@ Some Content
d => Assert.Equal("RZ9996", d.Id));
}
[Fact]
public void ChildContent_ExplicitChildContent_StartsWithCharThatIsOtherLetterCategory_WhenLocalizedComponentNamesIsAllowed()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
// Act
var generated = CompileToCSharp(@$"
<RenderChildContent>
<ChildContent>
</ChildContent>
<繁体字></繁体字>
</RenderChildContent>", supportLocalizedComponentNames: true);
// Assert
Assert.Collection(
generated.Diagnostics,
d => Assert.Equal("RZ10012", d.Id),
d => Assert.Equal("RZ9996", d.Id));
}
[Fact]
public void ChildContent_ExplicitChildContent_StartsWithCharThatIsOtherLetterCategory_WhenLocalizedComponentNamesIsDisallowed()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
// Act
var generated = CompileToCSharp(@$"
<RenderChildContent>
<ChildContent>
</ChildContent>
<繁体字></繁体字>
</RenderChildContent>", supportLocalizedComponentNames: false);
// Assert
Assert.Collection(
generated.Diagnostics,
d => Assert.Equal("RZ9996", d.Id));
}
[Fact]
public void ChildContent_ExplicitChildContent_UnrecogizedAttribute_ProducesDiagnostic()
{
......
......@@ -43,7 +43,6 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
var diagnostic = Assert.Single(generated.Diagnostics);
Assert.Equal("RZ9979", diagnostic.Id);
Assert.NotNull(diagnostic.GetMessage(CultureInfo.CurrentCulture));
}
[Fact]
......@@ -147,8 +146,10 @@ namespace Test
diagnostic.GetMessage(CultureInfo.CurrentCulture));
}
[Fact]
public void Element_DoesNotStartWithLowerCase_ReportsWarning()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Component_NotFound_ReportsWarning(bool supportLocalizedComponentNames)
{
// Arrange & Act
var generated = CompileToCSharp(@"
......@@ -156,7 +157,7 @@ namespace Test
@functions {
public string Text { get; set; } = ""text"";
}");
}", supportLocalizedComponentNames: supportLocalizedComponentNames);
// Assert
var diagnostic = Assert.Single(generated.Diagnostics);
......@@ -167,6 +168,41 @@ namespace Test
diagnostic.GetMessage(CultureInfo.CurrentCulture));
}
[Fact]
public void Component_NotFound_StartsWithOtherLetter_WhenLocalizedComponentNamesIsAllowed_ReportsWarning()
{
// Arrange & Act
var generated = CompileToCSharp(@"
<繁体字></繁体字>
@functions {
public string Text { get; set; } = ""text"";
}", supportLocalizedComponentNames: true);
// Assert
var diagnostic = Assert.Single(generated.Diagnostics);
Assert.Equal("RZ10012", diagnostic.Id);
Assert.Equal(RazorDiagnosticSeverity.Warning, diagnostic.Severity);
Assert.Equal(
"Found markup element with unexpected name '繁体字'. If this is intended to be a component, add a @using directive for its namespace.",
diagnostic.GetMessage(CultureInfo.CurrentCulture));
}
[Fact]
public void Component_NotFound_StartsWithOtherLetter_WhenLocalizedComponentNamesIsDisallowed()
{
// Arrange & Act
var generated = CompileToCSharp(@"
<繁体字></繁体字>
@functions {
public string Text { get; set; } = ""text"";
}", supportLocalizedComponentNames: false);
// Assert
Assert.Empty(generated.Diagnostics);
}
[Fact]
public void Element_DoesNotStartWithLowerCase_OverrideWithBang_NoWarning()
{
......
......@@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
internal virtual string WorkingDirectory { get; }
// intentionally private - we don't want individual tests messing with the project engine
private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, MetadataReference[] references)
private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, MetadataReference[] references, bool supportLocalizedComponentNames)
{
return RazorProjectEngine.Create(configuration, FileSystem, b =>
{
......@@ -121,6 +121,11 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Turn off checksums, we're testing code generation.
b.Features.Add(new SuppressChecksum());
if (supportLocalizedComponentNames)
{
b.Features.Add(new SupportLocalizedComponentNames());
}
b.Features.Add(new TestImportProjectFeature(ImportItems));
if (LineEnding != null)
......@@ -168,12 +173,12 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
};
}
protected CompileToCSharpResult CompileToCSharp(string cshtmlContent, bool throwOnFailure=true, string cssScope = null)
protected CompileToCSharpResult CompileToCSharp(string cshtmlContent, bool throwOnFailure=true, string cssScope = null, bool supportLocalizedComponentNames = false)
{
return CompileToCSharp(DefaultFileName, cshtmlContent, throwOnFailure, cssScope: cssScope);
return CompileToCSharp(DefaultFileName, cshtmlContent, throwOnFailure, cssScope: cssScope, supportLocalizedComponentNames: supportLocalizedComponentNames);
}
protected CompileToCSharpResult CompileToCSharp(string cshtmlRelativePath, string cshtmlContent, bool throwOnFailure = true, string fileKind = null, string cssScope = null)
protected CompileToCSharpResult CompileToCSharp(string cshtmlRelativePath, string cshtmlContent, bool throwOnFailure = true, string fileKind = null, string cssScope = null, bool supportLocalizedComponentNames = false)
{
if (DeclarationOnly && DesignTime)
{
......@@ -189,7 +194,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
// The first phase won't include any metadata references for component discovery. This mirrors
// what the build does.
var projectEngine = CreateProjectEngine(Configuration, Array.Empty<MetadataReference>());
var projectEngine = CreateProjectEngine(Configuration, Array.Empty<MetadataReference>(), supportLocalizedComponentNames);
RazorCodeDocument codeDocument;
foreach (var item in AdditionalRazorItems)
......@@ -218,7 +223,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Add the 'temp' compilation as a metadata reference
var references = BaseCompilation.References.Concat(new[] { tempAssembly.Compilation.ToMetadataReference() }).ToArray();
projectEngine = CreateProjectEngine(Configuration, references);
projectEngine = CreateProjectEngine(Configuration, references, supportLocalizedComponentNames);
// Now update the any additional files
foreach (var item in AdditionalRazorItems)
......@@ -247,7 +252,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
// For single phase compilation tests just use the base compilation's references.
// This will include the built-in components.
var projectEngine = CreateProjectEngine(Configuration, BaseCompilation.References.ToArray());
var projectEngine = CreateProjectEngine(Configuration, BaseCompilation.References.ToArray(), supportLocalizedComponentNames);
var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent, fileKind, cssScope);
......@@ -446,6 +451,18 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
}
}
private class SupportLocalizedComponentNames : IConfigureRazorCodeGenerationOptionsFeature
{
public int Order => 0;
public RazorEngine Engine { get; set; }
public void Configure(RazorCodeGenerationOptionsBuilder options)
{
options.SupportLocalizedComponentNames = true;
}
}
private class ForceLineEndingPhase : RazorEnginePhaseBase
{
public ForceLineEndingPhase(string lineEnding)
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册