Beispiel #1
0
        private void ProcessDuplicates(IntermediateNode node)
        {
            // Reverse order because we will remove nodes.
            //
            // Each 'property' node could be duplicated if there are multiple tag helpers that match that
            // particular attribute. This is common in our approach, which relies on 'fallback' tag helpers
            // that overlap with more specific ones.
            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                // For each usage of the general 'fallback' bind tag helper, it could duplicate
                // the usage of a more specific one. Look for duplicates and remove the fallback.
                var attribute = node.Children[i] as TagHelperPropertyIntermediateNode;
                if (attribute != null &&
                    attribute.TagHelper != null &&
                    attribute.TagHelper.IsFallbackBindTagHelper())
                {
                    for (var j = 0; j < node.Children.Count; j++)
                    {
                        var duplicate = node.Children[j] as TagHelperPropertyIntermediateNode;
                        if (duplicate != null &&
                            duplicate.TagHelper != null &&
                            duplicate.TagHelper.IsBindTagHelper() &&
                            duplicate.AttributeName == attribute.AttributeName &&
                            !object.ReferenceEquals(attribute, duplicate))
                        {
                            // Found a duplicate - remove the 'fallback' in favor of the
                            // more specific tag helper.
                            node.Children.RemoveAt(i);
                            break;
                        }
                    }
                }

                // Also treat the general <input bind="..." /> as a 'fallback' for that case and remove it.
                // This is a workaround for a limitation where you can't write a tag helper that binds only
                // when a specific attribute is **not** present.
                if (attribute != null &&
                    attribute.TagHelper != null &&
                    attribute.TagHelper.IsInputElementFallbackBindTagHelper())
                {
                    for (var j = 0; j < node.Children.Count; j++)
                    {
                        var duplicate = node.Children[j] as TagHelperPropertyIntermediateNode;
                        if (duplicate != null &&
                            duplicate.TagHelper != null &&
                            duplicate.TagHelper.IsInputElementBindTagHelper() &&
                            duplicate.AttributeName == attribute.AttributeName &&
                            !object.ReferenceEquals(attribute, duplicate))
                        {
                            // Found a duplicate - remove the 'fallback' input tag helper in favor of the
                            // more specific tag helper.
                            node.Children.RemoveAt(i);
                            break;
                        }
                    }
                }
            }

            // If we still have duplicates at this point then they are genuine conflicts.
            var duplicates = node.Children
                             .OfType <TagHelperPropertyIntermediateNode>()
                             .GroupBy(p => p.AttributeName)
                             .Where(g => g.Count() > 1);

            foreach (var duplicate in duplicates)
            {
                node.Diagnostics.Add(ComponentDiagnosticFactory.CreateBindAttribute_Duplicates(
                                         node.Source,
                                         duplicate.Key,
                                         duplicate.ToArray()));
                foreach (var property in duplicate)
                {
                    node.Children.Remove(property);
                }
            }
        }