private void HandleBoundAttribute(SetTagHelperProperty attribute, int attributeIndex, RenderTagHelper parent) { if (!attribute.AssociatedDescriptor.IsStringProperty || attribute.Value.Children.Count != 1 || !(attribute.Value.Children.First() is RenderHtml)) { return; } var plainTextValue = (attribute.Value.Children.First() as RenderHtml).Html; DeclarePreallocatedTagHelperAttribute declaration = null; for (var i = 0; i < _classDeclaration.Children.Count; i++) { var current = _classDeclaration.Children[i]; if (current is DeclarePreallocatedTagHelperAttribute) { var existingDeclaration = (DeclarePreallocatedTagHelperAttribute)current; if (string.Equals(existingDeclaration.Name, attribute.AttributeName, StringComparison.Ordinal) && string.Equals(existingDeclaration.Value, plainTextValue, StringComparison.Ordinal) && existingDeclaration.ValueStyle == attribute.ValueStyle) { declaration = existingDeclaration; break; } } } if (declaration == null) { var variableCount = _classDeclaration.Children.Count - _variableCountOffset; var preAllocatedAttributeVariableName = PreAllocatedAttributeVariablePrefix + variableCount; declaration = new DeclarePreallocatedTagHelperAttribute { VariableName = preAllocatedAttributeVariableName, Name = attribute.AttributeName, Value = plainTextValue, ValueStyle = attribute.ValueStyle, }; _classDeclaration.Children.Insert(0, declaration); } var setPreallocatedProperty = new SetPreallocatedTagHelperProperty { AttributeVariableName = declaration.VariableName, AttributeName = attribute.AttributeName, TagHelperTypeName = attribute.TagHelperTypeName, PropertyName = attribute.PropertyName, AssociatedDescriptor = attribute.AssociatedDescriptor, }; parent.Children[attributeIndex] = setPreallocatedProperty; }
private void AddTagHelperAttributes(IList <TagHelperAttributeTracker> attributes, IEnumerable <TagHelperDescriptor> descriptors) { var renderedBoundAttributeNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (var attribute in attributes) { var attributeValueChunk = attribute.Value; var associatedDescriptors = descriptors.Where(descriptor => descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name))); if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attribute.Name)) { if (attributeValueChunk == null) { // Minimized attributes are not valid for bound attributes. TagHelperBlockRewriter has already // logged an error if it was a bound attribute; so we can skip. continue; } foreach (var associatedDescriptor in associatedDescriptors) { var valueBlock = new CSharpBlock(); using (_context.Builder.UseBlock(valueBlock)) { Accept(attribute.Value); } var associatedAttributeDescriptor = associatedDescriptor.Attributes.First( attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name)); var associationBlock = attribute.Value.Association as Block; var documentLocation = attribute.Value.Start; // TODO: Do we need to handle @ at the beginning of non-string TH attributes? var contentLength = attribute.Value.Association.Length; var setTagHelperProperty = new SetTagHelperProperty { PropertyName = associatedAttributeDescriptor.PropertyName, AttributeName = attribute.Name, TagHelperTypeName = associatedDescriptor.TypeName, Value = valueBlock, DocumentLocation = CreateMappingLocation(documentLocation, contentLength), AssociatedDescriptor = associatedAttributeDescriptor, ValueStyle = attribute.ValueStyle }; _context.Builder.Add(setTagHelperProperty); } } else { var addHtmlAttribute = new AddTagHelperHtmlAttribute { Name = attribute.Name, ValueStyle = attribute.ValueStyle }; if (attributeValueChunk != null) { var valueBlock = new CSharpBlock(); using (_context.Builder.UseBlock(valueBlock)) { Accept(attribute.Value); } addHtmlAttribute.ValuePieces = valueBlock.Children; } _context.Builder.Add(addHtmlAttribute); } } }