public override void VisitMarkupElement(MarkupElementIntermediateNode node) { for (var i = 0; i < node.Children.Count; i++) { if (node.Children[i] is HtmlAttributeIntermediateNode attribute && attribute.AttributeName != null) { if (_attributes.TryGetValue(attribute.AttributeName, out var other)) { // As a special case we want to point it out explicitly where a directive or other construct // has emitted an attribute that causes a conflict. We're already looking at the lowered version // of this construct, so it's easy to detect. We just need the original name to report the issue. // // Example: `bind-value` will set `value` and `onchange`. var originalAttributeName = attribute.Annotations[ComponentMetadata.Common.OriginalAttributeName] as string ?? other.node.Annotations[ComponentMetadata.Common.OriginalAttributeName] as string; if (originalAttributeName != null) { other.node.Diagnostics.Add(ComponentDiagnosticFactory.Create_DuplicateMarkupAttributeDirective( other.name, originalAttributeName, other.node.Source ?? node.Source)); } else { // This is a conflict in the code the user wrote. other.node.Diagnostics.Add(ComponentDiagnosticFactory.Create_DuplicateMarkupAttribute( other.name, other.node.Source ?? node.Source)); } } // Replace the attribute we were previously tracking. Then if you have three, the two on the left will have // diagnostics. _attributes[attribute.AttributeName] = (attribute.AttributeName, attribute); } } _attributes.Clear(); base.VisitMarkupElement(node); }