Exemple #1
0
        private bool TryCachePreallocatedVariableName(TagHelperAttributeKey key, out string preAllocatedAttributeVariableName)
        {
            if (!_preAllocatedAttributes.TryGetValue(key, out preAllocatedAttributeVariableName))
            {
                preAllocatedAttributeVariableName = _preAllocatedAttributeVariablePrefix + _preAllocatedAttributes.Count;
                _preAllocatedAttributes[key]      = preAllocatedAttributeVariableName;
                return(true);
            }

            return(false);
        }
Exemple #2
0
        private void PreAllocateTagHelperAttributes(TagHelperChunk chunk)
        {
            var boundAttributes = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            for (var i = 0; i < chunk.Attributes.Count; i++)
            {
                var attribute = chunk.Attributes[i];
                var associatedAttributeDescriptors = chunk.Descriptors.SelectMany(descriptor => descriptor.Attributes)
                                                     .Where(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name));

                // If there's no descriptors associated or is a repeated attribute with same name as a bound attribute,
                // it is considered as an unbound attribute.
                var isUnBoundAttribute = !associatedAttributeDescriptors.Any() || !boundAttributes.Add(attribute.Name);

                // Perf: We will preallocate TagHelperAttribute for unbound attributes and simple bound string valued attributes.
                if (isUnBoundAttribute || CanPreallocateBoundAttribute(associatedAttributeDescriptors, attribute))
                {
                    string preAllocatedAttributeVariableName = null;

                    if (attribute.ValueStyle == HtmlAttributeValueStyle.Minimized)
                    {
                        Debug.Assert(attribute.Value == null);

                        var preAllocatedAttributeKey = new TagHelperAttributeKey(
                            attribute.Name,
                            value: null,
                            unBoundAttribute: isUnBoundAttribute,
                            valueStyle: attribute.ValueStyle);
                        if (TryCachePreallocatedVariableName(preAllocatedAttributeKey, out preAllocatedAttributeVariableName))
                        {
                            Writer
                            .Write("private static readonly global::")
                            .Write(_tagHelperContext.TagHelperAttributeTypeName)
                            .Write(" ")
                            .Write(preAllocatedAttributeVariableName)
                            .Write(" = ")
                            .WriteStartNewObject("global::" + _tagHelperContext.TagHelperAttributeTypeName)
                            .WriteStringLiteral(attribute.Name)
                            .WriteEndMethodInvocation();
                        }
                    }
                    else
                    {
                        Debug.Assert(attribute.Value != null);

                        string plainText;
                        if (CSharpTagHelperCodeRenderer.TryGetPlainTextValue(attribute.Value, out plainText))
                        {
                            var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Name, plainText, isUnBoundAttribute, attribute.ValueStyle);
                            if (TryCachePreallocatedVariableName(preAllocatedAttributeKey, out preAllocatedAttributeVariableName))
                            {
                                Writer
                                .Write("private static readonly global::")
                                .Write(_tagHelperContext.TagHelperAttributeTypeName)
                                .Write(" ")
                                .Write(preAllocatedAttributeVariableName)
                                .Write(" = ")
                                .WriteStartNewObject("global::" + _tagHelperContext.TagHelperAttributeTypeName)
                                .WriteStringLiteral(attribute.Name)
                                .WriteParameterSeparator();

                                if (isUnBoundAttribute)
                                {
                                    // For unbound attributes, we need to create HtmlString.
                                    Writer
                                    .WriteStartNewObject("global::" + _tagHelperContext.EncodedHtmlStringTypeName)
                                    .WriteStringLiteral(plainText)
                                    .WriteEndMethodInvocation(endLine: false);
                                }
                                else
                                {
                                    Writer.WriteStringLiteral(plainText);
                                }

                                Writer
                                .WriteParameterSeparator()
                                .Write($"global::{typeof(HtmlAttributeValueStyle).FullName}.{attribute.ValueStyle}")
                                .WriteEndMethodInvocation();
                            }
                        }
                    }

                    if (preAllocatedAttributeVariableName != null)
                    {
                        chunk.Attributes[i] = new TagHelperAttributeTracker(
                            attribute.Name,
                            new PreallocatedTagHelperAttributeChunk
                        {
                            AttributeVariableAccessor = preAllocatedAttributeVariableName
                        },
                            attribute.ValueStyle);
                    }
                }
            }
        }
        private void PreAllocateUnboundTagHelperAttributes(TagHelperChunk chunk)
        {
            var boundAttributes = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            for (var i = 0; i < chunk.Attributes.Count; i++)
            {
                var attribute = chunk.Attributes[i];
                var hasAssociatedDescriptors = chunk.Descriptors.Any(descriptor =>
                                                                     descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Key)));

                // If there's no descriptors associated or we're hitting a bound attribute a second time.
                if (!hasAssociatedDescriptors || !boundAttributes.Add(attribute.Key))
                {
                    string preAllocatedAttributeVariableName = null;

                    if (attribute.Value == null)
                    {
                        var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Key, value: null);
                        if (TryCachePreallocatedVariableName(preAllocatedAttributeKey, out preAllocatedAttributeVariableName))
                        {
                            Writer
                            .Write("private static readonly global::")
                            .Write(_tagHelperContext.TagHelperAttributeTypeName)
                            .Write(" ")
                            .Write(preAllocatedAttributeVariableName)
                            .Write(" = ")
                            .WriteStartNewObject("global::" + _tagHelperContext.TagHelperAttributeTypeName)
                            .WriteStringLiteral(attribute.Key)
                            .WriteEndMethodInvocation();
                        }
                    }
                    else
                    {
                        string plainText;
                        if (CSharpTagHelperCodeRenderer.TryGetPlainTextValue(attribute.Value, out plainText))
                        {
                            var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Key, plainText);
                            if (TryCachePreallocatedVariableName(preAllocatedAttributeKey, out preAllocatedAttributeVariableName))
                            {
                                Writer
                                .Write("private static readonly global::")
                                .Write(_tagHelperContext.TagHelperAttributeTypeName)
                                .Write(" ")
                                .Write(preAllocatedAttributeVariableName)
                                .Write(" = ")
                                .WriteStartNewObject("global::" + _tagHelperContext.TagHelperAttributeTypeName)
                                .WriteStringLiteral(attribute.Key)
                                .WriteParameterSeparator()
                                .WriteStartNewObject("global::" + _tagHelperContext.EncodedHtmlStringTypeName)
                                .WriteStringLiteral(plainText)
                                .WriteEndMethodInvocation(endLine: false)
                                .WriteEndMethodInvocation();
                            }
                        }
                    }

                    if (preAllocatedAttributeVariableName != null)
                    {
                        chunk.Attributes[i] = new KeyValuePair <string, Chunk>(
                            attribute.Key,
                            new PreallocatedTagHelperAttributeChunk
                        {
                            AttributeVariableAccessor = preAllocatedAttributeVariableName
                        });
                    }
                }
            }
        }