private ComponentChildContentIntermediateNode RewriteChildContent(BoundAttributeDescriptor attribute, SourceSpan?source, IntermediateNodeCollection children) { var childContent = new ComponentChildContentIntermediateNode() { BoundAttribute = attribute, Source = source, TypeName = attribute?.TypeName ?? BlazorApi.RenderFragment.FullTypeName, }; // There are two cases here: // 1. Implicit child content - the children will be non-taghelper nodes, just accept them // 2. Explicit child content - the children will be various tag helper nodes, that need special processing. for (var i = 0; i < children.Count; i++) { var child = children[i]; if (child is TagHelperBodyIntermediateNode body) { // The body is all of the content we want to render, the rest of the childen will // be the attributes. for (var j = 0; j < body.Children.Count; j++) { childContent.Children.Add(body.Children[j]); } } else if (child is TagHelperPropertyIntermediateNode property) { if (property.BoundAttribute.Kind == BlazorMetadata.ChildContent.TagHelperKind) { // Check for each child content with a parameter name, that the parameter name is specified // with literal text. For instance, the following is not allowed and should generate a diagnostic. // // <MyComponent><ChildContent Context="@Foo()">...</ChildContent></MyComponent> if (TryGetAttributeStringContent(property, out var parameterName)) { childContent.ParameterName = parameterName; continue; } // The parameter name is invalid. childContent.Diagnostics.Add(BlazorDiagnosticFactory.Create_ChildContentHasInvalidParameter(property.Source, property.AttributeName, attribute.Name)); continue; } // This is an unrecognized attribute, this is possible if you try to do something like put 'ref' on a child content. childContent.Diagnostics.Add(BlazorDiagnosticFactory.Create_ChildContentHasInvalidAttribute(property.Source, property.AttributeName, attribute.Name)); } else if (child is TagHelperHtmlAttributeIntermediateNode a) { // This is an HTML attribute on a child content. childContent.Diagnostics.Add(BlazorDiagnosticFactory.Create_ChildContentHasInvalidAttribute(a.Source, a.AttributeName, attribute.Name)); } else { // This is some other kind of node (likely an implicit child content) childContent.Children.Add(child); } } return(childContent); }
public void VisitExtension(ComponentChildContentIntermediateNode node) { // Check that each child content has a unique parameter name within its scope. This is important // because the parameter name can be implict, and it doesn't work well when nested. if (node.IsParameterized) { for (var i = 0; i < Ancestors.Count - 1; i++) { var ancestor = Ancestors[i] as ComponentChildContentIntermediateNode; if (ancestor != null && ancestor.IsParameterized && string.Equals(node.ParameterName, ancestor.ParameterName, StringComparison.Ordinal)) { // Duplicate name. We report an error because this will almost certainly also lead to an error // from the C# compiler that's way less clear. node.Diagnostics.Add(BlazorDiagnosticFactory.Create_ChildContentRepeatedParameterName( node.Source, node, (ComponentExtensionNode)Ancestors[0], // Encosing component ancestor, // conflicting child content node (ComponentExtensionNode)Ancestors[i + 1])); // Encosing component of conflicting child content node } } } base.VisitDefault(node); }
public static RazorDiagnostic Create_ChildContentRepeatedParameterName( SourceSpan?source, ComponentChildContentIntermediateNode childContent1, ComponentExtensionNode component1, ComponentChildContentIntermediateNode childContent2, ComponentExtensionNode component2) { Debug.Assert(childContent1.ParameterName == childContent2.ParameterName); Debug.Assert(childContent1.IsParameterized); Debug.Assert(childContent2.IsParameterized); return(RazorDiagnostic.Create( ChildContentRepeatedParameterName, source ?? SourceSpan.Undefined, childContent1.AttributeName, component1.TagName, childContent1.ParameterName, childContent2.AttributeName, component2.TagName)); }
public abstract void WriteComponentChildContent(CodeRenderingContext context, ComponentChildContentIntermediateNode node);