diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs index 26e350f2aea..af5ff495588 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.AspNetCore.Razor.Language; @@ -171,6 +172,20 @@ private static TagHelperDescriptor CreateNameMatchingDescriptor( builder.SetDocumentation(xml); } + // Collect properties exist with different casing. + using var caseSensitiveProperties = StringHashSetPool.OrdinalIgnoreCase.GetPooledObject(); + using (var caseInsensitivePropertyNameMap = StringDictionaryPool.OrdinalIgnoreCase.GetPooledObject()) + { + foreach (var (property, _) in properties) + { + var existingPropertyName = caseInsensitivePropertyNameMap.Object.GetOrAdd(property.Name, property.Name); + if (existingPropertyName != property.Name) + { + caseSensitiveProperties.Object.Add(property.Name); + } + } + } + foreach (var (property, kind) in properties) { if (kind == PropertyKind.Ignored) @@ -178,7 +193,7 @@ private static TagHelperDescriptor CreateNameMatchingDescriptor( continue; } - CreateProperty(builder, type, property, kind); + CreateProperty(builder, type, property, kind, caseSensitiveProperties.Object); } if (builder.BoundAttributes.Any(static a => a.IsParameterizedChildContentProperty()) && @@ -195,7 +210,7 @@ private static TagHelperDescriptor CreateNameMatchingDescriptor( return builder.Build(); } - private static void CreateProperty(TagHelperDescriptorBuilder builder, INamedTypeSymbol containingSymbol, IPropertySymbol property, PropertyKind kind) + private static void CreateProperty(TagHelperDescriptorBuilder builder, INamedTypeSymbol containingSymbol, IPropertySymbol property, PropertyKind kind, ISet caseSensitiveProperties) { builder.BindAttribute(pb => { @@ -207,6 +222,8 @@ private static void CreateProperty(TagHelperDescriptorBuilder builder, INamedTyp pb.IsEditorRequired = property.GetAttributes().Any( static a => a.AttributeClass.HasFullName("Microsoft.AspNetCore.Components.EditorRequiredAttribute")); + pb.CaseSensitive = caseSensitiveProperties.Contains(property.Name); + metadata.Add(PropertyName(property.Name)); metadata.Add(GloballyQualifiedTypeName(property.Type.ToDisplayString(GloballyQualifiedFullNameTypeDisplayFormat))); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs index 77c347e9808..071c20535fe 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs @@ -39,6 +39,7 @@ public sealed partial class BoundAttributeDescriptorBuilder : TagHelperObjectBui private string _kind; private DocumentationObject _documentationObject; private MetadataHolder _metadata; + private bool? _caseSensitive; private BoundAttributeDescriptorBuilder() { @@ -76,7 +77,11 @@ public string? Documentation public bool TryGetMetadataValue(string key, [NotNullWhen(true)] out string? value) => _metadata.TryGetMetadataValue(key, out value); - internal bool CaseSensitive => _parent.CaseSensitive; + internal bool CaseSensitive + { + get => _caseSensitive ?? _parent.CaseSensitive; + set => _caseSensitive = value; + } private TagHelperObjectBuilderCollection Parameters { get; } = new(BoundAttributeParameterDescriptorBuilder.Pool); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder_Pooling.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder_Pooling.cs index 24ca4757aa6..28d66b2ab4a 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder_Pooling.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder_Pooling.cs @@ -25,6 +25,7 @@ private protected override void Reset() _parent = null; _kind = null; _documentationObject = default; + _caseSensitive = null; Name = null; TypeName = null;