コード例 #1
0
        private ComponentIntermediateNode RewriteAsComponent(TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
        {
            var component = new ComponentIntermediateNode()
            {
                Component = tagHelper,
                Source    = node.Source,
                TagName   = node.TagName,
                TypeName  = tagHelper.GetTypeName(),
            };

            for (var i = 0; i < node.Diagnostics.Count; i++)
            {
                component.Diagnostics.Add(node.Diagnostics[i]);
            }

            var visitor = new ComponentRewriteVisitor(component);

            visitor.Visit(node);

            // Fixup the parameter names of child content elements. We can't do this during the rewrite
            // because we see the nodes in the wrong order.
            foreach (var childContent in component.ChildContents)
            {
                childContent.ParameterName = childContent.ParameterName ?? component.ChildContentParameterName ?? ComponentMetadata.ChildContent.DefaultParameterName;
            }

            return(component);
        }
コード例 #2
0
        private void AddField(Context context, TagHelperDescriptor tagHelper)
        {
            // We need to insert a node for the field that will hold the tag helper. We've already generated a field name
            // at this time and use it for all uses of the same tag helper type.
            //
            // We also want to preserve the ordering of the nodes for testability. So insert at the end of any existing
            // field nodes.
            var i = 0;

            while (i < context.Class.Children.Count && context.Class.Children[i] is DefaultTagHelperRuntimeIntermediateNode)
            {
                i++;
            }

            while (i < context.Class.Children.Count && context.Class.Children[i] is FieldDeclarationIntermediateNode)
            {
                i++;
            }

            context.Class.Children.Insert(i, new FieldDeclarationIntermediateNode()
            {
                Annotations =
                {
                    { CommonAnnotations.DefaultTagHelperExtension.TagHelperField, bool.TrueString },
                },
                Modifiers =
                {
                    "private",
                },
                FieldName = context.GetFieldName(tagHelper),
                FieldType = "global::" + tagHelper.GetTypeName(),
            });
        }
        private static TagHelperDescriptor FindAssociatedTagHelper(TagHelperDescriptor tagHelper, IReadOnlyList <TagHelperDescriptor> tagHelpers)
        {
            var typeName     = tagHelper.GetTypeName();
            var assemblyName = tagHelper.AssemblyName;

            for (var i = 0; i < tagHelpers.Count; i++)
            {
                var currentTagHelper = tagHelpers[i];

                if (tagHelper == currentTagHelper)
                {
                    // Same as the primary, we're looking for our other pair.
                    continue;
                }

                var currentTypeName = currentTagHelper.GetTypeName();
                if (!string.Equals(typeName, currentTypeName, StringComparison.Ordinal))
                {
                    continue;
                }

                if (!string.Equals(assemblyName, currentTagHelper.AssemblyName, StringComparison.Ordinal))
                {
                    continue;
                }

                // Found our associated TagHelper, there should only ever be 1 other associated TagHelper (fully qualified and non-fully qualified).
                return(currentTagHelper);
            }

            return(null);
        }
コード例 #4
0
        public static BoundElementDescriptionInfo From(TagHelperDescriptor tagHelper)
        {
            var tagHelperTypeName = tagHelper.GetTypeName();
            var descriptionInfo   = new BoundElementDescriptionInfo(tagHelperTypeName, tagHelper.Documentation);

            return(descriptionInfo);
        }
コード例 #5
0
        private void RewriteUsage(Context context, TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
        {
            if (!tagHelper.IsDefaultKind())
            {
                return;
            }

            context.Add(tagHelper);

            // First we need to insert a node for the creation of the tag helper, and the hook up to the execution
            // context. This should come after the body node and any existing create nodes.
            //
            // If we're dealing with something totally malformed, then we'll end up just inserting at the end, and that's not
            // so bad.
            var i = 0;

            // Find the body node.
            while (i < node.Children.Count && node.Children[i] is TagHelperBodyIntermediateNode)
            {
                i++;
            }
            while (i < node.Children.Count && node.Children[i] is DefaultTagHelperBodyIntermediateNode)
            {
                i++;
            }

            // Now find the last create node.
            while (i < node.Children.Count && node.Children[i] is DefaultTagHelperCreateIntermediateNode)
            {
                i++;
            }

            // Now i has the right insertion point.
            node.Children.Insert(i, new DefaultTagHelperCreateIntermediateNode()
            {
                FieldName = context.GetFieldName(tagHelper),
                TagHelper = tagHelper,
                TypeName  = tagHelper.GetTypeName(),
            });

            // Next we need to rewrite any property nodes to use the field and property name for this
            // tag helper.
            for (i = 0; i < node.Children.Count; i++)
            {
                if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
                    propertyNode.TagHelper == tagHelper)
                {
                    // This belongs to the current tag helper, replace it.
                    node.Children[i] = new DefaultTagHelperPropertyIntermediateNode(propertyNode)
                    {
                        FieldName    = context.GetFieldName(tagHelper),
                        PropertyName = propertyNode.BoundAttribute.GetPropertyName(),
                    };
                }
            }
        }
コード例 #6
0
        private void RewriteUsage(TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
        {
            // Ignore Kind here. Some versions of Razor have a bug in the serializer that ignores it.

            // We need to surround the contents of the node with open and close nodes to ensure the component
            // is scoped correctly.
            node.Children.Insert(0, new ComponentOpenExtensionNode()
            {
                TypeName = tagHelper.GetTypeName(),
            });

            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                if (node.Children[i] is TagHelperBodyIntermediateNode bodyNode)
                {
                    // Replace with a node that we recognize so that it we can do proper scope tracking.
                    //
                    // Note that we force the body node to be last, this is done to push it after the
                    // attribute nodes. This gives us the ordering we want for the render tree.
                    node.Children.RemoveAt(i);
                    node.Children.Add(new ComponentBodyExtensionNode(bodyNode)
                    {
                        TagMode = node.TagMode,
                        TagName = node.TagName,
                    });
                }
            }

            node.Children.Add(new ComponentCloseExtensionNode());

            // Now we need to rewrite any set property or HTML nodes to call the appropriate AddAttribute api.
            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
                    propertyNode.TagHelper == tagHelper)
                {
                    // We don't support 'complex' content for components (mixed C# and markup) right now.
                    // It's not clear yet if Blazor will have a good scenario to use these constructs.
                    //
                    // This is where a lot of the complexity in the Razor/TagHelpers model creeps in and we
                    // might be able to avoid it if these features aren't needed.
                    if (HasComplexChildContent(propertyNode))
                    {
                        node.Diagnostics.Add(BlazorDiagnosticFactory.Create_UnsupportedComplexContent(
                                                 propertyNode,
                                                 propertyNode.AttributeName));
                        node.Children.RemoveAt(i);
                        continue;
                    }

                    node.Children[i] = new ComponentAttributeExtensionNode(propertyNode);
                }
コード例 #7
0
        internal static bool TrySplitNamespaceAndType(TagHelperDescriptor tagHelperDescriptor, out StringSegment @namespace, out StringSegment typeName)
        {
            if (tagHelperDescriptor.ParsedTypeInfo is { } value)
            {
                @namespace = value.Namespace;
                typeName   = value.TypeName;
                return(value.Success);
            }

            var success = TrySplitNamespaceAndType(tagHelperDescriptor.GetTypeName(), out @namespace, out typeName);

            tagHelperDescriptor.ParsedTypeInfo = new(success, @namespace, typeName);
            return(success);
        }
コード例 #8
0
        private TagHelperDescriptor CreateChildContentDescriptor(ComponentSymbols symbols, TagHelperDescriptor component, BoundAttributeDescriptor attribute)
        {
            var typeName     = component.GetTypeName() + "." + attribute.Name;
            var assemblyName = component.AssemblyName;

            var builder = TagHelperDescriptorBuilder.Create(ComponentMetadata.ChildContent.TagHelperKind, typeName, assemblyName);

            builder.SetTypeName(typeName);
            builder.CaseSensitive = true;

            // This opts out this 'component' tag helper for any processing that's specific to the default
            // Razor ITagHelper runtime.
            builder.Metadata[TagHelperMetadata.Runtime.Name] = ComponentMetadata.ChildContent.RuntimeName;

            // Opt out of processing as a component. We'll process this specially as part of the component's body.
            builder.Metadata[ComponentMetadata.SpecialKindKey] = ComponentMetadata.ChildContent.TagHelperKind;

            var xml = attribute.Documentation;

            if (!string.IsNullOrEmpty(xml))
            {
                builder.Documentation = xml;
            }

            // Child content matches the property name, but only as a direct child of the component.
            builder.TagMatchingRule(r =>
            {
                r.TagName   = attribute.Name;
                r.ParentTag = component.TagMatchingRules.First().TagName;
            });

            if (attribute.IsParameterizedChildContentProperty())
            {
                // For child content attributes with a parameter, synthesize an attribute that allows you to name
                // the parameter.
                CreateContextParameter(builder, attribute.Name);
            }

            if (component.IsComponentFullyQualifiedNameMatch())
            {
                builder.Metadata[ComponentMetadata.Component.NameMatchKey] = ComponentMetadata.Component.FullyQualifiedNameMatch;
            }

            var descriptor = builder.Build();

            return(descriptor);
        }
コード例 #9
0
ファイル: ComponentLoweringPass.cs プロジェクト: okwh/Blazor
        private ComponentExtensionNode RewriteAsComponent(TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
        {
            var component = new ComponentExtensionNode()
            {
                Component = tagHelper,
                Source    = node.Source,
                TagName   = node.TagName,
                TypeName  = tagHelper.GetTypeName(),
            };

            for (var i = 0; i < node.Diagnostics.Count; i++)
            {
                component.Diagnostics.Add(node.Diagnostics[i]);
            }

            var visitor = new ComponentRewriteVisitor(component);

            visitor.Visit(node);

            return(component);
        }
コード例 #10
0
        private void RewriteUsage(TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
        {
            // We need to surround the contents of the node with open and close nodes to ensure the component
            // is scoped correctly.
            node.Children.Insert(0, new ComponentOpenExtensionNode()
            {
                TypeName = tagHelper.GetTypeName(),
            });

            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                if (node.Children[i] is TagHelperBodyIntermediateNode bodyNode)
                {
                    // Replace with a node that we recognize so that it we can do proper scope tracking.
                    //
                    // Note that we force the body node to be last, this is done to push it after the
                    // attribute nodes. This gives us the ordering we want for the render tree.
                    node.Children.RemoveAt(i);
                    node.Children.Add(new ComponentBodyExtensionNode(bodyNode)
                    {
                        TagMode = node.TagMode,
                        TagName = node.TagName,
                    });
                }
            }

            node.Children.Add(new ComponentCloseExtensionNode());

            // Now we need to rewrite any set property or HTML nodes to call the appropriate AddAttribute api.
            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
                    propertyNode.TagHelper == tagHelper)
                {
                    node.Children[i] = new ComponentAttributeExtensionNode(propertyNode);
                }
コード例 #11
0
 private static string GenerateFieldName(TagHelperDescriptor tagHelper)
 {
     return("__" + tagHelper.GetTypeName().Replace('.', '_'));
 }